diff --git a/src/intel_piix.c b/src/intel_piix.c index 08c71a6a5..4fc3ac0d6 100644 --- a/src/intel_piix.c +++ b/src/intel_piix.c @@ -10,13 +10,13 @@ * word 0 - base address * word 1 - bits 1-15 = byte count, bit 31 = end of transfer * - * Version: @(#)intel_piix.c 1.0.10 2017/12/15 + * Version: @(#)intel_piix.c 1.0.11 2018/02/01 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -104,11 +104,10 @@ void piix_write(int func, int addr, uint8_t val, void *priv) if (addr == 4 || (addr & ~3) == 0x20) /*Bus master base address*/ { uint16_t base = (card_piix_ide[0x20] & 0xf0) | (card_piix_ide[0x21] << 8); - io_removehandler(old_base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL); - if (card_piix_ide[0x04] & 1) - { + if (old_base) + io_removehandler(old_base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL); + if ((card_piix_ide[0x04] & 1) && base) io_sethandler(base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL); - } } } else @@ -638,8 +637,17 @@ void piix_bus_master_set_irq(int channel) } +static void piix_bus_master_reset(void) +{ + uint16_t old_base = (card_piix_ide[0x20] & 0xf0) | (card_piix_ide[0x21] << 8); + if (old_base) + io_removehandler(old_base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL); +} + + void piix_reset(void) { + piix_bus_master_reset(); memset(card_piix, 0, 256); card_piix[0x00] = 0x86; card_piix[0x01] = 0x80; /*Intel*/ card_piix[0x02] = 0x2e; card_piix[0x03] = 0x12; /*82371FB (PIIX)*/ @@ -681,6 +689,7 @@ void piix_reset(void) void piix3_reset(void) { + piix_bus_master_reset(); memset(card_piix, 0, 256); card_piix[0x00] = 0x86; card_piix[0x01] = 0x80; /*Intel*/ card_piix[0x02] = 0x00; card_piix[0x03] = 0x70; /*82371SB (PIIX3)*/ diff --git a/src/io.c b/src/io.c index 050733261..4fee6cdbd 100644 --- a/src/io.c +++ b/src/io.c @@ -8,17 +8,18 @@ * * Implement I/O ports and their operations. * - * Version: @(#)io.c 1.0.1 2017/12/16 + * Version: @(#)io.c 1.0.2 2018/02/01 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include +#include #include #include #include "86box.h" @@ -29,36 +30,22 @@ #define NPORTS 65536 /* PC/AT supports 64K ports */ -/* - * This should be redone using a - * - * typedef struct _io_ { - * uint8_t (*inb)(uint16_t addr, void *priv); - * uint16_t (*inw)(uint16_t addr, void *priv); - * uint32_t (*inl)(uint16_t addr, void *priv); - * - * void (*outb)(uint16_t addr, uint8_t val, void *priv); - * void (*outw)(uint16_t addr, uint16_t val, void *priv); - * void (*outl)(uint16_t addr, uint32_t val, void *priv); - * - * void *priv; - * - * struct _io_ *next; - * } io_t; - * - * at some point. We keep one base entry per I/O port, and if - * more than one entry is needed (some ports are like that), - * we just add a handler to the list for that port. - */ -static uint8_t (*port_inb[NPORTS][2])(uint16_t addr, void *priv); -static uint16_t (*port_inw[NPORTS][2])(uint16_t addr, void *priv); -static uint32_t (*port_inl[NPORTS][2])(uint16_t addr, void *priv); +typedef struct _io_ { + uint8_t (*inb)(uint16_t addr, void *priv); + uint16_t (*inw)(uint16_t addr, void *priv); + uint32_t (*inl)(uint16_t addr, void *priv); -static void (*port_outb[NPORTS][2])(uint16_t addr, uint8_t val, void *priv); -static void (*port_outw[NPORTS][2])(uint16_t addr, uint16_t val, void *priv); -static void (*port_outl[NPORTS][2])(uint16_t addr, uint32_t val, void *priv); + void (*outb)(uint16_t addr, uint8_t val, void *priv); + void (*outw)(uint16_t addr, uint16_t val, void *priv); + void (*outl)(uint16_t addr, uint32_t val, void *priv); -static void *port_priv[NPORTS][2]; + void *priv; + + struct _io_ *prev, *next; +} io_t; + +int initialized = 0; +io_t *io[NPORTS], *io_last[NPORTS]; #ifdef IO_CATCH @@ -75,25 +62,45 @@ void io_init(void) { int c; + io_t *p, *q; + + if (!initialized) { + for (c=0; cprev; + free(p); + p = q; + } + p = NULL; + } + #ifdef IO_CATCH - port_inb[c][0] = port_inb[c][1] = null_inb; - port_outb[c][0] = port_outb[c][1] = null_outb; - port_inw[c][0] = port_inw[c][1] = null_inw; - port_outw[c][0] = port_outw[c][1] = null_outw; - port_inl[c][0] = port_inl[c][1] = null_inl; - port_outl[c][0] = port_outl[c][1] = null_outl; + /* io[c] should be the only handler, pointing at the NULL catch handler. */ + p = (io_t *) malloc(sizeof(io_t)); + memset(p, 0, sizeof(io_t)); + io[c] = p; + p->next = NULL; + p->prev = NULL; + p->inb = null_inb; + p->outb = null_outb; + p->inw = null_inw; + p->outw = null_outw; + p->inl = null_inl; + p->outl = null_outl; + p->priv = NULL; #else - port_inb[c][0] = port_inb[c][1] = NULL; - port_outb[c][0] = port_outb[c][1] = NULL; - port_inw[c][0] = port_inw[c][1] = NULL; - port_outw[c][0] = port_outw[c][1] = NULL; - port_inl[c][0] = port_inl[c][1] = NULL; - port_outl[c][0] = port_outl[c][1] = NULL; + /* io[c] should be NULL. */ + io[c] = NULL; #endif - port_priv[c][0] = port_priv[c][1] = NULL; } } @@ -109,33 +116,32 @@ io_sethandler(uint16_t base, int size, void *priv) { int c; + io_t *p, *q = NULL; - for (c=0; cnext = q; + q->prev = p; + } else { + io[base + c] = q; + q->prev = NULL; } + + q->inb = inb; + q->inw = inw; + q->inl = inl; + + q->outb = outb; + q->outw = outw; + q->outl = outl; + + q->priv = priv; + q->next = NULL; + + io_last[base + c] = q; } } @@ -151,37 +157,30 @@ io_removehandler(uint16_t base, int size, void *priv) { int c; + io_t *p; - for (c=0; cinb == inb) && (p->inw == inw) && + (p->inl == inl) && (p->outb == outb) && + (p->outw == outw) && (p->outl == outl) && + (p->priv == priv)) { + if (p->prev) + p->prev->next = p->next; + else + io[base + c] = p->next; + if (p->next) + p->next->prev = p->prev; + else + io_last[base + c] = p->prev; + free(p); + p = NULL; + break; + } + p = p->next; } } } @@ -199,32 +198,30 @@ io_sethandler_interleaved(uint16_t base, int size, void *priv) { int c; + io_t *p, *q; size <<= 2; for (c=0; cnext = q; + q->prev = p; + } else { + io[base + c] = q; + q->prev = NULL; } + + q->inb = inb; + q->inw = inw; + q->inl = inl; + + q->outb = outb; + q->outw = outw; + q->outl = outl; + + q->priv = priv; } } @@ -240,38 +237,26 @@ io_removehandler_interleaved(uint16_t base, int size, void *priv) { int c; + io_t *p; size <<= 2; - for (c=0; cinb == inb) && (p->inw == inw) && + (p->inl == inl) && (p->outb == outb) && + (p->outw == outw) && (p->outl == outl) && + (p->priv == priv)) { + if (p->prev) + p->prev->next = p->next; + if (p->next) + p->next->prev = p->prev; + free(p); + break; + } + p = p->next; } } } @@ -282,11 +267,16 @@ uint8_t inb(uint16_t port) { uint8_t r = 0xff; + io_t *p; - if (port_inb[port][0]) - r &= port_inb[port][0](port, port_priv[port][0]); - if (port_inb[port][1]) - r &= port_inb[port][1](port, port_priv[port][1]); + p = io[port]; + if (p) { + while(p) { + if (p->inb) + r &= p->inb(port, p->priv); + p = p->next; + } + } #ifdef IO_TRACE if (CS == IO_TRACE) @@ -300,25 +290,38 @@ inb(uint16_t port) void outb(uint16_t port, uint8_t val) { - if (port_outb[port][0]) - port_outb[port][0](port, val, port_priv[port][0]); - if (port_outb[port][1]) - port_outb[port][1](port, val, port_priv[port][1]); + io_t *p; + + if (io[port]) { + p = io[port]; + while(p) { + if (p->outb) + p->outb(port, val, p->priv); + p = p->next; + } + } #ifdef IO_TRACE if (CS == IO_TRACE) pclog("IOTRACE(%04X): outb(%04x,%02x)\n", IO_TRACE, port, val); #endif + return; } uint16_t inw(uint16_t port) { - if (port_inw[port][0]) - return(port_inw[port][0](port, port_priv[port][0])); - if (port_inw[port][1]) - return(port_inw[port][1](port, port_priv[port][1])); + io_t *p; + + p = io[port]; + if (p) { + while(p) { + if (p->inw) + return p->inw(port, p->priv); + p = p->next; + } + } return(inb(port) | (inb(port + 1) << 8)); } @@ -327,27 +330,39 @@ inw(uint16_t port) void outw(uint16_t port, uint16_t val) { - if (port_outw[port][0]) { - port_outw[port][0](port, val, port_priv[port][0]); - return; - } - if (port_outw[port][1]) { - port_outw[port][1](port, val, port_priv[port][1]); - return; + io_t *p; + + p = io[port]; + if (p) { + while(p) { + if (p->outw) { + p->outw(port, val, p->priv); + return; + } + p = p->next; + } } outb(port,val); outb(port+1,val>>8); + + return; } uint32_t inl(uint16_t port) { - if (port_inl[port][0]) - return(port_inl[port][0](port, port_priv[port][0])); - if (port_inl[port][1]) - return(port_inl[port][1](port, port_priv[port][1])); + io_t *p; + + p = io[port]; + if (p) { + while(p) { + if (p->inl) + return p->inl(port, p->priv); + p = p->next; + } + } return(inw(port) | (inw(port + 2) << 16)); } @@ -356,15 +371,21 @@ inl(uint16_t port) void outl(uint16_t port, uint32_t val) { - if (port_outl[port][0]) { - port_outl[port][0](port, val, port_priv[port][0]); - return; - } - if (port_outl[port][1]) { - port_outl[port][1](port, val, port_priv[port][1]); - return; + io_t *p; + + p = io[port]; + if (p) { + while(p) { + if (p->outl) { + p->outl(port, val, p->priv); + return; + } + p = p->next; + } } outw(port, val); outw(port + 2, val >> 16); + + return; } diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index 4049f9dc7..a1524bf0d 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -14,7 +14,7 @@ * * NOTE: The file will also implement an NE1000 for 8-bit ISA systems. * - * Version: @(#)net_ne2000.c 1.0.28 2018/01/28 + * Version: @(#)net_ne2000.c 1.0.29 2018/02/01 * * Authors: Fred N. van Kempen, * Peter Grehan, @@ -26,7 +26,7 @@ * * Portions Copyright (C) 2002 MandrakeSoft S.A. * Portions Copyright (C) 2018 Sarah Walker. - * Copyright 2018 Fred N. van Kempen. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include @@ -1764,9 +1764,6 @@ nic_pnp_writeb(uint16_t addr, uint8_t val, void *priv) static void nic_pnp_io_set(nic_t *dev, uint16_t read_addr) { - io_sethandler(0x0A79, 1, - NULL, NULL, NULL, - nic_pnp_writeb, NULL, NULL, dev); if ((read_addr >= 0x0200) && (read_addr <= 0x03FF)) { io_sethandler(read_addr, 1, nic_pnp_readb, NULL, NULL, @@ -1779,12 +1776,11 @@ nic_pnp_io_set(nic_t *dev, uint16_t read_addr) static void nic_pnp_io_remove(nic_t *dev) { - io_removehandler(0x0A79, 1, - NULL, NULL, NULL, - nic_pnp_writeb, NULL, NULL, dev); - io_removehandler(dev->pnp_read, 1, - nic_pnp_readb, NULL, NULL, - NULL, NULL, NULL, dev); + if ((dev->pnp_read >= 0x0200) && (dev->pnp_read <= 0x03FF)) { + io_removehandler(dev->pnp_read, 1, + nic_pnp_readb, NULL, NULL, + NULL, NULL, NULL, dev); + } } @@ -1799,11 +1795,8 @@ nic_pnp_address_writeb(uint16_t addr, uint8_t val, void *priv) case PNP_PHASE_WAIT_FOR_KEY: if (val == pnp_init_key[dev->pnp_magic_count]) { dev->pnp_magic_count = (dev->pnp_magic_count + 1) & 0x1f; - if (!dev->pnp_magic_count) { - nic_pnp_io_remove(dev); - nic_pnp_io_set(dev, dev->pnp_read); + if (!dev->pnp_magic_count) dev->pnp_phase = PNP_PHASE_SLEEP; - } } else dev->pnp_magic_count = 0; break; @@ -2592,7 +2585,9 @@ nic_init(device_t *info) dev->eeprom[0x5C] += dev->eeprom[c]; dev->eeprom[0x5C] = -dev->eeprom[0x5C]; - nic_pnp_io_set(dev, dev->pnp_read); + io_sethandler(0x0A79, 1, + NULL, NULL, NULL, + nic_pnp_writeb, NULL, NULL, dev); } } diff --git a/src/sio_um8669f.c b/src/sio_um8669f.c index 8238ff5b4..1f2dccf11 100644 --- a/src/sio_um8669f.c +++ b/src/sio_um8669f.c @@ -53,6 +53,7 @@ typedef struct um8669f_t } dev[8]; fdc_t *fdc; + int pnp_active; } um8669f_t; @@ -128,7 +129,7 @@ void um8669f_pnp_write(uint16_t port, uint8_t val, void *p) } break; case DEV_COM1: - if (valxor) + if ((um8669f->cur_reg == REG_ENABLE) && valxor) { serial_remove(1); if (um8669f->dev[DEV_COM1].enable & 1) @@ -136,7 +137,7 @@ void um8669f_pnp_write(uint16_t port, uint8_t val, void *p) } break; case DEV_COM2: - if (valxor) + if ((um8669f->cur_reg == REG_ENABLE) && valxor) { serial_remove(2); if (um8669f->dev[DEV_COM2].enable & 1) @@ -144,7 +145,7 @@ void um8669f_pnp_write(uint16_t port, uint8_t val, void *p) } break; case DEV_LPT1: - if (valxor) + if ((um8669f->cur_reg == REG_ENABLE) && valxor) { lpt1_remove(); if (um8669f->dev[DEV_LPT1].enable & 1) @@ -186,6 +187,7 @@ uint8_t um8669f_pnp_read(uint16_t port, void *p) void um8669f_write(uint16_t port, uint8_t val, void *p) { um8669f_t *um8669f = (um8669f_t *)p; + int new_pnp_active; if (um8669f->locked) { @@ -206,15 +208,21 @@ void um8669f_write(uint16_t port, uint8_t val, void *p) /* pclog("Write UM8669f register %02x %02x %04x:%04x %i\n", um8669f_curreg, val, CS,cpu_state.pc, ins); */ um8669f->regs_108[um8669f->cur_reg_108] = val; - io_removehandler(0x0279, 0x0001, NULL, NULL, NULL, um8669f_pnp_write, NULL, NULL, um8669f); - io_removehandler(0x0a79, 0x0001, NULL, NULL, NULL, um8669f_pnp_write, NULL, NULL, um8669f); - io_removehandler(0x03e3, 0x0001, um8669f_pnp_read, NULL, NULL, NULL, NULL, NULL, um8669f); - if (um8669f->regs_108[0xc1] & 0x80) - { - io_sethandler(0x0279, 0x0001, NULL, NULL, NULL, um8669f_pnp_write, NULL, NULL, um8669f); - io_sethandler(0x0a79, 0x0001, NULL, NULL, NULL, um8669f_pnp_write, NULL, NULL, um8669f); - io_sethandler(0x03e3, 0x0001, um8669f_pnp_read, NULL, NULL, NULL, NULL, NULL, um8669f); - } + if (um8669f->cur_reg_108 == 0xc1) { + new_pnp_active = !!(um8669f->regs_108[0xc1] & 0x80); + if (new_pnp_active != um8669f->pnp_active) { + if (new_pnp_active) { + io_sethandler(0x0279, 0x0001, NULL, NULL, NULL, um8669f_pnp_write, NULL, NULL, um8669f); + io_sethandler(0x0a79, 0x0001, NULL, NULL, NULL, um8669f_pnp_write, NULL, NULL, um8669f); + io_sethandler(0x03e3, 0x0001, um8669f_pnp_read, NULL, NULL, NULL, NULL, NULL, um8669f); + } else { + io_removehandler(0x0279, 0x0001, NULL, NULL, NULL, um8669f_pnp_write, NULL, NULL, um8669f); + io_removehandler(0x0a79, 0x0001, NULL, NULL, NULL, um8669f_pnp_write, NULL, NULL, um8669f); + io_removehandler(0x03e3, 0x0001, um8669f_pnp_read, NULL, NULL, NULL, NULL, NULL, um8669f); + } + um8669f->pnp_active = new_pnp_active; + } + } } } } @@ -252,16 +260,19 @@ void um8669f_reset(void) lpt1_remove(); lpt1_init(0x378); + if (um8669f_global.pnp_active) { + io_removehandler(0x0279, 0x0001, NULL, NULL, NULL, um8669f_pnp_write, NULL, NULL, &um8669f_global); + io_removehandler(0x0a79, 0x0001, NULL, NULL, NULL, um8669f_pnp_write, NULL, NULL, &um8669f_global); + io_removehandler(0x03e3, 0x0001, um8669f_pnp_read, NULL, NULL, NULL, NULL, NULL, &um8669f_global); + um8669f_global.pnp_active = 0; + } + memset(&um8669f_global, 0, sizeof(um8669f_t)); um8669f_global.fdc = temp_fdc; um8669f_global.locked = 1; - io_removehandler(0x0279, 0x0001, NULL, NULL, NULL, um8669f_pnp_write, NULL, NULL, &um8669f_global); - io_removehandler(0x0a79, 0x0001, NULL, NULL, NULL, um8669f_pnp_write, NULL, NULL, &um8669f_global); - io_removehandler(0x03e3, 0x0001, um8669f_pnp_read, NULL, NULL, NULL, NULL, NULL, &um8669f_global); - um8669f_global.dev[DEV_FDC].enable = 1; um8669f_global.dev[DEV_FDC].addr = 0x03f0; um8669f_global.dev[DEV_FDC].irq = 6; diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index f4d354003..66e1c8aca 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -772,11 +772,12 @@ void sb_dsp_init(sb_dsp_t *dsp, int type) void sb_dsp_setaddr(sb_dsp_t *dsp, uint16_t addr) { // pclog("sb_dsp_setaddr : %04X\n", addr); - io_removehandler(dsp->sb_addr + 6, 0x0002, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); - io_removehandler(dsp->sb_addr + 0xa, 0x0006, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); + if (dsp->sb_addr != 0) { + io_removehandler(dsp->sb_addr + 6, 0x0002, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); + io_removehandler(dsp->sb_addr + 0xa, 0x0006, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); + } dsp->sb_addr = addr; - if (dsp->sb_addr != 0) - { + if (dsp->sb_addr != 0) { io_sethandler(dsp->sb_addr + 6, 0x0002, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); io_sethandler(dsp->sb_addr + 0xa, 0x0006, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); } diff --git a/src/win/win_cdrom_ioctl.c b/src/win/win_cdrom_ioctl.c index 5ca208261..48a4c60e6 100644 --- a/src/win/win_cdrom_ioctl.c +++ b/src/win/win_cdrom_ioctl.c @@ -9,7 +9,7 @@ * Implementation of the CD-ROM host drive IOCTL interface for * Windows using SCSI Passthrough Direct. * - * Version: @(#)cdrom_ioctl.c 1.0.9 2018/01/17 + * Version: @(#)cdrom_ioctl.c 1.0.10 2018/02/01 * * Authors: Sarah Walker, * Miran Grca, @@ -51,6 +51,7 @@ typedef struct { cdrom_ioctl_windows_t cdrom_ioctl_windows[CDROM_NUM]; + #ifdef ENABLE_CDROM_LOG int cdrom_ioctl_do_log = ENABLE_CDROM_LOG; #endif @@ -671,9 +672,9 @@ static int ioctl_get_block_length(uint8_t id, const UCHAR *cdb, int number_of_bl case 0x51: /* READ DISC INFORMATION */ case 0x52: /* READ TRACK INFORMATION */ case 0x5A: /* MODE SENSE (10) */ - return ((uint16_t) cdb[8]) + (((uint16_t) cdb[7]) << 8); + return (((uint32_t) cdb[7]) << 8) | ((uint32_t) cdb[8]); case 0xAD: /* READ DVD STRUCTURE */ - return (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + return (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); default: return 65534; } @@ -689,9 +690,9 @@ static int ioctl_get_block_length(uint8_t id, const UCHAR *cdb, int number_of_bl case 0x51: /* READ DISC INFORMATION */ case 0x52: /* READ TRACK INFORMATION */ case 0x5A: /* MODE SENSE (10) */ - return ((uint16_t) cdb[8]) + (((uint16_t) cdb[7]) << 8); - case 0xAD: /* READ DVD STRUCTURE */ - return (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + return (((uint32_t) cdb[7]) << 8) | ((uint32_t) cdb[8]); + case 0xAD: /* READ DVD STRUCTURE */ + return (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); case 0x08: case 0x28: case 0xa8: