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