Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Added RTC functionality (including interrupt injection) to nvram
[palacios.git] / palacios / src / devices / 8259a.c
1 #include <devices/8259a.h>
2 #include <palacios/vmm_intr.h>
3 #include <palacios/vmm_types.h>
4 #include <palacios/vmm.h>
5
6 #ifndef DEBUG_PIC
7 #undef PrintDebug
8 #define PrintDebug(fmt, args...)
9 #endif
10
11 typedef enum {RESET, ICW1, ICW2, ICW3, ICW4,  READY} pic_state_t;
12
13 static const uint_t MASTER_PORT1 = 0x20;
14 static const uint_t MASTER_PORT2 = 0x21;
15 static const uint_t SLAVE_PORT1 = 0xA0;
16 static const uint_t SLAVE_PORT2 = 0xA1;
17
18 #define IS_ICW1(x) (((x & 0x10) >> 4) == 0x1)
19 #define IS_OCW2(x) (((x & 0x18) >> 3) == 0x0)
20 #define IS_OCW3(x) (((x & 0x18) >> 3) == 0x1)
21
22
23 struct icw1 {
24   uint_t ic4    : 1;  // ICW4 has to be read
25   uint_t sngl   : 1;  // single (only one PIC)
26   uint_t adi    : 1;  // call address interval
27   uint_t ltim   : 1;  // level interrupt mode
28   uint_t one    : 1;
29   uint_t rsvd   : 3;
30 };
31
32
33 struct icw2 {
34   uint_t rsvd   : 3;
35   uint_t vector : 5;
36 };
37
38
39 // Each bit that is set indicates that the IR input has a slave
40 struct icw3_master {
41   uint_t S0   : 1;
42   uint_t S1   : 1;
43   uint_t S2   : 1;
44   uint_t S3   : 1;
45   uint_t S4   : 1;
46   uint_t S5   : 1;
47   uint_t S6   : 1;
48   uint_t S7   : 1;
49 };
50
51 // The ID is the Slave device ID
52 struct icw3_slave {
53   uint_t id     : 3;
54   uint_t zeroes : 5;
55 };
56
57 struct icw4 {
58   uint_t uPM    : 1;  // 1=x86
59   uint_t AEOI   : 1;  // Automatic End of Interrupt
60   uint_t M_S    : 1;  // only if buffered 1=master,0=slave 
61   uint_t BUF    : 1;  // buffered mode
62   uint_t SFNM   : 1;  // special fully nexted mode
63   uint_t zeroes : 3;
64 };
65
66
67 struct ocw1 {
68   uint_t m0     : 1;
69   uint_t m1     : 1;
70   uint_t m2     : 1;
71   uint_t m3     : 1;
72   uint_t m4     : 1;
73   uint_t m5     : 1;
74   uint_t m6     : 1;
75   uint_t m7     : 1;
76 };
77
78 struct ocw2 {
79   uint_t level  : 3;
80   uint_t cw_code : 2; // should be 00
81   uint_t EOI    : 1;
82   uint_t SL     : 1;
83   uint_t R      : 1;
84 };
85
86 struct ocw3 {
87   uint_t RIS    : 1;
88   uint_t RR     : 1;
89   uint_t P      : 1;
90   uint_t cw_code : 2; // should be 01
91   uint_t smm    : 1;
92   uint_t esmm   : 1;
93   uint_t zero2  : 1;
94 };
95
96
97 struct pic_internal {
98
99
100   uchar_t master_irr;
101   uchar_t slave_irr;
102   
103   uchar_t master_isr;
104   uchar_t slave_isr;
105
106   uchar_t master_icw1;
107   uchar_t master_icw2;
108   uchar_t master_icw3;
109   uchar_t master_icw4;
110
111
112   uchar_t slave_icw1;
113   uchar_t slave_icw2;
114   uchar_t slave_icw3;
115   uchar_t slave_icw4;
116
117
118   uchar_t master_imr;
119   uchar_t slave_imr;
120   uchar_t master_ocw2;
121   uchar_t master_ocw3;
122   uchar_t slave_ocw2;
123   uchar_t slave_ocw3;
124
125   pic_state_t master_state;
126   pic_state_t slave_state;
127 };
128
129
130 static void DumpPICState(struct pic_internal *p)
131 {
132
133   PrintDebug("8259 PIC: master_state=0x%x\n",p->master_state);
134   PrintDebug("8259 PIC: master_irr=0x%x\n",p->master_irr);
135   PrintDebug("8259 PIC: master_isr=0x%x\n",p->master_isr);
136   PrintDebug("8259 PIC: master_imr=0x%x\n",p->master_imr);
137
138   PrintDebug("8259 PIC: master_ocw2=0x%x\n",p->master_ocw2);
139   PrintDebug("8259 PIC: master_ocw3=0x%x\n",p->master_ocw3);
140
141   PrintDebug("8259 PIC: master_icw1=0x%x\n",p->master_icw1);
142   PrintDebug("8259 PIC: master_icw2=0x%x\n",p->master_icw2);
143   PrintDebug("8259 PIC: master_icw3=0x%x\n",p->master_icw3);
144   PrintDebug("8259 PIC: master_icw4=0x%x\n",p->master_icw4);
145
146   PrintDebug("8259 PIC: slave_state=0x%x\n",p->slave_state);
147   PrintDebug("8259 PIC: slave_irr=0x%x\n",p->slave_irr);
148   PrintDebug("8259 PIC: slave_isr=0x%x\n",p->slave_isr);
149   PrintDebug("8259 PIC: slave_imr=0x%x\n",p->slave_imr);
150
151   PrintDebug("8259 PIC: slave_ocw2=0x%x\n",p->slave_ocw2);
152   PrintDebug("8259 PIC: slave_ocw3=0x%x\n",p->slave_ocw3);
153
154   PrintDebug("8259 PIC: slave_icw1=0x%x\n",p->slave_icw1);
155   PrintDebug("8259 PIC: slave_icw2=0x%x\n",p->slave_icw2);
156   PrintDebug("8259 PIC: slave_icw3=0x%x\n",p->slave_icw3);
157   PrintDebug("8259 PIC: slave_icw4=0x%x\n",p->slave_icw4);
158
159 }
160
161
162 static int pic_raise_intr(void * private_data, int irq) {
163   struct pic_internal * state = (struct pic_internal*)private_data;
164
165   if (irq == 2) {
166     irq = 9;
167     state->master_irr |= 0x04;  // PAD
168   }
169
170   PrintDebug("8259 PIC: Raising irq %d in the PIC\n", irq);
171
172   if (irq <= 7) {
173     state->master_irr |= 0x01 << irq;
174   } else if ((irq > 7) && (irq < 16)) {
175     state->slave_irr |= 0x01 << (irq - 8);  // PAD if -7 then irq 15=no irq
176   } else {
177     PrintError("8259 PIC: Invalid IRQ raised (%d)\n", irq);
178     return -1;
179   }
180
181   return 0;
182 }
183
184 static int pic_intr_pending(void * private_data) {
185   struct pic_internal * state = (struct pic_internal*)private_data;
186
187   if ((state->master_irr & ~(state->master_imr)) || 
188       (state->slave_irr & ~(state->slave_imr))) {
189     return 1;
190   }
191
192   return 0;
193 }
194
195 static int pic_get_intr_number(void * private_data) {
196   struct pic_internal * state = (struct pic_internal*)private_data;
197   int i=0;
198   int irq=-1;
199
200   PrintDebug("8259 PIC: getnum: master_irr: 0x%x master_imr: 0x%x\n", i, state->master_irr, state->master_imr);
201   PrintDebug("8259 PIC: getnum: slave_irr: 0x%x slave_imr: 0x%x\n", i, state->slave_irr, state->slave_imr);
202
203   for (i = 0; i < 16; i++) {
204     if (i <= 7) {
205       if (((state->master_irr & ~(state->master_imr)) >> i) == 0x01) {
206         //state->master_isr |= (0x1 << i);
207         // reset the irr
208         //state->master_irr &= ~(0x1 << i);
209         PrintDebug("8259 PIC: IRQ: %d, master_icw2: %x\n", i, state->master_icw2);
210         irq= i + state->master_icw2;
211         break;
212       }
213     } else {
214       if (((state->slave_irr & ~(state->slave_imr)) >> (i - 8)) == 0x01) {
215         //state->slave_isr |= (0x1 << (i - 8));
216         //state->slave_irr &= ~(0x1 << (i - 8));
217         PrintDebug("8259 PIC: IRQ: %d, slave_icw2: %x\n", i, state->slave_icw2);
218         irq= (i - 8) + state->slave_icw2;
219         break;
220       }
221     }
222   }
223
224   if (i==15 || i==6) { 
225     DumpPICState(state);
226   }
227   
228   if (i==16) { 
229     return -1;
230   } else {
231     return irq;
232   }
233 }
234
235
236
237 /* The IRQ number is the number returned by pic_get_intr_number(), not the pin number */
238 static int pic_begin_irq(void * private_data, int irq) {
239   struct pic_internal * state = (struct pic_internal*)private_data;
240
241   if ((irq >= state->master_icw2) && (irq <= state->master_icw2 + 7)) {
242     irq &= 0x7;
243   } else if ((irq >= state->slave_icw2) && (irq <= state->slave_icw2 + 7)) {
244     irq &= 0x7;
245     irq += 8;
246   } else {
247     PrintError("8259 PIC: Could not find IRQ (0x%x) to Begin\n",irq);
248     return -1;
249   }
250
251   if (irq <= 7) {
252     if (((state->master_irr & ~(state->master_imr)) >> irq) == 0x01) {
253       state->master_isr |= (0x1 << irq);
254       state->master_irr &= ~(0x1 << irq);
255     }
256   } else {
257     state->slave_isr |= (0x1 << (irq - 8));
258     state->slave_irr &= ~(0x1 << (irq - 8));
259   }
260
261   return 0;
262 }
263
264
265 /*
266 static int pic_end_irq(void * private_data, int irq) {
267   return 0;
268 }
269 */
270
271 static struct intr_ctrl_ops intr_ops = {
272   .intr_pending = pic_intr_pending,
273   .get_intr_number = pic_get_intr_number,
274   .raise_intr = pic_raise_intr,
275   .begin_irq = pic_begin_irq,
276 };
277
278
279
280
281 int read_master_port1(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
282   struct pic_internal * state = (struct pic_internal*)dev->private_data;
283
284   if (length != 1) {
285     PrintError("8259 PIC: Invalid Read length (rd_Master1)\n");
286     return -1;
287   }
288   
289   if ((state->master_ocw3 & 0x03) == 0x02) {
290     *(uchar_t *)dst = state->master_irr;
291   } else if ((state->master_ocw3 & 0x03) == 0x03) {
292     *(uchar_t *)dst = state->master_isr;
293   } else {
294     *(uchar_t *)dst = 0;
295   }
296   
297   return 1;
298 }
299
300 int read_master_port2(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
301   struct pic_internal * state = (struct pic_internal*)dev->private_data;
302
303   if (length != 1) {
304     PrintError("8259 PIC: Invalid Read length (rd_Master2)\n");
305     return -1;
306   }
307
308   *(uchar_t *)dst = state->master_imr;
309
310   return 1;
311   
312 }
313
314 int read_slave_port1(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
315   struct pic_internal * state = (struct pic_internal*)dev->private_data;
316
317   if (length != 1) {
318     PrintError("8259 PIC: Invalid Read length (rd_Slave1)\n");
319     return -1;
320   }
321   
322   if ((state->slave_ocw3 & 0x03) == 0x02) {
323     *(uchar_t*)dst = state->slave_irr;
324   } else if ((state->slave_ocw3 & 0x03) == 0x03) {
325     *(uchar_t *)dst = state->slave_isr;
326   } else {
327     *(uchar_t *)dst = 0;
328   }
329
330   return 1;
331 }
332
333 int read_slave_port2(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
334   struct pic_internal * state = (struct pic_internal*)dev->private_data;
335
336   if (length != 1) {
337     PrintError("8259 PIC: Invalid Read length  (rd_Slave2)\n");
338     return -1;
339   }
340
341   *(uchar_t *)dst = state->slave_imr;
342
343   return 1;
344 }
345
346
347 int write_master_port1(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
348   struct pic_internal * state = (struct pic_internal*)dev->private_data;
349   uchar_t cw = *(uchar_t *)src;
350
351   PrintDebug("8259 PIC: Write master port 1 with 0x%x\n",cw);
352
353   if (length != 1) {
354     PrintError("8259 PIC: Invalid Write length (wr_Master1)\n");
355     return -1;
356   }
357   
358   if (IS_ICW1(cw)) {
359
360     PrintDebug("8259 PIC: Setting ICW1 = %x (wr_Master1)\n", cw);
361     
362     state->master_icw1 = cw;
363     state->master_state = ICW2;
364
365   } else if (state->master_state == READY) {
366     if (IS_OCW2(cw)) {
367       // handle the EOI here
368       struct ocw2 * cw2 =  (struct ocw2*)&cw;
369
370       PrintDebug("8259 PIC: Handling OCW2 = %x (wr_Master1)\n", cw);
371       
372       if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
373         // specific EOI;
374         state->master_isr &= ~(0x01 << cw2->level);
375       } else if ((cw2->EOI) & (!cw2->R) && (!cw2->SL)) {
376         int i;
377         // Non-specific EOI
378         PrintDebug("8259 PIC: Pre ISR = %x (wr_Master1)\n", state->master_isr);
379         for (i = 0; i < 8; i++) {
380           if (state->master_isr & (0x01 << i)) {
381             state->master_isr &= ~(0x01 << i);
382             break;
383           }
384         }       
385         PrintDebug("8259 PIC: Post ISR = %x (wr_Master1)\n", state->master_isr);
386       } else {
387         PrintError("8259 PIC: Command not handled, or in error (wr_Master1)\n");
388         return -1;
389       }
390
391       state->master_ocw2 = cw;
392     } else if (IS_OCW3(cw)) {
393       PrintDebug("8259 PIC: Handling OCW3 = %x (wr_Master1)\n", cw);
394       state->master_ocw3 = cw;
395     } else {
396       PrintError("8259 PIC: Invalid OCW to PIC (wr_Master1)\n");
397       PrintError("8259 PIC: CW=%x\n", cw);
398       return -1;
399     }
400   } else {
401     PrintError("8259 PIC: Invalid PIC State (wr_Master1)\n");
402     PrintError("8259 PIC: CW=%x\n", cw);
403     return -1;
404   }
405
406   return 1;
407 }
408
409 int write_master_port2(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
410     struct pic_internal * state = (struct pic_internal*)dev->private_data;
411     uchar_t cw = *(uchar_t *)src;    
412
413     PrintDebug("8259 PIC: Write master port 2 with 0x%x\n",cw);
414   
415     if (length != 1) {
416       PrintError("8259 PIC: Invalid Write length (wr_Master2)\n");
417       return -1;
418     }
419     
420     if (state->master_state == ICW2) {
421       struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
422
423       PrintDebug("8259 PIC: Setting ICW2 = %x (wr_Master2)\n", cw);
424       state->master_icw2 = cw;
425
426       if (cw1->sngl == 0) {
427         state->master_state = ICW3;
428       } else if (cw1->ic4 == 1) {
429         state->master_state = ICW4;
430       } else {
431         state->master_state = READY;
432       }
433
434     } else if (state->master_state == ICW3) {
435       struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
436
437       PrintDebug("8259 PIC: Setting ICW3 = %x (wr_Master2)\n", cw);
438
439       state->master_icw3 = cw;
440
441       if (cw1->ic4 == 1) {
442         state->master_state = ICW4;
443       } else {
444         state->master_state = READY;
445       }
446
447     } else if (state->master_state == ICW4) {
448       PrintDebug("8259 PIC: Setting ICW4 = %x (wr_Master2)\n", cw);
449       state->master_icw4 = cw;
450       state->master_state = READY;
451     } else if (state->master_state == READY) {
452       PrintDebug("8259 PIC: Setting IMR = %x (wr_Master2)\n", cw);
453       state->master_imr = cw;
454     } else {
455       // error
456       PrintError("8259 PIC: Invalid master PIC State (wr_Master2)\n");
457       return -1;
458     }
459
460     return 1;
461 }
462
463 int write_slave_port1(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
464   struct pic_internal * state = (struct pic_internal*)dev->private_data;
465   uchar_t cw = *(uchar_t *)src;
466
467   PrintDebug("8259 PIC: Write slave port 1 with 0x%x\n",cw);
468
469   if (length != 1) {
470     // error
471     PrintError("8259 PIC: Invalid Write length (wr_Slave1)\n");
472     return -1;
473   }
474
475   if (IS_ICW1(cw)) {
476     PrintDebug("8259 PIC: Setting ICW1 = %x (wr_Slave1)\n", cw);
477     state->slave_icw1 = cw;
478     state->slave_state = ICW2;
479   } else if (state->slave_state == READY) {
480     if (IS_OCW2(cw)) {
481       // handle the EOI here
482       struct ocw2 * cw2 =  (struct ocw2 *)&cw;
483
484       PrintDebug("8259 PIC: Setting OCW2 = %x (wr_Slave1)\n", cw);
485       
486       if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
487         // specific EOI;
488         state->slave_isr &= ~(0x01 << cw2->level);
489       } else if ((cw2->EOI) & (!cw2->R) && (!cw2->SL)) {
490         int i;
491         // Non-specific EOI
492         PrintDebug("8259 PIC: Pre ISR = %x (wr_Slave1)\n", state->slave_isr);
493         for (i = 0; i < 8; i++) {
494           if (state->slave_isr & (0x01 << i)) {
495             state->slave_isr &= ~(0x01 << i);
496             break;
497           }
498         }       
499         PrintDebug("8259 PIC: Post ISR = %x (wr_Slave1)\n", state->slave_isr);
500       } else {
501         PrintError("8259 PIC: Command not handled or invalid  (wr_Slave1)\n");
502         return -1;
503       }
504
505       state->slave_ocw2 = cw;
506     } else if (IS_OCW3(cw)) {
507       // Basically sets the IRR/ISR read flag
508       PrintDebug("8259 PIC: Setting OCW3 = %x (wr_Slave1)\n", cw);
509       state->slave_ocw3 = cw;
510     } else {
511       PrintError("8259 PIC: Invalid command work (wr_Slave1)\n");
512       return -1;
513     }
514   } else {
515     PrintError("8259 PIC: Invalid State writing (wr_Slave1)\n");
516     return -1;
517   }
518
519   return 1;
520 }
521
522 int write_slave_port2(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
523     struct pic_internal * state = (struct pic_internal*)dev->private_data;
524     uchar_t cw = *(uchar_t *)src;    
525
526     PrintDebug("8259 PIC: Write slave port 2 with 0x%x\n",cw);
527
528     if (length != 1) {
529       PrintError("8259 PIC: Invalid write length (wr_Slave2)\n");
530       return -1;
531     }
532
533     if (state->slave_state == ICW2) {
534       struct icw1 * cw1 =  (struct icw1 *)&(state->master_icw1);
535
536       PrintDebug("8259 PIC: Setting ICW2 = %x (wr_Slave2)\n", cw);
537
538       state->slave_icw2 = cw;
539
540       if (cw1->sngl == 0) {
541         state->slave_state = ICW3;
542       } else if (cw1->ic4 == 1) {
543         state->slave_state = ICW4;
544       } else {
545         state->slave_state = READY;
546       }
547
548     } else if (state->slave_state == ICW3) {
549       struct icw1 * cw1 =  (struct icw1 *)&(state->master_icw1);
550
551       PrintDebug("8259 PIC: Setting ICW3 = %x (wr_Slave2)\n", cw);
552
553       state->slave_icw3 = cw;
554
555       if (cw1->ic4 == 1) {
556         state->slave_state = ICW4;
557       } else {
558         state->slave_state = READY;
559       }
560
561     } else if (state->slave_state == ICW4) {
562       PrintDebug("8259 PIC: Setting ICW4 = %x (wr_Slave2)\n", cw);
563       state->slave_icw4 = cw;
564       state->slave_state = READY;
565     } else if (state->slave_state == READY) {
566       PrintDebug("8259 PIC: Setting IMR = %x (wr_Slave2)\n", cw);
567       state->slave_imr = cw;
568     } else {
569       PrintError("8259 PIC: Invalid State at write (wr_Slave2)\n");
570       return -1;
571     }
572
573     return 1;
574 }
575
576
577
578
579
580
581
582
583 int pic_init(struct vm_device * dev) {
584   struct pic_internal * state = (struct pic_internal*)dev->private_data;
585
586   set_intr_controller(dev->vm, &intr_ops, state);
587
588   state->master_irr = 0;
589   state->master_isr = 0;
590   state->master_icw1 = 0;
591   state->master_icw2 = 0;
592   state->master_icw3 = 0;
593   state->master_icw4 = 0;
594   state->master_imr = 0;
595   state->master_ocw2 = 0;
596   state->master_ocw3 = 0x02;
597   state->master_state = ICW1;
598
599
600   state->slave_irr = 0;
601   state->slave_isr = 0;
602   state->slave_icw1 = 0;
603   state->slave_icw2 = 0;
604   state->slave_icw3 = 0;
605   state->slave_icw4 = 0;
606   state->slave_imr = 0;
607   state->slave_ocw2 = 0;
608   state->slave_ocw3 = 0x02;
609   state->slave_state = ICW1;
610
611
612   dev_hook_io(dev, MASTER_PORT1, &read_master_port1, &write_master_port1);
613   dev_hook_io(dev, MASTER_PORT2, &read_master_port2, &write_master_port2);
614   dev_hook_io(dev, SLAVE_PORT1, &read_slave_port1, &write_slave_port1);
615   dev_hook_io(dev, SLAVE_PORT2, &read_slave_port2, &write_slave_port2);
616
617   return 0;
618 }
619
620
621 int pic_deinit(struct vm_device * dev) {
622   dev_unhook_io(dev, MASTER_PORT1);
623   dev_unhook_io(dev, MASTER_PORT2);
624   dev_unhook_io(dev, SLAVE_PORT1);
625   dev_unhook_io(dev, SLAVE_PORT2);
626
627   return 0;
628 }
629
630
631
632
633
634
635
636 static struct vm_device_ops dev_ops = {
637   .init = pic_init,
638   .deinit = pic_deinit,
639   .reset = NULL,
640   .start = NULL,
641   .stop = NULL,
642 };
643
644
645 struct vm_device * create_pic() {
646   struct pic_internal * state = NULL;
647   state = (struct pic_internal *)V3_Malloc(sizeof(struct pic_internal));
648   V3_ASSERT(state != NULL);
649
650   struct vm_device *device = create_device("8259A", &dev_ops, state);
651
652   return device;
653 }
654
655
656
657