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