--- trunk/src/devices/dev_8259.c 2007/10/08 16:19:16 19 +++ trunk/src/devices/dev_8259.c 2007/10/08 16:19:23 20 @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * - * $Id: dev_8259.c,v 1.15 2005/10/26 14:37:03 debug Exp $ + * $Id: dev_8259.c,v 1.22 2005/11/23 18:16:42 debug Exp $ * * 8259 Programmable Interrupt Controller. * @@ -100,62 +100,42 @@ " it was aborted? ]\n"); d->init_state = 0; - switch (idata) { - case 0x0a: + if (idata == 0x0a) { d->current_command = 0x0a; - break; - case 0x0b: + } else if (idata == 0x0b) { d->current_command = 0x0b; - break; - case 0x0c: + } else if (idata == 0x0c) { /* Put Master in Buffered Mode */ d->current_command = 0x0c; - break; - case 0x20: /* End Of Interrupt */ - /* - * TODO: in buffered mode, is this an EOI 0? - */ + } else if (idata == 0x20) { + int old_irr = d->irr; + /* End Of Interrupt */ + /* TODO: in buffered mode, is this an EOI 0? */ d->irr &= ~d->isr; d->isr = 0; - /* Recalculate interrupt assertions: */ - cpu_interrupt(cpu, d->irq_nr); - break; - case 0x21: /* Specific EOI */ - case 0x22: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: /* Specific EOI */ + /* Recalculate interrupt assertions, + if necessary: */ + if ((old_irr & ~d->ier) != (d->irr & ~d->ier)) + cpu_interrupt(cpu, d->irq_nr); + } else if ((idata >= 0x21 && idata <= 0x27) || + (idata >= 0x60 && idata <= 0x67) || + (idata >= 0xe0 && idata <= 0xe7)) { + /* Specific EOI */ + int old_irr = d->irr; d->irr &= ~(1 << (idata & 7)); d->isr &= ~(1 << (idata & 7)); - /* Recalculate interrupt assertions: */ - cpu_interrupt(cpu, d->irq_nr); - break; - case 0x68: /* Set Special Mask Mode */ + /* Recalc. int assertions, if necessary: */ + if ((old_irr & ~d->ier) != (d->irr & ~d->ier)) + cpu_interrupt(cpu, d->irq_nr); + } else if (idata == 0x68) { + /* Set Special Mask Mode */ /* TODO */ - break; - case 0xc0: - case 0xc1: - case 0xc2: - case 0xc3: - case 0xc4: - case 0xc5: - case 0xc6: - case 0xc7: /* Set IRQ Priority Order */ + } else if (idata >= 0xc0 && idata <= 0xc7) { + /* Set IRQ Priority Order */ /* TODO */ - break; - default: + } else { fatal("[ 8259: unimplemented command 0x%02x" - " ]\n", idata); + " ]\n", (int)idata); cpu->running = 0; } } else { @@ -168,6 +148,13 @@ break; case 0x0c: /* Buffered mode. */ + odata = 0x00; + for (i=0; i<8; i++) + if ((d->irr >> i) & 1) { + odata = 0x80 | i; + break; + } + break; default: odata = 0x00; for (i=0; i<8; i++) @@ -205,9 +192,12 @@ /* Slave attachment. TODO */ d->init_state = 3; } else if (d->init_state == 3) { - if (idata & 0x02) - fatal("[ 8259: WARNING! Bit 1 i" + if (idata & 0x02) { + /* Should not be set in PCs, but + on CATS, for example, it is set. */ + debug("[ 8259: WARNING! Bit 1 i" "n Init Cmd 4 is set! ]\n"); + } if (!(idata & 0x01)) fatal("[ 8259: WARNING! Bit 0 " "in Init Cmd 4 is not" @@ -218,9 +208,13 @@ } if (writeflag == MEM_WRITE) { + int old_ier = d->ier; d->ier = idata; - /* Recalculate interrupt assertions: */ - cpu_interrupt(cpu, d->irq_nr); + + /* Recalculate interrupt assertions, + if necessary: */ + if ((d->irr & ~old_ier) != (d->irr & ~d->ier)) + cpu_interrupt(cpu, d->irq_nr); } else { odata = d->ier; } @@ -279,7 +273,7 @@ memory_device_register(devinit->machine->memory, name2, devinit->addr, DEV_8259_LENGTH, dev_8259_access, d, - MEM_DEFAULT, NULL); + DM_DEFAULT, NULL); devinit->return_ptr = d; return 1;