1 #include <devices/8259a.h>
2 #include <palacios/vmm_intr.h>
3 #include <palacios/vmm_types.h>
4 #include <palacios/vmm.h>
7 typedef enum {RESET, ICW1, ICW2, ICW3, ICW4, READY} pic_state_t;
9 static const uint_t MASTER_PORT1 = 0x20;
10 static const uint_t MASTER_PORT2 = 0x21;
11 static const uint_t SLAVE_PORT1 = 0xA0;
12 static const uint_t SLAVE_PORT2 = 0xA1;
14 #define IS_OCW2(x) (((x & 0x18) >> 3) == 0x0)
15 #define IS_OCW3(x) (((x & 0x18) >> 3) == 0x1)
18 uint_t ic4 : 1; // ICW4 has to be read
19 uint_t sngl : 1; // single (only one PIC)
20 uint_t adi : 1; // call address interval
21 uint_t ltim : 1; // level interrupt mode
33 // Each bit that is set indicates that the IR input has a slave
45 // The ID is the Slave device ID
52 uint_t uPM : 1; // 1=x86
53 uint_t AEOI : 1; // Automatic End of Interrupt
54 uint_t M_S : 1; // only if buffered 1=master,0=slave
55 uint_t BUF : 1; // buffered mode
56 uint_t SFNM : 1; // special fully nexted mode
74 uint_t cw_code : 2; // should be 00
84 uint_t cw_code : 2; // should be 01
119 pic_state_t master_state;
120 pic_state_t slave_state;
125 static int pic_raise_intr(void * private_data, int irq, int error_code) {
126 struct pic_internal * state = (struct pic_internal*)private_data;
132 PrintDebug("Raising irq %d in the PIC\n", irq);
135 state->master_irr |= 0x01 << irq;
136 } else if ((irq > 7) && (irq < 16)) {
137 state->slave_irr |= 0x01 << (irq - 7);
139 PrintDebug("Invalid IRQ raised (%d)\n", irq);
146 static int pic_intr_pending(void * private_data) {
147 struct pic_internal * state = (struct pic_internal*)private_data;
149 if ((state->master_irr & ~(state->master_imr)) ||
150 (state->slave_irr & ~(state->slave_imr))) {
157 static int pic_get_intr_number(void * private_data) {
158 struct pic_internal * state = (struct pic_internal*)private_data;
161 for (i = 0; i < 16; i++) {
163 if (((state->master_irr & ~(state->master_imr)) >> i) == 0x01) {
164 //state->master_isr |= (0x1 << i);
166 //state->master_irr &= ~(0x1 << i);
167 PrintDebug("IRQ: %d, icw2: %x\n", i, state->master_icw2);
168 return i + state->master_icw2;
171 if (((state->slave_irr & ~(state->slave_imr)) >> (i - 8)) == 0x01) {
172 //state->slave_isr |= (0x1 << (i - 8));
173 //state->slave_irr &= ~(0x1 << (i - 8));
174 return (i - 8) + state->slave_icw2;
186 static int pic_begin_irq(void * private_data, int irq) {
187 struct pic_internal * state = (struct pic_internal*)private_data;
190 if (((state->master_irr & ~(state->master_imr)) >> irq) == 0x01) {
191 state->master_isr |= (0x1 << irq);
192 state->master_irr &= ~(0x1 << irq);
195 state->slave_isr |= (0x1 << (irq - 8));
196 state->slave_irr &= ~(0x1 << (irq - 8));
203 static int pic_end_irq(void * private_data, int irq) {
209 static struct intr_ctrl_ops intr_ops = {
210 .intr_pending = pic_intr_pending,
211 .get_intr_number = pic_get_intr_number,
212 .raise_intr = pic_raise_intr,
213 .begin_irq = pic_begin_irq,
219 int read_master_port1(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
220 struct pic_internal * state = (struct pic_internal*)dev->private_data;
225 if ((state->master_ocw3 & 0x03) == 0x02) {
226 *(char *)dst = state->master_irr;
227 } else if ((state->master_ocw3 & 0x03) == 0x03) {
228 *(char *)dst = state->master_isr;
236 int read_master_port2(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
237 struct pic_internal * state = (struct pic_internal*)dev->private_data;
242 *(char *)dst = state->master_imr;
248 int read_slave_port1(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
249 struct pic_internal * state = (struct pic_internal*)dev->private_data;
254 if ((state->slave_ocw3 & 0x03) == 0x02) {
255 *(char*)dst = state->slave_irr;
256 } else if ((state->slave_ocw3 & 0x03) == 0x03) {
257 *(char *)dst = state->slave_isr;
265 int read_slave_port2(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
266 struct pic_internal * state = (struct pic_internal*)dev->private_data;
271 *(char *)dst = state->slave_imr;
277 int write_master_port1(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
278 struct pic_internal * state = (struct pic_internal*)dev->private_data;
279 char cw = *(char *)src;
285 if (state->master_state == ICW1) {
286 state->master_icw1 = cw;
287 state->master_state = ICW2;
289 } else if (state->master_state == READY) {
291 // handle the EOI here
292 struct ocw2 * cw2 = (struct ocw2*)&cw;
295 if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
297 state->master_isr &= ~(0x01 << cw2->level);
298 } else if ((cw2->EOI) & (!cw2->R) && (!cw2->SL)) {
301 PrintDebug("Pre ISR = %x\n", state->master_isr);
302 for (i = 0; i < 8; i++) {
303 if (state->master_isr & (0x01 << i)) {
304 state->master_isr &= ~(0x01 << i);
308 PrintDebug("Post ISR = %x\n", state->master_isr);
313 state->master_ocw2 = cw;
314 } else if (IS_OCW3(cw)) {
315 state->master_ocw3 = cw;
326 int write_master_port2(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
327 struct pic_internal * state = (struct pic_internal*)dev->private_data;
328 char cw = *(char *)src;
334 if (state->master_state == ICW2) {
335 struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
337 PrintDebug("Setting ICW2 = %x\n", cw);
338 state->master_icw2 = cw;
340 if (cw1->sngl == 0) {
341 state->master_state = ICW3;
342 } else if (cw1->ic4 == 1) {
343 state->master_state = ICW4;
345 state->master_state = READY;
348 } else if (state->master_state == ICW3) {
349 struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
351 state->master_icw3 = cw;
354 state->master_state = ICW4;
356 state->master_state = READY;
359 } else if (state->master_state == ICW4) {
360 state->master_icw4 = cw;
361 state->master_state = READY;
362 } else if (state->master_state == READY) {
363 state->master_imr = cw;
371 int write_slave_port1(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
372 struct pic_internal * state = (struct pic_internal*)dev->private_data;
373 char cw = *(char *)src;
379 if (state->slave_state == ICW1) {
380 state->slave_icw1 = cw;
381 state->slave_state = ICW2;
382 } else if (state->slave_state == READY) {
384 // handle the EOI here
385 struct ocw2 * cw2 = (struct ocw2 *)&cw;
387 if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
389 state->slave_isr &= ~(0x01 << cw2->level);
390 } else if ((cw2->EOI) & (!cw2->R) && (!cw2->SL)) {
393 PrintDebug("Pre ISR = %x\n", state->slave_isr);
394 for (i = 0; i < 8; i++) {
395 if (state->slave_isr & (0x01 << i)) {
396 state->slave_isr &= ~(0x01 << i);
400 PrintDebug("Post ISR = %x\n", state->slave_isr);
405 state->slave_ocw2 = cw;
406 } else if (IS_OCW3(cw)) {
407 // Basically sets the IRR/ISR read flag
408 state->slave_ocw3 = cw;
419 int write_slave_port2(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
420 struct pic_internal * state = (struct pic_internal*)dev->private_data;
421 char cw = *(char *)src;
427 if (state->slave_state == ICW2) {
428 struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
430 state->slave_icw2 = cw;
432 if (cw1->sngl == 0) {
433 state->slave_state = ICW3;
434 } else if (cw1->ic4 == 1) {
435 state->slave_state = ICW4;
437 state->slave_state = READY;
440 } else if (state->slave_state == ICW3) {
441 struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
443 state->slave_icw3 = cw;
446 state->slave_state = ICW4;
448 state->slave_state = READY;
451 } else if (state->slave_state == ICW4) {
452 state->slave_icw4 = cw;
453 state->slave_state = READY;
454 } else if (state->slave_state == READY) {
455 state->slave_imr = cw;
470 int pic_init(struct vm_device * dev) {
471 struct pic_internal * state = (struct pic_internal*)dev->private_data;
473 set_intr_controller(dev->vm, &intr_ops, state);
475 state->master_irr = 0;
476 state->master_isr = 0;
477 state->master_icw1 = 0;
478 state->master_icw2 = 0;
479 state->master_icw3 = 0;
480 state->master_icw4 = 0;
481 state->master_imr = 0;
482 state->master_ocw2 = 0;
483 state->master_ocw3 = 0x02;
484 state->master_state = ICW1;
487 state->slave_irr = 0;
488 state->slave_isr = 0;
489 state->slave_icw1 = 0;
490 state->slave_icw2 = 0;
491 state->slave_icw3 = 0;
492 state->slave_icw4 = 0;
493 state->slave_imr = 0;
494 state->slave_ocw2 = 0;
495 state->slave_ocw3 = 0x02;
496 state->slave_state = ICW1;
499 dev_hook_io(dev, MASTER_PORT1, &read_master_port1, &write_master_port1);
500 dev_hook_io(dev, MASTER_PORT2, &read_master_port2, &write_master_port2);
501 dev_hook_io(dev, SLAVE_PORT1, &read_slave_port1, &write_slave_port1);
502 dev_hook_io(dev, SLAVE_PORT2, &read_slave_port2, &write_slave_port2);
508 int pic_deinit(struct vm_device * dev) {
509 dev_unhook_io(dev, MASTER_PORT1);
510 dev_unhook_io(dev, MASTER_PORT2);
511 dev_unhook_io(dev, SLAVE_PORT1);
512 dev_unhook_io(dev, SLAVE_PORT2);
523 static struct vm_device_ops dev_ops = {
525 .deinit = pic_deinit,
532 struct vm_device * create_pic() {
533 struct pic_internal * state = NULL;
534 V3_Malloc(struct pic_internal *, state, sizeof(struct pic_internal));
536 struct vm_device *device = create_device("8259A", &dev_ops, state);