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.


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