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.


modified interrupt interface to pass guest_info pointer
[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(struct guest_info * info, 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(struct guest_info * info, void * private_data, int irq) {
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(struct guest_info * info, 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(struct guest_info * info, 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(struct guest_info * info, 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 == ICW1) || (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) (state=%d)\n", 
521                 state->master_state);
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 == ICW1) || (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);