diff --git a/src/Makefile.local b/src/Makefile.local index c7726a9a7..31261d727 100644 --- a/src/Makefile.local +++ b/src/Makefile.local @@ -10,7 +10,7 @@ # settings, so we can avoid changing the main one for all of # our local setups. # -# Version: @(#)Makefile.local 1.0.8 2017/11/28 +# Version: @(#)Makefile.local 1.0.8 2017/12/15 # # Author: Fred N. van Kempen, # @@ -27,6 +27,7 @@ # Various compile-time options. # -DROM_TRACE=0xc800 traces ROM access from segment C800 # -DIO_TRACE=0x66 traces I/O on port 0x66 +# -DIO_CATCH enables I/O range catch logs STUFF := # Add feature selections here. diff --git a/src/io.c b/src/io.c index 92ac6073b..050733261 100644 --- a/src/io.c +++ b/src/io.c @@ -1,6 +1,22 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implement I/O ports and their operations. + * + * Version: @(#)io.c 1.0.1 2017/12/16 + * + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ #include #include #include @@ -10,305 +26,345 @@ #include "cpu/cpu.h" -uint8_t (*port_inb[0x10000][2])(uint16_t addr, void *priv); -uint16_t (*port_inw[0x10000][2])(uint16_t addr, void *priv); -uint32_t (*port_inl[0x10000][2])(uint16_t addr, void *priv); - -void (*port_outb[0x10000][2])(uint16_t addr, uint8_t val, void *priv); -void (*port_outw[0x10000][2])(uint16_t addr, uint16_t val, void *priv); -void (*port_outl[0x10000][2])(uint16_t addr, uint32_t val, void *priv); - -void *port_priv[0x10000][2]; +#define NPORTS 65536 /* PC/AT supports 64K ports */ -void io_init(void) -{ - int c; - pclog("io_init\n"); - for (c = 0; c < 0x10000; c++) - { - 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; - port_priv[c][0] = port_priv[c][1] = NULL; - } -} +/* + * 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); -void io_sethandler(uint16_t base, int size, - 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) -{ - int c; - for (c = 0; c < size; c++) - { - if (!port_inb[ base + c][0] && !port_inw[ base + c][0] && !port_inl[ base + c][0] && - !port_outb[base + c][0] && !port_outw[base + c][0] && !port_outl[base + c][0]) - { - port_inb[ base + c][0] = inb; - port_inw[ base + c][0] = inw; - port_inl[ base + c][0] = inl; - port_outb[base + c][0] = outb; - port_outw[base + c][0] = outw; - port_outl[base + c][0] = outl; - port_priv[base + c][0] = priv; - } - else if (!port_inb[ base + c][1] && !port_inw[ base + c][1] && !port_inl[ base + c][1] && - !port_outb[base + c][1] && !port_outw[base + c][1] && !port_outl[base + c][1]) - { - port_inb[ base + c][1] = inb; - port_inw[ base + c][1] = inw; - port_inl[ base + c][1] = inl; - port_outb[base + c][1] = outb; - port_outw[base + c][1] = outw; - port_outl[base + c][1] = outl; - port_priv[base + c][1] = 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 io_sethandler_interleaved(uint16_t base, int size, - 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) -{ - int c; - size <<= 2; - for (c = 0; c < size; c += 2) - { - if (!port_inb[ base + c][0] && !port_inw[ base + c][0] && !port_inl[ base + c][0] && - !port_outb[base + c][0] && !port_outw[base + c][0] && !port_outl[base + c][0]) - { - port_inb[ base + c][0] = inb; - port_inw[ base + c][0] = inw; - port_inl[ base + c][0] = inl; - port_outb[base + c][0] = outb; - port_outw[base + c][0] = outw; - port_outl[base + c][0] = outl; - port_priv[base + c][0] = priv; - } - else if (!port_inb[ base + c][1] && !port_inw[ base + c][1] && !port_inl[ base + c][1] && - !port_outb[base + c][1] && !port_outw[base + c][1] && !port_outl[base + c][1]) - { - port_inb[ base + c][1] = inb; - port_inw[ base + c][1] = inw; - port_inl[ base + c][1] = inl; - port_outb[base + c][1] = outb; - port_outw[base + c][1] = outw; - port_outl[base + c][1] = outl; - port_priv[base + c][1] = priv; - } - } -} +static void *port_priv[NPORTS][2]; -void io_removehandler(uint16_t base, int size, - 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) -{ - int c; - for (c = 0; c < size; c++) - { - if (port_priv[base + c][0] == priv) - { - if (port_inb[ base + c][0] == inb) - port_inb[ base + c][0] = NULL; - if (port_inw[ base + c][0] == inw) - port_inw[ base + c][0] = NULL; - if (port_inl[ base + c][0] == inl) - port_inl[ base + c][0] = NULL; - if (port_outb[ base + c][0] == outb) - port_outb[ base + c][0] = NULL; - if (port_outw[ base + c][0] == outw) - port_outw[ base + c][0] = NULL; - if (port_outl[ base + c][0] == outl) - port_outl[ base + c][0] = NULL; - port_priv[base + c][0] = NULL; - } - if (port_priv[base + c][1] == priv) - { - if (port_inb[ base + c][1] == inb) - port_inb[ base + c][1] = NULL; - if (port_inw[ base + c][1] == inw) - port_inw[ base + c][1] = NULL; - if (port_inl[ base + c][1] == inl) - port_inl[ base + c][1] = NULL; - if (port_outb[ base + c][1] == outb) - port_outb[ base + c][1] = NULL; - if (port_outw[ base + c][1] == outw) - port_outw[ base + c][1] = NULL; - if (port_outl[ base + c][1] == outl) - port_outl[ base + c][1] = NULL; - port_priv[base + c][1] = NULL; - } - } -} -void io_removehandler_interleaved(uint16_t base, int size, - 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) -{ - int c; - size <<= 2; - for (c = 0; c < size; c += 2) - { - if (port_priv[base + c][0] == priv) - { - if (port_inb[ base + c][0] == inb) - port_inb[ base + c][0] = NULL; - if (port_inw[ base + c][0] == inw) - port_inw[ base + c][0] = NULL; - if (port_inl[ base + c][0] == inl) - port_inl[ base + c][0] = NULL; - if (port_outb[ base + c][0] == outb) - port_outb[ base + c][0] = NULL; - if (port_outw[ base + c][0] == outw) - port_outw[ base + c][0] = NULL; - if (port_outl[ base + c][0] == outl) - port_outl[ base + c][0] = NULL; - port_priv[base + c][0] = NULL; - } - if (port_priv[base + c][1] == priv) - { - if (port_inb[ base + c][1] == inb) - port_inb[ base + c][1] = NULL; - if (port_inw[ base + c][1] == inw) - port_inw[ base + c][1] = NULL; - if (port_inl[ base + c][1] == inl) - port_inl[ base + c][1] = NULL; - if (port_outb[ base + c][1] == outb) - port_outb[ base + c][1] = NULL; - if (port_outw[ base + c][1] == outw) - port_outw[ base + c][1] = NULL; - if (port_outl[ base + c][1] == outl) - port_outl[ base + c][1] = NULL; - port_priv[base + c][1] = NULL; - } - } -} - -#if 0 -uint8_t cgamode,cgastat=0,cgacol; -int hsync; -uint8_t lpt2dat; -int sw9; -int t237=0; +#ifdef IO_CATCH +static uint8_t null_inb(uint16_t addr, void *priv) { pclog("IO: read(%04x)\n"); return(0xff); } +static uint16_t null_inw(uint16_t addr, void *priv) { pclog("IO: readw(%04x)\n"); return(0xffff); } +static uint32_t null_inl(uint16_t addr, void *priv) { pclog("IO: readl(%04x)\n"); return(0xffffffff); } +static void null_outb(uint16_t addr, uint8_t val, void *priv) { pclog("IO: write(%04x, %02x)\n", val); } +static void null_outw(uint16_t addr, uint16_t val, void *priv) { pclog("IO: writew(%04x, %04x)\n", val); } +static void null_outl(uint16_t addr, uint32_t val, void *priv) { pclog("IO: writel(%04x, %08lx)\n", val); } #endif -uint8_t inb(uint16_t port) -{ - uint8_t temp = 0xff; - if (port_inb[port][0]) - temp &= port_inb[port][0](port, port_priv[port][0]); - if (port_inb[port][1]) - temp &= port_inb[port][1](port, port_priv[port][1]); - - /* if (!port_inb[port][0] && !port_inb[port][1]) - pclog("Bad INB %04X %04X:%04X\n", port, CS, cpu_state.pc); */ - - /* if (port_inb[port][0] || port_inb[port][1]) - pclog("Good INB %04X %04X:%04X\n", port, CS, cpu_state.pc); */ - + +void +io_init(void) +{ + int c; + + pclog("IO: initializing\n"); + for (c=0; c>8); + outb(port,val); + outb(port+1,val>>8); } -uint32_t inl(uint16_t port) + +uint32_t +inl(uint16_t port) { -// pclog("INL %04X\n", 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]); - - return inw(port) | (inw(port + 2) << 16); + 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])); + + return(inw(port) | (inw(port + 2) << 16)); } -void outl(uint16_t port, uint32_t val) + +void +outl(uint16_t port, uint32_t val) { -/* if ((port & ~0xf) == 0xf000) - pclog("OUTL %04X %08X\n", port, 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; + } - if (port_outl[port][0]) - port_outl[port][0](port, val, port_priv[port][0]); - if (port_outl[port][1]) - port_outl[port][1](port, val, port_priv[port][1]); - - if (port_outl[port][0] || port_outl[port][1]) - return; - - outw(port, val); - outw(port + 2, val >> 16); + outw(port, val); + outw(port + 2, val >> 16); } diff --git a/src/io.h b/src/io.h index 081fbbff4..43b23c00d 100644 --- a/src/io.h +++ b/src/io.h @@ -1,43 +1,65 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -extern void io_init(void); +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Definitions for the I/O handler. + * + * Version: @(#)io.h 1.0.1 2017/12/16 + * + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ +#ifndef EMU_IO_H +# define EMU_IO_H -extern void io_sethandler(uint16_t base, int size, - 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); -extern void io_sethandler_interleaved(uint16_t base, int size, - 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); +extern void io_init(void); -extern void io_removehandler(uint16_t base, int size, - 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); +extern void io_sethandler(uint16_t base, int size, + 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); -extern void io_removehandler_interleaved(uint16_t base, int size, - 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); +extern void io_removehandler(uint16_t base, int size, + 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); + +#ifdef PC98 +extern void io_sethandler_interleaved(uint16_t base, int size, + 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); + +extern void io_removehandler_interleaved(uint16_t base, int size, + 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); +#endif extern uint8_t inb(uint16_t port); extern void outb(uint16_t port, uint8_t val); @@ -45,3 +67,6 @@ extern uint16_t inw(uint16_t port); extern void outw(uint16_t port, uint16_t val); extern uint32_t inl(uint16_t port); extern void outl(uint16_t port, uint32_t val); + + +#endif /*EMU_IO_H*/