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.


Succesful transition to vmxassist, then to the bios, where it dies in keyboard init.
[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 == ICW1) || (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) (state=%d)\n", 
522                 state->master_state);
523         return -1;
524     }
525
526     return 1;
527 }
528
529 static int write_slave_port1(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
530     struct pic_internal * state = (struct pic_internal*)dev->private_data;
531     uchar_t cw = *(uchar_t *)src;
532
533     PrintDebug("8259 PIC: Write slave port 1 with 0x%x\n",cw);
534
535     if (length != 1) {
536         // error
537         PrintError("8259 PIC: Invalid Write length (wr_Slave1)\n");
538         return -1;
539     }
540
541     if (IS_ICW1(cw)) {
542         PrintDebug("8259 PIC: Setting ICW1 = %x (wr_Slave1)\n", cw);
543         state->slave_icw1 = cw;
544         state->slave_state = ICW2;
545     } else if (state->slave_state == READY) {
546         if (IS_OCW2(cw)) {
547             // handle the EOI here
548             struct ocw2 * cw2 =  (struct ocw2 *)&cw;
549
550             PrintDebug("8259 PIC: Setting OCW2 = %x (wr_Slave1)\n", cw);
551
552             if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
553                 // specific EOI;
554                 state->slave_isr &= ~(0x01 << cw2->level);
555             } else if ((cw2->EOI) & (!cw2->R) && (!cw2->SL)) {
556                 int i;
557                 // Non-specific EOI
558                 PrintDebug("8259 PIC: Pre ISR = %x (wr_Slave1)\n", state->slave_isr);
559                 for (i = 0; i < 8; i++) {
560                     if (state->slave_isr & (0x01 << i)) {
561                         state->slave_isr &= ~(0x01 << i);
562                         break;
563                     }
564                 }
565                 PrintDebug("8259 PIC: Post ISR = %x (wr_Slave1)\n", state->slave_isr);
566             } else {
567                 PrintError("8259 PIC: Command not handled or invalid  (wr_Slave1)\n");
568                 return -1;
569             }
570
571             state->slave_ocw2 = cw;
572         } else if (IS_OCW3(cw)) {
573             // Basically sets the IRR/ISR read flag
574             PrintDebug("8259 PIC: Setting OCW3 = %x (wr_Slave1)\n", cw);
575             state->slave_ocw3 = cw;
576         } else {
577             PrintError("8259 PIC: Invalid command work (wr_Slave1)\n");
578             return -1;
579         }
580     } else {
581         PrintError("8259 PIC: Invalid State writing (wr_Slave1)\n");
582         return -1;
583     }
584
585     return 1;
586 }
587
588 static int write_slave_port2(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
589     struct pic_internal * state = (struct pic_internal*)dev->private_data;
590     uchar_t cw = *(uchar_t *)src;    
591
592     PrintDebug("8259 PIC: Write slave port 2 with 0x%x\n",cw);
593
594     if (length != 1) {
595         PrintError("8259 PIC: Invalid write length (wr_Slave2)\n");
596         return -1;
597     }
598
599     if (state->slave_state == ICW2) {
600         struct icw1 * cw1 =  (struct icw1 *)&(state->master_icw1);
601
602         PrintDebug("8259 PIC: Setting ICW2 = %x (wr_Slave2)\n", cw);
603
604         state->slave_icw2 = cw;
605
606         if (cw1->sngl == 0) {
607             state->slave_state = ICW3;
608         } else if (cw1->ic4 == 1) {
609             state->slave_state = ICW4;
610         } else {
611             state->slave_state = READY;
612         }
613
614     } else if (state->slave_state == ICW3) {
615         struct icw1 * cw1 =  (struct icw1 *)&(state->master_icw1);
616
617         PrintDebug("8259 PIC: Setting ICW3 = %x (wr_Slave2)\n", cw);
618
619         state->slave_icw3 = cw;
620
621         if (cw1->ic4 == 1) {
622             state->slave_state = ICW4;
623         } else {
624             state->slave_state = READY;
625         }
626
627     } else if (state->slave_state == ICW4) {
628         PrintDebug("8259 PIC: Setting ICW4 = %x (wr_Slave2)\n", cw);
629         state->slave_icw4 = cw;
630         state->slave_state = READY;
631     } else if ((state->slave_state == ICW1) || (state->slave_state == READY)) {
632         PrintDebug("8259 PIC: Setting IMR = %x (wr_Slave2)\n", cw);
633         state->slave_imr = cw;
634     } else {
635         PrintError("8259 PIC: Invalid State at write (wr_Slave2)\n");
636         return -1;
637     }
638
639     return 1;
640 }
641
642
643
644
645 static int read_elcr_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
646     struct pic_internal * state = (struct pic_internal*)dev->private_data;
647     
648     if (length != 1) {
649         PrintError("ELCR read of invalid length %d\n", length);
650         return -1;
651     }
652
653     if (port == ELCR1_PORT) {
654         // master
655         *(uint8_t *)dst = state->master_elcr;
656     } else if (port == ELCR2_PORT) {
657         *(uint8_t *)dst = state->slave_elcr;
658     } else {
659         PrintError("Invalid port %x\n", port);
660         return -1;
661     }
662
663     return length;
664 }
665
666
667 static int write_elcr_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
668     struct pic_internal * state = (struct pic_internal*)dev->private_data;
669     
670     if (length != 1) {
671         PrintError("ELCR read of invalid length %d\n", length);
672         return -1;
673     }
674
675     if (port == ELCR1_PORT) {
676         // master
677         state->master_elcr  = (*(uint8_t *)src) & state->master_elcr_mask;
678     } else if (port == ELCR2_PORT) {
679         state->slave_elcr  = (*(uint8_t *)src) & state->slave_elcr_mask;
680     } else {
681         PrintError("Invalid port %x\n", port);
682         return -1;
683     }
684
685     return length;
686 }
687
688
689
690
691
692
693 static int pic_free(struct vm_device * dev) {
694     v3_dev_unhook_io(dev, MASTER_PORT1);
695     v3_dev_unhook_io(dev, MASTER_PORT2);
696     v3_dev_unhook_io(dev, SLAVE_PORT1);
697     v3_dev_unhook_io(dev, SLAVE_PORT2);
698
699     return 0;
700 }
701
702
703
704
705
706
707
708 static struct v3_device_ops dev_ops = {
709     .free = pic_free,
710     .reset = NULL,
711     .start = NULL,
712     .stop = NULL,
713 };
714
715
716
717 static int pic_init(struct guest_info * vm, void * cfg_data) {
718     struct pic_internal * state = NULL;
719     state = (struct pic_internal *)V3_Malloc(sizeof(struct pic_internal));
720     V3_ASSERT(state != NULL);
721
722     struct vm_device * dev = v3_allocate_device("8259A", &dev_ops, state);
723
724     if (v3_attach_device(vm, dev) == -1) {
725         PrintError("Could not attach device %s\n", "8259A");
726         return -1;
727     }
728
729
730     v3_register_intr_controller(vm, &intr_ops, state);
731
732     state->master_irr = 0;
733     state->master_isr = 0;
734     state->master_elcr = 0;
735     state->master_elcr_mask = 0xf8;
736     state->master_icw1 = 0;
737     state->master_icw2 = 0;
738     state->master_icw3 = 0;
739     state->master_icw4 = 0;
740     state->master_imr = 0;
741     state->master_ocw2 = 0;
742     state->master_ocw3 = 0x02;
743     state->master_state = ICW1;
744
745
746     state->slave_irr = 0;
747     state->slave_isr = 0;
748     state->slave_elcr = 0;
749     state->slave_elcr_mask = 0xde;
750     state->slave_icw1 = 0;
751     state->slave_icw2 = 0;
752     state->slave_icw3 = 0;
753     state->slave_icw4 = 0;
754     state->slave_imr = 0;
755     state->slave_ocw2 = 0;
756     state->slave_ocw3 = 0x02;
757     state->slave_state = ICW1;
758
759
760     v3_dev_hook_io(dev, MASTER_PORT1, &read_master_port1, &write_master_port1);
761     v3_dev_hook_io(dev, MASTER_PORT2, &read_master_port2, &write_master_port2);
762     v3_dev_hook_io(dev, SLAVE_PORT1, &read_slave_port1, &write_slave_port1);
763     v3_dev_hook_io(dev, SLAVE_PORT2, &read_slave_port2, &write_slave_port2);
764
765
766     v3_dev_hook_io(dev, ELCR1_PORT, &read_elcr_port, &write_elcr_port);
767     v3_dev_hook_io(dev, ELCR2_PORT, &read_elcr_port, &write_elcr_port);
768
769     return 0;
770 }
771
772
773
774 device_register("8259A", pic_init);