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