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;
133 state->master_irr |= 0x1 << irq;
134 } else if ((irq > 7) && (irq < 16)) {
135 state->slave_irr |= 0x1 << (irq - 7);
143 static int pic_intr_pending(void * private_data) {
144 struct pic_internal * state = (struct pic_internal*)private_data;
146 if ((state->master_irr & ~(state->master_imr)) ||
147 (state->slave_irr & ~(state->slave_imr))) {
154 static int pic_get_intr_number(void * private_data) {
155 struct pic_internal * state = (struct pic_internal*)private_data;
158 for (i = 0; i < 16; i++) {
160 if (((state->master_irr & ~(state->master_imr)) >> i) == 0x1) {
164 if (((state->slave_irr & ~(state->slave_imr)) >> i) == 0x1) {
174 static struct intr_ctrl_ops intr_ops = {
175 .intr_pending = pic_intr_pending,
176 .get_intr_number = pic_get_intr_number,
177 .raise_intr = pic_raise_intr
186 int read_master_port1(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
187 struct pic_internal * state = (struct pic_internal*)dev->private_data;
192 if ((state->master_ocw3 & 0x3) == 0x2) {
193 *(char *)dst = state->master_irr;
194 } else if ((state->master_ocw3 & 0x3) == 0x3) {
195 *(char *)dst = state->master_isr;
203 int read_master_port2(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
204 struct pic_internal * state = (struct pic_internal*)dev->private_data;
209 *(char *)dst = state->master_imr;
215 int read_slave_port1(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
216 struct pic_internal * state = (struct pic_internal*)dev->private_data;
221 if ((state->slave_ocw3 & 0x3) == 0x2) {
222 *(char*)dst = state->slave_irr;
223 } else if ((state->slave_ocw3 & 0x3) == 0x3) {
224 *(char *)dst = state->slave_isr;
232 int read_slave_port2(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
233 struct pic_internal * state = (struct pic_internal*)dev->private_data;
238 *(char *)dst = state->slave_imr;
244 int write_master_port1(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
245 struct pic_internal * state = (struct pic_internal*)dev->private_data;
246 char cw = *(char *)src;
252 if (state->master_state == ICW1) {
253 state->master_icw1 = cw;
254 state->master_state = ICW2;
255 } else if (state->master_state == READY) {
257 state->master_ocw2 = cw;
258 } else if (IS_OCW3(cw)) {
259 state->master_ocw3 = cw;
270 int write_master_port2(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
271 struct pic_internal * state = (struct pic_internal*)dev->private_data;
272 char cw = *(char *)src;
278 if (state->master_state == ICW2) {
279 struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
281 state->master_icw2 = cw;
283 if (cw1->sngl == 0) {
284 state->master_state = ICW3;
285 } else if (cw1->ic4 == 1) {
286 state->master_state = ICW4;
288 state->master_state = READY;
291 } else if (state->master_state == ICW3) {
292 struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
294 state->master_icw3 = cw;
297 state->master_state = ICW4;
299 state->master_state = READY;
302 } else if (state->master_state == ICW4) {
303 state->master_icw4 = cw;
304 state->master_state = READY;
305 } else if (state->master_state == READY) {
306 state->master_imr = cw;
314 int write_slave_port1(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
315 struct pic_internal * state = (struct pic_internal*)dev->private_data;
316 char cw = *(char *)src;
322 if (state->slave_state == ICW1) {
323 state->slave_icw1 = cw;
324 state->slave_state = ICW2;
325 } else if (state->slave_state == READY) {
327 state->slave_ocw2 = cw;
328 } else if (IS_OCW3(cw)) {
329 state->slave_ocw3 = cw;
340 int write_slave_port2(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
341 struct pic_internal * state = (struct pic_internal*)dev->private_data;
342 char cw = *(char *)src;
348 if (state->slave_state == ICW2) {
349 struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
351 state->slave_icw2 = cw;
353 if (cw1->sngl == 0) {
354 state->slave_state = ICW3;
355 } else if (cw1->ic4 == 1) {
356 state->slave_state = ICW4;
358 state->slave_state = READY;
361 } else if (state->slave_state == ICW3) {
362 struct icw1 * cw1 = (struct icw1 *)&(state->master_icw1);
364 state->slave_icw3 = cw;
367 state->slave_state = ICW4;
369 state->slave_state = READY;
372 } else if (state->slave_state == ICW4) {
373 state->slave_icw4 = cw;
374 state->slave_state = READY;
375 } else if (state->slave_state == READY) {
376 state->slave_imr = cw;
391 int pic_init(struct vm_device * dev) {
392 struct pic_internal * state = (struct pic_internal*)dev->private_data;
394 set_intr_controller(dev->vm, &intr_ops, state);
396 state->master_irr = 0;
397 state->master_isr = 0;
398 state->master_icw1 = 0;
399 state->master_icw2 = 0;
400 state->master_icw3 = 0;
401 state->master_icw4 = 0;
402 state->master_imr = 0;
403 state->master_ocw2 = 0;
404 state->master_ocw3 = 0x2;
405 state->master_state = ICW1;
408 state->slave_irr = 0;
409 state->slave_isr = 0;
410 state->slave_icw1 = 0;
411 state->slave_icw2 = 0;
412 state->slave_icw3 = 0;
413 state->slave_icw4 = 0;
414 state->slave_imr = 0;
415 state->slave_ocw2 = 0;
416 state->slave_ocw3 = 0x2;
417 state->slave_state = ICW1;
420 dev_hook_io(dev, MASTER_PORT1, &read_master_port1, &write_master_port1);
421 dev_hook_io(dev, MASTER_PORT2, &read_master_port2, &write_master_port2);
422 dev_hook_io(dev, SLAVE_PORT1, &read_slave_port1, &write_slave_port1);
423 dev_hook_io(dev, SLAVE_PORT2, &read_slave_port2, &write_slave_port2);
429 int pic_deinit(struct vm_device * dev) {
430 dev_unhook_io(dev, MASTER_PORT1);
431 dev_unhook_io(dev, MASTER_PORT2);
432 dev_unhook_io(dev, SLAVE_PORT1);
433 dev_unhook_io(dev, SLAVE_PORT2);
444 static struct vm_device_ops dev_ops = {
446 .deinit = pic_deinit,
453 struct vm_device * create_pic() {
454 struct pic_internal * state = NULL;
455 VMMMalloc(struct pic_internal *, state, sizeof(struct pic_internal));
457 struct vm_device *device = create_device("8259A", &dev_ops, state);