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.


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