diff --git a/src/86box.h b/src/86box.h index cfff2409b..7846be212 100644 --- a/src/86box.h +++ b/src/86box.h @@ -93,7 +93,9 @@ extern int vid_cga_contrast, /* (C) video */ gfxcard; /* (C) graphics/video card */ extern int serial_enabled[], /* (C) enable serial ports */ lpt_enabled, /* (C) enable LPT ports */ - bugger_enabled; /* (C) enable ISAbugger */ + bugger_enabled, /* (C) enable ISAbugger */ + isamem_type[], /* (C) enable ISA mem cards */ + isartc_type; /* (C) enable ISA RTC card */ extern int sound_is_float, /* (C) sound uses FP values */ GAMEBLASTER, /* (C) sound option */ GUS, /* (C) sound option */ diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 53e2403cc..3f96340fc 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1,4 +1,4 @@ -/* +/* * VARCem Virtual ARchaeological Computer EMulator. * An emulator of (mostly) x86-based PC systems and devices, * using the ISA,EISA,VLB,MCA and PCI system buses, roughly diff --git a/src/device.c b/src/device.c index 2d1cd5df9..4bfb35a77 100644 --- a/src/device.c +++ b/src/device.c @@ -9,7 +9,7 @@ * Implementation of the generic device interface to handle * all devices attached to the emulator. * - * Version: @(#)device.c 1.0.8 2018/04/29 + * Version: @(#)device.c 1.0.9 2018/09/02 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -39,6 +39,7 @@ */ #include #include +#include #include #include #include @@ -54,9 +55,17 @@ #define DEVICE_MAX 256 /* max # of devices */ -static void *device_priv[DEVICE_MAX]; -static device_t *devices[DEVICE_MAX]; -static device_t *device_current; +typedef struct clonedev { + const device_t *master; + int count; + struct clonedev *next; +} clonedev_t; + + +static device_t *devices[DEVICE_MAX]; +static void *device_priv[DEVICE_MAX]; +static device_t *device_current; +static clonedev_t *clones; #ifdef ENABLE_DEVICE_LOG @@ -78,7 +87,7 @@ device_log(const char *format, ...) #endif } - +/* Initialize the module for use. */ void device_init(void) { @@ -86,6 +95,50 @@ device_init(void) } +/* Clone a master device for multi-instance devices. */ +const device_t * +device_clone(const device_t *master) +{ + char temp[1024], *sp; + clonedev_t *cl, *ptr; + device_t *dev; + + /* Look up the master. */ + for (ptr = clones; ptr != NULL; ptr = ptr->next) + if (ptr->master == master) break; + + /* If not found, add this master to the list. */ + if (ptr == NULL) { + ptr = (clonedev_t *)malloc(sizeof(clonedev_t)); + memset(ptr, 0x00, sizeof(clonedev_t)); + if (clones != NULL) { + for (cl = clones; cl->next != NULL; cl = cl->next) + ; + cl->next = ptr; + } else + clones = ptr; + ptr->master = master; + } + + /* Create a new device. */ + dev = (device_t *)malloc(sizeof(device_t)); + + /* Copy the master info. */ + memcpy(dev, ptr->master, sizeof(device_t)); + + /* Set up a clone. */ + if (++ptr->count > 1) + sprintf(temp, "%s #%i", ptr->master->name, ptr->count); + else + strcpy(temp, ptr->master->name); + sp = (char *)malloc(strlen(temp) + 1); + strcpy(sp, temp); + dev->name = (const char *)sp; + + return((const device_t *)dev); +} + + void * device_add(const device_t *d) { diff --git a/src/device.h b/src/device.h index 6256a3ea5..9e6508172 100644 --- a/src/device.h +++ b/src/device.h @@ -8,7 +8,7 @@ * * Definitions for the device handler. * - * Version: @(#)device.h 1.0.5 2018/04/26 + * Version: @(#)device.h 1.0.6 2018/09/02 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -114,6 +114,7 @@ extern "C" { #endif extern void device_init(void); +extern const device_t * device_clone(const device_t *master); extern void *device_add(const device_t *d); extern void device_add_ex(const device_t *d, void *priv); extern void device_close_all(void); diff --git a/src/isamem.c b/src/isamem.c new file mode 100644 index 000000000..0229f6eac --- /dev/null +++ b/src/isamem.c @@ -0,0 +1,971 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of a memory expansion board for the ISA Bus. + * + * Although modern systems use direct-connect local buses to + * connect the CPU with its memory, originally the main system + * bus(es) were used for that. Memory expension cards could add + * memory to the system through the ISA bus, using a variety of + * techniques. + * + * The majority of these boards could provide some (additional) + * conventional (low) memory, extended (high) memory on 80286 + * and higher systems, as well as EMS bank-switched memory. + * + * This implementation uses the LIM 3.2 specifications for EMS. + * + * With the EMS method, the system's standard memory is expanded + * by means of bank-switching. One or more 'frames' in the upper + * memory area (640K-1024K) are used as viewports into an array + * of RAM pages numbered 0 to N. Each page is defined to be 16KB + * in size, so, for a 1024KB board, 64 such pages are available. + * I/O control registers are used to set up the mappings. More + * modern boards even have multiple 'copies' of those registers, + * which can be switched very fast, to allow for multitasking. + * + * TODO: The EV159 is supposed to support 16b EMS transfers, but the + * EMM.sys driver for it doesn't seem to want to do that.. + * + * Version: @(#)isamem.c 1.0.1 2018/08/18 + * + * Author: Fred N. van Kempen, + * + * Copyright 2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include +#include "86box.h" +#include "cpu/cpu.h" +#include "machine/machine.h" +#include "io.h" +#include "mem.h" +#include "device.h" +#include "ui.h" +#include "plat.h" +#include "isamem.h" + + +#define RAM_TOPMEM (640 << 10) /* end of low memory */ +#define RAM_UMAMEM (384 << 10) /* upper memory block */ +#define RAM_EXTMEM (1024 << 10) /* start of high memory */ + +#define EMS_MAXSIZE (2048 << 10) /* max EMS memory size */ +#define EMS_PGSIZE (16 << 10) /* one page is this big */ +#define EMS_MAXPAGE 4 /* number of viewport pages */ + + +typedef struct { + int8_t enabled; /* 1=ENABLED */ + uint8_t page; /* page# in EMS RAM */ + uint8_t frame; /* (varies with board) */ + char pad; + uint8_t *addr; /* start addr in EMS RAM */ + mem_mapping_t mapping; /* mapping entry for page */ +} emsreg_t; + +typedef struct { + const char *name; + uint8_t board : 6, /* board type */ + instance : 2; /* device instance */ + + uint8_t flags; +#define FLAG_CONFIG 0x01 /* card is configured */ +#define FLAG_WIDE 0x10 /* card uses 16b mode */ +#define FLAG_FAST 0x20 /* fast (<= 120ns) chips */ +#define FLAG_EMS 0x40 /* card has EMS mode enabled */ + + uint16_t total_size; /* configured size in KB */ + uint32_t base_addr, /* configured I/O address */ + start_addr, /* configured memory start */ + frame_addr; /* configured frame address */ + + uint16_t ems_size, /* EMS size in KB */ + ems_pages; /* EMS size in pages */ + uint32_t ems_start; /* start of EMS in RAM */ + + uint8_t *ram; /* allocated RAM buffer */ + + mem_mapping_t low_mapping; /* mapping for low mem */ + mem_mapping_t high_mapping; /* mapping for high mem */ + + emsreg_t ems[EMS_MAXPAGE]; /* EMS controller registers */ +} memdev_t; + +/* Read one byte from onboard RAM. */ +static uint8_t +ram_readb(uint32_t addr, void *priv) +{ + mem_mapping_t *map = (mem_mapping_t *)priv; + memdev_t *dev = (memdev_t *)map->dev; + uint8_t ret = 0xff; + + /* Grab the data. */ + ret = *(uint8_t *)(dev->ram + (addr - map->base)); + + return(ret); +} + + +/* Read one word from onboard RAM. */ +static uint16_t +ram_readw(uint32_t addr, void *priv) +{ + mem_mapping_t *map = (mem_mapping_t *)priv; + memdev_t *dev = (memdev_t *)map->dev; + uint16_t ret = 0xffff; + + /* Grab the data. */ + ret = *(uint16_t *)(dev->ram + (addr - map->base)); + + return(ret); +} + + +/* Write one byte to onboard RAM. */ +static void +ram_writeb(uint32_t addr, uint8_t val, void *priv) +{ + mem_mapping_t *map = (mem_mapping_t *)priv; + memdev_t *dev = (memdev_t *)map->dev; + + /* Write the data. */ + *(uint8_t *)(dev->ram + (addr - map->base)) = val; +} + + +/* Write one word to onboard RAM. */ +static void +ram_writew(uint32_t addr, uint16_t val, void *priv) +{ + mem_mapping_t *map = (mem_mapping_t *)priv; + memdev_t *dev = (memdev_t *)map->dev; + + /* Write the data. */ + *(uint16_t *)(dev->ram + (addr - map->base)) = val; +} + + +/* Read one byte from onboard paged RAM. */ +static uint8_t +ems_readb(uint32_t addr, void *priv) +{ + mem_mapping_t *map = (mem_mapping_t *)priv; + memdev_t *dev = (memdev_t *)map->dev; + uint8_t ret = 0xff; + int vpage; + + /* Get the viewport page number. */ + vpage = ((addr & 0xffff) / EMS_PGSIZE); + + /* Grab the data. */ + ret = *(uint8_t *)(dev->ems[vpage].addr + (addr - map->base)); + + return(ret); +} + + +/* Read one word from onboard paged RAM. */ +static uint16_t +ems_readw(uint32_t addr, void *priv) +{ + mem_mapping_t *map = (mem_mapping_t *)priv; + memdev_t *dev = (memdev_t *)map->dev; + uint16_t ret = 0xffff; + int vpage; + + /* Get the viewport page number. */ + vpage = ((addr & 0xffff) / EMS_PGSIZE); + + /* Grab the data. */ + ret = *(uint16_t *)(dev->ems[vpage].addr + (addr - map->base)); + + return(ret); +} + + +/* Write one byte to onboard paged RAM. */ +static void +ems_writeb(uint32_t addr, uint8_t val, void *priv) +{ + mem_mapping_t *map = (mem_mapping_t *)priv; + memdev_t *dev = (memdev_t *)map->dev; + int vpage; + + /* Get the viewport page number. */ + vpage = ((addr & 0xffff) / EMS_PGSIZE); + + /* Write the data. */ + *(uint8_t *)(dev->ems[vpage].addr + (addr - map->base)) = val; +} + + +/* Write one word to onboard paged RAM. */ +static void +ems_writew(uint32_t addr, uint16_t val, void *priv) +{ + mem_mapping_t *map = (mem_mapping_t *)priv; + memdev_t *dev = (memdev_t *)map->dev; + int vpage; + + /* Get the viewport page number. */ + vpage = ((addr & 0xffff) / EMS_PGSIZE); + + /* Write the data. */ + *(uint16_t *)(dev->ems[vpage].addr + (addr - map->base)) = val; +} + + +/* Handle a READ operation from one of our registers. */ +static uint8_t +ems_read(uint16_t port, void *priv) +{ + memdev_t *dev = (memdev_t *)priv; + uint8_t ret = 0xff; + int vpage; + + /* Get the viewport page number. */ + vpage = (port / EMS_PGSIZE); + + switch(port & 0x02ff) { + case 0x0208: /* page number register */ + case 0x0218: + case 0x0258: + case 0x0268: + case 0x02a8: + case 0x02b8: + case 0x02e8: + ret = dev->ems[vpage].page; + if (dev->ems[vpage].enabled) + ret |= 0x80; + break; + } + +#if 0 + pclog("ISAMEM: read(%04x) = %02x)\n", port, ret); +#endif + + return(ret); +} + + +/* Handle a WRITE operation to one of our registers. */ +static void +ems_write(uint16_t port, uint8_t val, void *priv) +{ + memdev_t *dev = (memdev_t *)priv; + int vpage; + + /* Get the viewport page number. */ + vpage = (port / EMS_PGSIZE); + +#if 0 + pclog("ISAMEM: write(%04x, %02x) page=%d\n", port, val, vpage); +#endif + + switch(port & 0x02ff) { + case 0x0208: /* page mapping registers */ + case 0x0218: + case 0x0258: + case 0x0268: + case 0x02a8: + case 0x02b8: + case 0x02e8: + /* Set the page number. */ + dev->ems[vpage].enabled = (val & 0x80); + dev->ems[vpage].page = (val & 0x7f); + + /* Make sure we can do that.. */ + if (dev->flags & FLAG_CONFIG) { + if (dev->ems[vpage].page < dev->ems_pages) { + /* Pre-calculate the page address in EMS RAM. */ + dev->ems[vpage].addr = dev->ram + dev->ems_start + ((val & 0x7f) * EMS_PGSIZE); + } else { + /* That page does not exist. */ + dev->ems[vpage].enabled = 0; + } + + if (dev->ems[vpage].enabled) { + /* Update the EMS RAM address for this page. */ + mem_mapping_set_exec(&dev->ems[vpage].mapping, + dev->ems[vpage].addr); + + /* Enable this page. */ + mem_mapping_enable(&dev->ems[vpage].mapping); + } else { + /* Disable this page. */ + mem_mapping_disable(&dev->ems[vpage].mapping); + } + } + break; + + case 0x0209: /* page frame registers */ + case 0x0219: + case 0x0259: + case 0x0269: + case 0x02a9: + case 0x02b9: + case 0x02e9: + /* + * The EV-159 EMM driver configures the frame address + * by setting bits in these registers. The information + * in their manual is unclear, but here is what was + * found out by repeatedly changing EMM's config: + * + * 00 04 08 Address + * ----------------- + * 80 c0 e0 E0000 + */ + + dev->ems[vpage].frame = val; + if (val) + dev->flags |= FLAG_CONFIG; + break; + } +} + + +/* Initialize the device for use. */ +static void * +isamem_init(const device_t *info) +{ + memdev_t *dev; + uint32_t k, t; + uint32_t addr; + uint32_t tot; + uint8_t *ptr; + int i; + + /* Find our device and create an instance. */ + dev = (memdev_t *)malloc(sizeof(memdev_t)); + memset(dev, 0x00, sizeof(memdev_t)); + dev->name = info->name; + dev->board = info->local; + + /* Do per-board initialization. */ + tot = 0; + switch(dev->board) { + case 0: /* IBM PC/XT Memory Expansion Card */ + dev->total_size = device_get_config_int("size"); + dev->start_addr = device_get_config_int("start"); + tot = dev->total_size; + break; + + case 1: /* IBM PC/AT Memory Expansion Card */ + dev->total_size = device_get_config_int("size"); + dev->start_addr = device_get_config_int("start"); + tot = dev->total_size; + dev->flags |= FLAG_WIDE; + break; + + case 10: /* Everex EV-159 RAM 3000 */ + dev->base_addr = device_get_config_hex16("base"); + dev->total_size = device_get_config_int("size"); + dev->start_addr = device_get_config_int("start"); + tot = device_get_config_int("length"); + if (!!device_get_config_int("width")) + dev->flags |= FLAG_WIDE; + if (!!device_get_config_int("speed")) + dev->flags |= FLAG_FAST; + if (!!device_get_config_int("ems")) + dev->flags |= FLAG_EMS; +dev->frame_addr = 0xE0000; + break; + + case 11: + dev->base_addr = device_get_config_hex16("base"); + dev->total_size = device_get_config_int("size"); + dev->start_addr = device_get_config_int("start"); + dev->frame_addr = device_get_config_hex20("frame"); + if (!!device_get_config_int("width")) + dev->flags |= FLAG_WIDE; + if (!!device_get_config_int("speed")) + dev->flags |= FLAG_FAST; + break; + } + + /* Fix up the memory start address. */ + dev->start_addr <<= 10; + + /* Say hello! */ + pclog("ISAMEM: %s (%iKB", info->name, dev->total_size); + if (dev->total_size != tot) pclog(", %iKB for RAM", tot); + if (dev->flags & FLAG_FAST) pclog(", FAST"); + if (dev->flags & FLAG_WIDE) pclog(", 16BIT"); + pclog(")\n"); + + /* Force (back to) 8-bit bus if needed. */ + if (AT) { + if (! cpu_16bitbus) + pclog("ISAMEM: *WARNING* this board will slow down your PC!\n"); + } else { + pclog("ISAMEM: not AT+ system, forcing 8-bit mode!\n"); + dev->flags &= ~FLAG_WIDE; + } + + /* Allocate and initialize our RAM. */ + k = dev->total_size << 10; + dev->ram = (uint8_t *)malloc(k); + memset(dev->ram, 0x00, k); + ptr = dev->ram; + + /* + * The 'Memory Start Address' switch indicates at which address + * we should start adding memory. No memory is added if it is + * set to 0. + */ + tot <<= 10; + addr = dev->start_addr; + if (addr > 0 && tot > 0) { + /* Adjust K for the RAM we will use. */ + k -= tot; + + /* + * First, see if we have to expand the conventional + * (low) memory area. This can extend up to 640KB, + * so check this first. + */ + t = (addr < RAM_TOPMEM) ? RAM_TOPMEM - addr : 0; + if (t > 0) { + /* + * We need T bytes to extend that area. + * + * If the board doesn't have that much, grab + * as much as we can. + */ + if (t > tot) + t = tot; + pclog("ISAMEM: RAM at %05iKB (%iKB)\n", addr>>10, t>>10); + + /* Create, initialize and enable the low-memory mapping. */ + mem_mapping_add(&dev->low_mapping, addr, t, + ram_readb, + (dev->flags&FLAG_WIDE) ? ram_readw : NULL, + NULL, + ram_writeb, + (dev->flags&FLAG_WIDE) ? ram_writew : NULL, + NULL, + ptr, MEM_MAPPING_EXTERNAL, &dev->low_mapping); + mem_mapping_set_dev(&dev->low_mapping, dev); + + /* Tell the memory system this is external RAM. */ + mem_set_mem_state(addr, t, + MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + + /* Update pointers. */ + ptr += t; + tot -= t; + addr += t; + } + + /* Skip to high memory if needed. */ + if ((addr == RAM_TOPMEM) && (tot >= RAM_UMAMEM)) { + /* + * We have more RAM available, but we are at the + * top of conventional RAM. So, the next 384K are + * skipped, and placed into different mappings so + * they can be re-mapped later. + */ + t = RAM_UMAMEM; /* 384KB */ + + pclog("ISAMEM: RAM at %05iKB (%iKB)\n", addr>>10, t>>10); + + /* Update and enable the remap. */ + mem_mapping_del(&ram_remapped_mapping); + mem_mapping_add(&ram_remapped_mapping, + addr + tot, t, + ram_readb, ram_readw, NULL, + ram_writeb, ram_writew, NULL, + ptr, MEM_MAPPING_EXTERNAL, + &ram_remapped_mapping); + mem_mapping_set_exec(&ram_remapped_mapping, ptr); + mem_mapping_set_dev(&ram_remapped_mapping, dev); + mem_mapping_disable(&ram_remapped_mapping); + + /* Tell the memory system this is external RAM. */ + mem_set_mem_state(addr + tot, t, + MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + + /* Update pointers. */ + ptr += t; + tot -= t; + addr += t; + } + } + + /* + * Next, on systems that support it (80286 and up), we can add + * (some of) our RAM to the system as Extended Memory, that is, + * memory located above 1MB. This memory cannot be addressed in + * real mode (so, not by DOS, for example) but it can be used in + * protected mode. + */ + if (AT && addr > 0 && tot > 0) { + t = tot; + pclog("ISAMEM: RAM at %05iKB (%iKB)\n", addr>>10, t>>10); + + /* Create, initialize and enable the high-memory mapping. */ + mem_mapping_add(&dev->high_mapping, addr, t, + ram_readb, ram_readw, NULL, + ram_writeb, ram_writew, NULL, + ptr, MEM_MAPPING_EXTERNAL, &dev->high_mapping); + mem_mapping_set_dev(&dev->high_mapping, dev); + + /* Tell the memory system this is external RAM. */ + mem_set_mem_state(addr, t, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + + /* Update pointers. */ + ptr += t; + tot -= t; + addr += t; + } + + /* If EMS is enabled, use the remainder for EMS. */ + if (dev->flags & FLAG_EMS) { + /* EMS 3.2 cannot have more than 2048KB per board. */ + t = k; + if (t > EMS_MAXSIZE) + t = EMS_MAXSIZE; + + /* Set up where EMS begins in local RAM, and how much we have. */ + dev->ems_start = ptr - dev->ram; + dev->ems_size = t >> 10; + dev->ems_pages = t / EMS_PGSIZE; + pclog("ISAMEM: EMS enabled, I/O=%04xH, %iKB (%i pages)", + dev->base_addr, dev->ems_size, dev->ems_pages); + if (dev->frame_addr > 0) + pclog(", Frame=%05XH", dev->frame_addr); + pclog("\n"); + + /* + * For each supported page (we can have a maximum of 4), + * create, initialize and disable the mappings, and set + * up the I/O control handler. + */ + for (i = 0; i < EMS_MAXPAGE; i++) { + /* Create and initialize a page mapping. */ + mem_mapping_add(&dev->ems[i].mapping, + dev->frame_addr + (EMS_PGSIZE*i), EMS_PGSIZE, + ems_readb, + (dev->flags&FLAG_WIDE) ? ems_readw : NULL, + NULL, + ems_writeb, + (dev->flags&FLAG_WIDE) ? ems_writew : NULL, + NULL, + ptr, MEM_MAPPING_EXTERNAL, + &dev->ems[i].mapping); + mem_mapping_set_dev(&dev->ems[i].mapping, dev); + + /* For now, disable it. */ + mem_mapping_disable(&dev->ems[i].mapping); + + /* Set up an I/O port handler. */ + io_sethandler(dev->base_addr + (EMS_PGSIZE*i), 2, + ems_read,NULL,NULL, ems_write,NULL,NULL, dev); + } + } + + /* Just so its not NULL. */ + return((void *)dev); +} + + +/* Remove the device from the system. */ +static void +isamem_close(void *priv) +{ + memdev_t *dev = (memdev_t *)priv; + int i; + + if (dev->flags & FLAG_EMS) { + for (i = 0; i < EMS_MAXPAGE; i++) { + io_removehandler(dev->base_addr + (EMS_PGSIZE*i), 2, + ems_read,NULL,NULL, ems_write,NULL,NULL, dev); + + } + } + + if (dev->ram != NULL) + free(dev->ram); + + if (dev != NULL) + free(dev); +} + + +static const device_config_t ibmxt_config[] = +{ + { + "size", "Memory Size", CONFIG_SPINNER, "", 128, + { { 0 } }, + { { 0 } }, + { 0, 256, 16 } + }, + { + "start", "Start Address", CONFIG_SPINNER, "", 256, + { { 0 } }, + { { 0 } }, + { 0, 640-64, 64 } + }, + { + "", "", -1 + } +}; + +static const device_t ibmxt_device = { + "IBM PC/XT Memory Expansion", + DEVICE_ISA, + 0, + isamem_init, + isamem_close, + NULL, + NULL, + NULL, + NULL, + ibmxt_config +}; + + +static const device_config_t ibmat_config[] = +{ + { + "size", "Memory Size", CONFIG_SPINNER, "", 512, + { { 0 } }, + { { 0 } }, + { 0, 4096, 512 } + }, + { + "start", "Start Address", CONFIG_SPINNER, "", 512, + { { 0 } }, + { { 0 } }, + { 0, 16128, 128 } + }, + { + "", "", -1 + } +}; + +static const device_t ibmat_device = { + "IBM PC/AT Memory Expansion", + DEVICE_ISA, + 1, + isamem_init, isamem_close, NULL, + NULL, NULL, NULL, + ibmat_config +}; + + +static const device_config_t ev159_config[] = +{ + { + "size", "Memory Size", CONFIG_SPINNER, "", 512, + { { 0 } }, + { { 0 } }, + { 0, 3072, 512 } + }, + { + "start", "Start Address", CONFIG_SPINNER, "", 0, + { { 0 } }, + { { 0 } }, + { 0, 16128, 128 } + }, + { + "length", "Contiguous Size", CONFIG_SPINNER, "", 0, + { { 0 } }, + { { 0 } }, + { 0, 16384, 128 } + }, + { + "width", "I/O Width", CONFIG_SELECTION, "", 0, + { + { + "8-bit", 0 + }, + { + "16-bit", 1 + }, + { + "" + } + }, + }, + { + "speed", "Transfer Speed", CONFIG_SELECTION, "", 0, + { + { + "Standard (150ns)", 0 + }, + { + "High-Speed (120ns)", 1 + }, + { + "" + } + } + }, + { + "ems", "EMS mode", CONFIG_SELECTION, "", 0, + { + { + "Disabled", 0 + }, + { + "Enabled", 1 + }, + { + "" + } + }, + }, + { + "base", "Address", CONFIG_HEX16, "", 0x0258, + { + { + "208H", 0x0208 + }, + { + "218H", 0x0218 + }, + { + "258H", 0x0258 + }, + { + "268H", 0x0268 + }, + { + "2A8H", 0x02A8 + }, + { + "2B8H", 0x02B8 + }, + { + "2E8H", 0x02E8 + }, + { + "" + } + }, + }, + { + "", "", -1 + } +}; + +static const device_t ev159_device = { + "Everex EV-159 RAM 3000 Deluxe", + DEVICE_ISA, + 10, + isamem_init, isamem_close, NULL, + NULL, NULL, NULL, + ev159_config +}; + + +#ifdef USE_ISAMEM_RAMPAGE +static const device_config_t rampage_config[] = +{ + { + "base", "Address", CONFIG_HEX16, "", 0x0258, + { + { + "208H", 0x0208 + }, + { + "218H", 0x0218 + }, + { + "258H", 0x0258 + }, + { + "268H", 0x0268 + }, + { + "2A8H", 0x02A8 + }, + { + "2B8H", 0x02B8 + }, + { + "2E8H", 0x02E8 + }, + { + "" + } + }, + }, + { + "frame", "Frame Address", CONFIG_HEX20, "", 0, + { + { + "Disabled", 0x00000 + }, + { + "C000H", 0xC0000 + }, + { + "D000H", 0xD0000 + }, + { + "E000H", 0xE0000 + }, + { + "" + } + }, + }, + { + "width", "I/O Width", CONFIG_SELECTION, "", 8, + { + { + "8-bit", 8 + }, + { + "16-bit", 16 + }, + { + "" + } + }, + }, + { + "speed", "Transfer Speed", CONFIG_SELECTION, "", 0, + { + { + "Standard", 0 + }, + { + "High-Speed", 1 + }, + { + "" + } + } + }, + { + "size", "Memory Size", CONFIG_SPINNER, "", 128, + { { 0 } }, + { { 0 } }, + { 0, 8192, 128 } + }, + { + "", "", -1 + } +}; + +static const device_t isamem_rampage_device = { + "AST RAMpage/XT", + DEVICE_ISA, + 11, + isamem_init, isamem_close, NULL, + NULL, NULL, NULL, + rampage_config +}; +#endif + + +static const struct { + const char *name; + const char *internal_name; + const device_t *dev; +} boards[] = { + { "None", "none", NULL, }, + { "IBM PC/XT Memory Expansion", "ibmxt", &ibmxt_device, }, + { "IBM PC/AT Memory Expansion", "ibmat", &ibmat_device, }, + { "Everex EV-159 RAM 3000 Deluxe", "ev159", &ev159_device, }, + { "", "", NULL, }, +}; + + +void +isamem_reset(void) +{ + const device_t *dev; + int k, i; + + for (i = 0; i < ISAMEM_MAX; i++) { + k = isamem_type[i]; + if (k == 0) continue; + + /* Clone the device. */ + dev = device_clone(boards[k].dev); + + /* Add the instance to the system. */ + device_add(dev); + } +} + + +char * +isamem_get_name(int board) +{ + return((char *)boards[board].name); +} + + +char * +isamem_get_internal_name(int board) +{ + return((char *)boards[board].internal_name); +} + + + +int +isamem_get_from_internal_name(char *s) +{ + int c = 0; + + while (strlen((char *) boards[c].internal_name)) { + if (!strcmp((char *)boards[c].internal_name, s)) + return(c); + c++; + } + + /* Not found. */ + return(0); +} + + +const device_t * +isamem_get_device(int board) +{ + return(boards[board].dev); +} diff --git a/src/isamem.h b/src/isamem.h new file mode 100644 index 000000000..955103d71 --- /dev/null +++ b/src/isamem.h @@ -0,0 +1,77 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the ISAMEM cards. + * + * Version: @(#)isamem.h 1.0.1 2018/08/18 + * + * Authors: Fred N. van Kempen, + * + * Copyright 2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef ISAMEM_H +# define ISAMEM_H + + +#define ISAMEM_MAX 4 /* max #cards in system */ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Global variables. */ +extern const device_t isamem_device; +extern const device_t isamem_brat80_device; +extern const device_t isamem_ev159_device; + + +/* Functions. */ +extern void isamem_reset(void); + +extern char *isamem_get_name(int t); +extern char *isamem_get_internal_name(int t); +extern int isamem_get_from_internal_name(char *s); +extern const device_t *isamem_get_device(int t); + +#ifdef __cplusplus +} +#endif + + +#endif /*ISAMEM_H*/ diff --git a/src/isartc.c b/src/isartc.c new file mode 100644 index 000000000..9fc98a543 --- /dev/null +++ b/src/isartc.c @@ -0,0 +1,739 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of a Clock/RTC Card for the ISA PC/XT. + * + * Systems starting with the PC/XT had, by default, a realtime + * clock and NVR chip on the mainboard. The BIOS stored config + * data in the NVR, and the system could maintain time and date + * using the RTC. + * + * Originally, PC systems did not have this, and they first did + * show up in non-IBM clone systems. Shortly after, expansion + * cards with this function became available for the PC's (ISA) + * bus, and they came in many forms and designs. + * + * This implementation offers some of those boards: + * + * Everex EV-170 (using NatSemi MM58167 chip) + * DTK PII-147 Hexa I/O Plus (using UMC 82C8167 chip) + * + * and more will follow as time permits. + * + * NOTE: The IRQ functionalities have been implemented, but not yet + * tested, as I need to write test software for them first :) + * + * Version: @(#)isartc.c 1.0.4 2018/08/31 + * + * Author: Fred N. van Kempen, + * + * Copyright 2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include +#include +#include +#include +#include "86box.h" +#include "cpu/cpu.h" +#include "machine/machine.h" +#include "io.h" +#include "device.h" +#include "nvr.h" +#include "ui.h" +#include "plat.h" +#include "pic.h" +#include "isartc.h" + + +#define ISARTC_DEBUG 0 + + +typedef struct { + const char *name; /* board name */ + uint8_t board; /* board type */ + + uint8_t flags; /* various flags */ +#define FLAG_YEAR80 0x01 /* YEAR byte is base-80 */ +#define FLAG_YEARBCD 0x02 /* YEAR byte is in BCD */ + + int8_t irq; /* configured IRQ channel */ + int8_t base_addrsz; + uint32_t base_addr; /* configured I/O address */ + + /* Fields for the specific driver. */ + void (*f_wr)(uint16_t, uint8_t, void *); + uint8_t (*f_rd)(uint16_t, void *); + int8_t year; /* register for YEAR value */ + char pad[3]; + + nvr_t nvr; /* RTC/NVR */ +} rtcdev_t; + + +/************************************************************************ + * * + * Driver for the NatSemi MM58167 chip. * + * * + ************************************************************************/ +#define MM67_REGS 32 + +/* Define the RTC chip registers - see datasheet, pg4. */ +#define MM67_MSEC 0 /* milliseconds */ +#define MM67_HUNTEN 1 /* hundredths/tenths of seconds */ +#define MM67_SEC 2 /* seconds */ +#define MM67_MIN 3 /* minutes */ +#define MM67_HOUR 4 /* hours */ +#define MM67_DOW 5 /* day of the week */ +#define MM67_DOM 6 /* day of the month */ +#define MM67_MON 7 /* month */ +#define MM67_AL_MSEC 8 /* milliseconds */ +#define MM67_AL_HUNTEN 9 /* hundredths/tenths of seconds */ +#define MM67_AL_SEC 10 /* seconds */ +#define MM67_AL_MIN 11 /* minutes */ +#define MM67_AL_HOUR 12 /* hours */ +#define MM67_AL_DOW 13 /* day of the week */ +#define MM67_AL_DOM 14 /* day of the month */ +#define MM67_AL_MON 15 /* month */ +# define MM67_AL_DONTCARE 0xc0 /* always match in compare */ +#define MM67_ISTAT 16 /* IRQ status */ +#define MM67_ICTRL 17 /* IRQ control */ +# define MM67INT_COMPARE 0x01 /* Compare */ +# define MM67INT_TENTH 0x02 /* Tenth */ +# define MM67INT_SEC 0x04 /* Second */ +# define MM67INT_MIN 0x08 /* Minute */ +# define MM67INT_HOUR 0x10 /* Hour */ +# define MM67INT_DAY 0x20 /* Day */ +# define MM67INT_WEEK 0x40 /* Week */ +# define MM67INT_MON 0x80 /* Month */ +#define MM67_RSTCTR 18 /* reset counters */ +#define MM67_RSTRAM 19 /* reset RAM */ +#define MM67_STATUS 20 /* status bit */ +#define MM67_GOCMD 21 /* GO Command */ +#define MM67_STBYIRQ 22 /* standby IRQ */ +#define MM67_TEST 31 /* test mode */ + + +/* Check if the current time matches a set alarm time. */ +static int8_t +mm67_chkalrm(nvr_t *nvr, int8_t addr) +{ + return((nvr->regs[addr-MM67_AL_SEC+MM67_SEC] == nvr->regs[addr]) || + ((nvr->regs[addr] & MM67_AL_DONTCARE) == MM67_AL_DONTCARE)); +} + + +/* + * This is called every second through the NVR/RTC hook. + * + * We fake a 'running' RTC by updating its registers on + * each passing second. Not exactly accurate, but good + * enough. + * + * Note that this code looks nasty because of all the + * BCD to decimal vv going on. + */ +static void +mm67_tick(nvr_t *nvr) +{ + rtcdev_t *dev = (rtcdev_t *)nvr->data; + uint8_t *regs = nvr->regs; + int mon, year, f = 0; + + /* Update and set interrupt if needed. */ + regs[MM67_SEC] = RTC_BCDINC(nvr->regs[MM67_SEC], 1); + if (regs[MM67_ICTRL] & MM67INT_SEC) f = MM67INT_SEC; + + /* Roll over? */ + if (regs[MM67_SEC] >= RTC_BCD(60)) { + /* Update and set interrupt if needed. */ + regs[MM67_SEC] = RTC_BCD(0); + regs[MM67_MIN] = RTC_BCDINC(regs[MM67_MIN], 1); + if (regs[MM67_ICTRL] & MM67INT_MIN) f = MM67INT_MIN; + + /* Roll over? */ + if (regs[MM67_MIN] >= RTC_BCD(60)) { + /* Update and set interrupt if needed. */ + regs[MM67_MIN] = RTC_BCD(0); + regs[MM67_HOUR] = RTC_BCDINC(regs[MM67_HOUR], 1); + if (regs[MM67_ICTRL] & MM67INT_HOUR) f = MM67INT_HOUR; + + /* Roll over? */ + if (regs[MM67_HOUR] >= RTC_BCD(24)) { + /* Update and set interrupt if needed. */ + regs[MM67_HOUR] = RTC_BCD(0); + regs[MM67_DOW] = RTC_BCDINC(regs[MM67_DOW], 1); + if (regs[MM67_ICTRL] & MM67INT_DAY) f = MM67INT_DAY; + + /* Roll over? */ + if (regs[MM67_DOW] > RTC_BCD(7)) { + /* Update and set interrupt if needed. */ + regs[MM67_DOW] = RTC_BCD(1); + if (regs[MM67_ICTRL] & MM67INT_WEEK) f = MM67INT_WEEK; + } + + /* Roll over? */ + regs[MM67_DOM] = RTC_BCDINC(regs[MM67_DOM], 1); + mon = RTC_DCB(regs[MM67_MON]); + if (dev->year != -1) { + year = RTC_DCB(regs[dev->year]); + if (dev->flags & FLAG_YEAR80) + year += 80; + } else + year = 80; + year += 1900; + if (RTC_DCB(regs[MM67_DOM]) > nvr_get_days(mon, year)) { + /* Update and set interrupt if needed. */ + regs[MM67_DOM] = RTC_BCD(1); + regs[MM67_MON] = RTC_BCDINC(regs[MM67_MON], 1); + if (regs[MM67_ICTRL] & MM67INT_MON) f = MM67INT_MON; + + /* Roll over? */ + if (regs[MM67_MON] > RTC_BCD(12)) { + /* Update. */ + regs[MM67_MON] = RTC_BCD(1); + if (dev->year != -1) { + year++; + if (dev->flags & FLAG_YEAR80) + year -= 80; + + if (dev->flags & FLAG_YEARBCD) + regs[dev->year] = RTC_BCD(year % 100); + else + regs[dev->year] = year % 100; + } + } + } + } + } + } + + /* Check for programmed alarm interrupt. */ + if (regs[MM67_ICTRL] & MM67INT_COMPARE) { + year = 1; + for (mon = MM67_AL_SEC; mon <= MM67_AL_MON; mon++) + if (mon != dev->year) + year &= mm67_chkalrm(nvr, mon); + f = year ? MM67INT_COMPARE : 0x00; + } + + /* Raise the IRQ if needed (and if we have one..) */ + if (f != 0) { + regs[MM67_ISTAT] = f; + if (nvr->irq != -1) + picint(1 << nvr->irq); + } +} + + +/* Get the current NVR time. */ +static void +mm67_time_get(nvr_t *nvr, struct tm *tm) +{ + rtcdev_t *dev = (rtcdev_t *)nvr->data; + uint8_t *regs = nvr->regs; + + /* NVR is in BCD data mode. */ + tm->tm_sec = RTC_DCB(regs[MM67_SEC]); + tm->tm_min = RTC_DCB(regs[MM67_MIN]); + tm->tm_hour = RTC_DCB(regs[MM67_HOUR]); + tm->tm_wday = (RTC_DCB(regs[MM67_DOW]) - 1); + tm->tm_mday = RTC_DCB(regs[MM67_DOM]); + tm->tm_mon = (RTC_DCB(regs[MM67_MON]) - 1); + if (dev->year != -1) { + if (dev->flags & FLAG_YEARBCD) + tm->tm_year = RTC_DCB(regs[dev->year]); + else + tm->tm_year = regs[dev->year]; + if (dev->flags & FLAG_YEAR80) + tm->tm_year += 80; +#ifdef MM67_CENTURY + tm->tm_year += (regs[MM67_CENTURY] * 100) - 1900; +#endif +#if ISARTC_DEBUG > 1 + pclog("ISARTC: get_time: year=%i [%02x]\n", tm->tm_year, regs[dev->year]); +#endif + } +} + + +/* Set the current NVR time. */ +static void +mm67_time_set(nvr_t *nvr, struct tm *tm) +{ + rtcdev_t *dev = (rtcdev_t *)nvr->data; + uint8_t *regs = nvr->regs; + int year; + + /* NVR is in BCD data mode. */ + regs[MM67_SEC] = RTC_BCD(tm->tm_sec); + regs[MM67_MIN] = RTC_BCD(tm->tm_min); + regs[MM67_HOUR] = RTC_BCD(tm->tm_hour); + regs[MM67_DOW] = RTC_BCD(tm->tm_wday + 1); + regs[MM67_DOM] = RTC_BCD(tm->tm_mday); + regs[MM67_MON] = RTC_BCD(tm->tm_mon + 1); + if (dev->year != -1) { + year = tm->tm_year; + if (dev->flags & FLAG_YEAR80) + year -= 80; + if (dev->flags & FLAG_YEARBCD) + regs[dev->year] = RTC_BCD(year % 100); + else + regs[dev->year] = year % 100; +#ifdef MM67_CENTURY + regs[MM67_CENTURY] = (year + 1900) / 100; +#endif +#if ISARTC_DEBUG > 1 + pclog("ISARTC: set_time: [%02x] year=%i (%i)\n", regs[dev->year], year, tm->tm_year); +#endif + } +} + + +static void +mm67_start(nvr_t *nvr) +{ + struct tm tm; + + /* Initialize the internal and chip times. */ + if (time_sync) { + /* Use the internal clock's time. */ + nvr_time_get(&tm); + mm67_time_set(nvr, &tm); + } else { + /* Set the internal clock from the chip time. */ + mm67_time_get(nvr, &tm); + nvr_time_set(&tm); + } +} + + +/* Reset the RTC counters to a sane state. */ +static void +mm67_reset(nvr_t *nvr) +{ + int i; + + /* Initialize the RTC to a known state. */ + for (i = MM67_MSEC; i <= MM67_MON; i++) + nvr->regs[i] = RTC_BCD(0); + nvr->regs[MM67_DOW] = RTC_BCD(1); + nvr->regs[MM67_DOM] = RTC_BCD(1); + nvr->regs[MM67_MON] = RTC_BCD(1); +} + + +/* Handle a READ operation from one of our registers. */ +static uint8_t +mm67_read(uint16_t port, void *priv) +{ + rtcdev_t *dev = (rtcdev_t *)priv; + int reg = port - dev->base_addr; + uint8_t ret = 0xff; + + /* This chip is directly mapped on I/O. */ + cycles -= ISA_CYCLES(4); + + switch(reg) { + case MM67_ISTAT: /* IRQ status (RO) */ + ret = dev->nvr.regs[reg]; + dev->nvr.regs[reg] = 0x00; + if (dev->irq != -1) + picintc(1 << dev->irq); + break; + + default: + ret = dev->nvr.regs[reg]; + break; + } + +#if ISARTC_DEBUG + pclog("ISARTC: read(%04x) = %02x\n", port-dev->base_addr, ret); +#endif + + return(ret); +} + + +/* Handle a WRITE operation to one of our registers. */ +static void +mm67_write(uint16_t port, uint8_t val, void *priv) +{ + rtcdev_t *dev = (rtcdev_t *)priv; + int reg = port - dev->base_addr; + int i; + +#if ISARTC_DEBUG + pclog("ISARTC: write(%04x, %02x)\n", port-dev->base_addr, val); +#endif + + /* This chip is directly mapped on I/O. */ + cycles -= ISA_CYCLES(4); + + switch(reg) { + case MM67_ISTAT: /* intr status (RO) */ + break; + + case MM67_ICTRL: /* intr control */ + dev->nvr.regs[MM67_ISTAT] = 0x00; + dev->nvr.regs[reg] = val; + break; + + case MM67_RSTCTR: + if (val == 0xff) + mm67_reset(&dev->nvr); + break; + + case MM67_RSTRAM: + if (val == 0xff) { + for (i = MM67_AL_MSEC; i <= MM67_AL_MON; i++) + dev->nvr.regs[i] = RTC_BCD(0); + dev->nvr.regs[MM67_DOW] = RTC_BCD(1); + dev->nvr.regs[MM67_DOM] = RTC_BCD(1); + dev->nvr.regs[MM67_MON] = RTC_BCD(1); + if (dev->year != -1) { + val = (dev->flags & FLAG_YEAR80) ? 0 : 80; + if (dev->flags & FLAG_YEARBCD) + dev->nvr.regs[dev->year] = RTC_BCD(val); + else + dev->nvr.regs[dev->year] = val; +#ifdef MM67_CENTURY + dev->nvr.regs[MM67_CENTURY] = 19; +#endif + } + } + break; + + case MM67_STATUS: /* STATUS (RO) */ + break; + + case MM67_GOCMD: +pclog("RTC: write gocmd=%02x\n", val); + break; + + case MM67_STBYIRQ: +pclog("RTC: write stby=%02x\n", val); + break; + + case MM67_TEST: +pclog("RTC: write test=%02x\n", val); + break; + + default: + dev->nvr.regs[reg] = val; + break; + } +} + + +/************************************************************************ + * * + * Generic code for all supported chips. * + * * + ************************************************************************/ + +/* Initialize the device for use. */ +static void * +isartc_init(const device_t *info) +{ + rtcdev_t *dev; + + /* Create a device instance. */ + dev = (rtcdev_t *)malloc(sizeof(rtcdev_t)); + memset(dev, 0x00, sizeof(rtcdev_t)); + dev->name = info->name; + dev->board = info->local; + dev->irq = -1; + dev->year = -1; + dev->nvr.data = dev; + dev->nvr.size = 16; + + /* Do per-board initialization. */ + switch(dev->board) { + case 0: /* Everex EV-170 Magic I/O */ + dev->flags |= FLAG_YEAR80; + dev->base_addr = device_get_config_hex16("base"); + dev->base_addrsz = 32; + dev->irq = device_get_config_int("irq"); + dev->f_rd = mm67_read; + dev->f_wr = mm67_write; + dev->nvr.reset = mm67_reset; + dev->nvr.start = mm67_start; + dev->nvr.tick = mm67_tick; + dev->year = MM67_AL_DOM; /* year, NON STANDARD */ + break; + + case 1: /* DTK PII-147 Hexa I/O Plus */ + dev->flags |= FLAG_YEARBCD; + dev->base_addr = device_get_config_hex16("base"); + dev->base_addrsz = 32; + dev->f_rd = mm67_read; + dev->f_wr = mm67_write; + dev->nvr.reset = mm67_reset; + dev->nvr.start = mm67_start; + dev->nvr.tick = mm67_tick; + dev->year = MM67_AL_HUNTEN; /* year, NON STANDARD */ + break; + + case 2: /* Paradise Systems 5PAK */ + dev->flags |= FLAG_YEAR80; + dev->base_addr = 0x02c0; + dev->base_addrsz = 32; + dev->irq = device_get_config_int("irq"); + dev->f_rd = mm67_read; + dev->f_wr = mm67_write; + dev->nvr.reset = mm67_reset; + dev->nvr.start = mm67_start; + dev->nvr.tick = mm67_tick; + dev->year = MM67_AL_DOM; /* year, NON STANDARD */ + break; + + default: + break; + } + + /* Say hello! */ + pclog("ISARTC: %s (I/O=%04XH", info->name, dev->base_addr); + if (dev->irq != -1) + pclog(", IRQ%i", dev->irq); + pclog(")\n"); + + /* Set up an I/O port handler. */ + io_sethandler(dev->base_addr, dev->base_addrsz, + dev->f_rd,NULL,NULL, dev->f_wr,NULL,NULL, dev); + + /* Hook into the NVR backend. */ + dev->nvr.fn = (wchar_t *)isartc_get_internal_name(isartc_type); + dev->nvr.irq = dev->irq; + nvr_init(&dev->nvr); + + /* Let them know our device instance. */ + return((void *)dev); +} + + +/* Remove the device from the system. */ +static void +isartc_close(void *priv) +{ + rtcdev_t *dev = (rtcdev_t *)priv; + + io_removehandler(dev->base_addr, dev->base_addrsz, + dev->f_rd,NULL,NULL, dev->f_wr,NULL,NULL, dev); + + if (dev->nvr.fn != NULL) + free((wchar_t *)dev->nvr.fn); + + free(dev); +} + + +static const device_config_t ev170_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x02C0, + { + { + "240H", 0x0240 + }, + { + "2C0H", 0x02c0 + }, + { + "" + } + }, + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", -1, + { + { + "Disabled", -1 + }, + { + "IRQ2", 2 + }, + { + "IRQ5", 5 + }, + { + "IRQ7", 7 + }, + { + "" + } + }, + }, + { + "", "", -1 + } +}; + +static const device_t ev170_device = { + "Everex EV-170 Magic I/O", + DEVICE_ISA, + 0, + isartc_init, isartc_close, NULL, + NULL, NULL, NULL, + ev170_config +}; + + +static const device_config_t pii147_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x0240, + { + { + "Clock 1", 0x0240 + }, + { + "Clock 2", 0x0340 + }, + { + "" + } + }, + }, + { + "", "", -1 + } +}; + +static const device_t pii147_device = { + "DTK PII-147 Hexa I/O Plus", + DEVICE_ISA, + 1, + isartc_init, isartc_close, NULL, + NULL, NULL, NULL, + pii147_config +}; + + +static const device_config_t p5pak_config[] = { + { + "irq", "IRQ", CONFIG_SELECTION, "", -1, + { + { + "Disabled", -1 + }, + { + "IRQ2", 2 + }, + { + "IRQ3", 3 + }, + { + "IRQ5", 5 + }, + { + "" + } + }, + }, + { + "", "", -1 + } +}; + +static const device_t p5pak_device = { + "Paradise Systems 5-PAK", + DEVICE_ISA, + 2, + isartc_init, isartc_close, NULL, + NULL, NULL, NULL, + p5pak_config +}; + + +static const struct { + const char *name; + const char *internal_name; + const device_t *dev; +} boards[] = { + { "None", "none", NULL, }, + { "Everex EV-170 Magic I/O", "ev170", &ev170_device, }, + { "DTK PII-147 Hexa I/O Plus", "pii147", &pii147_device, }, + { "Paradise Systems 5-PAK", "p5pak", &p5pak_device, }, + { "", "", NULL, }, +}; + + +void +isartc_reset(void) +{ + if (isartc_type == 0) return; + + /* Add the device to the system. */ + device_add(boards[isartc_type].dev); +} + + +char * +isartc_get_name(int board) +{ + return((char *)boards[board].name); +} + + +char * +isartc_get_internal_name(int board) +{ + return((char *)boards[board].internal_name); +} + + +int +isartc_get_from_internal_name(char *s) +{ + int c = 0; + + while (strlen((char *) boards[c].internal_name)) { + if (! strcmp(boards[c].internal_name, s)) + return(c); + c++; + } + + /* Not found. */ + return(0); +} + + +const device_t * +isartc_get_device(int board) +{ + return(boards[board].dev); +} diff --git a/src/isartc.h b/src/isartc.h new file mode 100644 index 000000000..457cb1c6d --- /dev/null +++ b/src/isartc.h @@ -0,0 +1,71 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the ISARTC cards. + * + * Version: @(#)isartc.h 1.0.1 2018/08/27 + * + * Authors: Fred N. van Kempen, + * + * Copyright 2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef ISARTC_H +# define ISARTC_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Global variables. */ + + +/* Functions. */ +extern void isartc_reset(void); + +extern char *isartc_get_name(int t); +extern char *isartc_get_internal_name(int t); +extern int isartc_get_from_internal_name(char *s); +extern const device_t *isartc_get_device(int t); + +#ifdef __cplusplus +} +#endif + + +#endif /*ISARTC_H*/ diff --git a/src/machine/m_at.c b/src/machine/m_at.c index d4bf80adb..95fb5d182 100644 --- a/src/machine/m_at.c +++ b/src/machine/m_at.c @@ -1,3 +1,41 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Standard PC/AT implementation. + * + * Version: @(#)m_at.c 1.0.0 2018/09/02 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. +*/ #include #include #include @@ -46,6 +84,16 @@ machine_at_init(const machine_t *model) } +void +machine_at_ibm_init(const machine_t *model) +{ + machine_at_init(model); + + mem_remap_top(384); + + device_add(&fdc_at_device); +} + void machine_at_ps2_init(const machine_t *model) { @@ -80,30 +128,3 @@ machine_at_ps2_ide_init(const machine_t *model) device_add(&ide_isa_2ch_opt_device); } - - -void -machine_at_top_remap_init(const machine_t *model) -{ - machine_at_init(model); - - mem_remap_top_384k(); -} - - -void -machine_at_ide_top_remap_init(const machine_t *model) -{ - machine_at_ide_init(model); - - mem_remap_top_384k(); -} - - -void -machine_at_ibm_init(const machine_t *model) -{ - machine_at_top_remap_init(model); - - device_add(&fdc_at_device); -} diff --git a/src/machine/m_at_commodore.c b/src/machine/m_at_commodore.c index e12e13970..3fd264738 100644 --- a/src/machine/m_at_commodore.c +++ b/src/machine/m_at_commodore.c @@ -1,3 +1,41 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of the Commodore PC3 system. + * + * Version: @(#)m_at_commodore.c 1.0.0 2018/09/02 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. +*/ #include #include #include @@ -5,6 +43,7 @@ #include "../86box.h" #include "../device.h" #include "../io.h" +#include "../mem.h" #include "../lpt.h" #include "../serial.h" #include "../floppy/fdd.h" @@ -48,7 +87,10 @@ static void cbm_io_init() void machine_at_cmdpc_init(const machine_t *model) { - machine_at_ide_top_remap_init(model); + machine_at_ide_init(model); + + mem_remap_top(384); + device_add(&fdc_at_device); cbm_io_init(); diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 9497a8498..5b848873c 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -8,7 +8,7 @@ * * Emulation of various Compaq PC's. * - * Version: @(#)m_at_compaq.c 1.0.5 2018/03/18 + * Version: @(#)m_at_compaq.c 1.0.6 2018/09/02 * * Authors: Sarah Walker, * Miran Grca, @@ -100,7 +100,10 @@ write_raml(uint32_t addr, uint32_t val, void *priv) void machine_at_compaq_init(const machine_t *model) { - machine_at_top_remap_init(model); + machine_at_init(model); + + mem_remap_top(384); + device_add(&fdc_at_device); mem_mapping_add(&ram_mapping, 0xfa0000, 0x60000, diff --git a/src/machine/m_at_headland.c b/src/machine/m_at_headland.c index 4a0f9861c..aa28d4d16 100644 --- a/src/machine/m_at_headland.c +++ b/src/machine/m_at_headland.c @@ -523,9 +523,6 @@ headland_init(void) mem_mapping_disable(&headland_ems_mapping[i]); } - for(i=4; i<10; i++) - isram[i] = 0; - headland_memmap_state_update(); } diff --git a/src/machine/m_at_neat.c b/src/machine/m_at_neat.c index 2f789b3a1..19bd40304 100644 --- a/src/machine/m_at_neat.c +++ b/src/machine/m_at_neat.c @@ -1,89 +1,851 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Emulation of C&T CS8121 ("NEAT") 82C206/211/212/215 chipset. + * + * Note: The datasheet mentions that the chipset supports up to 8MB + * of DRAM. This is intepreted as 'being able to refresh up to + * 8MB of DRAM chips', because it works fine with bus-based + * memory expansion. + * + * Version: @(#)m_at_neat.c 1.0.1 2018/07/22 + * + * Author: Fred N. van Kempen, + * + * Copyright 2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/*This is the chipset used in the AMI 286 clone model*/ + #include #include +#include #include #include #include "../86box.h" #include "../device.h" -#include "../io.h" -#include "../keyboard.h" +#include "../cpu/cpu.h" +#include "../cpu/x86.h" #include "../floppy/fdd.h" #include "../floppy/fdc.h" +#include "../keyboard.h" +#include "../io.h" +#include "../mem.h" +#include "../nmi.h" +#include "../rom.h" #include "machine.h" - -static uint8_t neat_regs[256]; -static int neat_index; -static int neat_emspage[4]; +#define NEAT_DEBUG 0 -static void neat_write(uint16_t port, uint8_t val, void *priv) +#define EMS_MAXPAGE 4 +#define EMS_PGSIZE 16384 + + +/* CS8221 82C211 controller registers. */ +#define REG_RA0 0x60 /* PROCCLK selector */ +# define RA0_MASK 0x34 /* RR11 X1XR */ +# define RA0_READY 0x01 /* local bus READY timeout */ +# define RA0_RDYNMIEN 0x04 /* local bus READY tmo NMI enable */ +# define RA0_PROCCLK 0x10 /* PROCCLK=BCLK (1) or CLK2IN (0) */ +# define RA0_ALTRST 0x20 /* alternate CPU reset (1) */ +# define RA0_REV 0xc0 /* chip revision ID */ +# define RA0_REV_SH 6 +# define RA0_REV_ID 2 /* faked revision# for 82C211 */ + +#define REG_RA1 0x61 /* Command Delay */ +# define RA1_MASK 0xff /* 1111 1111 */ +# define RA1_BUSDLY 0x03 /* AT BUS command delay */ +# define RA1_BUSDLY_SH 0 +# define RA1_BUS8DLY 0x0c /* AT BUS 8bit command delay */ +# define RA1_BUS8DLY_SH 2 +# define RA1_MEMDLY 0x30 /* AT BUS 16bit memory delay */ +# define RA1_MEMDLY_SH 4 +# define RA1_QUICKEN 0x40 /* Quick Mode enable */ +# define RA1_HOLDDLY 0x80 /* Hold Time Delay */ + +#define REG_RA2 0x62 /* Wait State / BCLK selector */ +# define RA2_MASK 0x3f /* XX11 1111 */ +# define RA2_BCLK 0x03 /* BCLK select */ +# define RA2_BCLK_SH 0 +# define BCLK_IN2 0 /* BCLK = CLK2IN/2 */ +# define BCLK_IN 1 /* BCLK = CLK2IN */ +# define BCLK_AT 2 /* BCLK = ATCLK */ +# define RA2_AT8WS 0x0c /* AT 8-bit wait states */ +# define RA2_AT8WS_SH 2 +# define AT8WS_2 0 /* 2 wait states */ +# define AT8WS_3 1 /* 3 wait states */ +# define AT8WS_4 2 /* 4 wait states */ +# define AT8WS_5 4 /* 5 wait states */ +# define RA2_ATWS 0x30 /* AT 16-bit wait states */ +# define RA2_ATWS_SH 4 +# define ATWS_2 0 /* 2 wait states */ +# define ATWS_3 1 /* 3 wait states */ +# define ATWS_4 2 /* 4 wait states */ +# define ATWS_5 4 /* 5 wait states */ + +/* CS8221 82C212 controller registers. */ +#define REG_RB0 0x64 /* Version ID */ +# define RB0_MASK 0x60 /* R11X XXXX */ +# define RB0_REV 0x60 /* Chip revsion number */ +# define RB0_REV_SH 5 +# define RB0_REV_ID 2 /* faked revision# for 82C212 */ +# define RB0_VERSION 0x80 /* Chip version (0=82C212) */ + +#define REG_RB1 0x65 /* ROM configuration */ +# define RB1_MASK 0xff /* 1111 1111 */ +# define RB1_ROMF0 0x01 /* ROM F0000 enabled (0) */ +# define RB1_ROME0 0x02 /* ROM E0000 disabled (1) */ +# define RB1_ROMD0 0x04 /* ROM D0000 disabled (1) */ +# define RB1_ROMC0 0x08 /* ROM C0000 disabled (1) */ +# define RB1_SHADOWF0 0x10 /* Shadow F0000 R/W (0) */ +# define RB1_SHADOWE0 0x20 /* Shadow E0000 R/W (0) */ +# define RB1_SHADOWD0 0x40 /* Shadow D0000 R/W (0) */ +# define RB1_SHADOWC0 0x80 /* Shadow C0000 R/W (0) */ + +#define REG_RB2 0x66 /* Memory Enable 1 */ +# define RB2_MASK 0x80 /* 1XXX XXXX */ +# define RB2_TOP128 0x80 /* top 128K is on sysboard (1) */ + +#define REG_RB3 0x67 /* Memory Enable 2 */ +# define RB3_MASK 0xff /* 1111 1111 */ +# define RB3_SHENB0 0x01 /* enable B0000-B3FFF shadow (1) */ +# define RB3_SHENB4 0x02 /* enable B4000-B7FFF shadow (1) */ +# define RB3_SHENB8 0x04 /* enable B8000-BBFFF shadow (1) */ +# define RB3_SHENBC 0x08 /* enable BC000-BFFFF shadow (1) */ +# define RB3_SHENA0 0x10 /* enable A0000-A3FFF shadow (1) */ +# define RB3_SHENA4 0x20 /* enable A4000-A7FFF shadow (1) */ +# define RB3_SHENA8 0x40 /* enable A8000-ABFFF shadow (1) */ +# define RB3_SHENAC 0x80 /* enable AC000-AFFFF shadow (1) */ + +#define REG_RB4 0x68 /* Memory Enable 3 */ +# define RB4_MASK 0xff /* 1111 1111 */ +# define RB4_SHENC0 0x01 /* enable C0000-C3FFF shadow (1) */ +# define RB4_SHENC4 0x02 /* enable C4000-C7FFF shadow (1) */ +# define RB4_SHENC8 0x04 /* enable C8000-CBFFF shadow (1) */ +# define RB4_SHENCC 0x08 /* enable CC000-CFFFF shadow (1) */ +# define RB4_SHEND0 0x10 /* enable D0000-D3FFF shadow (1) */ +# define RB4_SHEND4 0x20 /* enable D4000-D7FFF shadow (1) */ +# define RB4_SHEND8 0x40 /* enable D8000-DBFFF shadow (1) */ +# define RB4_SHENDC 0x80 /* enable DC000-DFFFF shadow (1) */ + +#define REG_RB5 0x69 /* Memory Enable 4 */ +# define RB5_MASK 0xff /* 1111 1111 */ +# define RB5_SHENE0 0x01 /* enable E0000-E3FFF shadow (1) */ +# define RB5_SHENE4 0x02 /* enable E4000-E7FFF shadow (1) */ +# define RB5_SHENE8 0x04 /* enable E8000-EBFFF shadow (1) */ +# define RB5_SHENEC 0x08 /* enable EC000-EFFFF shadow (1) */ +# define RB5_SHENF0 0x10 /* enable F0000-F3FFF shadow (1) */ +# define RB5_SHENF4 0x20 /* enable F4000-F7FFF shadow (1) */ +# define RB5_SHENF8 0x40 /* enable F8000-FBFFF shadow (1) */ +# define RB5_SHENFC 0x80 /* enable FC000-FFFFF shadow (1) */ + +#define REG_RB6 0x6a /* Bank 0/1 Enable */ +# define RB6_MASK 0xe0 /* 111R RRRR */ +# define RB6_BANKS 0x20 /* #banks used (1=two) */ +# define RB6_RTYPE 0xc0 /* DRAM chip size used */ +# define RTYPE_SH 6 +# define RTYPE_NONE 0 /* Disabled */ +# define RTYPE_MIXED 1 /* 64K/256K mixed (for 640K) */ +# define RTYPE_256K 2 /* 256K (default) */ +# define RTYPE_1M 3 /* 1M */ + +#define REG_RB7 0x6b /* DRAM configuration */ +# define RB7_MASK 0xff /* 1111 1111 */ +# define RB7_ROMWS 0x03 /* ROM access wait states */ +# define RB7_ROMWS_SH 0 +# define ROMWS_0 0 /* 0 wait states */ +# define ROMWS_1 1 /* 1 wait states */ +# define ROMWS_2 2 /* 2 wait states */ +# define ROMWS_3 3 /* 3 wait states (default) */ +# define RB7_EMSWS 0x0c /* EMS access wait states */ +# define RB7_EMSWS_SH 2 +# define EMSWS_0 0 /* 0 wait states */ +# define EMSWS_1 1 /* 1 wait states */ +# define EMSWS_2 2 /* 2 wait states */ +# define EMSWS_3 3 /* 3 wait states (default) */ +# define RB7_EMSEN 0x10 /* enable EMS (1=on) */ +# define RB7_RAMWS 0x20 /* RAM access wait state (1=1ws) */ +# define RB7_UMAREL 0x40 /* relocate 640-1024K to 1M */ +# define RB7_PAGEEN 0x80 /* enable Page/Interleaved mode */ + +#define REG_RB8 0x6c /* Bank 2/3 Enable */ +# define RB8_MASK 0xf0 /* 1111 RRRR */ +# define RB8_4WAY 0x10 /* enable 4-way interleave mode */ +# define RB8_BANKS 0x20 /* enable 2 banks (1) */ +# define RB8_RTYPE 0xc0 /* DRAM chip size used */ +# define RB8_RTYPE_SH 6 + +#define REG_RB9 0x6d /* EMS base address */ +# define RB9_MASK 0xff /* 1111 1111 */ +# define RB9_BASE 0x0f /* I/O base address selection */ +# define RB9_BASE_SH 0 +# define RB9_FRAME 0xf0 /* frame address selection */ +# define RB9_FRAME_SH 4 + +#define REG_RB10 0x6e /* EMS address extension */ +# define RB10_MASK 0xff /* 1111 1111 */ +# define RB10_P3EXT 0x03 /* page 3 extension */ +# define RB10_P3EXT_SH 0 +# define PEXT_0M 0 /* page is at 0-2M */ +# define PEXT_2M 1 /* page is at 2-4M */ +# define PEXT_4M 2 /* page is at 4-6M */ +# define PEXT_6M 3 /* page is at 6-8M */ +# define RB10_P2EXT 0x0c /* page 2 extension */ +# define RB10_P2EXT_SH 2 +# define RB10_P1EXT 0x30 /* page 1 extension */ +# define RB10_P1EXT_SH 4 +# define RB10_P0EXT 0xc0 /* page 0 extension */ +# define RB10_P0EXT_SH 6 + +#define REG_RB11 0x6f /* Miscellaneous */ +# define RB11_MASK 0xe6 /* 111R R11R */ +# define RB11_GA20 0x02 /* gate for A20 */ +# define RB11_RASTMO 0x04 /* enable RAS timeout counter */ +# define RB11_EMSLEN 0xe0 /* EMS memory chunk size */ +# define RB11_EMSLEN_SH 5 + +typedef struct { + int8_t enabled; /* 1=ENABLED */ + char pad; + uint16_t page; /* selected page in EMS block */ + uint32_t start; /* start of EMS in RAM */ + uint8_t *addr; /* start addr in EMS RAM */ + mem_mapping_t mapping; /* mapping entry for page */ +} emspage_t; + +typedef struct { + uint8_t regs[128]; /* all the CS8221 registers */ + uint8_t indx; /* programmed index into registers */ + + char pad; + + uint16_t ems_base, /* configured base address */ + ems_oldbase; + uint32_t ems_frame, /* configured frame address */ + ems_oldframe; + uint16_t ems_size, /* EMS size in KB */ + ems_pages; /* EMS size in pages */ + emspage_t ems[EMS_MAXPAGE]; /* EMS page registers */ +} neat_t; + +/* Read one byte from paged RAM. */ +static uint8_t +ems_readb(uint32_t addr, void *priv) { - switch (port) - { - case 0x22: - neat_index = val; - break; - - case 0x23: - neat_regs[neat_index] = val; - switch (neat_index) - { - case 0x6E: /*EMS page extension*/ - neat_emspage[3] = (neat_emspage[3] & 0x7F) | (( val & 3) << 7); - neat_emspage[2] = (neat_emspage[2] & 0x7F) | (((val >> 2) & 3) << 7); - neat_emspage[1] = (neat_emspage[1] & 0x7F) | (((val >> 4) & 3) << 7); - neat_emspage[0] = (neat_emspage[0] & 0x7F) | (((val >> 6) & 3) << 7); - break; - } - break; + mem_mapping_t *map = (mem_mapping_t *)priv; + neat_t *dev = (neat_t *)map->dev; + uint8_t ret = 0xff; + int vpage; - case 0x0208: case 0x0209: case 0x4208: case 0x4209: - case 0x8208: case 0x8209: case 0xC208: case 0xC209: - neat_emspage[port >> 14] = (neat_emspage[port >> 14] & 0x180) | (val & 0x7F); - break; - } + /* Get the viewport page number. */ + vpage = ((addr & 0xffff) / EMS_PGSIZE); + + /* Grab the data. */ + ret = *(uint8_t *)(dev->ems[vpage].addr + (addr - map->base)); + + return(ret); } - -static uint8_t neat_read(uint16_t port, void *priv) +/* Read one word from paged RAM. */ +static uint16_t +ems_readw(uint32_t addr, void *priv) { - switch (port) - { - case 0x22: - return neat_index; - - case 0x23: - return neat_regs[neat_index]; - } - return 0xff; + mem_mapping_t *map = (mem_mapping_t *)priv; + neat_t *dev = (neat_t *)map->dev; + uint16_t ret = 0xffff; + int vpage; + + /* Get the viewport page number. */ + vpage = ((addr & 0xffff) / EMS_PGSIZE); + + /* Grab the data. */ + ret = *(uint16_t *)(dev->ems[vpage].addr + (addr - map->base)); + + return(ret); } - -#if NOT_USED -static void neat_writeems(uint32_t addr, uint8_t val) +/* Write one byte to paged RAM. */ +static void +ems_writeb(uint32_t addr, uint8_t val, void *priv) { - ram[(neat_emspage[(addr >> 14) & 3] << 14) + (addr & 0x3FFF)] = val; + mem_mapping_t *map = (mem_mapping_t *)priv; + neat_t *dev = (neat_t *)map->dev; + int vpage; + + /* Get the viewport page number. */ + vpage = ((addr & 0xffff) / EMS_PGSIZE); + + /* Write the data. */ + *(uint8_t *)(dev->ems[vpage].addr + (addr - map->base)) = val; } - -static uint8_t neat_readems(uint32_t addr) +/* Write one word to paged RAM. */ +static void +ems_writew(uint32_t addr, uint16_t val, void *priv) { - return ram[(neat_emspage[(addr >> 14) & 3] << 14) + (addr & 0x3FFF)]; + mem_mapping_t *map = (mem_mapping_t *)priv; + neat_t *dev = (neat_t *)map->dev; + int vpage; + + /* Get the viewport page number. */ + vpage = ((addr & 0xffff) / EMS_PGSIZE); + + /* Write the data. */ + *(uint16_t *)(dev->ems[vpage].addr + (addr - map->base)) = val; } + +/* Re-calculate the active-page physical address. */ +static void +ems_recalc(neat_t *dev, emspage_t *ems) +{ + if (ems->page >= dev->ems_pages) { + /* That page does not exist. */ + ems->enabled = 0; + } + + /* Pre-calculate the page address in EMS RAM. */ + ems->addr = ram + ems->start + (ems->page * EMS_PGSIZE); + + if (ems->enabled) { + /* Update the EMS RAM address for this page. */ + mem_mapping_set_exec(&ems->mapping, ems->addr); + + /* Enable this page. */ + mem_mapping_enable(&ems->mapping); + +#if NEAT_DEBUG > 1 + pclog("NEAT EMS: page %d set to %08lx, %sabled)\n", + ems->page, ems->addr-ram, ems->enabled?"en":"dis"); +#endif + } else { + /* Disable this page. */ + mem_mapping_disable(&ems->mapping); + } +} + +static void +ems_write(uint16_t port, uint8_t val, void *priv) +{ + neat_t *dev = (neat_t *)priv; + emspage_t *ems; + int vpage; + +#if NEAT_DEBUG > 1 + pclog("NEAT: ems_write(%04x, %02x)\n", port, val); #endif + /* Get the viewport page number. */ + vpage = (port / EMS_PGSIZE); + ems = &dev->ems[vpage]; -static void neat_init(void) + switch(port & 0x000f) { + case 0x0008: + case 0x0009: + ems->enabled = !!(val & 0x80); + ems->page &= 0x0180; /* clear lower bits */ + ems->page |= (val & 0x7f); /* add new bits */ + ems_recalc(dev, ems); + break; + } +} + +static uint8_t +ems_read(uint16_t port, void *priv) { - io_sethandler(0x0022, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL, NULL); - io_sethandler(0x0208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL, NULL); - io_sethandler(0x4208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL, NULL); - io_sethandler(0x8208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL, NULL); - io_sethandler(0xc208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL, NULL); + neat_t *dev = (neat_t *)priv; + uint8_t ret = 0xff; + int vpage; + + /* Get the viewport page number. */ + vpage = (port / EMS_PGSIZE); + + switch(port & 0x000f) { + case 0x0008: /* page number register */ + ret = dev->ems[vpage].page & 0x7f; + if (dev->ems[vpage].enabled) + ret |= 0x80; + break; + } + +#if NEAT_DEBUG > 1 + pclog("NEAT: ems_read(%04x) = %02x\n", port, ret); +#endif + + return(ret); +} + +/* Initialize the EMS module. */ +static void +ems_init(neat_t *dev, int en) +{ + int i; + + /* Remove if needed. */ + if (! en) { + if (dev->ems_base > 0) for (i = 0; i < EMS_MAXPAGE; i++) { + /* Disable for now. */ + mem_mapping_disable(&dev->ems[i].mapping); + + /* Remove I/O handler. */ + io_removehandler(dev->ems_base + (i * EMS_PGSIZE), 2, + ems_read,NULL,NULL, ems_write,NULL,NULL, dev); + } + + pclog("NEAT: EMS disabled\n"); + + return; + } + + /* Get configured I/O address. */ + i = (dev->regs[REG_RB9] & RB9_BASE) >> RB9_BASE_SH; + dev->ems_base = 0x0208 + (0x10 * i); + + /* Get configured frame address. */ + i = (dev->regs[REG_RB9] & RB9_FRAME) >> RB9_FRAME_SH; + dev->ems_frame = 0xC0000 + (EMS_PGSIZE * i); + + /* + * For each supported page (we can have a maximum of 4), + * create, initialize and disable the mappings, and set + * up the I/O control handler. + */ + for (i = 0; i < EMS_MAXPAGE; i++) { + /* Create and initialize a page mapping. */ + mem_mapping_add(&dev->ems[i].mapping, + dev->ems_frame + (EMS_PGSIZE*i), EMS_PGSIZE, + ems_readb, ems_readw, NULL, + ems_writeb, ems_writew, NULL, + ram, MEM_MAPPING_EXTERNAL, + &dev->ems[i].mapping); + mem_mapping_set_dev(&dev->ems[i].mapping, dev); + + /* Disable for now. */ + mem_mapping_disable(&dev->ems[i].mapping); + + /* Set up an I/O port handler. */ + io_sethandler(dev->ems_base + (i * EMS_PGSIZE), 2, + ems_read,NULL,NULL, ems_write,NULL,NULL, dev); + + /* + * TODO: update the 'high_mem' mapping to reflect that we now + * have NN MB less extended memory available.. + */ + } + + pclog("NEAT: EMS enabled, I/O=%04xH, Frame=%05XH\n", + dev->ems_base, dev->ems_frame); +} + +static void +neat_write(uint16_t port, uint8_t val, void *priv) +{ + neat_t *dev = (neat_t *)priv; + uint8_t xval, *reg; + int i; + +#if NEAT_DEBUG > 2 + pclog("NEAT: write(%04x, %02x)\n", port, val); +#endif + + switch (port) { + case 0x22: + dev->indx = val; + break; + + case 0x23: + reg = &dev->regs[dev->indx]; + xval = *reg ^ val; + switch (dev->indx) { + case REG_RA0: + val &= RA0_MASK; + *reg = (*reg & ~RA0_MASK) | val | \ + (RA0_REV_ID << RA0_REV_SH); +#if NEAT_DEBUG > 1 + pclog("NEAT: RA0=%02x(%02x)\n", val, *reg); +#endif + break; + + case REG_RA1: + val &= RA1_MASK; + *reg = (*reg & ~RA1_MASK) | val; +#if NEAT_DEBUG > 1 + pclog("NEAT: RA1=%02x(%02x)\n", val, *reg); +#endif + break; + + case REG_RA2: + val &= RA2_MASK; + *reg = (*reg & ~RA2_MASK) | val; +#if NEAT_DEBUG > 1 + pclog("NEAT: RA2=%02x(%02x)\n", val, *reg); +#endif + break; + + case REG_RB0: + val &= RB0_MASK; + *reg = (*reg & ~RB0_MASK) | val | \ + (RB0_REV_ID << RB0_REV_SH); +#if NEAT_DEBUG > 1 + pclog("NEAT: RB0=%02x(%02x)\n", val, *reg); +#endif + break; + + case REG_RB1: + val &= RB1_MASK; + *reg = (*reg & ~RB1_MASK) | val; +#if NEAT_DEBUG > 1 + pclog("NEAT: RB1=%02x(%02x)\n", val, *reg); +#endif + break; + + case REG_RB2: + val &= RB2_MASK; + *reg = (*reg & ~RB2_MASK) | val; +#if NEAT_DEBUG > 1 + pclog("NEAT: RB2=%02x(%02x)\n", val, *reg); +#endif + break; + + case REG_RB3: + val &= RB3_MASK; + *reg = (*reg & ~RB3_MASK) | val; +#if NEAT_DEBUG > 1 + pclog("NEAT: RB3=%02x(%02x)\n", val, *reg); +#endif + break; + + case REG_RB4: + val &= RB4_MASK; + *reg = (*reg & ~RB4_MASK) | val; +#if NEAT_DEBUG > 1 + pclog("NEAT: RB4=%02x(%02x)\n", val, *reg); +#endif + break; + + case REG_RB5: + val &= RB5_MASK; + *reg = (*reg & ~RB5_MASK) | val; +#if NEAT_DEBUG > 1 + pclog("NEAT: RB5=%02x(%02x)\n", val, *reg); +#endif + break; + + case REG_RB6: + val &= RB6_MASK; + *reg = (*reg & ~RB6_MASK) | val; +#if NEAT_DEBUG > 1 + pclog("NEAT: RB6=%02x(%02x)\n", val, *reg); +#endif + break; + + case REG_RB7: + val &= RB7_MASK; + *reg = (*reg & ~RB7_MASK) | val; +#if NEAT_DEBUG > 1 + pclog("NEAT: RB7=%02x(%02x)\n", val, *reg); +#endif + if (val & RB7_EMSEN) + ems_init(dev, 1); + else if (xval & RB7_EMSEN) + ems_init(dev, 0); + + if (xval & RB7_UMAREL) { + if (val & RB7_UMAREL) + mem_remap_top(384); + else + mem_remap_top(0); + } + break; + + case REG_RB8: + val &= RB8_MASK; + *reg = (*reg & ~RB8_MASK) | val; +#if NEAT_DEBUG > 1 + pclog("NEAT: RB8=%02x(%02x)\n", val, *reg); +#endif + break; + + case REG_RB9: + val &= RB9_MASK; + *reg = (*reg & ~RB9_MASK) | val; +#if NEAT_DEBUG > 1 + pclog("NEAT: RB9=%02x(%02x)\n", val, *reg); +#endif + if (dev->regs[REG_RB7] & RB7_EMSEN) { + ems_init(dev, 0); + ems_init(dev, 1); + } + break; + + case REG_RB10: + val &= RB10_MASK; + *reg = (*reg & ~RB10_MASK) | val; +#if NEAT_DEBUG > 1 + pclog("NEAT: RB10=%02x(%02x)\n", val, *reg); +#endif + + dev->ems[3].start = ((val & RB10_P3EXT) >> RB10_P3EXT_SH) << 21; + dev->ems[2].start = ((val & RB10_P2EXT) >> RB10_P2EXT_SH) << 21; + dev->ems[1].start = ((val & RB10_P1EXT) >> RB10_P1EXT_SH) << 21; + dev->ems[0].start = ((val & RB10_P0EXT) >> RB10_P0EXT_SH) << 21; + for (i = 0; i < EMS_MAXPAGE; i++) + ems_recalc(dev, &dev->ems[i]); + break; + + case REG_RB11: + val &= RB11_MASK; + *reg = (*reg & ~RB11_MASK) | val; +#if NEAT_DEBUG > 1 + pclog("NEAT: RB11=%02x(%02x)\n", val, *reg); +#endif + i = (val & RB11_EMSLEN) >> RB11_EMSLEN_SH; + switch(i) { + case 0: /* "less than 2MB" */ + dev->ems_size = 512; + break; + + case 1: /* 1 MB */ + case 2: /* 2 MB */ + case 3: /* 3 MB */ + case 4: /* 4 MB */ + case 5: /* 5 MB */ + case 6: /* 6 MB */ + case 7: /* 7 MB */ + dev->ems_size = i << 10; + break; + } + dev->ems_pages = (dev->ems_size << 10) / EMS_PGSIZE; + if (dev->regs[REG_RB7] & RB7_EMSEN) + pclog("NEAT: EMS %iKB (%i pages)\n", + dev->ems_size, dev->ems_pages); + break; + + default: + pclog("NEAT: inv write to reg %02x (%02x)\n", + dev->indx, val); + break; + } + break; + } +} + + +static uint8_t +neat_read(uint16_t port, void *priv) +{ + neat_t *dev = (neat_t *)priv; + uint8_t ret = 0xff; + + switch (port) { + case 0x22: + ret = dev->indx; + break; + + case 0x23: + ret = dev->regs[dev->indx]; + break; + + default: + break; + } + +#if NEAT_DEBUG > 2 + pclog("NEAT: read(%04x) = %02x\n", port, ret); +#endif + + return(ret); +} + + + + +static void +neat_init(void) +{ + neat_t *dev; + int i; + + /* Create an instance. */ + dev = (neat_t *)malloc(sizeof(neat_t)); + memset(dev, 0x00, sizeof(neat_t)); + + /* Initialize some of the registers to specific defaults. */ + for (i = REG_RA0; i <= REG_RB11; i++) { + dev->indx = i; + neat_write(0x0023, 0x00, dev); + } + + /* + * Based on the value of mem_size, we have to set up + * a proper DRAM configuration (so that EMS works.) + * + * TODO: We might also want to set 'valid' waitstate + * bits, based on our cpu speed. + */ + i = 0; + switch(mem_size) { + case 512: /* 512KB */ + /* 256K, 0, 0, 0 */ + dev->regs[REG_RB6] &= ~RB6_BANKS; /* one bank */ + dev->regs[REG_RB6] |= (RTYPE_256K<regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ + dev->regs[REG_RB8] |= (RTYPE_NONE<regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_MIXED<regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ + dev->regs[REG_RB8] |= (RTYPE_NONE<regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_256K<regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ + dev->regs[REG_RB8] |= (RTYPE_NONE<regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_256K<regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ + dev->regs[REG_RB8] |= (RTYPE_256K<regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_MIXED<regs[REG_RB8] |= RB8_BANKS; /* two banks */ + dev->regs[REG_RB8] |= (RTYPE_256K<regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_256K<regs[REG_RB8] |= RB8_BANKS; /* two banks */ + dev->regs[REG_RB8] |= (RTYPE_256K<regs[REG_RB8] |= RB8_4WAY; /* 4way intl */ + i = 11; +#else + /* 1M, 0, 0, 0 */ + dev->regs[REG_RB6] &= ~RB6_BANKS; /* one bank */ + dev->regs[REG_RB6] |= (RTYPE_1M<regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ + dev->regs[REG_RB8] |= (RTYPE_NONE<regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_256K<regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ + dev->regs[REG_RB8] |= (RTYPE_1M<regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_1M<regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ + dev->regs[REG_RB8] |= (RTYPE_NONE<regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_MIXED<regs[REG_RB8] |= RB8_BANKS; /* two banks */ + dev->regs[REG_RB8] |= (RTYPE_1M<regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_256K<regs[REG_RB8] |= RB8_BANKS; /* two banks */ + dev->regs[REG_RB8] |= (RTYPE_1M<regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_1M<regs[REG_RB8] &= ~RB8_BANKS; /* one bank */ + dev->regs[REG_RB8] |= (RTYPE_1M<regs[REG_RB6] |= RB6_BANKS; /* two banks */ + dev->regs[REG_RB6] |= (RTYPE_1M<regs[REG_RB8] |= RB8_BANKS; /* two banks */ + dev->regs[REG_RB8] |= (RTYPE_1M<regs[REG_RB8] |= RB8_4WAY; /* 4way intl */ + i = 14; + break; + + default: + pclog("NEAT: **INVALID DRAM SIZE %iKB !**\n", mem_size); + } + if (i > 0) + pclog("NEAT: using DRAM mode #%i (mem=%iKB)\n", i, mem_size); + + /* Set up an I/O handler for the chipset. */ + io_sethandler(0x0022, 2, + neat_read,NULL,NULL, neat_write,NULL,NULL, dev); } @@ -91,9 +853,10 @@ void machine_at_neat_init(const machine_t *model) { machine_at_init(model); - device_add(&fdc_at_device); - - neat_init(); + + neat_init(); + + device_add(&fdc_at_device); } @@ -102,8 +865,9 @@ machine_at_neat_ami_init(const machine_t *model) { machine_at_common_init(model); - device_add(&keyboard_at_ami_device); - device_add(&fdc_at_device); - - neat_init(); + neat_init(); + + device_add(&keyboard_at_ami_device); + + device_add(&fdc_at_device); } diff --git a/src/machine/m_at_scat.c b/src/machine/m_at_scat.c index c9af19fac..9cd99086b 100644 --- a/src/machine/m_at_scat.c +++ b/src/machine/m_at_scat.c @@ -10,7 +10,7 @@ * * Re-worked version based on the 82C235 datasheet and errata. * - * Version: @(#)m_at_scat.c 1.0.15 2018/04/29 + * Version: @(#)m_at_scat.c 1.0.16 2018/09/02 * * Authors: Original by GreatPsycho for PCem. * Fred N. van Kempen, @@ -1259,7 +1259,6 @@ scat_init() scat_port_92 = 0; mem_mapping_disable(&ram_low_mapping); - mem_mapping_disable(&ram_mid_mapping); mem_mapping_disable(&ram_high_mapping); for (i = 0; i < 4; i++) mem_mapping_disable(&bios_mapping[i]); @@ -1282,8 +1281,6 @@ scat_init() mem_mapping_add(&scat_ems_mapping[i], (i + (i >= 24 ? 28 : 16)) << 14, 0x04000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + ((i + (i >= 24 ? 28 : 16)) << 14), 0, &scat_stat[i]); } - for(i=4;i<10;i++) isram[i] = 0; - for (i = (scat_regs[SCAT_VERSION] < 4 ? 0 : 8); i < 16; i++) { mem_mapping_add(&scat_high_mapping[i], (i << 14) + 0xFC0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), 0, NULL); mem_mapping_enable(&scat_high_mapping[i]); @@ -1333,7 +1330,6 @@ scatsx_init() scat_port_92 = 0; mem_mapping_disable(&ram_low_mapping); - mem_mapping_disable(&ram_mid_mapping); mem_mapping_disable(&ram_high_mapping); for (i = 0; i < 4; i++) mem_mapping_disable(&bios_mapping[i]); diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index 46086b9a6..1df063517 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -28,7 +28,7 @@ * boot. Sometimes, they do, and then it shows an "Incorrect * DOS" error message?? --FvK * - * Version: @(#)m_ps1.c 1.0.9 2018/04/26 + * Version: @(#)m_ps1.c 1.0.10 2018/09/02 * * Authors: Sarah Walker, * Miran Grca, @@ -512,7 +512,7 @@ ps1_common_init(const machine_t *model) { machine_common_init(model); - mem_remap_top_384k(); + mem_remap_top(384); pit_set_out_func(&pit, 1, pit_refresh_timer_at); diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index d0c02a579..92390e629 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -1,3 +1,41 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of MCA-based PS/2 machines. + * + * Version: @(#)m_ps2_mca.c 1.0.0 2018/09/02 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. +*/ #include #include #include @@ -830,7 +868,7 @@ static void ps2_mca_board_model_50_init() { ps2_mca_board_common_init(); - mem_remap_top_384k(); + mem_remap_top(384); mca_init(4); ps2.planar_read = model_50_read; @@ -864,7 +902,7 @@ static void ps2_mca_board_model_55sx_init() NULL); - mem_remap_top_256k(); + mem_remap_top(256); ps2.option[3] = 0x10; memset(ps2.memory_bank, 0xf0, 8); @@ -1019,10 +1057,13 @@ static void mem_encoding_write_cached(uint16_t addr, uint8_t val, void *p) ps2.pending_cache_miss = 1; if ((val & 0x21) == 0x01 && (old & 0x21) != 0x01) ps2_cache_clean(); +#if 1 + // FIXME: Look into this!!! if (val & 0x01) ram_mid_mapping.flags |= MEM_MAPPING_ROM; else ram_mid_mapping.flags &= ~MEM_MAPPING_ROM; +#endif break; } ps2_mca_log("mem_encoding_write: addr=%02x val=%02x %04x:%04x %02x %02x\n", addr, val, CS,cpu_state.pc, ps2.mem_regs[1],ps2.mem_regs[2]); diff --git a/src/machine/machine.h b/src/machine/machine.h index 94e92a924..3293501db 100644 --- a/src/machine/machine.h +++ b/src/machine/machine.h @@ -8,7 +8,7 @@ * * Handling of the emulated machines. * - * Version: @(#)machine.h 1.0.26 2018/08/16 + * Version: @(#)machine.h 1.0.27 2018/09/02 * * Authors: Sarah Walker, * Miran Grca, @@ -96,14 +96,11 @@ extern void machine_common_init(const machine_t *); extern void machine_at_common_init(const machine_t *); extern void machine_at_init(const machine_t *); +extern void machine_at_ibm_init(const machine_t *); extern void machine_at_ps2_init(const machine_t *); extern void machine_at_common_ide_init(const machine_t *); extern void machine_at_ide_init(const machine_t *); extern void machine_at_ps2_ide_init(const machine_t *); -extern void machine_at_top_remap_init(const machine_t *); -extern void machine_at_ide_top_remap_init(const machine_t *); - -extern void machine_at_ibm_init(const machine_t *); extern void machine_at_t3100e_init(const machine_t *); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 8b025c343..19984903f 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -11,7 +11,7 @@ * NOTES: OpenAT wip for 286-class machine with open BIOS. * PS2_M80-486 wip, pending receipt of TRM's for machine. * - * Version: @(#)machine_table.c 1.0.33 2018/08/16 + * Version: @(#)machine_table.c 1.0.35 2018/09/02 * * Authors: Sarah Walker, * Miran Grca, @@ -34,37 +34,37 @@ const machine_t machines[] = { - { "[8088] AMI XT clone", ROM_AMIXT, "amixt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, - { "[8088] Compaq Portable", ROM_PORTABLE, "portable", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, machine_xt_compaq_init, NULL }, - { "[8088] DTK XT clone", ROM_DTKXT, "dtk", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, - { "[8088] IBM PC", ROM_IBMPC, "ibmpc", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 32, 0, machine_xt_init, NULL }, - { "[8088] IBM PCjr", ROM_IBMPCJR, "ibmpcjr", {{"", cpus_pcjr}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, machine_pcjr_init, pcjr_get_device }, - { "[8088] IBM XT", ROM_IBMXT, "ibmxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, - { "[8088] Generic XT clone", ROM_GENXT, "genxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, - { "[8088] Juko XT clone", ROM_JUKOPC, "jukopc", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, - { "[8088] Phoenix XT clone", ROM_PXXT, "pxxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, - { "[8088] Schneider EuroPC", ROM_EUROPC, "europc", {{"Siemens",cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_HDC | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 15, machine_europc_init, NULL }, - { "[8088] Tandy 1000", ROM_TANDY, "tandy", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 128, 640, 128, 0, machine_tandy1k_init, tandy1k_get_device }, - { "[8088] Tandy 1000 HX", ROM_TANDY1000HX, "tandy1000hx", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 256, 640, 128, 0, machine_tandy1k_init, tandy1k_hx_get_device }, - { "[8088] Toshiba T1000", ROM_T1000, "t1000", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO, 512, 1280, 768, 63, machine_xt_t1000_init, t1000_get_device }, + { "[8088] AMI XT clone", ROM_AMIXT, "amixt", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, + { "[8088] Compaq Portable", ROM_PORTABLE, "portable", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, machine_xt_compaq_init, NULL }, + { "[8088] DTK XT clone", ROM_DTKXT, "dtk", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, + { "[8088] IBM PC", ROM_IBMPC, "ibmpc", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 32, 0, machine_xt_init, NULL }, + { "[8088] IBM PCjr", ROM_IBMPCJR, "ibmpcjr", {{"Intel", cpus_pcjr}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, machine_pcjr_init, pcjr_get_device }, + { "[8088] IBM XT", ROM_IBMXT, "ibmxt", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, + { "[8088] Generic XT clone", ROM_GENXT, "genxt", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, + { "[8088] Juko XT clone", ROM_JUKOPC, "jukopc", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, + { "[8088] Phoenix XT clone", ROM_PXXT, "pxxt", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, + { "[8088] Schneider EuroPC", ROM_EUROPC, "europc", {{"Siemens", cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_HDC | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 15, machine_europc_init, NULL }, + { "[8088] Tandy 1000", ROM_TANDY, "tandy", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 128, 640, 128, 0, machine_tandy1k_init, tandy1k_get_device }, + { "[8088] Tandy 1000 HX", ROM_TANDY1000HX, "tandy1000hx", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 256, 640, 128, 0, machine_tandy1k_init, tandy1k_hx_get_device }, + { "[8088] Toshiba T1000", ROM_T1000, "t1000", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO, 512, 1280, 768, 63, machine_xt_t1000_init, t1000_get_device }, #if defined(DEV_BRANCH) && defined(USE_LASERXT) - { "[8088] VTech Laser Turbo XT", ROM_LTXT, "ltxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 512, 512, 256, 0, machine_xt_laserxt_init, NULL }, + { "[8088] VTech Laser Turbo XT", ROM_LTXT, "ltxt", {{"Intel", cpus_8088}, {"", NULL},, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 512, 512, 256, 0, machine_xt_laserxt_init, NULL }, #endif - { "[8088] Xi8088", ROM_XI8088, "xi8088", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 64, 1024, 128, 127, machine_xt_xi8088_init, NULL }, + { "[8088] Xi8088", ROM_XI8088, "xi8088", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 64, 1024, 128, 127, machine_xt_xi8088_init, NULL }, - { "[8086] Amstrad PC1512", ROM_PC1512, "pc1512", {{"", cpus_pc1512}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 63, machine_amstrad_init, NULL }, - { "[8086] Amstrad PC1640", ROM_PC1640, "pc1640", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 63, machine_amstrad_init, NULL }, - { "[8086] Amstrad PC2086", ROM_PC2086, "pc2086", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 63, machine_amstrad_init, NULL }, - { "[8086] Amstrad PC3086", ROM_PC3086, "pc3086", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 63, machine_amstrad_init, NULL }, - { "[8086] Amstrad PC20(0)", ROM_PC200, "pc200", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 63, machine_amstrad_init, NULL }, - { "[8086] Olivetti M24", ROM_OLIM24, "olivetti_m24", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 128, 640, 128, 0, machine_olim24_init, NULL }, - { "[8086] Tandy 1000 SL/2", ROM_TANDY1000SL2, "tandy1000sl2", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 512, 768, 128, 0, machine_tandy1k_init, NULL }, - { "[8086] Toshiba T1200", ROM_T1200, "t1200", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO, 1024, 2048,1024, 63, machine_xt_t1200_init, t1200_get_device }, + { "[8086] Amstrad PC1512", ROM_PC1512, "pc1512", {{"Intel", cpus_pc1512}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 63, machine_amstrad_init, NULL }, + { "[8086] Amstrad PC1640", ROM_PC1640, "pc1640", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 63, machine_amstrad_init, NULL }, + { "[8086] Amstrad PC2086", ROM_PC2086, "pc2086", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 63, machine_amstrad_init, NULL }, + { "[8086] Amstrad PC3086", ROM_PC3086, "pc3086", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 63, machine_amstrad_init, NULL }, + { "[8086] Amstrad PC20(0)", ROM_PC200, "pc200", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 63, machine_amstrad_init, NULL }, + { "[8086] Olivetti M24", ROM_OLIM24, "olivetti_m24", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 128, 640, 128, 0, machine_olim24_init, NULL }, + { "[8086] Tandy 1000 SL/2", ROM_TANDY1000SL2, "tandy1000sl2", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 512, 768, 128, 0, machine_tandy1k_init, NULL }, + { "[8086] Toshiba T1200", ROM_T1200, "t1200", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO, 1024, 2048,1024, 63, machine_xt_t1200_init, t1200_get_device }, #if defined(DEV_BRANCH) && defined(USE_LASERXT) - { "[8086] VTech Laser XT3", ROM_LXT3, "lxt3", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 256, 512, 256, 0, machine_xt_laserxt_init, NULL }, + { "[8086] VTech Laser XT3", ROM_LXT3, "lxt3", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 256, 512, 256, 0, machine_xt_laserxt_init, NULL }, #endif - { "[286 ISA] AMI 286 clone", ROM_AMI286, "ami286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_neat_ami_init, NULL }, + { "[286 ISA] AMI 286 clone", ROM_AMI286, "ami286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,8192, 128, 127, machine_at_neat_ami_init, NULL }, { "[286 ISA] Award 286 clone", ROM_AWARD286, "award286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_scat_init, NULL }, { "[286 ISA] Commodore PC 30 III", ROM_CMDPC30, "cmdpc30", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 127, machine_at_cmdpc_init, NULL }, { "[286 ISA] Compaq Portable II", ROM_PORTABLEII, "portableii", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 127, machine_at_compaq_init, NULL }, @@ -87,11 +87,11 @@ const machine_t machines[] = { { "[286 MCA] IBM PS/2 model 50", ROM_IBMPS2_M50, "ibmps2_m50", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2 | MACHINE_VIDEO, 1, 10, 1, 63, machine_ps2_model_50_init, NULL }, - { "[386SX ISA] AMA-932J", ROM_AMA932J, "ama932j", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, 512, 8192, 128, 127, machine_at_headland_init, at_ama932j_get_device }, + { "[386SX ISA] AMA-932J", ROM_AMA932J, "ama932j", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, 512, 8192, 128, 127, machine_at_headland_init, at_ama932j_get_device }, { "[386SX ISA] AMI 386SX clone", ROM_AMI386SX, "ami386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512,16384, 128, 127, machine_at_headland_init, NULL }, { "[386SX ISA] Amstrad MegaPC", ROM_MEGAPC, "megapc", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, 1, 16, 1, 127, machine_at_wd76c10_init, NULL }, { "[386SX ISA] Award 386SX clone", ROM_AWARD386SX_OPTI495, "award386sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_opti495_init, NULL }, - { "[386SX ISA] DTK 386SX clone", ROM_DTK386, "dtk386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512,16384, 128, 127, machine_at_neat_init, NULL }, + { "[386SX ISA] DTK 386SX clone", ROM_DTK386, "dtk386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512,8192, 128, 127, machine_at_neat_init, NULL }, { "[386SX ISA] IBM PS/1 model 2121", ROM_IBMPS1_2121, "ibmps1_2121", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 63, machine_ps1_m2121_init, NULL }, { "[386SX ISA] IBM PS/1 m.2121+ISA", ROM_IBMPS1_2121_ISA, "ibmps1_2121_isa", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 63, machine_ps1_m2121_init, NULL }, { "[386SX ISA] KMX-C-02", ROM_KMXC02, "kmxc02", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 512, 127, machine_at_scatsx_init, NULL }, @@ -101,7 +101,7 @@ const machine_t machines[] = { { "[386DX ISA] AMI 386DX clone", ROM_AMI386DX_OPTI495, "ami386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_opti495_ami_init, NULL }, { "[386DX ISA] Amstrad MegaPC 386DX", ROM_MEGAPCDX, "megapcdx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 32, 1, 127, machine_at_wd76c10_init, NULL }, { "[386DX ISA] Award 386DX clone", ROM_AWARD386DX_OPTI495, "award386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_opti495_init, NULL }, - { "[386DX ISA] MR 386DX clone", ROM_MR386DX_OPTI495, "mr386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_opti495_ami_init, NULL }, + { "[386DX ISA] MR 386DX clone", ROM_MR386DX_OPTI495, "mr386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_opti495_ami_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_PORTABLE3) { "[386DX ISA] Compaq Portable III (386)", ROM_PORTABLEIII386, "portableiii386", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, 1, 14, 1, 127, machine_at_compaq_init, NULL }, #endif diff --git a/src/mem.c b/src/mem.c index 632484a21..b77a32d17 100644 --- a/src/mem.c +++ b/src/mem.c @@ -12,7 +12,7 @@ * the DYNAMIC_TABLES=1 enables this. Will eventually go * away, either way... * - * Version: @(#)mem.c 1.0.11 2018/08/20 + * Version: @(#)mem.c 1.0.12 2018/09/02 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -71,19 +71,23 @@ #define DYNAMIC_TABLES 0 /* experimental */ -mem_mapping_t ram_low_mapping; -mem_mapping_t ram_high_mapping; -mem_mapping_t ram_mid_mapping; -mem_mapping_t bios_mapping[8]; -mem_mapping_t bios_high_mapping[8]; -mem_mapping_t romext_mapping; +mem_mapping_t base_mapping, + ram_low_mapping, /* 0..640K mapping */ +#if 1 + ram_mid_mapping, +#endif + ram_remapped_mapping, /* 640..1024K mapping */ + ram_high_mapping, /* 1024K+ mapping */ + ram_remapped_mapping, + ram_split_mapping, + bios_mapping[8], + bios_high_mapping[8], + romext_mapping; page_t *pages, /* RAM page table */ **page_lookup; /* pagetable lookup */ uint32_t pages_sz; /* #pages in table */ -uint8_t isram[0x10000]; - uint8_t *ram; /* the virtual RAM */ uint32_t rammask; @@ -139,9 +143,6 @@ static mem_mapping_t *_mem_mapping_r[0x40000]; static mem_mapping_t *_mem_mapping_w[0x40000]; static int _mem_state[0x40000]; -static mem_mapping_t base_mapping; -static mem_mapping_t ram_remapped_mapping; - #if FIXME static uint8_t ff_array[0x1000]; #else @@ -1359,7 +1360,7 @@ mem_mapping_write_allowed(uint32_t flags, int state) static void mem_mapping_recalc(uint64_t base, uint64_t size) { - mem_mapping_t *mapping = base_mapping.next; + mem_mapping_t *map = base_mapping.next; uint64_t c; if (! size) return; @@ -1369,7 +1370,6 @@ mem_mapping_recalc(uint64_t base, uint64_t size) _mem_read_b[c >> 14] = NULL; _mem_read_w[c >> 14] = NULL; _mem_read_l[c >> 14] = NULL; - _mem_exec[c >> 14] = NULL; _mem_priv_r[c >> 14] = NULL; _mem_mapping_r[c >> 14] = NULL; _mem_write_b[c >> 14] = NULL; @@ -1380,38 +1380,38 @@ mem_mapping_recalc(uint64_t base, uint64_t size) } /* Walk mapping list. */ - while (mapping != NULL) { + while (map != NULL) { /*In range?*/ - if (mapping->enable && (uint64_t)mapping->base < ((uint64_t)base + (uint64_t)size) && ((uint64_t)mapping->base + (uint64_t)mapping->size) > (uint64_t)base) { - uint64_t start = (mapping->base < base) ? mapping->base : base; - uint64_t end = (((uint64_t)mapping->base + (uint64_t)mapping->size) < (base + size)) ? ((uint64_t)mapping->base + (uint64_t)mapping->size) : (base + size); - if (start < mapping->base) - start = mapping->base; + if (map->enable && (uint64_t)map->base < ((uint64_t)base + (uint64_t)size) && ((uint64_t)map->base + (uint64_t)map->size) > (uint64_t)base) { + uint64_t start = (map->base < base) ? map->base : base; + uint64_t end = (((uint64_t)map->base + (uint64_t)map->size) < (base + size)) ? ((uint64_t)map->base + (uint64_t)map->size) : (base + size); + if (start < map->base) + start = map->base; for (c = start; c < end; c += 0x4000) { - if ((mapping->read_b || mapping->read_w || mapping->read_l) && - mem_mapping_read_allowed(mapping->flags, _mem_state[c >> 14])) { - _mem_read_b[c >> 14] = mapping->read_b; - _mem_read_w[c >> 14] = mapping->read_w; - _mem_read_l[c >> 14] = mapping->read_l; - if (mapping->exec) - _mem_exec[c >> 14] = mapping->exec + (c - mapping->base); + if ((map->read_b || map->read_w || map->read_l) && + mem_mapping_read_allowed(map->flags, _mem_state[c >> 14])) { + _mem_read_b[c >> 14] = map->read_b; + _mem_read_w[c >> 14] = map->read_w; + _mem_read_l[c >> 14] = map->read_l; + if (map->exec) + _mem_exec[c >> 14] = map->exec + (c - map->base); else _mem_exec[c >> 14] = NULL; - _mem_priv_r[c >> 14] = mapping->p; - _mem_mapping_r[c >> 14] = mapping; + _mem_priv_r[c >> 14] = map->p; + _mem_mapping_r[c >> 14] = map; } - if ((mapping->write_b || mapping->write_w || mapping->write_l) && - mem_mapping_write_allowed(mapping->flags, _mem_state[c >> 14])) { - _mem_write_b[c >> 14] = mapping->write_b; - _mem_write_w[c >> 14] = mapping->write_w; - _mem_write_l[c >> 14] = mapping->write_l; - _mem_priv_w[c >> 14] = mapping->p; - _mem_mapping_w[c >> 14] = mapping; + if ((map->write_b || map->write_w || map->write_l) && + mem_mapping_write_allowed(map->flags, _mem_state[c >> 14])) { + _mem_write_b[c >> 14] = map->write_b; + _mem_write_w[c >> 14] = map->write_w; + _mem_write_l[c >> 14] = map->write_l; + _mem_priv_w[c >> 14] = map->p; + _mem_mapping_w[c >> 14] = map; } } } - mapping = mapping->next; + map = map->next; } flushmmucache_cr3(); @@ -1419,7 +1419,24 @@ mem_mapping_recalc(uint64_t base, uint64_t size) void -mem_mapping_add(mem_mapping_t *mapping, +mem_mapping_del(mem_mapping_t *map) +{ + mem_mapping_t *ptr; + + /* Disable the entry. */ + mem_mapping_disable(map); + + /* Zap it from the list. */ + for (ptr = &base_mapping; ptr->next != NULL; ptr = ptr->next) { + if (ptr->next == map) { + ptr->next = map->next; + break; + } + } +} + +void +mem_mapping_add(mem_mapping_t *map, uint32_t base, uint32_t size, uint8_t (*read_b)(uint32_t addr, void *p), @@ -1429,7 +1446,7 @@ mem_mapping_add(mem_mapping_t *mapping, void (*write_w)(uint32_t addr, uint16_t val, void *p), void (*write_l)(uint32_t addr, uint32_t val, void *p), uint8_t *exec, - uint32_t flags, + uint32_t fl, void *p) { mem_mapping_t *dest = &base_mapping; @@ -1437,32 +1454,33 @@ mem_mapping_add(mem_mapping_t *mapping, /* Add mapping to the end of the list.*/ while (dest->next) dest = dest->next; - dest->next = mapping; - mapping->prev = dest; + dest->next = map; + map->prev = dest; if (size) - mapping->enable = 1; + map->enable = 1; else - mapping->enable = 0; - mapping->base = base; - mapping->size = size; - mapping->read_b = read_b; - mapping->read_w = read_w; - mapping->read_l = read_l; - mapping->write_b = write_b; - mapping->write_w = write_w; - mapping->write_l = write_l; - mapping->exec = exec; - mapping->flags = flags; - mapping->p = p; - mapping->next = NULL; + map->enable = 0; + map->base = base; + map->size = size; + map->read_b = read_b; + map->read_w = read_w; + map->read_l = read_l; + map->write_b = write_b; + map->write_w = write_w; + map->write_l = write_l; + map->exec = exec; + map->flags = fl; + map->p = p; + map->dev = NULL; + map->next = NULL; - mem_mapping_recalc(mapping->base, mapping->size); + mem_mapping_recalc(map->base, map->size); } void -mem_mapping_set_handler(mem_mapping_t *mapping, +mem_mapping_set_handler(mem_mapping_t *map, uint8_t (*read_b)(uint32_t addr, void *p), uint16_t (*read_w)(uint32_t addr, void *p), uint32_t (*read_l)(uint32_t addr, void *p), @@ -1470,64 +1488,71 @@ mem_mapping_set_handler(mem_mapping_t *mapping, void (*write_w)(uint32_t addr, uint16_t val, void *p), void (*write_l)(uint32_t addr, uint32_t val, void *p)) { - mapping->read_b = read_b; - mapping->read_w = read_w; - mapping->read_l = read_l; - mapping->write_b = write_b; - mapping->write_w = write_w; - mapping->write_l = write_l; + map->read_b = read_b; + map->read_w = read_w; + map->read_l = read_l; + map->write_b = write_b; + map->write_w = write_w; + map->write_l = write_l; - mem_mapping_recalc(mapping->base, mapping->size); + mem_mapping_recalc(map->base, map->size); } void -mem_mapping_set_addr(mem_mapping_t *mapping, uint32_t base, uint32_t size) +mem_mapping_set_addr(mem_mapping_t *map, uint32_t base, uint32_t size) { /* Remove old mapping. */ - mapping->enable = 0; - mem_mapping_recalc(mapping->base, mapping->size); + map->enable = 0; + mem_mapping_recalc(map->base, map->size); /* Set new mapping. */ - mapping->enable = 1; - mapping->base = base; - mapping->size = size; + map->enable = 1; + map->base = base; + map->size = size; - mem_mapping_recalc(mapping->base, mapping->size); + mem_mapping_recalc(map->base, map->size); } void -mem_mapping_set_exec(mem_mapping_t *mapping, uint8_t *exec) +mem_mapping_set_exec(mem_mapping_t *map, uint8_t *exec) { - mapping->exec = exec; + map->exec = exec; - mem_mapping_recalc(mapping->base, mapping->size); + mem_mapping_recalc(map->base, map->size); } void -mem_mapping_set_p(mem_mapping_t *mapping, void *p) +mem_mapping_set_p(mem_mapping_t *map, void *p) { - mapping->p = p; + map->p = p; } void -mem_mapping_disable(mem_mapping_t *mapping) +mem_mapping_set_dev(mem_mapping_t *map, void *p) { - mapping->enable = 0; - - mem_mapping_recalc(mapping->base, mapping->size); + map->dev = p; } void -mem_mapping_enable(mem_mapping_t *mapping) +mem_mapping_disable(mem_mapping_t *map) { - mapping->enable = 1; + map->enable = 0; - mem_mapping_recalc(mapping->base, mapping->size); + mem_mapping_recalc(map->base, map->size); +} + + +void +mem_mapping_enable(mem_mapping_t *map) +{ + map->enable = 1; + + mem_mapping_recalc(map->base, map->size); } @@ -1754,15 +1779,6 @@ mem_log("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz); } } - /* Initialize the tables. */ - memset(isram, 0x00, sizeof(isram)); - for (c = 0; c < (mem_size / 64); c++) { - isram[c] = 1; - if ((c >= 0xa && c <= 0xf) || - (cpu_16bitbus && c >= 0xfe && c <= 0xff)) - isram[c] = 0; - } - memset(_mem_read_b, 0x00, sizeof(_mem_read_b)); memset(_mem_read_w, 0x00, sizeof(_mem_read_w)); memset(_mem_read_l, 0x00, sizeof(_mem_read_l)); @@ -1811,18 +1827,18 @@ mem_log("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz); mem_read_ram,mem_read_ramw,mem_read_raml, mem_write_ram,mem_write_ramw,mem_write_raml, ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL); - + if (romset == ROM_IBMPS1_2011) mem_mapping_add(&romext_mapping, 0xc8000, 0x08000, mem_read_romext,mem_read_romextw,mem_read_romextl, NULL,NULL, NULL, romext, 0, NULL); mem_mapping_add(&ram_remapped_mapping, mem_size * 1024, 256 * 1024, - mem_read_remapped, mem_read_remappedw, mem_read_remappedl, - mem_write_remapped, mem_write_remappedw, mem_write_remappedl, - ram + 0xA0000, MEM_MAPPING_INTERNAL, NULL); - mem_mapping_disable(&ram_remapped_mapping); - + mem_read_remapped,mem_read_remappedw,mem_read_remappedl, + mem_write_remapped,mem_write_remappedw,mem_write_remappedl, + ram + 0xa0000, MEM_MAPPING_INTERNAL, NULL); + mem_mapping_disable(&ram_remapped_mapping); + mem_a20_init(); } @@ -1858,45 +1874,33 @@ mem_init(void) } -static void -mem_remap_top(int max_size) +void +mem_remap_top(int kb) { - uint32_t c; + uint32_t start = (mem_size >= 1024) ? mem_size : 1024; + int size = mem_size - 640; - if (mem_size > 640) { - uint32_t start = (mem_size >= 1024) ? mem_size : 1024; - int size = mem_size - 640; - if (size > max_size) - size = max_size; +pclog("MEM: remapping top %iKB (mem=%i)\n", kb, mem_size); + if (mem_size <= 640) return; - for (c = (start / 64); c < ((start + size - 1) / 64); c++) - isram[c] = 1; + if (kb == 0) { + /* Called to disable the mapping. */ + mem_mapping_disable(&ram_remapped_mapping); - mem_set_mem_state(start * 1024, size * 1024, - MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_set_addr(&ram_remapped_mapping, - start * 1024, size * 1024); + return; + } + + if (size > kb) + size = kb; + + mem_set_mem_state(start * 1024, size * 1024, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_mapping_set_addr(&ram_remapped_mapping, start * 1024, size * 1024); mem_mapping_set_exec(&ram_remapped_mapping, ram + (start * 1024)); - flushmmucache(); - } + flushmmucache(); } - -void -mem_remap_top_256k(void) -{ - mem_remap_top(256); -} - - -void -mem_remap_top_384k(void) -{ - mem_remap_top(384); -} - - void mem_reset_page_blocks(void) { diff --git a/src/mem.h b/src/mem.h index 660bab616..6139b6dad 100644 --- a/src/mem.h +++ b/src/mem.h @@ -8,7 +8,7 @@ * * Definitions for the memory interface. * - * Version: @(#)mem.h 1.0.4 2018/03/16 + * Version: @(#)mem.h 1.0.5 2018/09/02 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -77,7 +77,9 @@ typedef struct _mem_mapping_ { uint32_t flags; - void *p; + void *p; /* backpointer to mapping or device */ + + void *dev; /* backpointer to memory device */ } mem_mapping_t; typedef struct _page_ { @@ -114,12 +116,16 @@ extern uintptr_t *writelookup2; extern int writelnext; extern uint32_t ram_mapped_addr[64]; -extern mem_mapping_t bios_mapping[8], - bios_high_mapping[8], - romext_mapping, +mem_mapping_t base_mapping, ram_low_mapping, +#if 1 ram_mid_mapping, - ram_high_mapping; +#endif + ram_remapped_mapping, + ram_high_mapping, + bios_mapping[8], + bios_high_mapping[8], + romext_mapping; extern uint32_t mem_logical_addr; @@ -135,7 +141,6 @@ extern int readlnum, extern int nopageerrors; extern int memspeed[11]; -extern uint8_t isram[0x10000]; extern int mmu_perm; @@ -165,7 +170,10 @@ extern uint32_t mmutranslatereal(uint32_t addr, int rw); extern void addreadlookup(uint32_t virt, uint32_t phys); extern void addwritelookup(uint32_t virt, uint32_t phys); -extern void mem_mapping_add(mem_mapping_t *mapping, + +extern void mem_mapping_del(mem_mapping_t *); + +extern void mem_mapping_add(mem_mapping_t *, uint32_t base, uint32_t size, uint8_t (*read_b)(uint32_t addr, void *p), @@ -178,7 +186,7 @@ extern void mem_mapping_add(mem_mapping_t *mapping, uint32_t flags, void *p); -extern void mem_mapping_set_handler(mem_mapping_t *mapping, +extern void mem_mapping_set_handler(mem_mapping_t *, uint8_t (*read_b)(uint32_t addr, void *p), uint16_t (*read_w)(uint32_t addr, void *p), uint32_t (*read_l)(uint32_t addr, void *p), @@ -186,22 +194,26 @@ extern void mem_mapping_set_handler(mem_mapping_t *mapping, void (*write_w)(uint32_t addr, uint16_t val, void *p), void (*write_l)(uint32_t addr, uint32_t val, void *p)); -extern void mem_mapping_set_p(mem_mapping_t *mapping, void *p); +extern void mem_mapping_set_p(mem_mapping_t *, void *p); -extern void mem_mapping_set_addr(mem_mapping_t *mapping, +extern void mem_mapping_set_dev(mem_mapping_t *, void *dev); + +extern void mem_mapping_set_addr(mem_mapping_t *, uint32_t base, uint32_t size); -extern void mem_mapping_set_exec(mem_mapping_t *mapping, uint8_t *exec); -extern void mem_mapping_disable(mem_mapping_t *mapping); -extern void mem_mapping_enable(mem_mapping_t *mapping); +extern void mem_mapping_set_exec(mem_mapping_t *, uint8_t *exec); +extern void mem_mapping_disable(mem_mapping_t *); +extern void mem_mapping_enable(mem_mapping_t *); extern void mem_set_mem_state(uint32_t base, uint32_t size, int state); extern uint8_t mem_readb_phys(uint32_t addr); extern uint8_t mem_readb_phys_dma(uint32_t addr); extern uint16_t mem_readw_phys(uint32_t addr); +extern uint32_t mem_readl_phys(uint32_t addr); extern void mem_writeb_phys(uint32_t addr, uint8_t val); extern void mem_writeb_phys_dma(uint32_t addr, uint8_t val); extern void mem_writew_phys(uint32_t addr, uint16_t val); +extern void mem_writel_phys(uint32_t addr, uint32_t val); extern uint8_t mem_read_ram(uint32_t addr, void *priv); extern uint16_t mem_read_ramw(uint32_t addr, void *priv); @@ -240,8 +252,7 @@ extern void mem_add_bios(void); extern void mem_init(void); extern void mem_reset(void); -extern void mem_remap_top_256k(void); -extern void mem_remap_top_384k(void); +extern void mem_remap_top(int kb); extern uint8_t port_92_read(uint16_t port, void *priv); extern void port_92_write(uint16_t port, uint8_t val, void *priv); diff --git a/src/pc.c b/src/pc.c index ef1381563..5f302cd4e 100644 --- a/src/pc.c +++ b/src/pc.c @@ -8,7 +8,7 @@ * * Main emulator module where most things are controlled. * - * Version: @(#)pc.c 1.0.75 2018/08/16 + * Version: @(#)pc.c 1.0.76 2018/09/02 * * Authors: Sarah Walker, * Miran Grca, @@ -47,6 +47,8 @@ #include "nvr.h" #include "machine/machine.h" #include "bugger.h" +#include "isamem.h" +#include "isartc.h" #include "lpt.h" #include "serial.h" #include "keyboard.h" @@ -107,7 +109,9 @@ int vid_cga_contrast = 0, /* (C) video */ force_43 = 0; /* (C) video */ int serial_enabled[SERIAL_MAX] = {0,0}, /* (C) enable serial ports */ lpt_enabled = 0, /* (C) enable LPT ports */ - bugger_enabled = 0; /* (C) enable ISAbugger */ + bugger_enabled = 0, /* (C) enable ISAbugger */ + isamem_type[ISAMEM_MAX] = { 0,0,0,0 }, /* (C) enable ISA mem cards */ + isartc_type = 0; /* (C) enable ISA RTC card */ int gfxcard = 0; /* (C) graphics/video card */ int sound_is_float = 1, /* (C) sound uses FP values */ GAMEBLASTER = 0, /* (C) sound option */ @@ -769,6 +773,12 @@ pc_reset_hard_init(void) video_font_reset(); /* Reset (deallocate) the video font arrays. */ machine_init(); + /* Reset any ISA memory cards. */ + isamem_reset(); + + /* Reset any ISA RTC cards. */ + isartc_reset(); + fdd_reset(); /* diff --git a/src/sound/snd_mpu401.c b/src/sound/snd_mpu401.c index c73db820d..0923a4a35 100644 --- a/src/sound/snd_mpu401.c +++ b/src/sound/snd_mpu401.c @@ -30,6 +30,7 @@ #include "../86box.h" #include "../device.h" #include "../io.h" +#include "../mca.h" #include "../pic.h" #include "../timer.h" #include "sound.h" @@ -73,6 +74,7 @@ mpu401_log(const char *fmt, ...) #endif } +int mca_version = 0; static void QueueByte(mpu_t *mpu, uint8_t data) @@ -827,7 +829,7 @@ MPU401_Event(void *priv) next_event: /* mpu401_event_callback = 0LL; */ new_time = ((mpu->clock.tempo * mpu->clock.timebase * mpu->clock.tempo_rel)/0x40); - if (new_time == 0) { + if (new_time == 0) { mpu401_event_callback = 0LL; return; } else { @@ -873,11 +875,52 @@ mpu401_device_add(void) if (!mpu401_standalone_enable) return; n = sound_card_get_internal_name(sound_card_current); - if (n != NULL) { - if (!strcmp(n, "sb16") || !strcmp(n, "sbawe32")) return; + if (n != NULL) + { + if (!strcmp(n, "ncraudio")) + mca_version = 1; + else + mca_version = 0; + + if (!strcmp(n, "sb16") || !strcmp(n, "sbawe32") || !strcmp(n, "replysb16")) return; } - device_add(&mpu401_device); + if (mca_version) + device_add(&mpu401_mca_device); + else + device_add(&mpu401_device); +} + +static uint8_t mpu401_mca_read(int port, void *p) +{ + mpu_t *mpu = (mpu_t *)p; + + return mpu->pos_regs[port & 7]; +} + +static void mpu401_mca_write(int port, uint8_t val, void *p) +{ + mpu_t *mpu = (mpu_t *)p; + uint16_t addr; + + if (port < 0x102) + return; + + addr = (mpu->pos_regs[2] & 2) ? 0x0330 : 0x1330; + + io_removehandler(addr, 2, + mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu); + io_removehandler(0x2A20, 16, + NULL, NULL, NULL, imf_write, NULL, NULL, mpu); + + mpu->pos_regs[port & 7] = val; + + if (mpu->pos_regs[2] & 1) + { + addr = (mpu->pos_regs[2] & 2) ? 0x0330 : 0x1330; + + mpu401_init(mpu, addr, device_get_config_int("irq"), device_get_config_int("mode")); + } } @@ -890,9 +933,17 @@ mpu401_standalone_init(const device_t *info) memset(mpu, 0, sizeof(mpu_t)); mpu401_log("mpu_init\n"); - mpu401_init(mpu, device_get_config_hex16("base"), device_get_config_int("irq"), device_get_config_int("mode")); + + if (info->flags & DEVICE_MCA) + { + mca_add(mpu401_mca_read, mpu401_mca_write, mpu); + mpu->pos_regs[0] = 0x0F; + mpu->pos_regs[1] = 0x6C; + } + else + mpu401_init(mpu, device_get_config_hex16("base"), device_get_config_int("irq"), device_get_config_int("mode")); - return(mpu); + return(mpu); } @@ -967,12 +1018,69 @@ static const device_config_t mpu401_standalone_config[] = }; +static const device_config_t mpu401_mca_standalone_config[] = +{ + { + "irq", "MPU-401 IRQ", CONFIG_SELECTION, "", 9, + { + { + "IRQ 9", 9 + }, + { + "IRQ 3", 3 + }, + { + "IRQ 4", 4 + }, + { + "IRQ 5", 5 + }, + { + "IRQ 7", 7 + }, + { + "IRQ 10", 10 + }, + { + "" + } + } + }, + { + "mode", "Mode", CONFIG_SELECTION, "", 1, + { + { + "UART", M_UART + }, + { + "Intelligent", M_INTELLIGENT + }, + { + "" + } + } + }, + { + "", "", -1 + } +}; + const device_t mpu401_device = { "MPU-401 (Standalone)", - 0, 0, + DEVICE_ISA, 0, mpu401_standalone_init, mpu401_standalone_close, NULL, NULL, NULL, NULL, mpu401_standalone_config }; + +const device_t mpu401_mca_device = { + "MPU-401 MCA (Standalone)", + DEVICE_MCA, 0, + mpu401_standalone_init, mpu401_standalone_close, NULL, + NULL, + NULL, + NULL, + mpu401_mca_standalone_config +}; diff --git a/src/sound/snd_mpu401.h b/src/sound/snd_mpu401.h index 0dda1b25a..835594db4 100644 --- a/src/sound/snd_mpu401.h +++ b/src/sound/snd_mpu401.h @@ -80,15 +80,18 @@ typedef struct mpu_t uint8_t cth_rate,cth_counter; int clock_to_host,cth_active; } clock; + + uint8_t pos_regs[8]; } mpu_t; uint8_t MPU401_ReadData(mpu_t *mpu); void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode); +extern int mca_version; extern int mpu401_standalone_enable; void mpu401_device_add(void); const device_t mpu401_device; +const device_t mpu401_mca_device; -void mpu401_uart_init(mpu_t *mpu, uint16_t addr); diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index dc45ae143..d2dc8c067 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -38,6 +38,7 @@ #include "vid_ati_eeprom.h" #include "vid_svga.h" #include "vid_svga_render.h" +#include "vid_sc1502x_ramdac.h" #define BIOS_ATIKOR_PATH L"roms/video/ati28800/atikorvga.bin" @@ -58,6 +59,7 @@ typedef struct ati28800_t { svga_t svga; ati_eeprom_t eeprom; + sc1502x_ramdac_t ramdac; rom_t bios_rom; @@ -65,6 +67,7 @@ typedef struct ati28800_t int index; uint32_t memory; + uint8_t id; uint8_t port_03dd_val; uint16_t get_korean_font_kind; @@ -95,6 +98,7 @@ ati28800_log(const char *fmt, ...) #endif } +static void ati28800_recalctimings(svga_t *svga); static void ati28800_out(uint16_t addr, uint8_t val, void *p) { @@ -115,25 +119,43 @@ static void ati28800_out(uint16_t addr, uint8_t val, void *p) case 0x1cf: old=ati28800->regs[ati28800->index]; ati28800->regs[ati28800->index] = val; + pclog("ATI write reg=%02x\n", ati28800->index); switch (ati28800->index) { case 0xb2: - case 0xbe: + case 0xbe: + case 0xbd: if (ati28800->regs[0xbe] & 8) /*Read/write bank mode*/ { - svga->read_bank = ((ati28800->regs[0xb2] >> 5) & 7) * 0x10000; - svga->write_bank = ((ati28800->regs[0xb2] >> 1) & 7) * 0x10000; + if (ati28800->regs[0xbd] & 4) + { + svga->read_bank = (((ati28800->regs[0xb2] >> 5) & 7) * 0x20000); + svga->write_bank = (((ati28800->regs[0xb2] >> 1) & 7) * 0x20000); + } + else + { + svga->read_bank = (((ati28800->regs[0xb2] >> 5) & 7) * 0x10000); + svga->write_bank = (((ati28800->regs[0xb2] >> 1) & 7) * 0x10000); + } } else /*Single bank mode*/ - svga->read_bank = svga->write_bank = ((ati28800->regs[0xb2] >> 1) & 7) * 0x10000; + { + if (ati28800->regs[0xbd] & 4) + { + svga->read_bank = (((ati28800->regs[0xb2] >> 1) & 7) * 0x20000); + svga->write_bank = (((ati28800->regs[0xb2] >> 1) & 7) * 0x20000); + } + else + { + svga->read_bank = (((ati28800->regs[0xb2] >> 1) & 7) * 0x10000); + svga->write_bank = (((ati28800->regs[0xb2] >> 1) & 7) * 0x10000); + } + } break; case 0xb3: ati_eeprom_write(&ati28800->eeprom, val & 8, val & 2, val & 1); break; case 0xb6: - if (val & 1) - pclog("Extended 0xB6 bit 0 enabled\n"); - if((old ^ val) & 0x10) svga_recalctimings(svga); break; case 0xb8: @@ -141,9 +163,14 @@ static void ati28800_out(uint16_t addr, uint8_t val, void *p) break; case 0xb9: if((old ^ val) & 2) svga_recalctimings(svga); + break; } break; - + + case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: + sc1502x_ramdac_out(addr, val, &ati28800->ramdac, svga); + return; + case 0x3D4: svga->crtcreg = val & 0x3f; return; @@ -250,15 +277,20 @@ static uint8_t ati28800_in(uint16_t addr, void *p) case 0x1cf: switch (ati28800->index) { - case 0xb0: - if (ati28800->memory == 256) - return 0x08; - else if (ati28800->memory == 512) - return 0x10; - else - return 0x18; + case 0xaa: + temp = ati28800->id; break; + case 0xb0: + if (ati28800->memory == 1024) + temp = 0x08; + else if (ati28800->memory == 512) + temp = 0x10; + else + temp = 0x00; + ati28800->regs[0xb0] |= temp; + break; + case 0xb7: temp = ati28800->regs[ati28800->index] & ~8; if (ati_eeprom_read(&ati28800->eeprom)) @@ -277,6 +309,10 @@ static uint8_t ati28800_in(uint16_t addr, void *p) else temp = 0x10; break; + + case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: + return sc1502x_ramdac_in(addr, &ati28800->ramdac, svga); + case 0x3D4: temp = svga->crtcreg; break; @@ -359,12 +395,12 @@ static void ati28800_recalctimings(svga_t *svga) if(ati28800->regs[0xb8] & 0x40) svga->clock *= 2; - if (ati28800->regs[0xb6] & 0x10) - { - svga->hdisp <<= 1; - svga->htotal <<= 1; - svga->rowoffset <<= 1; - } + if (ati28800->regs[0xb6] & 0x10) + { + svga->hdisp <<= 1; + svga->htotal <<= 1; + svga->rowoffset <<= 1; + } if(svga->crtc[0x17] & 4) { @@ -377,10 +413,21 @@ static void ati28800_recalctimings(svga_t *svga) if (!svga->scrblank && (ati28800->regs[0xb0] & 0x20)) /*Extended 256 colour modes*/ { - svga->render = svga_render_8bpp_highres; - svga->bpp = 8; - svga->rowoffset <<= 1; - svga->ma <<= 1; + switch (svga->bpp) + { + case 8: + svga->render = svga_render_8bpp_highres; + svga->rowoffset <<= 1; + svga->ma <<= 1; + break; + + case 15: + svga->render = svga_render_15bpp_highres; + svga->hdisp >>= 1; + svga->rowoffset <<= 1; + svga->ma <<= 1; + break; + } } } @@ -435,15 +482,16 @@ ati28800k_init(const device_t *info) static void * ati28800_init(const device_t *info) { - ati28800_t *ati; - ati = malloc(sizeof(ati28800_t)); - memset(ati, 0x00, sizeof(ati28800_t)); + ati28800_t *ati28800; + ati28800 = malloc(sizeof(ati28800_t)); + memset(ati28800, 0x00, sizeof(ati28800_t)); - ati->memory = device_get_config_int("memory"); + ati28800->memory = device_get_config_int("memory"); switch(info->local) { case GFX_VGAWONDERXL: - rom_init_interleaved(&ati->bios_rom, + ati28800->id = 6; + rom_init_interleaved(&ati28800->bios_rom, BIOS_VGAXL_EVEN_PATH, BIOS_VGAXL_ODD_PATH, 0xc0000, 0x10000, 0xffff, @@ -452,7 +500,8 @@ ati28800_init(const device_t *info) #if defined(DEV_BRANCH) && defined(USE_XL24) case GFX_VGAWONDERXL24: - rom_init_interleaved(&ati->bios_rom, + ati28800->id = 6; + rom_init_interleaved(&ati28800->bios_rom, BIOS_XL24_EVEN_PATH, BIOS_XL24_ODD_PATH, 0xc0000, 0x10000, 0xffff, @@ -461,47 +510,48 @@ ati28800_init(const device_t *info) #endif default: - rom_init(&ati->bios_rom, + ati28800->id = 5; + rom_init(&ati28800->bios_rom, BIOS_ROM_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); break; } - svga_init(&ati->svga, ati, ati->memory << 10, /*default: 512kb*/ + svga_init(&ati28800->svga, ati28800, ati28800->memory << 10, /*default: 512kb*/ ati28800_recalctimings, ati28800_in, ati28800_out, NULL, - NULL); - + NULL); + io_sethandler(0x01ce, 2, ati28800_in, NULL, NULL, - ati28800_out, NULL, NULL, ati); + ati28800_out, NULL, NULL, ati28800); io_sethandler(0x03c0, 32, ati28800_in, NULL, NULL, - ati28800_out, NULL, NULL, ati); + ati28800_out, NULL, NULL, ati28800); - ati->svga.miscout = 1; + ati28800->svga.miscout = 1; switch (info->local) { case GFX_VGAWONDERXL: - ati_eeprom_load(&ati->eeprom, L"ati28800xl.nvr", 0); + ati_eeprom_load(&ati28800->eeprom, L"ati28800xl.nvr", 0); break; #if defined(DEV_BRANCH) && defined(USE_XL24) case GFX_VGAWONDERXL24: - ati_eeprom_load(&ati->eeprom, L"ati28800xl24.nvr", 0); + ati_eeprom_load(&ati28800->eeprom, L"ati28800xl24.nvr", 0); break; #endif default: - ati_eeprom_load(&ati->eeprom, L"ati28800.nvr", 0); + ati_eeprom_load(&ati28800->eeprom, L"ati28800.nvr", 0); break; } - return(ati); + return(ati28800); } @@ -538,11 +588,11 @@ ati28800_wonderxl24_available(void) static void ati28800_close(void *priv) { - ati28800_t *ati = (ati28800_t *)priv; + ati28800_t *ati28800 = (ati28800_t *)priv; - svga_close(&ati->svga); + svga_close(&ati28800->svga); - free(ati); + free(ati28800); } @@ -558,9 +608,9 @@ ati28800_speed_changed(void *p) static void ati28800_force_redraw(void *priv) { - ati28800_t *ati = (ati28800_t *)priv; + ati28800_t *ati28800 = (ati28800_t *)priv; - ati->svga.fullchange = changeframecount; + ati28800->svga.fullchange = changeframecount; } diff --git a/src/video/vid_table.c b/src/video/vid_table.c index d329e655f..61c4f6ed3 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -8,7 +8,7 @@ * * Define all known video cards. * - * Version: @(#)vid_table.c 1.0.33 2018/08/16 + * Version: @(#)vid_table.c 1.0.35 2018/09/02 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -62,6 +62,7 @@ enum { VIDEO_ISA = 0, + VIDEO_MCA, VIDEO_BUS }; @@ -84,7 +85,7 @@ static const VIDEO_CARD video_cards[] = { { "None", "none", NULL, GFX_NONE }, { "Internal", "internal", NULL, GFX_INTERNAL, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, - { "[ISA] ATI Graphics Pro Turbo (Mach64 GX)", "mach64gx_isa", &mach64gx_isa_device, GFX_MACH64GX_ISA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}}, + { "[ISA] ATI Graphics Pro Turbo (Mach64 GX)", "mach64gx_isa", &mach64gx_isa_device, GFX_MACH64GX_ISA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}}, { "[ISA] ATI Korean VGA (ATI-28800-5)", "ati28800k", &ati28800k_device, GFX_ATIKOREANVGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}}, { "[ISA] ATI VGA-88 (ATI-18800-1)", "ati18800v", &ati18800_vga88_device, GFX_VGA88, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, { "[ISA] ATI VGA Charger (ATI-28800-5)", "ati28800", &ati28800_device, GFX_VGACHARGER, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}}, @@ -125,7 +126,7 @@ video_cards[] = { {"[ISA] Tseng ET4000AX", "et4000ax", &et4000_isa_device, GFX_ET4000_ISA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}}, {"[ISA] VGA", "vga", &vga_device, GFX_VGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, {"[ISA] Wyse 700", "wy700", &wy700_device, GFX_WY700, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, - {"[MCA] Tseng ET4000AX", "et4000mca", &et4000_mca_device, GFX_ET4000_MCA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 3, 3, 6, 5, 5, 10}}, + {"[MCA] Tseng ET4000AX", "et4000mca", &et4000_mca_device, GFX_ET4000_MCA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_MCA, 4, 5, 10, 5, 5, 10}}, {"[PCI] ATI Graphics Pro Turbo (Mach64 GX)", "mach64gx_pci", &mach64gx_pci_device, GFX_MACH64GX_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}}, {"[PCI] ATI Video Xpression (Mach64 VT2)", "mach64vt2", &mach64vt2_device, GFX_MACH64VT2, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}}, {"[PCI] Cardex Tseng ET4000/w32p", "et4000w32p_pci", &et4000w32p_cardex_pci_device, GFX_ET4000W32_CARDEX_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 4, 10, 10, 10}}, diff --git a/src/win/86Box.rc b/src/win/86Box.rc index d119bffc1..69b011bc4 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -8,7 +8,7 @@ * * Application resource script for Windows. * - * Version: @(#)86Box.rc 1.0.40 2018/08/04 + * Version: @(#)86Box.rc 1.0.41 2018/09/02 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -434,7 +434,7 @@ BEGIN BS_AUTOCHECKBOX | WS_TABSTOP,7,82,94,10 END -DLG_CFG_PERIPHERALS DIALOG DISCARDABLE 97, 0, 267, 97 +DLG_CFG_PERIPHERALS DIALOG DISCARDABLE 97, 0, 267, 200 STYLE DS_CONTROL | WS_CHILD FONT 9, "Segoe UI" BEGIN @@ -458,6 +458,29 @@ BEGIN CONTROL "ISABugger device",IDC_CHECK_BUGGER,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,7,80,94,10 + + LTEXT "ISA RTC",IDT_1767,7,99,61,10 + COMBOBOX IDC_COMBO_ISARTC,71,98,140,120, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Configure",IDC_CONFIGURE_ISARTC,214,98,46,12 + + GROUPBOX "ISA Memory Expansion",IDC_GROUP_ISAMEM,7,118,255,70 + LTEXT "#1:",IDT_1763,12,130,21,10 + COMBOBOX IDC_COMBO_ISAMEM_1,25,129,180,120, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Configure",IDC_CONFIGURE_ISAMEM_1,209,129,46,12 + LTEXT "#2:",IDT_1764,12,144,21,10 + COMBOBOX IDC_COMBO_ISAMEM_2,25,143,180,120, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Configure",IDC_CONFIGURE_ISAMEM_2,209,143,46,12 + LTEXT "#3:",IDT_1765,12,158,21,10 + COMBOBOX IDC_COMBO_ISAMEM_3,25,157,180,120, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Configure",IDC_CONFIGURE_ISAMEM_3,209,157,46,12 + LTEXT "#4:",IDT_1766,12,172,21,10 + COMBOBOX IDC_COMBO_ISAMEM_4,25,171,180,120, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Configure",IDC_CONFIGURE_ISAMEM_4,209,171,46,12 END DLG_CFG_HARD_DISKS DIALOG DISCARDABLE 97, 0, 267, 154 diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 21d1b89a3..b1ff669bf 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -8,7 +8,7 @@ # # Makefile for Win32 (MinGW32) environment. # -# Version: @(#)Makefile.mingw 1.0.122 2018/08/01 +# Version: @(#)Makefile.mingw 1.0.123 2018/09/02 # # Authors: Miran Grca, # Fred N. van Kempen, @@ -70,7 +70,7 @@ ifeq ($(DEV_BUILD), y) endif else ifndef DEBUG - DEBUG := n + DEBUG := y endif ifndef DEV_BRANCH DEV_BRANCH := n @@ -443,7 +443,7 @@ MCHOBJ := machine.o machine_table.o \ m_at_sis_85c471.o m_at_sis_85c496.o \ m_at_4x0.o -DEVOBJ := bugger.o lpt.o $(SERIAL) \ +DEVOBJ := bugger.o isamem.o isartc.o lpt.o $(SERIAL) \ sio_fdc37c66x.o sio_fdc37c669.o sio_fdc37c93x.o \ sio_pc87306.o sio_w83877f.o sio_um8669f.o \ keyboard.o \ diff --git a/src/win/resource.h b/src/win/resource.h index db21beaab..376f086f4 100644 --- a/src/win/resource.h +++ b/src/win/resource.h @@ -8,7 +8,7 @@ * * Windows resource defines. * - * Version: @(#)resource.h 1.0.27 2018/08/04 + * Version: @(#)resource.h 1.0.28 2018/09/02 * * Authors: Sarah Walker, * Miran Grca, @@ -92,6 +92,11 @@ #define IDT_1757 1757 /* Progress: */ #define IDT_1758 1758 /* Speed: */ #define IDT_1759 1759 /* ZIP drives: */ +#define IDT_1763 1763 /* Board #1: */ +#define IDT_1764 1764 /* Board #2: */ +#define IDT_1765 1765 /* Board #3: */ +#define IDT_1766 1766 /* Board #4: */ +#define IDT_1767 1767 /* ISA RTC: */ /* @@ -166,69 +171,81 @@ #define IDC_CHECK_IDE_QUA 1127 #define IDC_BUTTON_IDE_QUA 1128 #define IDC_CHECK_BUGGER 1129 +#define IDC_CONFIGURE_BUGGER 1130 +#define IDC_COMBO_ISARTC 1131 +#define IDC_CONFIGURE_ISARTC 1132 +#define IDC_GROUP_ISAMEM 1140 +#define IDC_COMBO_ISAMEM_1 1141 +#define IDC_COMBO_ISAMEM_2 1142 +#define IDC_COMBO_ISAMEM_3 1143 +#define IDC_COMBO_ISAMEM_4 1144 +#define IDC_CONFIGURE_ISAMEM_1 1145 +#define IDC_CONFIGURE_ISAMEM_2 1146 +#define IDC_CONFIGURE_ISAMEM_3 1147 +#define IDC_CONFIGURE_ISAMEM_4 1148 -#define IDC_HARD_DISKS 1130 /* hard disk config */ -#define IDC_LIST_HARD_DISKS 1131 -#define IDC_BUTTON_HDD_ADD_NEW 1132 -#define IDC_BUTTON_HDD_ADD 1133 -#define IDC_BUTTON_HDD_REMOVE 1134 -#define IDC_COMBO_HD_BUS 1135 -#define IDC_COMBO_HD_CHANNEL 1136 -#define IDC_COMBO_HD_ID 1137 -#define IDC_COMBO_HD_LUN 1138 -#define IDC_COMBO_HD_CHANNEL_IDE 1139 +#define IDC_HARD_DISKS 1150 /* hard disk config */ +#define IDC_LIST_HARD_DISKS 1151 +#define IDC_BUTTON_HDD_ADD_NEW 1152 +#define IDC_BUTTON_HDD_ADD 1153 +#define IDC_BUTTON_HDD_REMOVE 1154 +#define IDC_COMBO_HD_BUS 1155 +#define IDC_COMBO_HD_CHANNEL 1156 +#define IDC_COMBO_HD_ID 1157 +#define IDC_COMBO_HD_LUN 1158 +#define IDC_COMBO_HD_CHANNEL_IDE 1159 -#define IDC_EDIT_HD_FILE_NAME 1140 /* add hard disk dialog */ -#define IDC_EDIT_HD_SPT 1141 -#define IDC_EDIT_HD_HPC 1142 -#define IDC_EDIT_HD_CYL 1143 -#define IDC_EDIT_HD_SIZE 1144 -#define IDC_COMBO_HD_TYPE 1145 -#define IDC_PBAR_IMG_CREATE 1146 +#define IDC_EDIT_HD_FILE_NAME 1160 /* add hard disk dialog */ +#define IDC_EDIT_HD_SPT 1161 +#define IDC_EDIT_HD_HPC 1162 +#define IDC_EDIT_HD_CYL 1163 +#define IDC_EDIT_HD_SIZE 1164 +#define IDC_COMBO_HD_TYPE 1165 +#define IDC_PBAR_IMG_CREATE 1166 -#define IDC_REMOV_DEVICES 1150 /* removable dev config */ -#define IDC_LIST_FLOPPY_DRIVES 1151 -#define IDC_COMBO_FD_TYPE 1152 -#define IDC_CHECKTURBO 1153 -#define IDC_CHECKBPB 1154 -#define IDC_LIST_CDROM_DRIVES 1155 -#define IDC_COMBO_CD_BUS 1156 -#define IDC_COMBO_CD_ID 1157 -#define IDC_COMBO_CD_LUN 1158 -#define IDC_COMBO_CD_CHANNEL_IDE 1159 -#define IDC_LIST_ZIP_DRIVES 1160 -#define IDC_COMBO_ZIP_BUS 1161 -#define IDC_COMBO_ZIP_ID 1162 -#define IDC_COMBO_ZIP_LUN 1163 -#define IDC_COMBO_ZIP_CHANNEL_IDE 1164 -#define IDC_CHECK250 1165 -#define IDC_COMBO_CD_SPEED 1166 +#define IDC_REMOV_DEVICES 1170 /* removable dev config */ +#define IDC_LIST_FLOPPY_DRIVES 1171 +#define IDC_COMBO_FD_TYPE 1172 +#define IDC_CHECKTURBO 1173 +#define IDC_CHECKBPB 1174 +#define IDC_LIST_CDROM_DRIVES 1175 +#define IDC_COMBO_CD_BUS 1176 +#define IDC_COMBO_CD_ID 1177 +#define IDC_COMBO_CD_LUN 1178 +#define IDC_COMBO_CD_CHANNEL_IDE 1179 +#define IDC_LIST_ZIP_DRIVES 1180 +#define IDC_COMBO_ZIP_BUS 1181 +#define IDC_COMBO_ZIP_ID 1182 +#define IDC_COMBO_ZIP_LUN 1183 +#define IDC_COMBO_ZIP_CHANNEL_IDE 1184 +#define IDC_CHECK250 1185 +#define IDC_COMBO_CD_SPEED 1186 -#define IDC_SLIDER_GAIN 1180 /* sound gain dialog */ +#define IDC_SLIDER_GAIN 1190 /* sound gain dialog */ -#define IDC_EDIT_FILE_NAME 1190 /* new floppy image dialog */ -#define IDC_COMBO_DISK_SIZE 1191 -#define IDC_COMBO_RPM_MODE 1192 +#define IDC_EDIT_FILE_NAME 1200 /* new floppy image dialog */ +#define IDC_COMBO_DISK_SIZE 1201 +#define IDC_COMBO_RPM_MODE 1202 /* For the DeviceConfig code, re-do later. */ -#define IDC_CONFIG_BASE 1200 -#define IDC_CONFIGURE_VID 1200 -#define IDC_CONFIGURE_SND 1201 -#define IDC_CONFIGURE_VOODOO 1202 -#define IDC_CONFIGURE_MOD 1203 -#define IDC_CONFIGURE_NET_TYPE 1204 -#define IDC_CONFIGURE_BUSLOGIC 1205 -#define IDC_CONFIGURE_PCAP 1206 -#define IDC_CONFIGURE_NET 1207 -#define IDC_CONFIGURE_MIDI 1208 -#define IDC_JOY1 1210 -#define IDC_JOY2 1211 -#define IDC_JOY3 1212 -#define IDC_JOY4 1213 -#define IDC_HDTYPE 1280 -#define IDC_RENDER 1281 -#define IDC_STATUS 1282 +#define IDC_CONFIG_BASE 1300 +#define IDC_CONFIGURE_VID 1300 +#define IDC_CONFIGURE_SND 1301 +#define IDC_CONFIGURE_VOODOO 1302 +#define IDC_CONFIGURE_MOD 1303 +#define IDC_CONFIGURE_NET_TYPE 1304 +#define IDC_CONFIGURE_BUSLOGIC 1305 +#define IDC_CONFIGURE_PCAP 1306 +#define IDC_CONFIGURE_NET 1307 +#define IDC_CONFIGURE_MIDI 1308 +#define IDC_JOY1 1310 +#define IDC_JOY2 1311 +#define IDC_JOY3 1312 +#define IDC_JOY4 1313 +#define IDC_HDTYPE 1380 +#define IDC_RENDER 1381 +#define IDC_STATUS 1382 #define IDM_ABOUT 40001 diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 3e5481da1..8eac8a6a0 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -36,6 +36,8 @@ #include "../nvr.h" #include "../machine/machine.h" #include "../game/gameport.h" +#include "../isamem.h" +#include "../isartc.h" #include "../lpt.h" #include "../mouse.h" #include "../scsi/scsi.h" @@ -103,6 +105,8 @@ static int temp_scsi_card, temp_ide_ter, temp_ide_qua; static char temp_hdc_name[32]; static char *hdc_names[32]; static int temp_bugger; +static int temp_isartc; +static int temp_isamem[ISAMEM_MAX]; static uint8_t temp_deviceconfig; @@ -243,7 +247,12 @@ win_settings_init(void) temp_ide_ter = ide_ter_enabled; temp_ide_qua = ide_qua_enabled; temp_bugger = bugger_enabled; - + temp_isartc = isartc_type; + + /* ISA memory boards. */ + for (i = 0; i < ISAMEM_MAX; i++) + temp_isamem[i] = isamem_type[i]; + mfm_tracking = xta_tracking = esdi_tracking = ide_tracking = 0; for (i = 0; i < 2; i++) scsi_tracking[i] = 0; @@ -261,8 +270,8 @@ win_settings_init(void) ide_tracking |= (1 << (hdd[i].ide_channel << 3)); else if (hdd[i].bus == HDD_BUS_SCSI) scsi_tracking[hdd[i].scsi_id >> 3] |= (1 << ((hdd[i].scsi_id & 0x07) << 3)); - } - + } + /* Floppy drives category */ for (i = 0; i < FDD_NUM; i++) { temp_fdd_types[i] = fdd_get_type(i); @@ -345,7 +354,12 @@ win_settings_changed(void) i = i || (temp_ide_ter != ide_ter_enabled); i = i || (temp_ide_qua != ide_qua_enabled); i = i || (temp_bugger != bugger_enabled); + i = i || (temp_isartc != isartc_type); + /* ISA memory boards. */ + for (j = 0; j < ISAMEM_MAX; j++) + i = i || (temp_isamem[j] != isamem_type[j]); + /* Hard disks category */ i = i || memcmp(hdd, temp_hdd, HDD_NUM * sizeof(hard_disk_t)); @@ -451,6 +465,10 @@ win_settings_save(void) ide_qua_enabled = temp_ide_qua; bugger_enabled = temp_bugger; + /* ISA memory boards. */ + for (i = 0; i < ISAMEM_MAX; i++) + isamem_type[i] = temp_isamem[i]; + /* Hard disks category */ memcpy(hdd, temp_hdd, HDD_NUM * sizeof(hard_disk_t)); @@ -1077,7 +1095,7 @@ mpu401_present(void) n = sound_card_get_internal_name(temp_sound_card); if (n != NULL) { - if (!strcmp(n, "sb16") || !strcmp(n, "sbawe32")) + if (!strcmp(n, "sb16") || !strcmp(n, "sbawe32") || !strcmp(n, "replysb16")) return 1; } @@ -1093,7 +1111,7 @@ mpu401_standalone_allow(void) n = sound_card_get_internal_name(temp_sound_card); md = midi_device_get_internal_name(temp_midi_device); if (n != NULL) { - if (!strcmp(n, "sb16") || !strcmp(n, "sbawe32")) + if (!strcmp(n, "sb16") || !strcmp(n, "sbawe32") || !strcmp(n, "replysb16")) return 0; } @@ -1275,8 +1293,22 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) break; case IDC_CONFIGURE_MPU401: - temp_deviceconfig |= deviceconfig_open(hdlg, (void *)&mpu401_device); - break; + { + char *n; + + n = sound_card_get_internal_name(sound_card_current); + + if (n != NULL) + { + if (!strcmp(n, "ncraudio")) + mca_version = 1; + else + mca_version = 0; + } + + temp_deviceconfig |= deviceconfig_open(hdlg, mca_version ? (void *)&mpu401_mca_device : (void *)&mpu401_device); + } + break; } return FALSE; @@ -1457,7 +1489,7 @@ static BOOL CALLBACK win_settings_peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { HWND h; - int c, d, temp_hdc_type; + int c, d, e, temp_hdc_type; LPTSTR lptsTemp; const device_t *scsi_dev; @@ -1526,6 +1558,65 @@ win_settings_peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPa h=GetDlgItem(hdlg, IDC_CHECK_BUGGER); SendMessage(h, BM_SETCHECK, temp_bugger, 0); + /* Populate the ISA RTC card dropdown. */ + e = 0; + h = GetDlgItem(hdlg, IDC_COMBO_ISARTC); + for (d = 0; ; d++) { + char *s = isartc_get_name(d); + if (!s[0]) + break; + + settings_device_to_list[d] = e; + + if (d == 0) { + /* Translate "None". */ + SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_2112)); + } else { + mbstowcs(lptsTemp, s, strlen(s) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); + } + + settings_list_to_device[e] = d; + e++; + } + SendMessage(h, CB_SETCURSEL, temp_isartc, 0); + h = GetDlgItem(hdlg, IDC_CONFIGURE_ISARTC); + if (temp_isartc != 0) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + + /* Populate the ISA memory card dropdowns. */ + for (c = 0; c < ISAMEM_MAX; c++) { + e = 0; + h = GetDlgItem(hdlg, IDC_COMBO_ISAMEM_1 + c); + for (d = 0; ; d++) { + char *s = isamem_get_name(d); + + if (!s[0]) + break; + + settings_device_to_list[d] = e; + + if (d == 0) { + /* Translate "None". */ + SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_2112)); + } else { + mbstowcs(lptsTemp, s, strlen(s) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp); + } + + settings_list_to_device[e] = d; + e++; + } + SendMessage(h, CB_SETCURSEL, temp_isamem[c], 0); + h = GetDlgItem(hdlg, IDC_CONFIGURE_ISAMEM_1 + c); + if (temp_isamem[c] != 0) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + } + free(lptsTemp); return TRUE; @@ -1565,6 +1656,96 @@ win_settings_peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPa EnableWindow(h, FALSE); break; + case IDC_CONFIGURE_ISARTC: + h = GetDlgItem(hdlg, IDC_COMBO_ISARTC); + temp_isartc = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)isartc_get_device(temp_isartc)); + break; + + case IDC_COMBO_ISARTC: + h = GetDlgItem(hdlg, IDC_COMBO_ISARTC); + temp_isartc = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + h = GetDlgItem(hdlg, IDC_CONFIGURE_ISARTC); + if (temp_isartc != 0) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + break; + + case IDC_CONFIGURE_ISAMEM_1: + h = GetDlgItem(hdlg, IDC_COMBO_ISAMEM_1); + temp_isamem[0] = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)isamem_get_device(temp_isamem[0])); + break; + + case IDC_CONFIGURE_ISAMEM_2: + h = GetDlgItem(hdlg, IDC_COMBO_ISAMEM_2); + temp_isamem[1] = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)isamem_get_device(temp_isamem[1])); + break; + + case IDC_CONFIGURE_ISAMEM_3: + h = GetDlgItem(hdlg, IDC_COMBO_ISAMEM_3); + temp_isamem[2] = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)isamem_get_device(temp_isamem[2])); + break; + + case IDC_CONFIGURE_ISAMEM_4: + h = GetDlgItem(hdlg, IDC_COMBO_ISAMEM_4); + temp_isamem[3] = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)isamem_get_device(temp_isamem[3])); + break; + + case IDC_COMBO_ISAMEM_1: + h = GetDlgItem(hdlg, IDC_COMBO_ISAMEM_1); + temp_isamem[0] = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + h = GetDlgItem(hdlg, IDC_CONFIGURE_ISAMEM_1); + if (temp_isamem[0] != 0) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + break; + + case IDC_COMBO_ISAMEM_2: + h = GetDlgItem(hdlg, IDC_COMBO_ISAMEM_2); + temp_isamem[1] = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + h = GetDlgItem(hdlg, IDC_CONFIGURE_ISAMEM_2); + if (temp_isamem[1] != 0) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + break; + + case IDC_COMBO_ISAMEM_3: + h = GetDlgItem(hdlg, IDC_COMBO_ISAMEM_3); + temp_isamem[2] = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + h = GetDlgItem(hdlg, IDC_CONFIGURE_ISAMEM_3); + if (temp_isamem[2] != 0) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + break; + + case IDC_COMBO_ISAMEM_4: + h = GetDlgItem(hdlg, IDC_COMBO_ISAMEM_4); + temp_isamem[3] = settings_list_to_device[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + h = GetDlgItem(hdlg, IDC_CONFIGURE_ISAMEM_4); + if (temp_isamem[3] != 0) + EnableWindow(h, TRUE); + else + EnableWindow(h, FALSE); + break; + case IDC_CHECK_IDE_TER: h = GetDlgItem(hdlg, IDC_CHECK_IDE_TER); temp_ide_ter = SendMessage(h, BM_GETCHECK, 0, 0);