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.


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