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 ackable interrupts
[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 #include <palacios/vm_guest.h>
27
28 #ifndef V3_CONFIG_DEBUG_PIC
29 #undef PrintDebug
30 #define PrintDebug(fmt, args...)
31 #endif
32
33
34 typedef enum {RESET, ICW1, ICW2, ICW3, ICW4,  READY} pic_state_t;
35
36 static const uint_t MASTER_PORT1 = 0x20;
37 static const uint_t MASTER_PORT2 = 0x21;
38 static const uint_t SLAVE_PORT1 = 0xA0;
39 static const uint_t SLAVE_PORT2 = 0xA1;
40
41 static const uint_t ELCR1_PORT = 0x4d0;
42 static const uint_t ELCR2_PORT = 0x4d1;
43
44
45 #define IS_ICW1(x) (((x & 0x10) >> 4) == 0x1)
46 #define IS_OCW2(x) (((x & 0x18) >> 3) == 0x0)
47 #define IS_OCW3(x) (((x & 0x18) >> 3) == 0x1)
48
49
50 struct icw1 {
51     uint_t ic4    : 1;  // ICW4 has to be read
52     uint_t sngl   : 1;  // single (only one PIC)
53     uint_t adi    : 1;  // call address interval
54     uint_t ltim   : 1;  // level interrupt mode
55     uint_t one    : 1;
56     uint_t rsvd   : 3;
57 };
58
59
60 struct icw2 {
61     uint_t rsvd   : 3;
62     uint_t vector : 5;
63 };
64
65
66 // Each bit that is set indicates that the IR input has a slave
67 struct icw3_master {
68     uint_t S0   : 1;
69     uint_t S1   : 1;
70     uint_t S2   : 1;
71     uint_t S3   : 1;
72     uint_t S4   : 1;
73     uint_t S5   : 1;
74     uint_t S6   : 1;
75     uint_t S7   : 1;
76 };
77
78 // The ID is the Slave device ID
79 struct icw3_slave {
80     uint_t id     : 3;
81     uint_t zeroes : 5;
82 };
83
84 struct icw4 {
85     uint_t uPM    : 1;  // 1=x86
86     uint_t AEOI   : 1;  // Automatic End of Interrupt
87     uint_t M_S    : 1;  // only if buffered 1=master,0=slave 
88     uint_t BUF    : 1;  // buffered mode
89     uint_t SFNM   : 1;  // special fully nexted mode
90     uint_t zeroes : 3;
91 };
92
93
94 struct ocw1 {
95     uint_t m0     : 1;
96     uint_t m1     : 1;
97     uint_t m2     : 1;
98     uint_t m3     : 1;
99     uint_t m4     : 1;
100     uint_t m5     : 1;
101     uint_t m6     : 1;
102     uint_t m7     : 1;
103 };
104
105 struct ocw2 {
106     uint_t level  : 3;
107     uint_t cw_code : 2; // should be 00
108     uint_t EOI    : 1;
109     uint_t SL     : 1;
110     uint_t R      : 1;
111 };
112
113 struct ocw3 {
114     uint_t RIS    : 1;
115     uint_t RR     : 1;
116     uint_t P      : 1;
117     uint_t cw_code : 2; // should be 01
118     uint_t smm    : 1;
119     uint_t esmm   : 1;
120     uint_t zero2  : 1;
121 };
122
123
124 struct pic_internal {
125
126
127     uint8_t master_irr;
128     uint8_t slave_irr;
129   
130     uint8_t master_isr;
131     uint8_t slave_isr;
132
133     uint8_t master_elcr;
134     uint8_t slave_elcr;
135     uint8_t master_elcr_mask;
136     uint8_t slave_elcr_mask;
137
138     uint8_t master_icw1;
139     uint8_t master_icw2;
140     uint8_t master_icw3;
141     uint8_t master_icw4;
142
143
144     uint8_t slave_icw1;
145     uint8_t slave_icw2;
146     uint8_t slave_icw3;
147     uint8_t slave_icw4;
148
149
150     uint8_t master_imr;
151     uint8_t slave_imr;
152     uint8_t master_ocw2;
153     uint8_t master_ocw3;
154     uint8_t slave_ocw2;
155     uint8_t slave_ocw3;
156
157     pic_state_t master_state;
158     pic_state_t slave_state;
159
160     struct guest_info * core;
161
162
163     void * router_handle;
164     void * controller_handle;
165 };
166
167
168 static void DumpPICState(struct pic_internal *p)
169 {
170
171     PrintDebug("8259 PIC: master_state=0x%x\n",p->master_state);
172     PrintDebug("8259 PIC: master_irr=0x%x\n",p->master_irr);
173     PrintDebug("8259 PIC: master_isr=0x%x\n",p->master_isr);
174     PrintDebug("8259 PIC: master_imr=0x%x\n",p->master_imr);
175
176     PrintDebug("8259 PIC: master_ocw2=0x%x\n",p->master_ocw2);
177     PrintDebug("8259 PIC: master_ocw3=0x%x\n",p->master_ocw3);
178
179     PrintDebug("8259 PIC: master_icw1=0x%x\n",p->master_icw1);
180     PrintDebug("8259 PIC: master_icw2=0x%x\n",p->master_icw2);
181     PrintDebug("8259 PIC: master_icw3=0x%x\n",p->master_icw3);
182     PrintDebug("8259 PIC: master_icw4=0x%x\n",p->master_icw4);
183
184     PrintDebug("8259 PIC: slave_state=0x%x\n",p->slave_state);
185     PrintDebug("8259 PIC: slave_irr=0x%x\n",p->slave_irr);
186     PrintDebug("8259 PIC: slave_isr=0x%x\n",p->slave_isr);
187     PrintDebug("8259 PIC: slave_imr=0x%x\n",p->slave_imr);
188
189     PrintDebug("8259 PIC: slave_ocw2=0x%x\n",p->slave_ocw2);
190     PrintDebug("8259 PIC: slave_ocw3=0x%x\n",p->slave_ocw3);
191
192     PrintDebug("8259 PIC: slave_icw1=0x%x\n",p->slave_icw1);
193     PrintDebug("8259 PIC: slave_icw2=0x%x\n",p->slave_icw2);
194     PrintDebug("8259 PIC: slave_icw3=0x%x\n",p->slave_icw3);
195     PrintDebug("8259 PIC: slave_icw4=0x%x\n",p->slave_icw4);
196
197 }
198
199
200 static int pic_raise_intr(struct v3_vm_info * vm, void * private_data, struct v3_irq * irq) {
201     struct pic_internal * state = (struct pic_internal*)private_data;
202     uint8_t irq_num = irq->irq;
203
204     if (irq_num == 2) {
205         irq_num = 9;
206         state->master_irr |= 0x04;
207     }
208
209     PrintDebug("8259 PIC: Raising irq %d in the PIC\n", irq_num);
210
211     if (irq_num <= 7) {
212         state->master_irr |= 0x01 << irq_num;
213     } else if ((irq_num > 7) && (irq_num < 16)) {
214         state->slave_irr |= 0x01 << (irq_num - 8);
215     } else {
216         PrintDebug("8259 PIC: Invalid IRQ raised (%d)\n", irq_num);
217         return -1;
218     }
219
220     if (V3_Get_CPU() != vm->cores[0].pcpu_id) {
221         // guest is running on another core, interrupt it to deliver irq
222         v3_interrupt_cpu(vm, 0, 0);
223     }
224
225     return 0;
226 }
227
228
229 static int pic_lower_intr(struct v3_vm_info * vm, void * private_data, struct v3_irq * irq) {
230     struct pic_internal * state = (struct pic_internal*)private_data;
231     uint8_t irq_num = irq->irq;
232
233
234     PrintDebug("[pic_lower_intr] IRQ line %d now low\n", irq_num);
235     if (irq_num <= 7) {
236
237         state->master_irr &= ~(1 << irq_num);
238         if ((state->master_irr & ~(state->master_imr)) == 0) {
239             PrintDebug("\t\tFIXME: Master maybe should do sth\n");
240         }
241     } else if ((irq_num > 7) && (irq_num < 16)) {
242
243         state->slave_irr &= ~(1 << (irq_num - 8));
244         if ((state->slave_irr & (~(state->slave_imr))) == 0) {
245             PrintDebug("\t\tFIXME: Slave maybe should do sth\n");
246         }
247     }
248     return 0;
249 }
250
251
252
253 static int pic_intr_pending(struct guest_info * info, void * private_data) {
254     struct pic_internal * state = (struct pic_internal*)private_data;
255
256     if ((state->master_irr & ~(state->master_imr)) || 
257         (state->slave_irr & ~(state->slave_imr))) {
258         return 1;
259     }
260
261     return 0;
262 }
263
264 static int pic_get_intr_number(struct guest_info * info, void * private_data) {
265     struct pic_internal * state = (struct pic_internal *)private_data;
266     int i = 0;
267     int irq = -1;
268
269     PrintDebug("8259 PIC: getnum: master_irr: 0x%x master_imr: 0x%x\n", state->master_irr, state->master_imr);
270     PrintDebug("8259 PIC: getnum: slave_irr: 0x%x slave_imr: 0x%x\n", state->slave_irr, state->slave_imr);
271
272     for (i = 0; i < 16; i++) {
273         if (i <= 7) {
274             if (((state->master_irr & ~(state->master_imr)) >> i) & 0x01) {
275                 //state->master_isr |= (0x1 << i);
276                 // reset the irr
277                 //state->master_irr &= ~(0x1 << i);
278                 PrintDebug("8259 PIC: IRQ: %d, master_icw2: %x\n", i, state->master_icw2);
279                 irq = i + state->master_icw2;
280                 break;
281             }
282         } else {
283             if (((state->slave_irr & ~(state->slave_imr)) >> (i - 8)) & 0x01) {
284                 //state->slave_isr |= (0x1 << (i - 8));
285                 //state->slave_irr &= ~(0x1 << (i - 8));
286                 PrintDebug("8259 PIC: IRQ: %d, slave_icw2: %x\n", i, state->slave_icw2);
287                 irq = (i - 8) + state->slave_icw2;
288                 break;
289             }
290         }
291     }
292
293 #if 1
294     if ((i == 15) || (i == 6)) { 
295         DumpPICState(state);
296     }
297 #endif
298   
299     if (i == 16) { 
300         return -1;
301     } else {
302         PrintDebug("8259 PIC: get num is returning %d\n",irq);
303         return irq;
304     }
305 }
306
307
308
309 /* The IRQ number is the number returned by pic_get_intr_number(), not the pin number */
310 static int pic_begin_irq(struct guest_info * info, void * private_data, int irq) {
311     struct pic_internal * state = (struct pic_internal*)private_data;
312     
313     if ((irq >= state->master_icw2) && (irq <= state->master_icw2 + 7)) {
314        irq &= 0x7;
315     } else if ((irq >= state->slave_icw2) && (irq <= state->slave_icw2 + 7)) {
316        irq &= 0x7;
317        irq += 8;
318     } else {
319        //    PrintError("8259 PIC: Could not find IRQ (0x%x) to Begin\n",irq);
320        return -1;
321     }
322     
323     if (irq <= 7) {
324         // This should always be true: See pic_get_intr_number
325        if (((state->master_irr & ~(state->master_imr)) >> irq) & 0x01) {
326            state->master_isr |= (0x1 << irq);
327
328            if (!(state->master_elcr & (0x1 << irq))) {
329                state->master_irr &= ~(0x1 << irq);
330            }
331        } else {
332            PrintDebug("8259 PIC: (master) Ignoring begin_irq for %d since I don't own it\n",irq);
333        }
334
335     } else {
336         // This should always be true: See pic_get_intr_number
337         if (((state->slave_irr & ~(state->slave_imr)) >> (irq - 8)) & 0x01) {
338            state->slave_isr |= (0x1 << (irq - 8));
339            
340            if (!(state->slave_elcr & (0x1 << (irq - 8)))) {
341                state->slave_irr &= ~(0x1 << (irq - 8));
342            }
343         } else {
344            PrintDebug("8259 PIC: (slave) Ignoring begin_irq for %d since I don't own it\n",irq);
345         }
346
347     }
348
349     return 0;
350 }
351
352
353 /*
354   static int pic_end_irq(void * private_data, int irq) {
355   return 0;
356   }
357 */
358
359
360
361 static struct intr_ctrl_ops intr_ops = {
362     .intr_pending = pic_intr_pending,
363     .get_intr_number = pic_get_intr_number,
364     .begin_irq = pic_begin_irq
365 };
366
367 static struct intr_router_ops router_ops = {
368     .raise_intr = pic_raise_intr,
369     .lower_intr = pic_lower_intr
370 };
371
372
373 static int read_master_port1(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) {
374     struct pic_internal * state = (struct pic_internal *)priv_data;
375
376     if (length != 1) {
377         PrintError("8259 PIC: Invalid Read length (rd_Master1)\n");
378         return -1;
379     }
380   
381     if ((state->master_ocw3 & 0x03) == 0x02) {
382         *(uint8_t *)dst = state->master_irr;
383     } else if ((state->master_ocw3 & 0x03) == 0x03) {
384         *(uint8_t *)dst = state->master_isr;
385     } else {
386         *(uint8_t *)dst = 0;
387     }
388   
389     return 1;
390 }
391
392 static int read_master_port2(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) {
393     struct pic_internal * state = (struct pic_internal *)priv_data;
394
395     if (length != 1) {
396         PrintError("8259 PIC: Invalid Read length (rd_Master2)\n");
397         return -1;
398     }
399
400     *(uint8_t *)dst = state->master_imr;
401
402     return 1;
403   
404 }
405
406 static int read_slave_port1(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) {
407     struct pic_internal * state = (struct pic_internal *)priv_data;
408
409     if (length != 1) {
410         PrintError("8259 PIC: Invalid Read length (rd_Slave1)\n");
411         return -1;
412     }
413   
414     if ((state->slave_ocw3 & 0x03) == 0x02) {
415         *(uint8_t*)dst = state->slave_irr;
416     } else if ((state->slave_ocw3 & 0x03) == 0x03) {
417         *(uint8_t *)dst = state->slave_isr;
418     } else {
419         *(uint8_t *)dst = 0;
420     }
421
422     return 1;
423 }
424
425 static int read_slave_port2(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) {
426     struct pic_internal * state = (struct pic_internal *)priv_data;
427
428     if (length != 1) {
429         PrintError("8259 PIC: Invalid Read length  (rd_Slave2)\n");
430         return -1;
431     }
432
433     *(uint8_t *)dst = state->slave_imr;
434
435     return 1;
436 }
437
438
439 static int write_master_port1(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
440     struct pic_internal * state = (struct pic_internal *)priv_data;
441     uint8_t cw = *(uint8_t *)src;
442
443     PrintDebug("8259 PIC: Write master port 1 with 0x%x\n",cw);
444
445     if (length != 1) {
446         PrintError("8259 PIC: Invalid Write length (wr_Master1)\n");
447         return -1;
448     }
449
450     v3_clear_pending_intr(core);
451
452     if (IS_ICW1(cw)) {
453
454         PrintDebug("8259 PIC: Setting ICW1 = %x (wr_Master1)\n", cw);
455
456         state->master_icw1 = cw;
457         state->master_state = ICW2;
458
459     } else if (state->master_state == READY) {
460         if (IS_OCW2(cw)) {
461             // handle the EOI here
462             struct ocw2 * cw2 =  (struct ocw2*)&cw;
463
464             PrintDebug("8259 PIC: Handling OCW2 = %x (wr_Master1)\n", cw);
465
466             if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
467                 // specific EOI;
468                 state->master_isr &= ~(0x01 << cw2->level);
469             } else if ((cw2->EOI) & (!cw2->R) && (!cw2->SL)) {
470                 int i;
471                 // Non-specific EOI
472                 PrintDebug("8259 PIC: Pre ISR = %x (wr_Master1)\n", state->master_isr);
473                 for (i = 0; i < 8; i++) {
474                     if (state->master_isr & (0x01 << i)) {
475                         state->master_isr &= ~(0x01 << i);
476                         break;
477                     }
478                 }       
479                 PrintDebug("8259 PIC: Post ISR = %x (wr_Master1)\n", state->master_isr);
480             } else if (!(cw2->EOI) && (cw2->R) && (cw2->SL)) {
481                 PrintDebug("8259 PIC: Ignoring set-priority, priorities not implemented (level=%d, wr_Master1)\n", cw2->level);
482             } else if (!(cw2->EOI) && !(cw2->R) && (cw2->SL)) {
483                 PrintDebug("8259 PIC: Ignoring no-op (level=%d, wr_Master1)\n", cw2->level);
484             } else {
485                 PrintError("8259 PIC: Command not handled, or in error (wr_Master1)\n");
486                 return -1;
487             }
488
489             state->master_ocw2 = cw;
490         } else if (IS_OCW3(cw)) {
491             PrintDebug("8259 PIC: Handling OCW3 = %x (wr_Master1)\n", cw);
492             state->master_ocw3 = cw;
493         } else {
494             PrintError("8259 PIC: Invalid OCW to PIC (wr_Master1)\n");
495             PrintError("8259 PIC: CW=%x\n", cw);
496             return -1;
497         }
498     } else {
499         PrintError("8259 PIC: Invalid PIC State (wr_Master1)\n");
500         PrintError("8259 PIC: CW=%x\n", cw);
501         return -1;
502     }
503
504     return 1;
505 }
506
507 static int write_master_port2(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
508     struct pic_internal * state = (struct pic_internal *)priv_data;
509     uint8_t cw = *(uint8_t *)src;    
510
511     PrintDebug("8259 PIC: Write master port 2 with 0x%x\n",cw);
512
513     if (length != 1) {
514         PrintError("8259 PIC: Invalid Write length (wr_Master2)\n");
515         return -1;
516     }
517
518     v3_clear_pending_intr(core);
519
520     if (state->master_state == ICW2) {
521         struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
522
523         PrintDebug("8259 PIC: Setting ICW2 = %x (wr_Master2)\n", cw);
524         state->master_icw2 = cw;
525
526
527
528         if (cw1->sngl == 0) {
529             state->master_state = ICW3;
530         } else if (cw1->ic4 == 1) {
531             state->master_state = ICW4;
532         } else {
533             state->master_state = READY;
534         }
535
536
537
538     } else if (state->master_state == ICW3) {
539         struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
540
541         PrintDebug("8259 PIC: Setting ICW3 = %x (wr_Master2)\n", cw);
542
543         state->master_icw3 = cw;
544
545         if (cw1->ic4 == 1) {
546             state->master_state = ICW4;
547         } else {
548             state->master_state = READY;
549         }
550
551     } else if (state->master_state == ICW4) {
552         PrintDebug("8259 PIC: Setting ICW4 = %x (wr_Master2)\n", cw);
553         state->master_icw4 = cw;
554         state->master_state = READY;
555     } else if ((state->master_state == ICW1) || (state->master_state == READY)) {
556         PrintDebug("8259 PIC: Setting IMR = %x (wr_Master2)\n", cw);
557         state->master_imr = cw;
558     } else {
559         // error
560         PrintError("8259 PIC: Invalid master PIC State (wr_Master2) (state=%d)\n", 
561                 state->master_state);
562         return -1;
563     }
564
565     return 1;
566 }
567
568 static int write_slave_port1(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
569     struct pic_internal * state = (struct pic_internal *)priv_data;
570     uint8_t cw = *(uint8_t *)src;
571
572     PrintDebug("8259 PIC: Write slave port 1 with 0x%x\n",cw);
573
574     if (length != 1) {
575         // error
576         PrintError("8259 PIC: Invalid Write length (wr_Slave1)\n");
577         return -1;
578     }
579
580     v3_clear_pending_intr(core);
581
582     if (IS_ICW1(cw)) {
583         PrintDebug("8259 PIC: Setting ICW1 = %x (wr_Slave1)\n", cw);
584         state->slave_icw1 = cw;
585         state->slave_state = ICW2;
586     } else if (state->slave_state == READY) {
587         if (IS_OCW2(cw)) {
588             // handle the EOI here
589             struct ocw2 * cw2 =  (struct ocw2 *)&cw;
590
591             PrintDebug("8259 PIC: Setting OCW2 = %x (wr_Slave1)\n", cw);
592
593             if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
594                 // specific EOI;
595                 state->slave_isr &= ~(0x01 << cw2->level);
596             } else if ((cw2->EOI) & (!cw2->R) && (!cw2->SL)) {
597                 int i;
598                 // Non-specific EOI
599                 PrintDebug("8259 PIC: Pre ISR = %x (wr_Slave1)\n", state->slave_isr);
600                 for (i = 0; i < 8; i++) {
601                     if (state->slave_isr & (0x01 << i)) {
602                         state->slave_isr &= ~(0x01 << i);
603                         break;
604                     }
605                 }
606                 PrintDebug("8259 PIC: Post ISR = %x (wr_Slave1)\n", state->slave_isr);
607             } else {
608                 PrintError("8259 PIC: Command not handled or invalid  (wr_Slave1)\n");
609                 return -1;
610             }
611
612             state->slave_ocw2 = cw;
613         } else if (IS_OCW3(cw)) {
614             // Basically sets the IRR/ISR read flag
615             PrintDebug("8259 PIC: Setting OCW3 = %x (wr_Slave1)\n", cw);
616             state->slave_ocw3 = cw;
617         } else {
618             PrintError("8259 PIC: Invalid command work (wr_Slave1)\n");
619             return -1;
620         }
621     } else {
622         PrintError("8259 PIC: Invalid State writing (wr_Slave1)\n");
623         return -1;
624     }
625
626     return 1;
627 }
628
629 static int write_slave_port2(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
630     struct pic_internal * state = (struct pic_internal *)priv_data;
631     uint8_t cw = *(uint8_t *)src;    
632
633     PrintDebug("8259 PIC: Write slave port 2 with 0x%x\n",cw);
634
635     if (length != 1) {
636         PrintError("8259 PIC: Invalid write length (wr_Slave2)\n");
637         return -1;
638     }
639
640     v3_clear_pending_intr(core);
641
642
643     if (state->slave_state == ICW2) {
644         struct icw1 * cw1 =  (struct icw1 *)&(state->master_icw1);
645
646         PrintDebug("8259 PIC: Setting ICW2 = %x (wr_Slave2)\n", cw);
647
648         state->slave_icw2 = cw;
649
650         if (cw1->sngl == 0) {
651             state->slave_state = ICW3;
652         } else if (cw1->ic4 == 1) {
653             state->slave_state = ICW4;
654         } else {
655             state->slave_state = READY;
656         }
657
658     } else if (state->slave_state == ICW3) {
659         struct icw1 * cw1 =  (struct icw1 *)&(state->master_icw1);
660
661         PrintDebug("8259 PIC: Setting ICW3 = %x (wr_Slave2)\n", cw);
662
663         state->slave_icw3 = cw;
664
665         if (cw1->ic4 == 1) {
666             state->slave_state = ICW4;
667         } else {
668             state->slave_state = READY;
669         }
670
671     } else if (state->slave_state == ICW4) {
672         PrintDebug("8259 PIC: Setting ICW4 = %x (wr_Slave2)\n", cw);
673         state->slave_icw4 = cw;
674         state->slave_state = READY;
675     } else if ((state->slave_state == ICW1) || (state->slave_state == READY)) {
676         PrintDebug("8259 PIC: Setting IMR = %x (wr_Slave2)\n", cw);
677         state->slave_imr = cw;
678     } else {
679         PrintError("8259 PIC: Invalid State at write (wr_Slave2)\n");
680         return -1;
681     }
682
683     return 1;
684 }
685
686
687
688
689 static int read_elcr_port(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) {
690     struct pic_internal * state = (struct pic_internal *)priv_data;
691     
692     if (length != 1) {
693         PrintError("ELCR read of invalid length %d\n", length);
694         return -1;
695     }
696
697     if (port == ELCR1_PORT) {
698         // master
699         *(uint8_t *)dst = state->master_elcr;
700     } else if (port == ELCR2_PORT) {
701         *(uint8_t *)dst = state->slave_elcr;
702     } else {
703         PrintError("Invalid port %x\n", port);
704         return -1;
705     }
706
707     return length;
708 }
709
710
711 static int write_elcr_port(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
712     struct pic_internal * state = (struct pic_internal *)priv_data;
713     
714     if (length != 1) {
715         PrintError("ELCR read of invalid length %d\n", length);
716         return -1;
717     }
718
719     if (port == ELCR1_PORT) {
720         // master
721         state->master_elcr  = (*(uint8_t *)src) & state->master_elcr_mask;
722     } else if (port == ELCR2_PORT) {
723         state->slave_elcr  = (*(uint8_t *)src) & state->slave_elcr_mask;
724     } else {
725         PrintError("Invalid port %x\n", port);
726         return -1;
727     }
728
729     return length;
730 }
731
732
733
734 static int pic_free(struct pic_internal * state) {
735     struct guest_info * core = state->core;
736
737     v3_remove_intr_controller(core, state->controller_handle);
738     v3_remove_intr_router(core->vm_info, state->router_handle);
739
740     V3_Free(state);
741     return 0;
742 }
743
744 #ifdef V3_CONFIG_CHECKPOINT
745 static int pic_save(struct v3_chkpt_ctx * ctx, void * private_data) {
746     struct pic_internal * pic = (struct pic_internal *)private_data;
747
748     v3_chkpt_save_8(ctx, "MASTER_IRR", &(pic->master_irr));
749     v3_chkpt_save_8(ctx, "SLAVE_IRR", &(pic->slave_irr));
750   
751     v3_chkpt_save_8(ctx, "MASTER_ISR", &(pic->master_isr));
752     v3_chkpt_save_8(ctx, "SLAVE_ISR", &(pic->slave_isr));
753
754     v3_chkpt_save_8(ctx, "MASTER_ELCR", &(pic->master_elcr));
755     v3_chkpt_save_8(ctx, "SLAVE_ELCR", &(pic->slave_elcr));
756     v3_chkpt_save_8(ctx, "MASTER_ELCR_MASK", &(pic->master_elcr_mask));
757     v3_chkpt_save_8(ctx, "SLAVE_ELCR_MASK", &(pic->slave_elcr_mask));
758
759     v3_chkpt_save_8(ctx, "MASTER_ICW1", &(pic->master_icw1));
760     v3_chkpt_save_8(ctx, "MASTER_ICW2", &(pic->master_icw2));
761     v3_chkpt_save_8(ctx, "MASTER_ICW3", &(pic->master_icw3));
762     v3_chkpt_save_8(ctx, "MASTER_ICW4", &(pic->master_icw4));
763
764
765     v3_chkpt_save_8(ctx, "SLAVE_ICW1", &(pic->slave_icw1));
766     v3_chkpt_save_8(ctx, "SLAVE_ICW2", &(pic->slave_icw2));
767     v3_chkpt_save_8(ctx, "SLAVE_ICW3", &(pic->slave_icw3));
768     v3_chkpt_save_8(ctx, "SLAVE_ICW4", &(pic->slave_icw4));
769
770
771     v3_chkpt_save_8(ctx, "MASTER_IMR", &(pic->master_imr));
772     v3_chkpt_save_8(ctx, "SLAVE_IMR", &(pic->slave_imr));
773     v3_chkpt_save_8(ctx, "MASTER_OCW2", &(pic->master_ocw2));
774     v3_chkpt_save_8(ctx, "MASTER_OCW3", &(pic->master_ocw3));
775     v3_chkpt_save_8(ctx, "SLAVE_OCW2", &(pic->slave_ocw2));
776     v3_chkpt_save_8(ctx, "SLAVE_OCW3", &(pic->slave_ocw3));
777
778     v3_chkpt_save_8(ctx, "MASTER_STATE", &(pic->master_state));
779     v3_chkpt_save_8(ctx, "SLAVE_STATE", &(pic->slave_state));
780
781     
782     return 0;
783
784 }
785
786 static int pic_load(struct v3_chkpt_ctx * ctx, void * private_data) {
787     struct pic_internal * pic = (struct pic_internal *)private_data;
788
789    
790     v3_chkpt_load_8(ctx, "MASTER_IRR", &(pic->master_irr));
791     v3_chkpt_load_8(ctx, "SLAVE_IRR", &(pic->slave_irr));
792   
793     v3_chkpt_load_8(ctx, "MASTER_ISR", &(pic->master_isr));
794     v3_chkpt_load_8(ctx, "SLAVE_ISR", &(pic->slave_isr));
795
796     v3_chkpt_load_8(ctx, "MASTER_ELCR", &(pic->master_elcr));
797     v3_chkpt_load_8(ctx, "SLAVE_ELCR", &(pic->slave_elcr));
798     v3_chkpt_load_8(ctx, "MASTER_ELCR_MASK", &(pic->master_elcr_mask));
799     v3_chkpt_load_8(ctx, "SLAVE_ELCR_MASK", &(pic->slave_elcr_mask));
800
801     v3_chkpt_load_8(ctx, "MASTER_ICW1", &(pic->master_icw1));
802     v3_chkpt_load_8(ctx, "MASTER_ICW2", &(pic->master_icw2));
803     v3_chkpt_load_8(ctx, "MASTER_ICW3", &(pic->master_icw3));
804     v3_chkpt_load_8(ctx, "MASTER_ICW4", &(pic->master_icw4));
805
806
807     v3_chkpt_load_8(ctx, "SLAVE_ICW1", &(pic->slave_icw1));
808     v3_chkpt_load_8(ctx, "SLAVE_ICW2", &(pic->slave_icw2));
809     v3_chkpt_load_8(ctx, "SLAVE_ICW3", &(pic->slave_icw3));
810     v3_chkpt_load_8(ctx, "SLAVE_ICW4", &(pic->slave_icw4));
811
812
813     v3_chkpt_load_8(ctx, "MASTER_IMR", &(pic->master_imr));
814     v3_chkpt_load_8(ctx, "SLAVE_IMR", &(pic->slave_imr));
815     v3_chkpt_load_8(ctx, "MASTER_OCW2", &(pic->master_ocw2));
816     v3_chkpt_load_8(ctx, "MASTER_OCW3", &(pic->master_ocw3));
817     v3_chkpt_load_8(ctx, "SLAVE_OCW2", &(pic->slave_ocw2));
818     v3_chkpt_load_8(ctx, "SLAVE_OCW3", &(pic->slave_ocw3));
819
820     v3_chkpt_load_8(ctx, "MASTER_STATE", &(pic->master_state));
821     v3_chkpt_load_8(ctx, "SLAVE_STATE", &(pic->slave_state));
822
823     return 0;
824 }
825
826 #endif
827
828
829 static struct v3_device_ops dev_ops = {
830     .free = (int (*)(void *))pic_free,
831 #ifdef V3_CONFIG_CHECKPOINT
832     .save = pic_save,
833     .load = pic_load
834 #endif
835 };
836
837
838
839
840
841 static int pic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
842     struct pic_internal * state = NULL;
843     char * dev_id = v3_cfg_val(cfg, "ID");
844     int ret = 0;
845
846     // PIC is only usable in non-multicore environments
847     // just hardcode the core context
848     struct guest_info * core = &(vm->cores[0]);
849         
850     state = (struct pic_internal *)V3_Malloc(sizeof(struct pic_internal));
851
852     V3_ASSERT(state != NULL);
853
854     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, state);
855
856     if (dev == NULL) {
857         PrintError("Could not add device %s\n", dev_id);
858         V3_Free(state);
859         return -1;
860     }
861
862     state->core = core;
863
864     state->controller_handle = v3_register_intr_controller(core, &intr_ops, state);
865     state->router_handle = v3_register_intr_router(vm, &router_ops, state);
866
867     state->master_irr = 0;
868     state->master_isr = 0;
869     state->master_elcr = 0;
870     state->master_elcr_mask = 0xf8;
871     state->master_icw1 = 0;
872     state->master_icw2 = 0;
873     state->master_icw3 = 0;
874     state->master_icw4 = 0;
875     state->master_imr = 0;
876     state->master_ocw2 = 0;
877     state->master_ocw3 = 0x02;
878     state->master_state = ICW1;
879
880
881     state->slave_irr = 0;
882     state->slave_isr = 0;
883     state->slave_elcr = 0;
884     state->slave_elcr_mask = 0xde;
885     state->slave_icw1 = 0;
886     state->slave_icw2 = 0;
887     state->slave_icw3 = 0;
888     state->slave_icw4 = 0;
889     state->slave_imr = 0;
890     state->slave_ocw2 = 0;
891     state->slave_ocw3 = 0x02;
892     state->slave_state = ICW1;
893
894
895     ret |= v3_dev_hook_io(dev, MASTER_PORT1, &read_master_port1, &write_master_port1);
896     ret |= v3_dev_hook_io(dev, MASTER_PORT2, &read_master_port2, &write_master_port2);
897     ret |= v3_dev_hook_io(dev, SLAVE_PORT1, &read_slave_port1, &write_slave_port1);
898     ret |= v3_dev_hook_io(dev, SLAVE_PORT2, &read_slave_port2, &write_slave_port2);
899
900
901     ret |= v3_dev_hook_io(dev, ELCR1_PORT, &read_elcr_port, &write_elcr_port);
902     ret |= v3_dev_hook_io(dev, ELCR2_PORT, &read_elcr_port, &write_elcr_port);
903
904     if (ret != 0) {
905         PrintError("Error hooking io ports\n");
906         v3_remove_device(dev);
907         return -1;
908     }
909
910     return 0;
911 }
912
913
914
915 device_register("8259A", pic_init);