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 support for multiple interrupt controllers
[palacios.git] / palacios / src / devices / 8259a.c
1 /*
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20
21 #include <devices/8259a.h>
22 #include <palacios/vmm_intr.h>
23 #include <palacios/vmm_types.h>
24 #include <palacios/vmm.h>
25
26 #ifndef DEBUG_PIC
27 #undef PrintDebug
28 #define PrintDebug(fmt, args...)
29 #endif
30
31
32 typedef enum {RESET, ICW1, ICW2, ICW3, ICW4,  READY} pic_state_t;
33
34 static const uint_t MASTER_PORT1 = 0x20;
35 static const uint_t MASTER_PORT2 = 0x21;
36 static const uint_t SLAVE_PORT1 = 0xA0;
37 static const uint_t SLAVE_PORT2 = 0xA1;
38
39 #define IS_ICW1(x) (((x & 0x10) >> 4) == 0x1)
40 #define IS_OCW2(x) (((x & 0x18) >> 3) == 0x0)
41 #define IS_OCW3(x) (((x & 0x18) >> 3) == 0x1)
42
43
44 struct icw1 {
45   uint_t ic4    : 1;  // ICW4 has to be read
46   uint_t sngl   : 1;  // single (only one PIC)
47   uint_t adi    : 1;  // call address interval
48   uint_t ltim   : 1;  // level interrupt mode
49   uint_t one    : 1;
50   uint_t rsvd   : 3;
51 };
52
53
54 struct icw2 {
55   uint_t rsvd   : 3;
56   uint_t vector : 5;
57 };
58
59
60 // Each bit that is set indicates that the IR input has a slave
61 struct icw3_master {
62   uint_t S0   : 1;
63   uint_t S1   : 1;
64   uint_t S2   : 1;
65   uint_t S3   : 1;
66   uint_t S4   : 1;
67   uint_t S5   : 1;
68   uint_t S6   : 1;
69   uint_t S7   : 1;
70 };
71
72 // The ID is the Slave device ID
73 struct icw3_slave {
74   uint_t id     : 3;
75   uint_t zeroes : 5;
76 };
77
78 struct icw4 {
79   uint_t uPM    : 1;  // 1=x86
80   uint_t AEOI   : 1;  // Automatic End of Interrupt
81   uint_t M_S    : 1;  // only if buffered 1=master,0=slave 
82   uint_t BUF    : 1;  // buffered mode
83   uint_t SFNM   : 1;  // special fully nexted mode
84   uint_t zeroes : 3;
85 };
86
87
88 struct ocw1 {
89   uint_t m0     : 1;
90   uint_t m1     : 1;
91   uint_t m2     : 1;
92   uint_t m3     : 1;
93   uint_t m4     : 1;
94   uint_t m5     : 1;
95   uint_t m6     : 1;
96   uint_t m7     : 1;
97 };
98
99 struct ocw2 {
100   uint_t level  : 3;
101   uint_t cw_code : 2; // should be 00
102   uint_t EOI    : 1;
103   uint_t SL     : 1;
104   uint_t R      : 1;
105 };
106
107 struct ocw3 {
108   uint_t RIS    : 1;
109   uint_t RR     : 1;
110   uint_t P      : 1;
111   uint_t cw_code : 2; // should be 01
112   uint_t smm    : 1;
113   uint_t esmm   : 1;
114   uint_t zero2  : 1;
115 };
116
117
118 struct pic_internal {
119
120
121   uchar_t master_irr;
122   uchar_t slave_irr;
123   
124   uchar_t master_isr;
125   uchar_t slave_isr;
126
127   uchar_t master_icw1;
128   uchar_t master_icw2;
129   uchar_t master_icw3;
130   uchar_t master_icw4;
131
132
133   uchar_t slave_icw1;
134   uchar_t slave_icw2;
135   uchar_t slave_icw3;
136   uchar_t slave_icw4;
137
138
139   uchar_t master_imr;
140   uchar_t slave_imr;
141   uchar_t master_ocw2;
142   uchar_t master_ocw3;
143   uchar_t slave_ocw2;
144   uchar_t slave_ocw3;
145
146   pic_state_t master_state;
147   pic_state_t slave_state;
148 };
149
150
151 static void DumpPICState(struct pic_internal *p)
152 {
153
154   PrintDebug("8259 PIC: master_state=0x%x\n",p->master_state);
155   PrintDebug("8259 PIC: master_irr=0x%x\n",p->master_irr);
156   PrintDebug("8259 PIC: master_isr=0x%x\n",p->master_isr);
157   PrintDebug("8259 PIC: master_imr=0x%x\n",p->master_imr);
158
159   PrintDebug("8259 PIC: master_ocw2=0x%x\n",p->master_ocw2);
160   PrintDebug("8259 PIC: master_ocw3=0x%x\n",p->master_ocw3);
161
162   PrintDebug("8259 PIC: master_icw1=0x%x\n",p->master_icw1);
163   PrintDebug("8259 PIC: master_icw2=0x%x\n",p->master_icw2);
164   PrintDebug("8259 PIC: master_icw3=0x%x\n",p->master_icw3);
165   PrintDebug("8259 PIC: master_icw4=0x%x\n",p->master_icw4);
166
167   PrintDebug("8259 PIC: slave_state=0x%x\n",p->slave_state);
168   PrintDebug("8259 PIC: slave_irr=0x%x\n",p->slave_irr);
169   PrintDebug("8259 PIC: slave_isr=0x%x\n",p->slave_isr);
170   PrintDebug("8259 PIC: slave_imr=0x%x\n",p->slave_imr);
171
172   PrintDebug("8259 PIC: slave_ocw2=0x%x\n",p->slave_ocw2);
173   PrintDebug("8259 PIC: slave_ocw3=0x%x\n",p->slave_ocw3);
174
175   PrintDebug("8259 PIC: slave_icw1=0x%x\n",p->slave_icw1);
176   PrintDebug("8259 PIC: slave_icw2=0x%x\n",p->slave_icw2);
177   PrintDebug("8259 PIC: slave_icw3=0x%x\n",p->slave_icw3);
178   PrintDebug("8259 PIC: slave_icw4=0x%x\n",p->slave_icw4);
179
180 }
181
182
183 static int pic_raise_intr(void * private_data, int irq) {
184   struct pic_internal * state = (struct pic_internal*)private_data;
185
186   if (irq == 2) {
187     irq = 9;
188     state->master_irr |= 0x04;  // PAD
189   }
190
191   PrintDebug("8259 PIC: Raising irq %d in the PIC\n", irq);
192
193   if (irq <= 7) {
194     state->master_irr |= 0x01 << irq;
195   } else if ((irq > 7) && (irq < 16)) {
196     state->slave_irr |= 0x01 << (irq - 8);  // PAD if -7 then irq 15=no irq
197   } else {
198     PrintError("8259 PIC: Invalid IRQ raised (%d)\n", irq);
199     return -1;
200   }
201
202   return 0;
203 }
204
205
206 static int pic_lower_intr(void *private_data, int irq) {
207
208   struct pic_internal *state = (struct pic_internal*)private_data;
209
210   PrintDebug("[pic_lower_intr] IRQ line %d now low\n", irq);
211   if (irq <= 7) {
212
213     state->master_irr &= ~(1 << irq);
214     if ((state->master_irr & ~(state->master_imr)) == 0) {
215       PrintDebug("\t\tFIXME: Master maybe should do sth\n");
216     }
217   } else if ((irq > 7) && (irq < 16)) {
218
219     state->slave_irr &= ~(1 << (irq - 8));
220     if ((state->slave_irr & (~(state->slave_imr))) == 0) {
221       PrintDebug("\t\tFIXME: Slave maybe should do sth\n");
222     }
223   }
224   return 0;
225 }
226
227
228
229 static int pic_intr_pending(void * private_data) {
230   struct pic_internal * state = (struct pic_internal*)private_data;
231
232   if ((state->master_irr & ~(state->master_imr)) || 
233       (state->slave_irr & ~(state->slave_imr))) {
234     return 1;
235   }
236
237   return 0;
238 }
239
240 static int pic_get_intr_number(void * private_data) {
241   struct pic_internal * state = (struct pic_internal *)private_data;
242   int i = 0;
243   int irq = -1;
244
245   PrintDebug("8259 PIC: getnum: master_irr: 0x%x master_imr: 0x%x\n", state->master_irr, state->master_imr);
246   PrintDebug("8259 PIC: getnum: slave_irr: 0x%x slave_imr: 0x%x\n", state->slave_irr, state->slave_imr);
247
248   for (i = 0; i < 16; i++) {
249     if (i <= 7) {
250       if (((state->master_irr & ~(state->master_imr)) >> i) == 0x01) {
251         //state->master_isr |= (0x1 << i);
252         // reset the irr
253         //state->master_irr &= ~(0x1 << i);
254         PrintDebug("8259 PIC: IRQ: %d, master_icw2: %x\n", i, state->master_icw2);
255         irq= i + state->master_icw2;
256         break;
257       }
258     } else {
259       if (((state->slave_irr & ~(state->slave_imr)) >> (i - 8)) == 0x01) {
260         //state->slave_isr |= (0x1 << (i - 8));
261         //state->slave_irr &= ~(0x1 << (i - 8));
262         PrintDebug("8259 PIC: IRQ: %d, slave_icw2: %x\n", i, state->slave_icw2);
263         irq= (i - 8) + state->slave_icw2;
264         break;
265       }
266     }
267   }
268
269   if ((i == 15) || (i == 6)) { 
270     DumpPICState(state);
271   }
272   
273   if (i == 16) { 
274     return -1;
275   } else {
276     return irq;
277   }
278 }
279
280
281
282 /* The IRQ number is the number returned by pic_get_intr_number(), not the pin number */
283 static int pic_begin_irq(void * private_data, int irq) {
284   struct pic_internal * state = (struct pic_internal*)private_data;
285
286   if ((irq >= state->master_icw2) && (irq <= state->master_icw2 + 7)) {
287     irq &= 0x7;
288   } else if ((irq >= state->slave_icw2) && (irq <= state->slave_icw2 + 7)) {
289     irq &= 0x7;
290     irq += 8;
291   } else {
292     PrintError("8259 PIC: Could not find IRQ (0x%x) to Begin\n",irq);
293     return -1;
294   }
295
296   if (irq <= 7) {
297     if (((state->master_irr & ~(state->master_imr)) >> irq) == 0x01) {
298       state->master_isr |= (0x1 << irq);
299       state->master_irr &= ~(0x1 << irq);
300     }
301   } else {
302     state->slave_isr |= (0x1 << (irq - 8));
303     state->slave_irr &= ~(0x1 << (irq - 8));
304   }
305
306   return 0;
307 }
308
309
310 /*
311 static int pic_end_irq(void * private_data, int irq) {
312   return 0;
313 }
314 */
315
316
317
318 static struct intr_ctrl_ops intr_ops = {
319   .intr_pending = pic_intr_pending,
320   .get_intr_number = pic_get_intr_number,
321   .raise_intr = pic_raise_intr,
322   .begin_irq = pic_begin_irq,
323   .lower_intr = pic_lower_intr, 
324
325 };
326
327
328
329
330 static int read_master_port1(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
331   struct pic_internal * state = (struct pic_internal*)dev->private_data;
332
333   if (length != 1) {
334     PrintError("8259 PIC: Invalid Read length (rd_Master1)\n");
335     return -1;
336   }
337   
338   if ((state->master_ocw3 & 0x03) == 0x02) {
339     *(uchar_t *)dst = state->master_irr;
340   } else if ((state->master_ocw3 & 0x03) == 0x03) {
341     *(uchar_t *)dst = state->master_isr;
342   } else {
343     *(uchar_t *)dst = 0;
344   }
345   
346   return 1;
347 }
348
349 static int read_master_port2(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
350   struct pic_internal * state = (struct pic_internal*)dev->private_data;
351
352   if (length != 1) {
353     PrintError("8259 PIC: Invalid Read length (rd_Master2)\n");
354     return -1;
355   }
356
357   *(uchar_t *)dst = state->master_imr;
358
359   return 1;
360   
361 }
362
363 static int read_slave_port1(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
364   struct pic_internal * state = (struct pic_internal*)dev->private_data;
365
366   if (length != 1) {
367     PrintError("8259 PIC: Invalid Read length (rd_Slave1)\n");
368     return -1;
369   }
370   
371   if ((state->slave_ocw3 & 0x03) == 0x02) {
372     *(uchar_t*)dst = state->slave_irr;
373   } else if ((state->slave_ocw3 & 0x03) == 0x03) {
374     *(uchar_t *)dst = state->slave_isr;
375   } else {
376     *(uchar_t *)dst = 0;
377   }
378
379   return 1;
380 }
381
382 static int read_slave_port2(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
383   struct pic_internal * state = (struct pic_internal*)dev->private_data;
384
385   if (length != 1) {
386     PrintError("8259 PIC: Invalid Read length  (rd_Slave2)\n");
387     return -1;
388   }
389
390   *(uchar_t *)dst = state->slave_imr;
391
392   return 1;
393 }
394
395
396 static int write_master_port1(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
397   struct pic_internal * state = (struct pic_internal*)dev->private_data;
398   uchar_t cw = *(uchar_t *)src;
399
400   PrintDebug("8259 PIC: Write master port 1 with 0x%x\n",cw);
401
402   if (length != 1) {
403     PrintError("8259 PIC: Invalid Write length (wr_Master1)\n");
404     return -1;
405   }
406   
407   if (IS_ICW1(cw)) {
408
409     PrintDebug("8259 PIC: Setting ICW1 = %x (wr_Master1)\n", cw);
410     
411     state->master_icw1 = cw;
412     state->master_state = ICW2;
413
414   } else if (state->master_state == READY) {
415     if (IS_OCW2(cw)) {
416       // handle the EOI here
417       struct ocw2 * cw2 =  (struct ocw2*)&cw;
418
419       PrintDebug("8259 PIC: Handling OCW2 = %x (wr_Master1)\n", cw);
420       
421       if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
422         // specific EOI;
423         state->master_isr &= ~(0x01 << cw2->level);
424       } else if ((cw2->EOI) & (!cw2->R) && (!cw2->SL)) {
425         int i;
426         // Non-specific EOI
427         PrintDebug("8259 PIC: Pre ISR = %x (wr_Master1)\n", state->master_isr);
428         for (i = 0; i < 8; i++) {
429           if (state->master_isr & (0x01 << i)) {
430             state->master_isr &= ~(0x01 << i);
431             break;
432           }
433         }       
434         PrintDebug("8259 PIC: Post ISR = %x (wr_Master1)\n", state->master_isr);
435       } else {
436         PrintError("8259 PIC: Command not handled, or in error (wr_Master1)\n");
437         return -1;
438       }
439
440       state->master_ocw2 = cw;
441     } else if (IS_OCW3(cw)) {
442       PrintDebug("8259 PIC: Handling OCW3 = %x (wr_Master1)\n", cw);
443       state->master_ocw3 = cw;
444     } else {
445       PrintError("8259 PIC: Invalid OCW to PIC (wr_Master1)\n");
446       PrintError("8259 PIC: CW=%x\n", cw);
447       return -1;
448     }
449   } else {
450     PrintError("8259 PIC: Invalid PIC State (wr_Master1)\n");
451     PrintError("8259 PIC: CW=%x\n", cw);
452     return -1;
453   }
454
455   return 1;
456 }
457
458 static int write_master_port2(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
459     struct pic_internal * state = (struct pic_internal*)dev->private_data;
460     uchar_t cw = *(uchar_t *)src;    
461
462     PrintDebug("8259 PIC: Write master port 2 with 0x%x\n",cw);
463   
464     if (length != 1) {
465       PrintError("8259 PIC: Invalid Write length (wr_Master2)\n");
466       return -1;
467     }
468     
469     if (state->master_state == ICW2) {
470       struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
471
472       PrintDebug("8259 PIC: Setting ICW2 = %x (wr_Master2)\n", cw);
473       state->master_icw2 = cw;
474
475       if (cw1->sngl == 0) {
476         state->master_state = ICW3;
477       } else if (cw1->ic4 == 1) {
478         state->master_state = ICW4;
479       } else {
480         state->master_state = READY;
481       }
482
483     } else if (state->master_state == ICW3) {
484       struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
485
486       PrintDebug("8259 PIC: Setting ICW3 = %x (wr_Master2)\n", cw);
487
488       state->master_icw3 = cw;
489
490       if (cw1->ic4 == 1) {
491         state->master_state = ICW4;
492       } else {
493         state->master_state = READY;
494       }
495
496     } else if (state->master_state == ICW4) {
497       PrintDebug("8259 PIC: Setting ICW4 = %x (wr_Master2)\n", cw);
498       state->master_icw4 = cw;
499       state->master_state = READY;
500     } else if (state->master_state == READY) {
501       PrintDebug("8259 PIC: Setting IMR = %x (wr_Master2)\n", cw);
502       state->master_imr = cw;
503     } else {
504       // error
505       PrintError("8259 PIC: Invalid master PIC State (wr_Master2)\n");
506       return -1;
507     }
508
509     return 1;
510 }
511
512 static int write_slave_port1(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
513   struct pic_internal * state = (struct pic_internal*)dev->private_data;
514   uchar_t cw = *(uchar_t *)src;
515
516   PrintDebug("8259 PIC: Write slave port 1 with 0x%x\n",cw);
517
518   if (length != 1) {
519     // error
520     PrintError("8259 PIC: Invalid Write length (wr_Slave1)\n");
521     return -1;
522   }
523
524   if (IS_ICW1(cw)) {
525     PrintDebug("8259 PIC: Setting ICW1 = %x (wr_Slave1)\n", cw);
526     state->slave_icw1 = cw;
527     state->slave_state = ICW2;
528   } else if (state->slave_state == READY) {
529     if (IS_OCW2(cw)) {
530       // handle the EOI here
531       struct ocw2 * cw2 =  (struct ocw2 *)&cw;
532
533       PrintDebug("8259 PIC: Setting OCW2 = %x (wr_Slave1)\n", cw);
534       
535       if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
536         // specific EOI;
537         state->slave_isr &= ~(0x01 << cw2->level);
538       } else if ((cw2->EOI) & (!cw2->R) && (!cw2->SL)) {
539         int i;
540         // Non-specific EOI
541         PrintDebug("8259 PIC: Pre ISR = %x (wr_Slave1)\n", state->slave_isr);
542         for (i = 0; i < 8; i++) {
543           if (state->slave_isr & (0x01 << i)) {
544             state->slave_isr &= ~(0x01 << i);
545             break;
546           }
547         }       
548         PrintDebug("8259 PIC: Post ISR = %x (wr_Slave1)\n", state->slave_isr);
549       } else {
550         PrintError("8259 PIC: Command not handled or invalid  (wr_Slave1)\n");
551         return -1;
552       }
553
554       state->slave_ocw2 = cw;
555     } else if (IS_OCW3(cw)) {
556       // Basically sets the IRR/ISR read flag
557       PrintDebug("8259 PIC: Setting OCW3 = %x (wr_Slave1)\n", cw);
558       state->slave_ocw3 = cw;
559     } else {
560       PrintError("8259 PIC: Invalid command work (wr_Slave1)\n");
561       return -1;
562     }
563   } else {
564     PrintError("8259 PIC: Invalid State writing (wr_Slave1)\n");
565     return -1;
566   }
567
568   return 1;
569 }
570
571 static int write_slave_port2(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
572     struct pic_internal * state = (struct pic_internal*)dev->private_data;
573     uchar_t cw = *(uchar_t *)src;    
574
575     PrintDebug("8259 PIC: Write slave port 2 with 0x%x\n",cw);
576
577     if (length != 1) {
578       PrintError("8259 PIC: Invalid write length (wr_Slave2)\n");
579       return -1;
580     }
581
582     if (state->slave_state == ICW2) {
583       struct icw1 * cw1 =  (struct icw1 *)&(state->master_icw1);
584
585       PrintDebug("8259 PIC: Setting ICW2 = %x (wr_Slave2)\n", cw);
586
587       state->slave_icw2 = cw;
588
589       if (cw1->sngl == 0) {
590         state->slave_state = ICW3;
591       } else if (cw1->ic4 == 1) {
592         state->slave_state = ICW4;
593       } else {
594         state->slave_state = READY;
595       }
596
597     } else if (state->slave_state == ICW3) {
598       struct icw1 * cw1 =  (struct icw1 *)&(state->master_icw1);
599
600       PrintDebug("8259 PIC: Setting ICW3 = %x (wr_Slave2)\n", cw);
601
602       state->slave_icw3 = cw;
603
604       if (cw1->ic4 == 1) {
605         state->slave_state = ICW4;
606       } else {
607         state->slave_state = READY;
608       }
609
610     } else if (state->slave_state == ICW4) {
611       PrintDebug("8259 PIC: Setting ICW4 = %x (wr_Slave2)\n", cw);
612       state->slave_icw4 = cw;
613       state->slave_state = READY;
614     } else if (state->slave_state == READY) {
615       PrintDebug("8259 PIC: Setting IMR = %x (wr_Slave2)\n", cw);
616       state->slave_imr = cw;
617     } else {
618       PrintError("8259 PIC: Invalid State at write (wr_Slave2)\n");
619       return -1;
620     }
621
622     return 1;
623 }
624
625
626
627
628
629
630
631
632 static int pic_init(struct vm_device * dev) {
633   struct pic_internal * state = (struct pic_internal*)dev->private_data;
634
635   v3_register_intr_controller(dev->vm, &intr_ops, state);
636
637   state->master_irr = 0;
638   state->master_isr = 0;
639   state->master_icw1 = 0;
640   state->master_icw2 = 0;
641   state->master_icw3 = 0;
642   state->master_icw4 = 0;
643   state->master_imr = 0;
644   state->master_ocw2 = 0;
645   state->master_ocw3 = 0x02;
646   state->master_state = ICW1;
647
648
649   state->slave_irr = 0;
650   state->slave_isr = 0;
651   state->slave_icw1 = 0;
652   state->slave_icw2 = 0;
653   state->slave_icw3 = 0;
654   state->slave_icw4 = 0;
655   state->slave_imr = 0;
656   state->slave_ocw2 = 0;
657   state->slave_ocw3 = 0x02;
658   state->slave_state = ICW1;
659
660
661   v3_dev_hook_io(dev, MASTER_PORT1, &read_master_port1, &write_master_port1);
662   v3_dev_hook_io(dev, MASTER_PORT2, &read_master_port2, &write_master_port2);
663   v3_dev_hook_io(dev, SLAVE_PORT1, &read_slave_port1, &write_slave_port1);
664   v3_dev_hook_io(dev, SLAVE_PORT2, &read_slave_port2, &write_slave_port2);
665
666   return 0;
667 }
668
669
670 static int pic_deinit(struct vm_device * dev) {
671   v3_dev_unhook_io(dev, MASTER_PORT1);
672   v3_dev_unhook_io(dev, MASTER_PORT2);
673   v3_dev_unhook_io(dev, SLAVE_PORT1);
674   v3_dev_unhook_io(dev, SLAVE_PORT2);
675
676   return 0;
677 }
678
679
680
681
682
683
684
685 static struct vm_device_ops dev_ops = {
686   .init = pic_init,
687   .deinit = pic_deinit,
688   .reset = NULL,
689   .start = NULL,
690   .stop = NULL,
691 };
692
693
694 struct vm_device * v3_create_pic() {
695   struct pic_internal * state = NULL;
696   state = (struct pic_internal *)V3_Malloc(sizeof(struct pic_internal));
697   V3_ASSERT(state != NULL);
698
699   struct vm_device *device = v3_create_device("8259A", &dev_ops, state);
700
701   return device;
702 }
703
704
705
706