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 static int pic_begin_irq(void * private_data, int irq) {
184
185   return 0;
186 }
187
188 /*
189 static int pic_end_irq(void * private_data, int irq) {
190
191   return 0;
192 }
193 */
194
195 static struct intr_ctrl_ops intr_ops = {
196   .intr_pending = pic_intr_pending,
197   .get_intr_number = pic_get_intr_number,
198   .raise_intr = pic_raise_intr,
199   .begin_irq = pic_begin_irq,
200 };
201
202
203
204
205 int read_master_port1(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
206   struct pic_internal * state = (struct pic_internal*)dev->private_data;
207   if (length != 1) {
208     //error
209   }
210   
211   if ((state->master_ocw3 & 0x03) == 0x02) {
212     *(char *)dst = state->master_irr;
213   } else if ((state->master_ocw3 & 0x03) == 0x03) {
214     *(char *)dst = state->master_isr;
215   } else {
216     *(char *)dst = 0;
217   }
218   
219   return 1;
220 }
221
222 int read_master_port2(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
223   struct pic_internal * state = (struct pic_internal*)dev->private_data;
224   if (length != 1) {
225     // error
226   }
227
228   *(char *)dst = state->master_imr;
229
230   return 1;
231   
232 }
233
234 int read_slave_port1(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
235   struct pic_internal * state = (struct pic_internal*)dev->private_data;
236   if (length != 1) {
237     // error
238   }
239   
240   if ((state->slave_ocw3 & 0x03) == 0x02) {
241     *(char*)dst = state->slave_irr;
242   } else if ((state->slave_ocw3 & 0x03) == 0x03) {
243     *(char *)dst = state->slave_isr;
244   } else {
245     *(char *)dst = 0;
246   }
247
248   return 1;
249 }
250
251 int read_slave_port2(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
252   struct pic_internal * state = (struct pic_internal*)dev->private_data;
253   if (length != 1) {
254     // error
255   }
256
257   *(char *)dst = state->slave_imr;
258
259   return 1;
260 }
261
262
263 int write_master_port1(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
264   struct pic_internal * state = (struct pic_internal*)dev->private_data;
265   char cw = *(char *)src;
266
267   if (length != 1) {
268     // error
269   }
270   
271   if (state->master_state == ICW1) {
272     state->master_icw1 = cw;
273     state->master_state = ICW2;
274
275   } else if (state->master_state == READY) {
276     if (IS_OCW2(cw)) {
277       // handle the EOI here
278       struct ocw2 * cw2 =  (struct ocw2*)&cw;
279
280       
281       if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
282         // specific EOI;
283         state->master_isr &= ~(0x01 << cw2->level);
284       } else if ((cw2->EOI) & (!cw2->R) && (!cw2->SL)) {
285         int i;
286         // Non-specific EOI
287         PrintDebug("Pre ISR = %x\n", state->master_isr);
288         for (i = 0; i < 8; i++) {
289           if (state->master_isr & (0x01 << i)) {
290             state->master_isr &= ~(0x01 << i);
291             break;
292           }
293         }       
294         PrintDebug("Post ISR = %x\n", state->master_isr);
295       } else {
296         // error;
297       }
298
299       state->master_ocw2 = cw;
300     } else if (IS_OCW3(cw)) {
301       state->master_ocw3 = cw;
302     } else {
303       // error
304     }
305   } else {
306     // error
307   }
308
309   return 1;
310 }
311
312 int write_master_port2(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
313     struct pic_internal * state = (struct pic_internal*)dev->private_data;
314     char cw = *(char *)src;    
315
316     if (length != 1) {
317       //error
318     }
319     
320     if (state->master_state == ICW2) {
321       struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
322
323       PrintDebug("Setting ICW2 = %x\n", cw);
324       state->master_icw2 = cw;
325
326       if (cw1->sngl == 0) {
327         state->master_state = ICW3;
328       } else if (cw1->ic4 == 1) {
329         state->master_state = ICW4;
330       } else {
331         state->master_state = READY;
332       }
333
334     } else if (state->master_state == ICW3) {
335       struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
336
337       state->master_icw3 = cw;
338
339       if (cw1->ic4 == 1) {
340         state->master_state = ICW4;
341       } else {
342         state->master_state = READY;
343       }
344
345     } else if (state->master_state == ICW4) {
346       state->master_icw4 = cw;
347       state->master_state = READY;
348     } else if (state->master_state == READY) {
349       state->master_imr = cw;
350     } else {
351       // error
352     }
353
354     return 1;
355 }
356
357 int write_slave_port1(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
358   struct pic_internal * state = (struct pic_internal*)dev->private_data;
359   char cw = *(char *)src;
360
361   if (length != 1) {
362     // error
363   }
364
365   if (state->slave_state == ICW1) {
366     state->slave_icw1 = cw;
367     state->slave_state = ICW2;
368   } else if (state->slave_state == READY) {
369     if (IS_OCW2(cw)) {
370       // handle the EOI here
371       struct ocw2 * cw2 =  (struct ocw2 *)&cw;
372       
373       if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
374         // specific EOI;
375         state->slave_isr &= ~(0x01 << cw2->level);
376       } else if ((cw2->EOI) & (!cw2->R) && (!cw2->SL)) {
377         int i;
378         // Non-specific EOI
379         PrintDebug("Pre ISR = %x\n", state->slave_isr);
380         for (i = 0; i < 8; i++) {
381           if (state->slave_isr & (0x01 << i)) {
382             state->slave_isr &= ~(0x01 << i);
383             break;
384           }
385         }       
386         PrintDebug("Post ISR = %x\n", state->slave_isr);
387       } else {
388         // error;
389       }
390
391       state->slave_ocw2 = cw;
392     } else if (IS_OCW3(cw)) {
393       // Basically sets the IRR/ISR read flag
394       state->slave_ocw3 = cw;
395     } else {
396       // error
397     }
398   } else {
399     // error
400   }
401
402   return 1;
403 }
404
405 int write_slave_port2(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
406     struct pic_internal * state = (struct pic_internal*)dev->private_data;
407     char cw = *(char *)src;    
408
409     if (length != 1) {
410       //error
411     }
412
413     if (state->slave_state == ICW2) {
414       struct icw1 * cw1 =  (struct icw1 *)&(state->master_icw1);
415
416       state->slave_icw2 = cw;
417
418       if (cw1->sngl == 0) {
419         state->slave_state = ICW3;
420       } else if (cw1->ic4 == 1) {
421         state->slave_state = ICW4;
422       } else {
423         state->slave_state = READY;
424       }
425
426     } else if (state->slave_state == ICW3) {
427       struct icw1 * cw1 =  (struct icw1 *)&(state->master_icw1);
428
429       state->slave_icw3 = cw;
430
431       if (cw1->ic4 == 1) {
432         state->slave_state = ICW4;
433       } else {
434         state->slave_state = READY;
435       }
436
437     } else if (state->slave_state == ICW4) {
438       state->slave_icw4 = cw;
439       state->slave_state = READY;
440     } else if (state->slave_state == READY) {
441       state->slave_imr = cw;
442     } else {
443       // error
444     }
445
446     return 1;
447 }
448
449
450
451
452
453
454
455
456 int pic_init(struct vm_device * dev) {
457   struct pic_internal * state = (struct pic_internal*)dev->private_data;
458
459   set_intr_controller(dev->vm, &intr_ops, state);
460
461   state->master_irr = 0;
462   state->master_isr = 0;
463   state->master_icw1 = 0;
464   state->master_icw2 = 0;
465   state->master_icw3 = 0;
466   state->master_icw4 = 0;
467   state->master_imr = 0;
468   state->master_ocw2 = 0;
469   state->master_ocw3 = 0x02;
470   state->master_state = ICW1;
471
472
473   state->slave_irr = 0;
474   state->slave_isr = 0;
475   state->slave_icw1 = 0;
476   state->slave_icw2 = 0;
477   state->slave_icw3 = 0;
478   state->slave_icw4 = 0;
479   state->slave_imr = 0;
480   state->slave_ocw2 = 0;
481   state->slave_ocw3 = 0x02;
482   state->slave_state = ICW1;
483
484
485   dev_hook_io(dev, MASTER_PORT1, &read_master_port1, &write_master_port1);
486   dev_hook_io(dev, MASTER_PORT2, &read_master_port2, &write_master_port2);
487   dev_hook_io(dev, SLAVE_PORT1, &read_slave_port1, &write_slave_port1);
488   dev_hook_io(dev, SLAVE_PORT2, &read_slave_port2, &write_slave_port2);
489
490   return 0;
491 }
492
493
494 int pic_deinit(struct vm_device * dev) {
495   dev_unhook_io(dev, MASTER_PORT1);
496   dev_unhook_io(dev, MASTER_PORT2);
497   dev_unhook_io(dev, SLAVE_PORT1);
498   dev_unhook_io(dev, SLAVE_PORT2);
499
500   return 0;
501 }
502
503
504
505
506
507
508
509 static struct vm_device_ops dev_ops = {
510   .init = pic_init,
511   .deinit = pic_deinit,
512   .reset = NULL,
513   .start = NULL,
514   .stop = NULL,
515 };
516
517
518 struct vm_device * create_pic() {
519   struct pic_internal * state = NULL;
520   VMMMalloc(struct pic_internal *, state, sizeof(struct pic_internal));
521
522   struct vm_device *device = create_device("8259A", &dev_ops, state);
523
524   return device;
525 }
526
527
528
529