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 CLGI window
[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         PrintDebug("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 }