diff --git a/src/sio/sio_pc87306.c b/src/sio/sio_pc87306.c index f9e066b1f..38e695727 100644 --- a/src/sio/sio_pc87306.c +++ b/src/sio/sio_pc87306.c @@ -38,6 +38,7 @@ typedef struct pc87306_t { uint8_t tries; + uint8_t cfg_lock; uint8_t regs[29]; uint8_t gpio[2]; uint16_t gpioba; @@ -125,6 +126,7 @@ lpt_handler(pc87306_t *dev) uint8_t lpt_irq = LPT2_IRQ; uint8_t cnfgb_readout = 0x08; + pclog("Removing LPT port...\n"); lpt_port_remove(dev->lpt); temp = dev->regs[0x01] & 3; @@ -155,6 +157,9 @@ lpt_handler(pc87306_t *dev) break; } + if (!(dev->regs[0x00] & 0x01)) + lpt_port = 0x000; + if (dev->regs[0x1b] & 0x10) lpt_irq = (dev->regs[0x1b] & 0x20) ? 7 : 5; @@ -167,8 +172,10 @@ lpt_handler(pc87306_t *dev) lpt_set_epp(dev->lpt, !!(dev->regs[0x04] & 0x01)); lpt_set_ecp(dev->lpt, !!(dev->regs[0x04] & 0x04)); - if (lpt_port) + if (lpt_port) { + pclog("Setting up LPT port at %04X...\n", lpt_port); lpt_port_setup(dev->lpt, lpt_port); + } lpt_port_irq(dev->lpt, lpt_irq); @@ -187,18 +194,20 @@ serial_handler(pc87306_t *dev, int uart) uint8_t pnp_shift; uint8_t irq; - temp = (dev->regs[0x01] >> (2 << uart)) & 3; + serial_remove(dev->uart[uart]); fer_shift = 2 << uart; /* 2 for UART 1, 4 for UART 2 */ pnp_shift = 2 + (uart << 2); /* 2 for UART 1, 6 for UART 2 */ + temp = (dev->regs[0x01] >> fer_shift) & 3; + /* 0 = COM1 (IRQ 4), 1 = COM2 (IRQ 3), 2 = COM3 (IRQ 4), 3 = COM4 (IRQ 3) */ fer_irq = ((dev->regs[1] >> fer_shift) & 1) ? 3 : 4; pnp1_irq = ((dev->regs[0x1c] >> pnp_shift) & 1) ? 4 : 3; irq = (dev->regs[0x1c] & 1) ? pnp1_irq : fer_irq; - switch (temp) { + if (dev->regs[0x00] & fer_shift) switch (temp) { case 0: serial_setup(dev->uart[uart], COM1_ADDR, irq); break; @@ -273,13 +282,15 @@ pc87306_write(uint16_t port, uint8_t val, void *priv) return; } else { if (dev->tries) { - if ((dev->cur_reg == 0) && (val == 8)) - val = 0x4b; + if (dev->cfg_lock) + return; + valxor = val ^ dev->regs[dev->cur_reg]; dev->tries = 0; - if ((dev->cur_reg <= 28) && (dev->cur_reg != 8)) { - if (dev->cur_reg == 0) - val &= 0x5f; + if ((dev->cur_reg <= 0x1c) && (dev->cur_reg != 0x08)) { + if ((dev->cur_reg == 0x00) && (val == 0x08)) + val = 0x4f; + dev->regs[dev->cur_reg] = val; } else return; @@ -291,21 +302,12 @@ pc87306_write(uint16_t port, uint8_t val, void *priv) switch (dev->cur_reg) { case 0x00: - if (valxor & 0x01) { - lpt_port_remove(dev->lpt); - if ((val & 1) && !(dev->regs[0x02] & 1)) - lpt_handler(dev); - } - if (valxor & 0x02) { - serial_remove(dev->uart[0x00]); - if ((val & 2) && !(dev->regs[0x02] & 1)) - serial_handler(dev, 0); - } - if (valxor & 0x04) { - serial_remove(dev->uart[0x01]); - if ((val & 4) && !(dev->regs[0x02] & 1)) - serial_handler(dev, 1); - } + if (valxor & 0x01) + lpt_handler(dev); + if (valxor & 0x02) + serial_handler(dev, 0); + if (valxor & 0x04) + serial_handler(dev, 1); if (valxor & 0x28) { fdc_remove(dev->fdc); if ((val & 8) && !(dev->regs[0x02] & 1)) @@ -313,52 +315,24 @@ pc87306_write(uint16_t port, uint8_t val, void *priv) } break; case 0x01: - if (valxor & 0x03) { - lpt_port_remove(dev->lpt); - if ((dev->regs[0x00] & 1) && !(dev->regs[0x02] & 1)) - lpt_handler(dev); - } - if (valxor & 0xcc) { - serial_remove(dev->uart[0x00]); - if ((dev->regs[0x00] & 2) && !(dev->regs[0x02] & 1)) - serial_handler(dev, 0); - } - if (valxor & 0xf0) { - serial_remove(dev->uart[0x01]); - if ((dev->regs[0x00] & 4) && !(dev->regs[0x02] & 1)) - serial_handler(dev, 1); - } + if (valxor & 0x03) + lpt_handler(dev); + if (valxor & 0xcc) + serial_handler(dev, 0); + if (valxor & 0xf0) + serial_handler(dev, 1); break; case 0x02: - if (valxor & 0x01) { - lpt_port_remove(dev->lpt); - serial_remove(dev->uart[0x00]); - serial_remove(dev->uart[0x01]); - fdc_remove(dev->fdc); - - if (!(val & 1)) { - if (dev->regs[0x00] & 0x01) - lpt_handler(dev); - if (dev->regs[0x00] & 0x02) - serial_handler(dev, 0); - if (dev->regs[0x00] & 0x04) - serial_handler(dev, 1); - if (dev->regs[0x00] & 0x08) - fdc_set_base(dev->fdc, (dev->regs[0x00] & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); - } - } - if (valxor & 0x88) { - lpt_port_remove(dev->lpt); - if ((dev->regs[0x00] & 1) && !(dev->regs[0x02] & 1)) - lpt_handler(dev); - } + if (valxor & 0x01) + fdc_set_power_down(dev->fdc, val & 0x01); + if (valxor & 0x40) + dev->cfg_lock = val & 0x40; + if (valxor & 0x88) + lpt_handler(dev); break; case 0x04: - if (valxor & (0x05)) { - lpt_port_remove(dev->lpt); - if ((dev->regs[0x00] & 0x01) && !(dev->regs[0x02] & 0x01)) - lpt_handler(dev); - } + if (valxor & (0x05)) + lpt_handler(dev); if (valxor & 0x80) nvr_lock_set(0x00, 256, !!(val & 0x80), dev->nvr); break; @@ -389,37 +363,24 @@ pc87306_write(uint16_t port, uint8_t val, void *priv) pc87306_gpio_handler(dev); break; case 0x18: - if (valxor & (0x0e)) { - lpt_port_remove(dev->lpt); - if ((dev->regs[0x00] & 0x01) && !(dev->regs[0x02] & 0x01)) - lpt_handler(dev); - } + if (valxor & (0x0e)) + lpt_handler(dev); break; case 0x19: - if (valxor) { - lpt_port_remove(dev->lpt); - if ((dev->regs[0x00] & 1) && !(dev->regs[0x02] & 1)) - lpt_handler(dev); - } + if (valxor) + lpt_handler(dev); break; case 0x1b: if (valxor & 0x70) { - lpt_port_remove(dev->lpt); if (!(val & 0x40)) dev->regs[0x19] = 0xef; - if ((dev->regs[0x00] & 1) && !(dev->regs[0x02] & 1)) - lpt_handler(dev); + lpt_handler(dev); } break; case 0x1c: if (valxor) { - serial_remove(dev->uart[0x00]); - serial_remove(dev->uart[0x01]); - - if ((dev->regs[0x00] & 2) && !(dev->regs[0x02] & 1)) - serial_handler(dev, 0); - if ((dev->regs[0x00] & 4) && !(dev->regs[0x02] & 1)) - serial_handler(dev, 1); + serial_handler(dev, 0); + serial_handler(dev, 1); } break; @@ -437,15 +398,17 @@ pc87306_read(uint16_t port, void *priv) index = (port & 1) ? 0 : 1; - if (dev->tries == 0xff) { - ret = 0x88; - dev->tries = 0xfe; - } else if (dev->tries == 0xfe) { - ret = 0x00; - dev->tries = 0; - } else if (index) { - ret = dev->cur_reg & 0x1f; - dev->tries = 0; + if (index) { + if (dev->tries == 0xff) { + ret = 0x88; + dev->tries = 0xfe; + } else if (dev->tries == 0xfe) { + ret = 0x00; + dev->tries = 0; + } else { + ret = dev->cur_reg & 0x1f; + dev->tries = 0; + } } else { if (dev->cur_reg == 8) ret = 0x70; @@ -462,30 +425,27 @@ pc87306_reset_common(void *priv) { pc87306_t *dev = (pc87306_t *) priv; - memset(dev->regs, 0, 29); - + memset(dev->regs, 0x00, 29); dev->tries = 0xff; - dev->regs[0x00] = 0x0B; - dev->regs[0x01] = 0x01; + dev->regs[0x00] = 0x00; + dev->regs[0x01] = 0x10; + dev->regs[0x02] = 0x08; dev->regs[0x03] = 0x01; - dev->regs[0x05] = 0x0D; + dev->regs[0x05] = 0x0d; dev->regs[0x08] = 0x70; - dev->regs[0x09] = 0xC0; + dev->regs[0x09] = 0xc0; dev->regs[0x0b] = 0x80; - dev->regs[0x0f] = 0x1E; + dev->regs[0x0f] = 0x1e; dev->regs[0x12] = 0x30; - dev->regs[0x19] = 0xEF; + dev->regs[0x19] = 0xef; /* 0 = 360 rpm @ 500 kbps for 3.5" 1 = Default, 300 rpm @ 500, 300, 250, 1000 kbps for 3.5" */ lpt_set_cnfga_readout(dev->lpt, 0x10); - lpt_port_remove(dev->lpt); lpt_handler(dev); - serial_remove(dev->uart[0x00]); - serial_remove(dev->uart[0x01]); serial_handler(dev, 0); serial_handler(dev, 1); fdc_reset(dev->fdc); @@ -495,6 +455,8 @@ pc87306_reset_common(void *priv) nvr_at_handler(1, 0x0070, dev->nvr); nvr_bank_set(0, 0, dev->nvr); nvr_wp_set(0, 0, dev->nvr); + + dev->cfg_lock = 0; } void