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.


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