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.


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