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 new copyright and license
[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 /*Zheng 07/30/2008*/
207
208 static int pic_lower_intr(void *private_data, int irq_no) {
209
210   struct pic_internal *state = (struct pic_internal*)private_data;
211
212   PrintDebug("[pic_lower_intr] IRQ line %d now low\n", (unsigned) irq_no);
213   if (irq_no <= 7) {
214
215     state->master_irr &= ~(1 << irq_no);
216     if ((state->master_irr & ~(state->master_imr)) == 0) {
217       PrintDebug("\t\tFIXME: Master maybe should do sth\n");
218     }
219   } else if ((irq_no > 7) && (irq_no <= 15)) {
220
221     state->slave_irr &= ~(1 << (irq_no - 8));
222     if ((state->slave_irr & (~(state->slave_imr))) == 0) {
223       PrintDebug("\t\tFIXME: Slave maybe should do sth\n");
224     }
225   }
226   return 0;
227 }
228
229
230
231 static int pic_intr_pending(void * private_data) {
232   struct pic_internal * state = (struct pic_internal*)private_data;
233
234   if ((state->master_irr & ~(state->master_imr)) || 
235       (state->slave_irr & ~(state->slave_imr))) {
236     return 1;
237   }
238
239   return 0;
240 }
241
242 static int pic_get_intr_number(void * private_data) {
243   struct pic_internal * state = (struct pic_internal *)private_data;
244   int i = 0;
245   int irq = -1;
246
247   PrintDebug("8259 PIC: getnum: master_irr: 0x%x master_imr: 0x%x\n", i, state->master_irr, state->master_imr);
248   PrintDebug("8259 PIC: getnum: slave_irr: 0x%x slave_imr: 0x%x\n", i, state->slave_irr, state->slave_imr);
249
250   for (i = 0; i < 16; i++) {
251     if (i <= 7) {
252       if (((state->master_irr & ~(state->master_imr)) >> i) == 0x01) {
253         //state->master_isr |= (0x1 << i);
254         // reset the irr
255         //state->master_irr &= ~(0x1 << i);
256         PrintDebug("8259 PIC: IRQ: %d, master_icw2: %x\n", i, state->master_icw2);
257         irq= i + state->master_icw2;
258         break;
259       }
260     } else {
261       if (((state->slave_irr & ~(state->slave_imr)) >> (i - 8)) == 0x01) {
262         //state->slave_isr |= (0x1 << (i - 8));
263         //state->slave_irr &= ~(0x1 << (i - 8));
264         PrintDebug("8259 PIC: IRQ: %d, slave_icw2: %x\n", i, state->slave_icw2);
265         irq= (i - 8) + state->slave_icw2;
266         break;
267       }
268     }
269   }
270
271   if ((i == 15) || (i == 6)) { 
272     DumpPICState(state);
273   }
274   
275   if (i == 16) { 
276     return -1;
277   } else {
278     return irq;
279   }
280 }
281
282
283
284 /* The IRQ number is the number returned by pic_get_intr_number(), not the pin number */
285 static int pic_begin_irq(void * private_data, int irq) {
286   struct pic_internal * state = (struct pic_internal*)private_data;
287
288   if ((irq >= state->master_icw2) && (irq <= state->master_icw2 + 7)) {
289     irq &= 0x7;
290   } else if ((irq >= state->slave_icw2) && (irq <= state->slave_icw2 + 7)) {
291     irq &= 0x7;
292     irq += 8;
293   } else {
294     PrintError("8259 PIC: Could not find IRQ (0x%x) to Begin\n",irq);
295     return -1;
296   }
297
298   if (irq <= 7) {
299     if (((state->master_irr & ~(state->master_imr)) >> irq) == 0x01) {
300       state->master_isr |= (0x1 << irq);
301       state->master_irr &= ~(0x1 << irq);
302     }
303   } else {
304     state->slave_isr |= (0x1 << (irq - 8));
305     state->slave_irr &= ~(0x1 << (irq - 8));
306   }
307
308   return 0;
309 }
310
311
312 /*
313 static int pic_end_irq(void * private_data, int irq) {
314   return 0;
315 }
316 */
317
318
319 /*Zheng 07/30/2008*/
320 static struct intr_ctrl_ops intr_ops = {
321   .intr_pending = pic_intr_pending,
322   .get_intr_number = pic_get_intr_number,
323   .raise_intr = pic_raise_intr,
324   .begin_irq = pic_begin_irq,
325   .lower_intr = pic_lower_intr, //Zheng added
326
327 };
328
329
330
331
332 int read_master_port1(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
333   struct pic_internal * state = (struct pic_internal*)dev->private_data;
334
335   if (length != 1) {
336     PrintError("8259 PIC: Invalid Read length (rd_Master1)\n");
337     return -1;
338   }
339   
340   if ((state->master_ocw3 & 0x03) == 0x02) {
341     *(uchar_t *)dst = state->master_irr;
342   } else if ((state->master_ocw3 & 0x03) == 0x03) {
343     *(uchar_t *)dst = state->master_isr;
344   } else {
345     *(uchar_t *)dst = 0;
346   }
347   
348   return 1;
349 }
350
351 int read_master_port2(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
352   struct pic_internal * state = (struct pic_internal*)dev->private_data;
353
354   if (length != 1) {
355     PrintError("8259 PIC: Invalid Read length (rd_Master2)\n");
356     return -1;
357   }
358
359   *(uchar_t *)dst = state->master_imr;
360
361   return 1;
362   
363 }
364
365 int read_slave_port1(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
366   struct pic_internal * state = (struct pic_internal*)dev->private_data;
367
368   if (length != 1) {
369     PrintError("8259 PIC: Invalid Read length (rd_Slave1)\n");
370     return -1;
371   }
372   
373   if ((state->slave_ocw3 & 0x03) == 0x02) {
374     *(uchar_t*)dst = state->slave_irr;
375   } else if ((state->slave_ocw3 & 0x03) == 0x03) {
376     *(uchar_t *)dst = state->slave_isr;
377   } else {
378     *(uchar_t *)dst = 0;
379   }
380
381   return 1;
382 }
383
384 int read_slave_port2(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
385   struct pic_internal * state = (struct pic_internal*)dev->private_data;
386
387   if (length != 1) {
388     PrintError("8259 PIC: Invalid Read length  (rd_Slave2)\n");
389     return -1;
390   }
391
392   *(uchar_t *)dst = state->slave_imr;
393
394   return 1;
395 }
396
397
398 int write_master_port1(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
399   struct pic_internal * state = (struct pic_internal*)dev->private_data;
400   uchar_t cw = *(uchar_t *)src;
401
402   PrintDebug("8259 PIC: Write master port 1 with 0x%x\n",cw);
403
404   if (length != 1) {
405     PrintError("8259 PIC: Invalid Write length (wr_Master1)\n");
406     return -1;
407   }
408   
409   if (IS_ICW1(cw)) {
410
411     PrintDebug("8259 PIC: Setting ICW1 = %x (wr_Master1)\n", cw);
412     
413     state->master_icw1 = cw;
414     state->master_state = ICW2;
415
416   } else if (state->master_state == READY) {
417     if (IS_OCW2(cw)) {
418       // handle the EOI here
419       struct ocw2 * cw2 =  (struct ocw2*)&cw;
420
421       PrintDebug("8259 PIC: Handling OCW2 = %x (wr_Master1)\n", cw);
422       
423       if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
424         // specific EOI;
425         state->master_isr &= ~(0x01 << cw2->level);
426       } else if ((cw2->EOI) & (!cw2->R) && (!cw2->SL)) {
427         int i;
428         // Non-specific EOI
429         PrintDebug("8259 PIC: Pre ISR = %x (wr_Master1)\n", state->master_isr);
430         for (i = 0; i < 8; i++) {
431           if (state->master_isr & (0x01 << i)) {
432             state->master_isr &= ~(0x01 << i);
433             break;
434           }
435         }       
436         PrintDebug("8259 PIC: Post ISR = %x (wr_Master1)\n", state->master_isr);
437       } else {
438         PrintError("8259 PIC: Command not handled, or in error (wr_Master1)\n");
439         return -1;
440       }
441
442       state->master_ocw2 = cw;
443     } else if (IS_OCW3(cw)) {
444       PrintDebug("8259 PIC: Handling OCW3 = %x (wr_Master1)\n", cw);
445       state->master_ocw3 = cw;
446     } else {
447       PrintError("8259 PIC: Invalid OCW to PIC (wr_Master1)\n");
448       PrintError("8259 PIC: CW=%x\n", cw);
449       return -1;
450     }
451   } else {
452     PrintError("8259 PIC: Invalid PIC State (wr_Master1)\n");
453     PrintError("8259 PIC: CW=%x\n", cw);
454     return -1;
455   }
456
457   return 1;
458 }
459
460 int write_master_port2(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
461     struct pic_internal * state = (struct pic_internal*)dev->private_data;
462     uchar_t cw = *(uchar_t *)src;    
463
464     PrintDebug("8259 PIC: Write master port 2 with 0x%x\n",cw);
465   
466     if (length != 1) {
467       PrintError("8259 PIC: Invalid Write length (wr_Master2)\n");
468       return -1;
469     }
470     
471     if (state->master_state == ICW2) {
472       struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
473
474       PrintDebug("8259 PIC: Setting ICW2 = %x (wr_Master2)\n", cw);
475       state->master_icw2 = cw;
476
477       if (cw1->sngl == 0) {
478         state->master_state = ICW3;
479       } else if (cw1->ic4 == 1) {
480         state->master_state = ICW4;
481       } else {
482         state->master_state = READY;
483       }
484
485     } else if (state->master_state == ICW3) {
486       struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
487
488       PrintDebug("8259 PIC: Setting ICW3 = %x (wr_Master2)\n", cw);
489
490       state->master_icw3 = cw;
491
492       if (cw1->ic4 == 1) {
493         state->master_state = ICW4;
494       } else {
495         state->master_state = READY;
496       }
497
498     } else if (state->master_state == ICW4) {
499       PrintDebug("8259 PIC: Setting ICW4 = %x (wr_Master2)\n", cw);
500       state->master_icw4 = cw;
501       state->master_state = READY;
502     } else if (state->master_state == READY) {
503       PrintDebug("8259 PIC: Setting IMR = %x (wr_Master2)\n", cw);
504       state->master_imr = cw;
505     } else {
506       // error
507       PrintError("8259 PIC: Invalid master PIC State (wr_Master2)\n");
508       return -1;
509     }
510
511     return 1;
512 }
513
514 int write_slave_port1(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
515   struct pic_internal * state = (struct pic_internal*)dev->private_data;
516   uchar_t cw = *(uchar_t *)src;
517
518   PrintDebug("8259 PIC: Write slave port 1 with 0x%x\n",cw);
519
520   if (length != 1) {
521     // error
522     PrintError("8259 PIC: Invalid Write length (wr_Slave1)\n");
523     return -1;
524   }
525
526   if (IS_ICW1(cw)) {
527     PrintDebug("8259 PIC: Setting ICW1 = %x (wr_Slave1)\n", cw);
528     state->slave_icw1 = cw;
529     state->slave_state = ICW2;
530   } else if (state->slave_state == READY) {
531     if (IS_OCW2(cw)) {
532       // handle the EOI here
533       struct ocw2 * cw2 =  (struct ocw2 *)&cw;
534
535       PrintDebug("8259 PIC: Setting OCW2 = %x (wr_Slave1)\n", cw);
536       
537       if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
538         // specific EOI;
539         state->slave_isr &= ~(0x01 << cw2->level);
540       } else if ((cw2->EOI) & (!cw2->R) && (!cw2->SL)) {
541         int i;
542         // Non-specific EOI
543         PrintDebug("8259 PIC: Pre ISR = %x (wr_Slave1)\n", state->slave_isr);
544         for (i = 0; i < 8; i++) {
545           if (state->slave_isr & (0x01 << i)) {
546             state->slave_isr &= ~(0x01 << i);
547             break;
548           }
549         }       
550         PrintDebug("8259 PIC: Post ISR = %x (wr_Slave1)\n", state->slave_isr);
551       } else {
552         PrintError("8259 PIC: Command not handled or invalid  (wr_Slave1)\n");
553         return -1;
554       }
555
556       state->slave_ocw2 = cw;
557     } else if (IS_OCW3(cw)) {
558       // Basically sets the IRR/ISR read flag
559       PrintDebug("8259 PIC: Setting OCW3 = %x (wr_Slave1)\n", cw);
560       state->slave_ocw3 = cw;
561     } else {
562       PrintError("8259 PIC: Invalid command work (wr_Slave1)\n");
563       return -1;
564     }
565   } else {
566     PrintError("8259 PIC: Invalid State writing (wr_Slave1)\n");
567     return -1;
568   }
569
570   return 1;
571 }
572
573 int write_slave_port2(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
574     struct pic_internal * state = (struct pic_internal*)dev->private_data;
575     uchar_t cw = *(uchar_t *)src;    
576
577     PrintDebug("8259 PIC: Write slave port 2 with 0x%x\n",cw);
578
579     if (length != 1) {
580       PrintError("8259 PIC: Invalid write length (wr_Slave2)\n");
581       return -1;
582     }
583
584     if (state->slave_state == ICW2) {
585       struct icw1 * cw1 =  (struct icw1 *)&(state->master_icw1);
586
587       PrintDebug("8259 PIC: Setting ICW2 = %x (wr_Slave2)\n", cw);
588
589       state->slave_icw2 = cw;
590
591       if (cw1->sngl == 0) {
592         state->slave_state = ICW3;
593       } else if (cw1->ic4 == 1) {
594         state->slave_state = ICW4;
595       } else {
596         state->slave_state = READY;
597       }
598
599     } else if (state->slave_state == ICW3) {
600       struct icw1 * cw1 =  (struct icw1 *)&(state->master_icw1);
601
602       PrintDebug("8259 PIC: Setting ICW3 = %x (wr_Slave2)\n", cw);
603
604       state->slave_icw3 = cw;
605
606       if (cw1->ic4 == 1) {
607         state->slave_state = ICW4;
608       } else {
609         state->slave_state = READY;
610       }
611
612     } else if (state->slave_state == ICW4) {
613       PrintDebug("8259 PIC: Setting ICW4 = %x (wr_Slave2)\n", cw);
614       state->slave_icw4 = cw;
615       state->slave_state = READY;
616     } else if (state->slave_state == READY) {
617       PrintDebug("8259 PIC: Setting IMR = %x (wr_Slave2)\n", cw);
618       state->slave_imr = cw;
619     } else {
620       PrintError("8259 PIC: Invalid State at write (wr_Slave2)\n");
621       return -1;
622     }
623
624     return 1;
625 }
626
627
628
629
630
631
632
633
634 int pic_init(struct vm_device * dev) {
635   struct pic_internal * state = (struct pic_internal*)dev->private_data;
636
637   set_intr_controller(dev->vm, &intr_ops, state);
638
639   state->master_irr = 0;
640   state->master_isr = 0;
641   state->master_icw1 = 0;
642   state->master_icw2 = 0;
643   state->master_icw3 = 0;
644   state->master_icw4 = 0;
645   state->master_imr = 0;
646   state->master_ocw2 = 0;
647   state->master_ocw3 = 0x02;
648   state->master_state = ICW1;
649
650
651   state->slave_irr = 0;
652   state->slave_isr = 0;
653   state->slave_icw1 = 0;
654   state->slave_icw2 = 0;
655   state->slave_icw3 = 0;
656   state->slave_icw4 = 0;
657   state->slave_imr = 0;
658   state->slave_ocw2 = 0;
659   state->slave_ocw3 = 0x02;
660   state->slave_state = ICW1;
661
662
663   dev_hook_io(dev, MASTER_PORT1, &read_master_port1, &write_master_port1);
664   dev_hook_io(dev, MASTER_PORT2, &read_master_port2, &write_master_port2);
665   dev_hook_io(dev, SLAVE_PORT1, &read_slave_port1, &write_slave_port1);
666   dev_hook_io(dev, SLAVE_PORT2, &read_slave_port2, &write_slave_port2);
667
668   return 0;
669 }
670
671
672 int pic_deinit(struct vm_device * dev) {
673   dev_unhook_io(dev, MASTER_PORT1);
674   dev_unhook_io(dev, MASTER_PORT2);
675   dev_unhook_io(dev, SLAVE_PORT1);
676   dev_unhook_io(dev, SLAVE_PORT2);
677
678   return 0;
679 }
680
681
682
683
684
685
686
687 static struct vm_device_ops dev_ops = {
688   .init = pic_init,
689   .deinit = pic_deinit,
690   .reset = NULL,
691   .start = NULL,
692   .stop = NULL,
693 };
694
695
696 struct vm_device * create_pic() {
697   struct pic_internal * state = NULL;
698   state = (struct pic_internal *)V3_Malloc(sizeof(struct pic_internal));
699   V3_ASSERT(state != NULL);
700
701   struct vm_device *device = create_device("8259A", &dev_ops, state);
702
703   return device;
704 }
705
706
707
708