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