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