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