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