+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+
#include <devices/8259a.h>
#include <palacios/vmm_intr.h>
#include <palacios/vmm_types.h>
#define PrintDebug(fmt, args...)
#endif
+
typedef enum {RESET, ICW1, ICW2, ICW3, ICW4, READY} pic_state_t;
static const uint_t MASTER_PORT1 = 0x20;
return 0;
}
+
+static int pic_lower_intr(void *private_data, int irq) {
+
+ struct pic_internal *state = (struct pic_internal*)private_data;
+
+ PrintDebug("[pic_lower_intr] IRQ line %d now low\n", irq);
+ if (irq <= 7) {
+
+ state->master_irr &= ~(1 << irq);
+ if ((state->master_irr & ~(state->master_imr)) == 0) {
+ PrintDebug("\t\tFIXME: Master maybe should do sth\n");
+ }
+ } else if ((irq > 7) && (irq < 16)) {
+
+ state->slave_irr &= ~(1 << (irq - 8));
+ if ((state->slave_irr & (~(state->slave_imr))) == 0) {
+ PrintDebug("\t\tFIXME: Slave maybe should do sth\n");
+ }
+ }
+ return 0;
+}
+
+
+
static int pic_intr_pending(void * private_data) {
struct pic_internal * state = (struct pic_internal*)private_data;
}
static int pic_get_intr_number(void * private_data) {
- struct pic_internal * state = (struct pic_internal*)private_data;
- int i=0;
- int irq=-1;
+ struct pic_internal * state = (struct pic_internal *)private_data;
+ int i = 0;
+ int irq = -1;
PrintDebug("8259 PIC: getnum: master_irr: 0x%x master_imr: 0x%x\n", i, state->master_irr, state->master_imr);
PrintDebug("8259 PIC: getnum: slave_irr: 0x%x slave_imr: 0x%x\n", i, state->slave_irr, state->slave_imr);
}
}
- if (i==15 || i==6) {
+ if ((i == 15) || (i == 6)) {
DumpPICState(state);
}
- if (i==16) {
+ if (i == 16) {
return -1;
} else {
return irq;
}
*/
+
+
static struct intr_ctrl_ops intr_ops = {
.intr_pending = pic_intr_pending,
.get_intr_number = pic_get_intr_number,
.raise_intr = pic_raise_intr,
.begin_irq = pic_begin_irq,
+ .lower_intr = pic_lower_intr,
+
};
-int read_master_port1(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
+static int read_master_port1(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
struct pic_internal * state = (struct pic_internal*)dev->private_data;
if (length != 1) {
return 1;
}
-int read_master_port2(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
+static int read_master_port2(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
struct pic_internal * state = (struct pic_internal*)dev->private_data;
if (length != 1) {
}
-int read_slave_port1(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
+static int read_slave_port1(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
struct pic_internal * state = (struct pic_internal*)dev->private_data;
if (length != 1) {
return 1;
}
-int read_slave_port2(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
+static int read_slave_port2(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
struct pic_internal * state = (struct pic_internal*)dev->private_data;
if (length != 1) {
}
-int write_master_port1(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
+static int write_master_port1(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
struct pic_internal * state = (struct pic_internal*)dev->private_data;
uchar_t cw = *(uchar_t *)src;
+ PrintDebug("8259 PIC: Write master port 1 with 0x%x\n",cw);
+
if (length != 1) {
PrintError("8259 PIC: Invalid Write length (wr_Master1)\n");
return -1;
}
if (IS_ICW1(cw)) {
+
+ PrintDebug("8259 PIC: Setting ICW1 = %x (wr_Master1)\n", cw);
+
state->master_icw1 = cw;
state->master_state = ICW2;
// handle the EOI here
struct ocw2 * cw2 = (struct ocw2*)&cw;
+ PrintDebug("8259 PIC: Handling OCW2 = %x (wr_Master1)\n", cw);
if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
// specific EOI;
state->master_ocw2 = cw;
} else if (IS_OCW3(cw)) {
+ PrintDebug("8259 PIC: Handling OCW3 = %x (wr_Master1)\n", cw);
state->master_ocw3 = cw;
} else {
PrintError("8259 PIC: Invalid OCW to PIC (wr_Master1)\n");
return 1;
}
-int write_master_port2(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
+static int write_master_port2(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
struct pic_internal * state = (struct pic_internal*)dev->private_data;
uchar_t cw = *(uchar_t *)src;
+ PrintDebug("8259 PIC: Write master port 2 with 0x%x\n",cw);
+
if (length != 1) {
PrintError("8259 PIC: Invalid Write length (wr_Master2)\n");
return -1;
} else if (state->master_state == ICW3) {
struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
+ PrintDebug("8259 PIC: Setting ICW3 = %x (wr_Master2)\n", cw);
+
state->master_icw3 = cw;
if (cw1->ic4 == 1) {
}
} else if (state->master_state == ICW4) {
+ PrintDebug("8259 PIC: Setting ICW4 = %x (wr_Master2)\n", cw);
state->master_icw4 = cw;
state->master_state = READY;
} else if (state->master_state == READY) {
+ PrintDebug("8259 PIC: Setting IMR = %x (wr_Master2)\n", cw);
state->master_imr = cw;
} else {
// error
return 1;
}
-int write_slave_port1(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
+static int write_slave_port1(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
struct pic_internal * state = (struct pic_internal*)dev->private_data;
uchar_t cw = *(uchar_t *)src;
+ PrintDebug("8259 PIC: Write slave port 1 with 0x%x\n",cw);
+
if (length != 1) {
// error
PrintError("8259 PIC: Invalid Write length (wr_Slave1)\n");
}
if (IS_ICW1(cw)) {
+ PrintDebug("8259 PIC: Setting ICW1 = %x (wr_Slave1)\n", cw);
state->slave_icw1 = cw;
state->slave_state = ICW2;
} else if (state->slave_state == READY) {
if (IS_OCW2(cw)) {
// handle the EOI here
struct ocw2 * cw2 = (struct ocw2 *)&cw;
+
+ PrintDebug("8259 PIC: Setting OCW2 = %x (wr_Slave1)\n", cw);
if ((cw2->EOI) && (!cw2->R) && (cw2->SL)) {
// specific EOI;
state->slave_ocw2 = cw;
} else if (IS_OCW3(cw)) {
// Basically sets the IRR/ISR read flag
+ PrintDebug("8259 PIC: Setting OCW3 = %x (wr_Slave1)\n", cw);
state->slave_ocw3 = cw;
} else {
PrintError("8259 PIC: Invalid command work (wr_Slave1)\n");
return 1;
}
-int write_slave_port2(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
+static int write_slave_port2(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
struct pic_internal * state = (struct pic_internal*)dev->private_data;
uchar_t cw = *(uchar_t *)src;
+ PrintDebug("8259 PIC: Write slave port 2 with 0x%x\n",cw);
+
if (length != 1) {
PrintError("8259 PIC: Invalid write length (wr_Slave2)\n");
return -1;
if (state->slave_state == ICW2) {
struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
+ PrintDebug("8259 PIC: Setting ICW2 = %x (wr_Slave2)\n", cw);
+
state->slave_icw2 = cw;
if (cw1->sngl == 0) {
} else if (state->slave_state == ICW3) {
struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
+ PrintDebug("8259 PIC: Setting ICW3 = %x (wr_Slave2)\n", cw);
+
state->slave_icw3 = cw;
if (cw1->ic4 == 1) {
}
} else if (state->slave_state == ICW4) {
+ PrintDebug("8259 PIC: Setting ICW4 = %x (wr_Slave2)\n", cw);
state->slave_icw4 = cw;
state->slave_state = READY;
} else if (state->slave_state == READY) {
+ PrintDebug("8259 PIC: Setting IMR = %x (wr_Slave2)\n", cw);
state->slave_imr = cw;
} else {
PrintError("8259 PIC: Invalid State at write (wr_Slave2)\n");
-int pic_init(struct vm_device * dev) {
+static int pic_init(struct vm_device * dev) {
struct pic_internal * state = (struct pic_internal*)dev->private_data;
- set_intr_controller(dev->vm, &intr_ops, state);
+ v3_set_intr_controller(dev->vm, &intr_ops, state);
state->master_irr = 0;
state->master_isr = 0;
state->slave_state = ICW1;
- dev_hook_io(dev, MASTER_PORT1, &read_master_port1, &write_master_port1);
- dev_hook_io(dev, MASTER_PORT2, &read_master_port2, &write_master_port2);
- dev_hook_io(dev, SLAVE_PORT1, &read_slave_port1, &write_slave_port1);
- dev_hook_io(dev, SLAVE_PORT2, &read_slave_port2, &write_slave_port2);
+ v3_dev_hook_io(dev, MASTER_PORT1, &read_master_port1, &write_master_port1);
+ v3_dev_hook_io(dev, MASTER_PORT2, &read_master_port2, &write_master_port2);
+ v3_dev_hook_io(dev, SLAVE_PORT1, &read_slave_port1, &write_slave_port1);
+ v3_dev_hook_io(dev, SLAVE_PORT2, &read_slave_port2, &write_slave_port2);
return 0;
}
-int pic_deinit(struct vm_device * dev) {
- dev_unhook_io(dev, MASTER_PORT1);
- dev_unhook_io(dev, MASTER_PORT2);
- dev_unhook_io(dev, SLAVE_PORT1);
- dev_unhook_io(dev, SLAVE_PORT2);
+static int pic_deinit(struct vm_device * dev) {
+ v3_dev_unhook_io(dev, MASTER_PORT1);
+ v3_dev_unhook_io(dev, MASTER_PORT2);
+ v3_dev_unhook_io(dev, SLAVE_PORT1);
+ v3_dev_unhook_io(dev, SLAVE_PORT2);
return 0;
}
};
-struct vm_device * create_pic() {
+struct vm_device * v3_create_pic() {
struct pic_internal * state = NULL;
state = (struct pic_internal *)V3_Malloc(sizeof(struct pic_internal));
V3_ASSERT(state != NULL);
- struct vm_device *device = create_device("8259A", &dev_ops, state);
+ struct vm_device *device = v3_create_device("8259A", &dev_ops, state);
return device;
}