diff --git a/src/machine/m_at_scat.c b/src/machine/m_at_scat.c index bf8bfdb51..37c4b2080 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.9 2018/01/28 + * Version: @(#)m_at_scat.c 1.0.10 2018/03/02 * * Authors: Original by GreatPsycho for PCem. * Fred N. van Kempen, @@ -29,710 +29,685 @@ #include "../floppy/fdc.h" #include "../io.h" #include "../mem.h" +#include "../nmi.h" #include "machine.h" -#define SCAT_DEBUG 1 +#define SCAT_DMA_WAIT_STATE_CONTROL 0x01 +#define SCAT_VERSION 0x40 +#define SCAT_CLOCK_CONTROL 0x41 +#define SCAT_PERIPHERAL_CONTROL 0x44 +#define SCAT_MISCELLANEOUS_STATUS 0x45 +#define SCAT_POWER_MANAGEMENT 0x46 +#define SCAT_ROM_ENABLE 0x48 +#define SCAT_RAM_WRITE_PROTECT 0x49 +#define SCAT_SHADOW_RAM_ENABLE_1 0x4A +#define SCAT_SHADOW_RAM_ENABLE_2 0x4B +#define SCAT_SHADOW_RAM_ENABLE_3 0x4C +#define SCAT_DRAM_CONFIGURATION 0x4D +#define SCAT_EXTENDED_BOUNDARY 0x4E +#define SCAT_EMS_CONTROL 0x4F -#define SCAT_DMA_WS_CTL 0x01 -#define SCAT_VERSION 0x40 -#define SCAT_CLOCK_CTL 0x41 -#define SCAT_PERIPH_CTL 0x44 -#define SCAT_MISC_STATUS 0x45 -#define SCAT_POWER_MGMT 0x46 -#define SCAT_ROM_ENABLE 0x48 -#define SCAT_RAM_WR_PROTECT 0x49 -#define SCAT_SHADOW_RAM_EN_1 0x4a -#define SCAT_SHADOW_RAM_EN_2 0x4b -#define SCAT_SHADOW_RAM_EN_3 0x4c -#define SCAT_DRAM_CONFIG 0x4d -#define SCAT_EXT_BOUNDARY 0x4e -#define SCAT_EMS_CTL 0x4f -#define SCAT_SYS_CTL 0x7f /* port 92 */ +#define SCATSX_LAPTOP_FEATURES 0x60 +#define SCATSX_FAST_VIDEO_CONTROL 0x61 +#define SCATSX_FAST_VIDEORAM_ENABLE 0x62 +#define SCATSX_HIGH_PERFORMANCE_REFRESH 0x63 +#define SCATSX_CAS_TIMING_FOR_DMA 0x64 - -typedef struct { - uint8_t regs_2x8; - uint8_t regs_2x9; -} ems_t; - - -static uint8_t scat_regs[128]; -static int scat_index; -static uint32_t scat_xms_bound; -static uint8_t scat_ems_reg = 0; -static ems_t scat_ems[32]; /* EMS page regs */ -static mem_mapping_t scat_mapping[32]; /* EMS pages */ -static mem_mapping_t scat_top_mapping[24]; /* top 384K mapping */ -static mem_mapping_t scat_A000_mapping; /* A000-C000 mapping */ -static mem_mapping_t scat_shadowram_mapping[6]; /* BIOS shadowing */ -static mem_mapping_t scat_high_mapping[16]; /* >1M mapping */ - - -static void -shadow_state_update(void) +typedef struct scat_t { - int i, val; + uint8_t regs_2x8; + uint8_t regs_2x9; +} scat_t; - /* TODO - ROMCS enable features should be implemented later. */ - for (i=0; i<24; i++) { - val = ((scat_regs[SCAT_SHADOW_RAM_EN_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTERNAL; - if (i < 8) { - val |= ((scat_regs[SCAT_SHADOW_RAM_EN_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTERNAL; - } else { - if ((scat_regs[SCAT_RAM_WR_PROTECT] >> ((i - 8) >> 1)) & 1) - val |= MEM_WRITE_DISABLED; - else - val |= ((scat_regs[SCAT_SHADOW_RAM_EN_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTERNAL; - } - mem_set_mem_state((i + 40) << 14, 0x4000, val); - } - flushmmucache(); +static uint8_t scat_regs[256]; +static int scat_index; +static uint8_t scat_port_92 = 0; +static uint8_t scat_ems_reg_2xA = 0; +static mem_mapping_t scat_mapping[32]; +static mem_mapping_t scat_high_mapping[16]; +static scat_t scat_stat[32]; +static uint32_t scat_xms_bound; +static mem_mapping_t scat_shadowram_mapping[6]; +static mem_mapping_t scat_4000_9FFF_mapping[24]; +static mem_mapping_t scat_A000_BFFF_mapping; + +// TODO - 82C836 chipset's memory address mapping isn't fully implemented yet, so memory configuration is hardcoded now. +static int scatsx_mem_conf_val[33] = { 0x00, 0x01, 0x03, 0x04, 0x05, 0x08, 0x06, 0x06, + 0x0c, 0x09, 0x07, 0x07, 0x0d, 0x0a, 0x0f, 0x0f, + 0x0e, 0x0e, 0x10, 0x10, 0x13, 0x13, 0x11, 0x11, + 0x14, 0x14, 0x12, 0x12, 0x15, 0x15, 0x15, 0x15, + 0x16 }; + +uint8_t scat_read(uint16_t port, void *priv); +void scat_write(uint16_t port, uint8_t val, void *priv); + +void scat_shadow_state_update() +{ + int i, val; + + // TODO - ROMCS enable features should be implemented later. + for (i = 0; i < 24; i++) + { + val = ((scat_regs[SCAT_SHADOW_RAM_ENABLE_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTERNAL; + if (i < 8) + { + val |= ((scat_regs[SCAT_SHADOW_RAM_ENABLE_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTERNAL; + } + else + { + if ((scat_regs[SCAT_RAM_WRITE_PROTECT] >> ((i - 8) >> 1)) & 1) + { + val |= MEM_WRITE_DISABLED; + } + else + { + val |= ((scat_regs[SCAT_SHADOW_RAM_ENABLE_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTERNAL; + } + } + mem_set_mem_state((i + 40) << 14, 0x4000, val); + } + + flushmmucache(); } - -static void -set_xms_bound(uint8_t val) +void scat_set_xms_bound(uint8_t val) { - uint32_t max_xms, max_mem; - int i; + uint32_t max_xms_size = (mem_size >= 16128) ? (((scat_regs[SCAT_VERSION] & 0xF0) != 0 && ((val & 0x10) != 0)) ? 0xFE0000 : 0xFC0000) : mem_size << 10; + int i; - max_mem = (mem_size << 10); - max_xms = (mem_size >= 16384) ? 0xFC0000 : max_mem; - pclog("SCAT: set_xms_bound(%02x): max_mem=%d, max_xms=%d\n", - val, max_mem, max_xms); + switch (val & 0x0F) + { + case 1: + scat_xms_bound = 0x100000; + break; + case 2: + scat_xms_bound = 0x140000; + break; + case 3: + scat_xms_bound = 0x180000; + break; + case 4: + scat_xms_bound = 0x200000; + break; + case 5: + scat_xms_bound = 0x300000; + break; + case 6: + scat_xms_bound = 0x400000; + break; + case 7: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x600000 : 0x500000; + break; + case 8: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x800000 : 0x700000; + break; + case 9: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xA00000 : 0x800000; + break; + case 10: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xC00000 : 0x900000; + break; + case 11: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xE00000 : 0xA00000; + break; + case 12: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xB00000; + break; + case 13: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xC00000; + break; + case 14: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xD00000; + break; + case 15: + scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xF00000; + break; + default: + scat_xms_bound = max_xms_size; + break; + } - switch (val & 0x0f) { - case 1: - scat_xms_bound = 0x100000; - break; + if ((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (val & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3)) + { + if (val != 1) + { + if(mem_size > 1024) mem_mapping_disable(&ram_high_mapping); + for(i=0;i<6;i++) + mem_mapping_enable(&scat_shadowram_mapping[i]); + if ((val & 0x0F) == 0) + scat_xms_bound = 0x160000; + } + else + { + for(i=0;i<6;i++) + mem_mapping_disable(&scat_shadowram_mapping[i]); + if(mem_size > 1024) mem_mapping_enable(&ram_high_mapping); + } + pclog("Set XMS bound(%02X) = %06X(%dKbytes for EMS access)\n", val, scat_xms_bound, (0x160000 - scat_xms_bound) >> 10); + if (scat_xms_bound > 0x100000) + mem_set_mem_state(0x100000, scat_xms_bound - 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + if (scat_xms_bound < 0x160000) + mem_set_mem_state(scat_xms_bound, 0x160000 - scat_xms_bound, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } + else + { + for(i=0;i<6;i++) + mem_mapping_disable(&scat_shadowram_mapping[i]); + if(mem_size > 1024) mem_mapping_enable(&ram_high_mapping); - case 2: - scat_xms_bound = 0x140000; - break; - - case 3: - scat_xms_bound = 0x180000; - break; - - case 4: - scat_xms_bound = 0x200000; - break; - - case 5: - scat_xms_bound = 0x300000; - break; - - case 6: - scat_xms_bound = 0x400000; - break; - - case 7: - scat_xms_bound = 0x600000; - break; - - case 8: - scat_xms_bound = 0x800000; - break; - - case 9: - scat_xms_bound = 0xA00000; - break; - - case 10: - scat_xms_bound = 0xC00000; - break; - - case 11: - scat_xms_bound = 0xE00000; - break; - - default: - scat_xms_bound = max_xms; - break; - } - - if ((val & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIG] & 0x0f) == 3) { - if (val != 1) { - if (mem_size > 1024) - mem_mapping_disable(&ram_high_mapping); - for (i=0; i<6; i++) - mem_mapping_enable(&scat_shadowram_mapping[i]); - if ((val & 0x0f) == 0) - scat_xms_bound = 0x160000; - } else { - for (i=0; i<6; i++) - mem_mapping_disable(&scat_shadowram_mapping[i]); - if (mem_size > 1024) - mem_mapping_enable(&ram_high_mapping); - } - pclog("SCAT: set XMS bound(%02X) = %06X (%dK for EMS)\n", - val, scat_xms_bound, (0x160000-scat_xms_bound)>>10); - - if (scat_xms_bound > 0x100000) - mem_set_mem_state(0x100000, - scat_xms_bound - 0x100000, - MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - if (scat_xms_bound < 0x160000) - mem_set_mem_state(scat_xms_bound, - 0x160000 - scat_xms_bound, - MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - } else { - for (i=0; i<6; i++) - mem_mapping_disable(&scat_shadowram_mapping[i]); - if (mem_size > 1024) - mem_mapping_enable(&ram_high_mapping); - - if (scat_xms_bound > max_xms) - scat_xms_bound = max_xms; - pclog("SCAT: set XMS bound(%02X) = %06X (%dK for EMS)\n", - val, scat_xms_bound, (max_mem-scat_xms_bound)>>10); - - if (scat_xms_bound > 0x100000) - mem_set_mem_state(0x100000, - scat_xms_bound-0x100000, - MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - if (scat_xms_bound < max_mem) - mem_set_mem_state(scat_xms_bound, - (mem_size<<10)-scat_xms_bound, - MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - } + if (scat_xms_bound > max_xms_size) + scat_xms_bound = max_xms_size; + pclog("Set XMS bound(%02X) = %06X(%dKbytes for EMS access)\n", val, scat_xms_bound, ((mem_size << 10) - scat_xms_bound) >> 10); + if (scat_xms_bound > 0x100000) + mem_set_mem_state(0x100000, scat_xms_bound - 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + if (scat_xms_bound < (mem_size << 10)) + mem_set_mem_state(scat_xms_bound, (mem_size << 10) - scat_xms_bound, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } } - -static uint32_t -get_addr(uint32_t addr, ems_t *p) +uint32_t get_scat_addr(uint32_t addr, scat_t *p) { - if (p && (scat_regs[SCAT_EMS_CTL] & 0x80) && (p->regs_2x9 & 0x80)) { - addr = (addr & 0x3fff) | (((p->regs_2x9 & 3)<<8) | p->regs_2x8)<<14; - } + if (p && (scat_regs[SCAT_EMS_CONTROL] & 0x80) && (p->regs_2x9 & 0x80)) + addr = (addr & 0x3fff) | (((p->regs_2x9 & 3) << 8) | p->regs_2x8) << 14; - if (mem_size < 2048 && - ((scat_regs[SCAT_DRAM_CONFIG] & 0x0F) > 7 || - (scat_regs[SCAT_EXT_BOUNDARY] & 0x40) != 0)) - addr = (addr & ~0x780000) | ((addr & 0x600000) >> 2); - else - if ((scat_regs[SCAT_DRAM_CONFIG] & 0x0F) < 8 && - (scat_regs[SCAT_EXT_BOUNDARY] & 0x40) == 0) { - addr &= ~0x600000; - if (mem_size > 2048 || (mem_size == 2048 && - (scat_regs[SCAT_DRAM_CONFIG] & 0x0F) < 6)) - addr |= (addr & 0x180000) << 2; - } + if ((scat_regs[SCAT_VERSION] & 0xF0) == 0) + { + if (mem_size < 2048 && ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) > 7 || (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) != 0)) + addr = (addr & ~0x780000) | ((addr & 0x600000) >> 2); + else if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 8 && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) + { + addr &= ~0x600000; + if(mem_size > 2048 || (mem_size == 2048 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 6)) + addr |= (addr & 0x180000) << 2; + } - if ((scat_regs[SCAT_EXT_BOUNDARY] & 0x40) == 0 && - (scat_regs[SCAT_DRAM_CONFIG] & 0x0F) == 3 && - (addr & ~0x600000) >= 0x100000 && (addr & ~0x600000) < 0x160000) - addr ^= mem_size < 2048 ? 0x1F0000 : 0x670000; - - return(addr); + if ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3 && (addr & ~0x600000) >= 0x100000 && (addr & ~0x600000) < 0x160000) + addr ^= mem_size < 2048 ? 0x1F0000 : 0x670000; + } + else + { + if ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3 && (addr & ~0x600000) >= 0x100000 && (addr & ~0x600000) < 0x160000) + addr ^= 0x1F0000; + } + return addr; } - -static void -memmap_state_update(void) +void scat_memmap_state_update() { - uint32_t addr; - int i; + int i; + uint32_t addr; - for (i=16; i<24; i++) { - addr = get_addr(0x40000 + (i<<14), NULL); - mem_mapping_set_exec(&scat_top_mapping[i], - addr < (mem_size<<10) ? ram+addr : NULL); - } + for(i=16;i<24;i++) + { + addr = get_scat_addr(0x40000 + (i << 14), NULL); + mem_mapping_set_exec(&scat_4000_9FFF_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL); + } + addr = get_scat_addr(0xA0000, NULL); + mem_mapping_set_exec(&scat_A000_BFFF_mapping, addr < (mem_size << 10) ? ram + addr : NULL); + for(i=0;i<6;i++) + { + addr = get_scat_addr(0x100000 + (i << 16), NULL); + mem_mapping_set_exec(&scat_shadowram_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL); + } - addr = get_addr(0xA0000, NULL); - mem_mapping_set_exec(&scat_A000_mapping, - addr < (mem_size<<10) ? ram+addr : NULL); - - for (i=0; i<6; i++) { - addr = get_addr(0x100000 + (i<<16), NULL); - mem_mapping_set_exec(&scat_shadowram_mapping[i], - addr < (mem_size<<10) ? ram+addr : NULL); - } - - flushmmucache(); + flushmmucache(); } - -static void -ems_state(int state) +void scat_set_global_EMS_state(int state) { - uint32_t base_addr, virt_addr; - int i; + int i; + uint32_t base_addr, virt_addr; - for (i=0; i<32; i++) { - base_addr = (i + 16) << 14; - - if (i >= 24) - base_addr += 0x30000; - - if (state && (scat_ems[i].regs_2x9 & 0x80)) { - virt_addr = get_addr(base_addr, &scat_ems[i]); - if (i < 24) - mem_mapping_disable(&scat_top_mapping[i]); - mem_mapping_enable(&scat_mapping[i]); - if (virt_addr < (mem_size<<10)) - mem_mapping_set_exec(&scat_mapping[i], ram+virt_addr); - else - mem_mapping_set_exec(&scat_mapping[i], NULL); - } else { - mem_mapping_set_exec(&scat_mapping[i], ram+base_addr); - mem_mapping_disable(&scat_mapping[i]); - if (i < 24) - mem_mapping_enable(&scat_top_mapping[i]); - } - } + for(i=((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0 : 24; i<32; i++) + { + base_addr = (i + 16) << 14; + if(i >= 24) + base_addr += 0x30000; + if(state && (scat_stat[i].regs_2x9 & 0x80)) + { + virt_addr = get_scat_addr(base_addr, &scat_stat[i]); + if(i < 24) mem_mapping_disable(&scat_4000_9FFF_mapping[i]); + mem_mapping_enable(&scat_mapping[i]); + if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_mapping[i], ram + virt_addr); + else mem_mapping_set_exec(&scat_mapping[i], NULL); + } + else + { + mem_mapping_set_exec(&scat_mapping[i], ram + base_addr); + mem_mapping_disable(&scat_mapping[i]); + if(i < 24) mem_mapping_enable(&scat_4000_9FFF_mapping[i]); + } + } + flushmmucache(); } - -/* Read a byte from a LIM/EMS page. */ -static uint8_t -ems_pgrd(uint32_t vaddr, void *priv) +void scat_write(uint16_t port, uint8_t val, void *priv) { - ems_t *ems = (ems_t *)priv; - uint32_t addr; - uint8_t val = 0xff; - - addr = get_addr(vaddr, ems); - if (addr < (mem_size << 10)) - val = mem_read_ram(addr, priv); -#if SCAT_DEBUG > 1 - pclog("SCAT: ems_pgrd(%06x->%06x) = %02x\n", vaddr, addr, val); -#endif - - return(val); -} - - -/* Write a byte to a LIM/EMS page. */ -static void -ems_pgwr(uint32_t vaddr, uint8_t val, void *priv) -{ - ems_t *ems = (ems_t *)priv; - uint32_t addr; - - addr = get_addr(vaddr, ems); -#if SCAT_DEBUG > 1 - pclog("SCAT: ems_pgwr(%06x->%06x, %02x)\n", vaddr, addr, val); -#endif - if (addr < (mem_size << 10)) - mem_write_ram(addr, val, priv); -} - - -/* Read from a LIM/EMS control register. */ -static uint8_t -ems_read(uint16_t port, void *priv) -{ - uint8_t val = 0xff; - uint8_t idx; - - switch (port) { - case 0x208: - case 0x218: - if ((scat_regs[SCAT_EMS_CTL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { - idx = scat_ems_reg & 0x1f; - val = scat_ems[idx].regs_2x8; - } - break; - - case 0x209: - case 0x219: - if ((scat_regs[SCAT_EMS_CTL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { - idx = scat_ems_reg & 0x1f; - val = scat_ems[idx].regs_2x9; - } - break; - - case 0x20A: - case 0x21A: - if ((scat_regs[SCAT_EMS_CTL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { - val = scat_ems_reg; - } - break; - } - -#if SCAT_DEBUG > 2 - pclog("SCAT: ems_read(%04x) = %02x\n", port, val); -#endif - return(val); -} - - -/* Write to one of the LIM/EMS control registers. */ -static void -ems_write(uint16_t port, uint8_t val, void *priv) -{ - uint32_t base_addr, virt_addr; - uint8_t idx; + uint8_t scat_reg_valid = 0, scat_shadow_update = 0, scat_map_update = 0, index; + uint32_t base_addr, virt_addr; -#if SCAT_DEBUG > 1 - pclog("SCAT: ems_write(%04x, %02x)\n", port, val); -#endif - switch(port) { - case 0x208: - case 0x218: - if ((scat_regs[SCAT_EMS_CTL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { - idx = scat_ems_reg & 0x1f; - scat_ems[idx].regs_2x8 = val; - base_addr = (idx + 16) << 14; - if (idx >= 24) - base_addr += 0x30000; + switch (port) + { + case 0x22: + scat_index = val; + break; + + case 0x23: + switch (scat_index) + { + case SCAT_DMA_WAIT_STATE_CONTROL: + case SCAT_CLOCK_CONTROL: + case SCAT_PERIPHERAL_CONTROL: + scat_reg_valid = 1; + break; + case SCAT_EMS_CONTROL: + if(val & 0x40) + { + if(val & 1) + { + io_sethandler(0x0218, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + io_removehandler(0x0208, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + } + else + { + io_sethandler(0x0208, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + io_removehandler(0x0218, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + } + } + else + { + io_removehandler(0x0208, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + io_removehandler(0x0218, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + } + scat_set_global_EMS_state(val & 0x80); + scat_reg_valid = 1; + break; + case SCAT_POWER_MANAGEMENT: + // TODO - Only use AUX parity disable bit for this version. Other bits should be implemented later. + val &= (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x40 : 0x60; + scat_reg_valid = 1; + break; + case SCAT_DRAM_CONFIGURATION: + if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) || ((scat_regs[SCAT_VERSION] & 0xF0) != 0)) + { + if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (val & 0x0F) == 3) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (val & 0x1F) == 3)) + { + if(mem_size > 1024) mem_mapping_disable(&ram_high_mapping); + for(index=0;index<6;index++) + mem_mapping_enable(&scat_shadowram_mapping[index]); + } + else + { + for(index=0;index<6;index++) + mem_mapping_disable(&scat_shadowram_mapping[index]); + if(mem_size > 1024) mem_mapping_enable(&ram_high_mapping); + } + } + else + { + for(index=0;index<6;index++) + mem_mapping_disable(&scat_shadowram_mapping[index]); + if(mem_size > 1024) mem_mapping_enable(&ram_high_mapping); + } + scat_map_update = 1; - if ((scat_regs[SCAT_EMS_CTL] & 0x80) && (scat_ems[idx].regs_2x9 & 0x80)) { - virt_addr = get_addr(base_addr, &scat_ems[idx]); - if (virt_addr < (mem_size << 10)) - mem_mapping_set_exec(&scat_mapping[idx], ram + virt_addr); - else - mem_mapping_set_exec(&scat_mapping[idx], NULL); - flushmmucache(); - } - } - break; + if((scat_regs[SCAT_VERSION] & 0xF0) == 0) + { + cpu_waitstates = (val & 0x70) == 0 ? 1 : 2; + cpu_update_waitstates(); + } + else + { + if(mem_size != 1024 || ((val & 0x1F) != 2 && (val & 0x1F) != 3)) + val = (val & 0xe0) | scatsx_mem_conf_val[mem_size >> 9]; + } - case 0x209: - case 0x219: - if ((scat_regs[SCAT_EMS_CTL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { - idx = scat_ems_reg & 0x1f; - scat_ems[idx].regs_2x9 = val; - base_addr = (idx + 16) << 14; - if (idx >= 24) - base_addr += 0x30000; + scat_reg_valid = 1; + break; + case SCAT_EXTENDED_BOUNDARY: + scat_set_xms_bound(val & ((scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x4f : 0x1f)); + mem_set_mem_state(0x40000, 0x60000, (val & 0x20) ? MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL : MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + if((val ^ scat_regs[SCAT_EXTENDED_BOUNDARY]) & 0x40) scat_map_update = 1; + scat_reg_valid = 1; + break; + case SCAT_ROM_ENABLE: + case SCAT_RAM_WRITE_PROTECT: + case SCAT_SHADOW_RAM_ENABLE_1: + case SCAT_SHADOW_RAM_ENABLE_2: + case SCAT_SHADOW_RAM_ENABLE_3: + scat_reg_valid = 1; + scat_shadow_update = 1; + break; + case SCATSX_LAPTOP_FEATURES: + if((scat_regs[SCAT_VERSION] & 0xF0) != 0) + { + val = (val & ~8) | (scat_regs[SCATSX_LAPTOP_FEATURES] & 8); + scat_reg_valid = 1; + } + break; + case SCATSX_FAST_VIDEO_CONTROL: + case SCATSX_FAST_VIDEORAM_ENABLE: + case SCATSX_HIGH_PERFORMANCE_REFRESH: + case SCATSX_CAS_TIMING_FOR_DMA: + if((scat_regs[SCAT_VERSION] & 0xF0) != 0) scat_reg_valid = 1; + break; + default: + break; + } + if (scat_reg_valid) + scat_regs[scat_index] = val; + else pclog("Attemped to write unimplemented SCAT register %02X at %04X:%04X\n", scat_index, val, CS, cpu_state.pc); + if (scat_shadow_update) + scat_shadow_state_update(); + if (scat_map_update) + scat_memmap_state_update(); +// pclog("Write SCAT Register %02X to %02X at %04X:%04X\n", scat_index, val, CS, cpu_state.pc); + break; - if (scat_regs[SCAT_EMS_CTL] & 0x80) { - if (val & 0x80) { - virt_addr = get_addr(base_addr, &scat_ems[idx]); - if (idx < 24) - mem_mapping_disable(&scat_top_mapping[idx]); - if (virt_addr < (mem_size << 10)) - mem_mapping_set_exec(&scat_mapping[idx], ram+virt_addr); - else - mem_mapping_set_exec(&scat_mapping[idx], NULL); - mem_mapping_enable(&scat_mapping[idx]); - } else { - mem_mapping_set_exec(&scat_mapping[idx], ram + base_addr); - mem_mapping_disable(&scat_mapping[idx]); - if (idx < 24) - mem_mapping_enable(&scat_top_mapping[idx]); - } - flushmmucache(); - } + case 0x92: + if ((mem_a20_alt ^ val) & 2) + { + mem_a20_alt = val & 2; + mem_a20_recalc(); + } + if ((~scat_port_92 & val) & 1) + { + softresetx86(); + cpu_set_edx(); + } + scat_port_92 = val; + break; - if (scat_ems_reg & 0x80) { - scat_ems_reg = (scat_ems_reg & 0xe0) | ((scat_ems_reg + 1) & 0x1f); - } - } - break; + case 0x208: + case 0x218: + if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) + { +// pclog("Write SCAT EMS Control Port %04X to %02X at %04X:%04X\n", port, val, CS, cpu_state.pc); + if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F; + else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24; + scat_stat[index].regs_2x8 = val; + base_addr = (index + 16) << 14; + if(index >= 24) + base_addr += 0x30000; - case 0x20A: - case 0x21A: - if ((scat_regs[SCAT_EMS_CTL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) { - scat_ems_reg = val; - } - break; - } + if((scat_regs[SCAT_EMS_CONTROL] & 0x80) && (scat_stat[index].regs_2x9 & 0x80)) + { + virt_addr = get_scat_addr(base_addr, &scat_stat[index]); + if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_mapping[index], ram + virt_addr); + else mem_mapping_set_exec(&scat_mapping[index], NULL); + flushmmucache(); + } + } + break; + case 0x209: + case 0x219: + if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) + { +// pclog("Write SCAT EMS Control Port %04X to %02X at %04X:%04X\n", port, val, CS, cpu_state.pc); + if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F; + else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24; + scat_stat[index].regs_2x9 = val; + base_addr = (index + 16) << 14; + if(index >= 24) + base_addr += 0x30000; + + if (scat_regs[SCAT_EMS_CONTROL] & 0x80) + { + if (val & 0x80) + { + virt_addr = get_scat_addr(base_addr, &scat_stat[index]); + if(index < 24) mem_mapping_disable(&scat_4000_9FFF_mapping[index]); + if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_mapping[index], ram + virt_addr); + else mem_mapping_set_exec(&scat_mapping[index], NULL); + mem_mapping_enable(&scat_mapping[index]); +// pclog("Map page %d(address %05X) to address %06X\n", scat_ems_reg_2xA & 0x1f, base_addr, virt_addr); + } + else + { + mem_mapping_set_exec(&scat_mapping[index], ram + base_addr); + mem_mapping_disable(&scat_mapping[index]); + if(index < 24) mem_mapping_enable(&scat_4000_9FFF_mapping[index]); +// pclog("Unmap page %d(address %06X)\n", scat_ems_reg_2xA & 0x1f, base_addr); + } + flushmmucache(); + } + + if (scat_ems_reg_2xA & 0x80) + { + scat_ems_reg_2xA = (scat_ems_reg_2xA & 0xe0) | ((scat_ems_reg_2xA + 1) & (((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0x1f : 3)); + } + } + break; + case 0x20A: + case 0x21A: + if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) + { +// pclog("Write SCAT EMS Control Port %04X to %02X at %04X:%04X\n", port, val, CS, cpu_state.pc); + scat_ems_reg_2xA = ((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? val : val & 0xc3; + } + break; + } } - -static uint8_t -scat_read(uint16_t port, void *priv) +uint8_t scat_read(uint16_t port, void *priv) { - uint8_t val = 0xff; + uint8_t val = 0xff, index; + switch (port) + { + case 0x23: + switch (scat_index) + { + case SCAT_MISCELLANEOUS_STATUS: + val = (scat_regs[scat_index] & 0x3f) | (~nmi_mask & 0x80) | ((mem_a20_key & 2) << 5); + break; + case SCAT_DRAM_CONFIGURATION: + if ((scat_regs[SCAT_VERSION] & 0xF0) == 0) val = (scat_regs[scat_index] & 0x8f) | (cpu_waitstates == 1 ? 0 : 0x10); + else if(mem_size != 1024) val = (scat_regs[scat_index] & 0xe0) | scatsx_mem_conf_val[mem_size >> 9]; + else val = scat_regs[scat_index]; + break; + default: + val = scat_regs[scat_index]; + break; + } +// pclog("Read SCAT Register %02X at %04X:%04X\n", scat_index, CS, cpu_state.pc); + break; - switch (port) { - case 0x23: - switch (scat_index) { - case SCAT_MISC_STATUS: - val = (scat_regs[scat_index] & 0xbf) | ((mem_a20_key & 2) << 5); - break; + case 0x92: + val = scat_port_92; + break; - case SCAT_DRAM_CONFIG: - val = (scat_regs[scat_index] & 0x8f) | (cpu_waitstates == 1 ? 0 : 0x10); - break; - - case SCAT_SYS_CTL: - val = port_92_read(0x0092, priv); - break; - - default: - val = scat_regs[scat_index]; - break; - } - break; - - case 0x92: - val = scat_regs[SCAT_SYS_CTL]; - break; - - } - -#if SCAT_DEBUG > 2 - pclog("SCAT: read(%04x) = %02x\n", port, val); -#endif - return(val); + case 0x208: + case 0x218: + if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) + { +// pclog("Read SCAT EMS Control Port %04X at %04X:%04X\n", port, CS, cpu_state.pc); + if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F; + else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24; + val = scat_stat[index].regs_2x8; + } + break; + case 0x209: + case 0x219: + if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) + { +// pclog("Read SCAT EMS Control Port %04X at %04X:%04X\n", port, CS, cpu_state.pc); + if((scat_regs[SCAT_VERSION] & 0xF0) == 0) index = scat_ems_reg_2xA & 0x1F; + else index = ((scat_ems_reg_2xA & 0x40) >> 4) + (scat_ems_reg_2xA & 0x3) + 24; + val = scat_stat[index].regs_2x9; + } + break; + case 0x20A: + case 0x21A: + if ((scat_regs[SCAT_EMS_CONTROL] & 0x41) == (0x40 | ((port & 0x10) >> 4))) + { +// pclog("Read SCAT EMS Control Port %04X at %04X:%04X\n", port, CS, cpu_state.pc); + val = scat_ems_reg_2xA; + } + break; + } + return val; } - -/* Write to one of the Internal Control Registers. */ -static void -ics_write(uint8_t idx, uint8_t val) +uint8_t mem_read_scatems(uint32_t addr, void *priv) { - uint8_t reg_valid = 0; - uint8_t shadow_update = 0; - uint8_t map_update = 0; + uint8_t val = 0xff; + scat_t *stat = (scat_t *)priv; -#if SCAT_DEBUG > 1 - pclog("SCAT: icr_write(%02x, %02x)\n", idx, val); -#endif - switch (idx) { - case SCAT_DMA_WS_CTL: - case SCAT_CLOCK_CTL: - case SCAT_PERIPH_CTL: - reg_valid = 1; - break; + addr = get_scat_addr(addr, stat); + if (addr < (mem_size << 10)) + val = mem_read_ram(addr, priv); - case SCAT_EMS_CTL: - if (val & 0x40) { - if (val & 1) { - io_sethandler(0x0218, 3, - ems_read, NULL, NULL, - ems_write, NULL, NULL, NULL); - io_removehandler(0x0208, 3, - ems_read, NULL, NULL, - ems_write, NULL, NULL, NULL); - } else { - io_sethandler(0x0208, 3, - ems_read, NULL, NULL, - ems_write, NULL, NULL, NULL); - io_removehandler(0x0218, 3, - ems_read, NULL, NULL, - ems_write, NULL, NULL, NULL); - } - } else { - io_removehandler(0x0208, 3, - ems_read, NULL, NULL, - ems_write, NULL, NULL, NULL); - io_removehandler(0x0218, 3, - ems_read, NULL, NULL, - ems_write, NULL, NULL, NULL); - } - ems_state(val & 0x80); - reg_valid = 1; - break; - - case SCAT_POWER_MGMT: - val &= 0x40; - reg_valid = 1; - break; - - case SCAT_DRAM_CONFIG: - if ((scat_regs[SCAT_EXT_BOUNDARY] & 0x40) == 0) { - if ((val & 0x0f) == 3) { - if (mem_size > 1024) - mem_mapping_disable(&ram_high_mapping); - for (idx=0; idx<6; idx++) - mem_mapping_enable(&scat_shadowram_mapping[idx]); - } else { - for (idx=0; idx<6; idx++) - mem_mapping_disable(&scat_shadowram_mapping[idx]); - if (mem_size > 1024) - mem_mapping_enable(&ram_high_mapping); - } - } else { - for (idx=0; idx<6; idx++) - mem_mapping_disable(&scat_shadowram_mapping[idx]); - if (mem_size > 1024) - mem_mapping_enable(&ram_high_mapping); - } - map_update = 1; - - cpu_waitstates = (val & 0x70) == 0 ? 1 : 2; - cpu_update_waitstates(); - - reg_valid = 1; - break; - - case SCAT_EXT_BOUNDARY: - set_xms_bound(val & 0x4f); - mem_set_mem_state(0x40000, 0x60000, - (val & 0x20) ? MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL : MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - if ((val ^ scat_regs[SCAT_EXT_BOUNDARY]) & 0x40) - map_update = 1; - reg_valid = 1; - break; - - case SCAT_ROM_ENABLE: - case SCAT_RAM_WR_PROTECT: - case SCAT_SHADOW_RAM_EN_1: - case SCAT_SHADOW_RAM_EN_2: - case SCAT_SHADOW_RAM_EN_3: - reg_valid = 1; - shadow_update = 1; - break; - - case SCAT_SYS_CTL: - port_92_write(0x0092, val, NULL); - break; - - default: - break; - } - - if (reg_valid) - scat_regs[scat_index] = val; -#ifndef RELEASE_BUILD - else - pclog("SCAT: attemped write to register %02X at %04X:%04X\n", - idx, val, CS, cpu_state.pc); -#endif - - if (shadow_update) - shadow_state_update(); - - if (map_update) - memmap_state_update(); + return val; } - -static void -scat_write(uint16_t port, uint8_t val, void *priv) +void mem_write_scatems(uint32_t addr, uint8_t val, void *priv) { -#if SCAT_DEBUG > 2 - pclog("SCAT: write(%04x, %02x)\n", port, val); -#endif - switch (port) { - case 0x22: - scat_index = val; - break; + scat_t *stat = (scat_t *)priv; - case 0x23: - ics_write(scat_index, val); - break; - } + addr = get_scat_addr(addr, stat); + if (addr < (mem_size << 10)) + mem_write_ram(addr, val, priv); } static void scat_init(void) { - int i; + int i; -#if SCAT_DEBUG - pclog("SCAT: initializing..\n"); -#endif - io_sethandler(0x0022, 2, - scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + io_sethandler(0x0022, 2, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); - port_92_reset(); + port_92_reset(); - port_92_add(); + port_92_add(); - for (i=0; i<128; i++) - scat_regs[i] = 0xff; - scat_regs[SCAT_DMA_WS_CTL] = 0x00; - scat_regs[SCAT_VERSION] = 0x04; - scat_regs[SCAT_CLOCK_CTL] = 0x02; - scat_regs[SCAT_PERIPH_CTL] = 0x80; - scat_regs[SCAT_MISC_STATUS] = 0x37; - scat_regs[SCAT_POWER_MGMT] = 0x00; - scat_regs[SCAT_ROM_ENABLE] = 0xC0; - scat_regs[SCAT_RAM_WR_PROTECT] = 0x00; - scat_regs[SCAT_SHADOW_RAM_EN_1] = 0x00; - scat_regs[SCAT_SHADOW_RAM_EN_2] = 0x00; - scat_regs[SCAT_SHADOW_RAM_EN_3] = 0x00; - scat_regs[SCAT_DRAM_CONFIG] = cpu_waitstates == 1 ? 0x00 : 0x10; - scat_regs[SCAT_EXT_BOUNDARY] = 0x00; - scat_regs[SCAT_EMS_CTL] = 0x00; - scat_regs[SCAT_SYS_CTL] = 0x00; + for (i = 0; i < 256; i++) + { + scat_regs[i] = 0xff; + } - /* Limit RAM size to 16MB. */ - mem_mapping_set_addr(&ram_low_mapping, 0x000000, 0x40000); + scat_regs[SCAT_DMA_WAIT_STATE_CONTROL] = 0; + scat_regs[SCAT_VERSION] = 4; + scat_regs[SCAT_CLOCK_CONTROL] = 2; + scat_regs[SCAT_PERIPHERAL_CONTROL] = 0x80; + scat_regs[SCAT_MISCELLANEOUS_STATUS] = 0x37; + scat_regs[SCAT_POWER_MANAGEMENT] = 0; + scat_regs[SCAT_ROM_ENABLE] = 0xC0; + scat_regs[SCAT_RAM_WRITE_PROTECT] = 0; + scat_regs[SCAT_SHADOW_RAM_ENABLE_1] = 0; + scat_regs[SCAT_SHADOW_RAM_ENABLE_2] = 0; + scat_regs[SCAT_SHADOW_RAM_ENABLE_3] = 0; + scat_regs[SCAT_DRAM_CONFIGURATION] = cpu_waitstates == 1 ? 2 : 0x12; + scat_regs[SCAT_EXTENDED_BOUNDARY] = 0; + scat_regs[SCAT_EMS_CONTROL] = 0; + scat_port_92 = 0; - /* - * Configure the DRAM controller. - * - * Since SCAT allows mixing of the various-sized DRAM chips, - * memory configuration is not simple. The SCAT datasheet - * tells us in table 6-6 how to set up the four banks: - * - * MEM SIZE MIX_EN RAMCFG Ext RAM Comments - * 0 K 0 0x00 No RAM installed - * 512 K 0 0x01 0 K - * 640 K 0 0x02 0 K - * 1 M 0 0x03 384K - * 1 M 0 0x04 0 K - * 1.5 M 0 0x05 512K - * 2 M 0 0x06 1 M 4x512K - * 2 M 0 0x08 1 M 1x2M - * 2.5 M 1 0x01 1.5M 2M+512K - * 3 M 1 0x04 2 M 1x2M - * 4 M 0 0x09 3 M 2x2M - * 4.5 M 1 0x02 3.5M 2x2M+512K - * 5 M 1 0x05 4 M 2x2M+2x512K - * 6 M 0 0x0a 5 M 3x2M - * 6.5 M 1 0x03 5.5M 3x2M+512K - * 8 M 0 0x0b 7 M 4x2M - */ - pclog("SCAT: mem_size=%d\n", mem_size); + mem_mapping_set_addr(&ram_low_mapping, 0, 0x40000); - /* Create the 32 EMS page frame mappings for 256-640K. */ - for (i=0; i<24; i++) { - mem_mapping_add(&scat_top_mapping[i], - 0x40000 + (i<<14), 0x4000, - ems_pgrd, NULL, NULL, - ems_pgwr, NULL, NULL, - mem_size > 256+(i<<4) ? ram+0x40000+(i<<14) : NULL, - MEM_MAPPING_INTERNAL, NULL); - mem_mapping_enable(&scat_top_mapping[i]); - } + for (i = 0; i < 24; i++) + { + mem_mapping_add(&scat_4000_9FFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL); + mem_mapping_enable(&scat_4000_9FFF_mapping[i]); + } - /* Re-map the 128K at A0000 (video BIOS) to above 16MB+top. */ - mem_mapping_add(&scat_A000_mapping, - 0xA0000, 0x20000, - ems_pgrd, NULL, NULL, - ems_pgwr, NULL, NULL, - ram+0xA0000, - MEM_MAPPING_INTERNAL, NULL); - mem_mapping_disable(&scat_A000_mapping); + mem_mapping_add(&scat_A000_BFFF_mapping, 0xA0000, 0x20000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, ram + 0xA0000, MEM_MAPPING_INTERNAL, NULL); + mem_mapping_enable(&scat_A000_BFFF_mapping); - /* Create 32 page frames for EMS, each 16K. */ - for (i=0; i<32; i++) { - scat_ems[i].regs_2x8 = 0xff; - scat_ems[i].regs_2x9 = 0x03; - mem_mapping_add(&scat_mapping[i], - (i + (i >= 24 ? 28 : 16)) << 14, 0x04000, - ems_pgrd, NULL, NULL, - ems_pgwr, NULL, NULL, - ram + ((i + (i >= 24 ? 28 : 16)) << 14), - 0, &scat_ems[i]); - mem_mapping_disable(&scat_mapping[i]); - } + for (i = 0; i < 32; i++) + { + scat_stat[i].regs_2x8 = 0xff; + scat_stat[i].regs_2x9 = 0x03; + mem_mapping_add(&scat_mapping[i], (i + (i >= 24 ? 28 : 16)) << 14, 0x04000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, ram + ((i + (i >= 24 ? 28 : 16)) << 14), 0, &scat_stat[i]); + mem_mapping_disable(&scat_mapping[i]); + } - for (i=4; i<10; i++) isram[i] = 0; + for(i=4;i<10;i++) isram[i] = 0; - /* Re-map the BIOS ROM (C0000-FFFFF) area. */ - for (i=12; 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); - } + /* TODO - Only normal CPU accessing address FF0000 to FFFFFF mapped to ROM. + Normal CPU accessing address FC0000 to FEFFFF map to ROM should be implemented later. */ + for (i = 12; 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); + } - for (i=0; i<6; i++) { - mem_mapping_add(&scat_shadowram_mapping[i], - 0x100000 + (i<<16), 0x10000, - ems_pgrd, NULL, NULL, - ems_pgwr, NULL, NULL, - mem_size >= 1024 ? ram+get_addr(0x100000+(i<<16), NULL) : NULL, - MEM_MAPPING_INTERNAL, NULL); - } + for(i=0;i<6;i++) + mem_mapping_add(&scat_shadowram_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL); - set_xms_bound(0); - shadow_state_update(); + scat_set_xms_bound(0); + scat_shadow_state_update(); +} + + +static void +scatsx_init() +{ + int i; + + io_sethandler(0x0022, 0x0002, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + + port_92_reset(); + + port_92_add(); + + for (i = 0; i < 256; i++) + { + scat_regs[i] = 0xff; + } + + scat_regs[SCAT_DMA_WAIT_STATE_CONTROL] = 0; + scat_regs[SCAT_VERSION] = 0x13; + scat_regs[SCAT_CLOCK_CONTROL] = 6; + scat_regs[SCAT_PERIPHERAL_CONTROL] = 0; + scat_regs[SCAT_MISCELLANEOUS_STATUS] = 0x37; + scat_regs[SCAT_POWER_MANAGEMENT] = 0; + scat_regs[SCAT_ROM_ENABLE] = 0xC0; + scat_regs[SCAT_RAM_WRITE_PROTECT] = 0; + scat_regs[SCAT_SHADOW_RAM_ENABLE_1] = 0; + scat_regs[SCAT_SHADOW_RAM_ENABLE_2] = 0; + scat_regs[SCAT_SHADOW_RAM_ENABLE_3] = 0; + scat_regs[SCAT_DRAM_CONFIGURATION] = 1; + scat_regs[SCAT_EXTENDED_BOUNDARY] = 0; + scat_regs[SCAT_EMS_CONTROL] = 0; + scat_regs[SCATSX_LAPTOP_FEATURES] = 0; + scat_regs[SCATSX_FAST_VIDEO_CONTROL] = 0; + scat_regs[SCATSX_FAST_VIDEORAM_ENABLE] = 0; + scat_regs[SCATSX_HIGH_PERFORMANCE_REFRESH] = 8; + scat_regs[SCATSX_CAS_TIMING_FOR_DMA] = 3; + scat_port_92 = 0; + + mem_mapping_set_addr(&ram_low_mapping, 0, 0x80000); + + for (i = 16; i < 24; i++) + { + mem_mapping_add(&scat_4000_9FFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL); + mem_mapping_enable(&scat_4000_9FFF_mapping[i]); + } + + mem_mapping_add(&scat_A000_BFFF_mapping, 0xA0000, 0x20000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, ram + 0xA0000, MEM_MAPPING_INTERNAL, NULL); + mem_mapping_enable(&scat_A000_BFFF_mapping); + + for (i = 24; i < 32; i++) + { + scat_stat[i].regs_2x8 = 0xff; + scat_stat[i].regs_2x9 = 0x03; + mem_mapping_add(&scat_mapping[i], (i + 28) << 14, 0x04000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, ram + ((i + 28) << 14), 0, &scat_stat[i]); + mem_mapping_disable(&scat_mapping[i]); + } + + /* TODO - Only normal CPU accessing address FF0000 to FFFFFF mapped to ROM. + Normal CPU accessing address FC0000 to FEFFFF map to ROM should be implemented later. */ + for (i = 12; 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); + } + + for(i=0;i<6;i++) + mem_mapping_add(&scat_shadowram_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL); + + scat_set_xms_bound(0); + scat_shadow_state_update(); } @@ -744,3 +719,13 @@ machine_at_scat_init(machine_t *model) scat_init(); } + + +void +machine_at_scatsx_init(machine_t *model) +{ + machine_at_init(model); + device_add(&fdc_at_device); + + scatsx_init(); +} diff --git a/src/machine/machine.h b/src/machine/machine.h index 68154743b..be4840664 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.20 2018/03/02 + * Version: @(#)machine.h 1.0.21 2018/03/02 * * Authors: Sarah Walker, * Miran Grca, @@ -141,6 +141,7 @@ extern void machine_at_neat_ami_init(machine_t *); extern void machine_at_opti495_init(machine_t *); extern void machine_at_opti495_ami_init(machine_t *); extern void machine_at_scat_init(machine_t *); +extern void machine_at_scatsx_init(machine_t *); extern void machine_at_compaq_init(machine_t *); extern void machine_at_dtk486_init(machine_t *); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 49e5d71bf..c54e3c403 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.20 2018/03/02 + * Version: @(#)machine_table.c 1.0.21 2018/03/02 * * Authors: Sarah Walker, * Miran Grca, @@ -71,12 +71,14 @@ machine_t machines[] = { #if defined(DEV_BRANCH) && defined(USE_PORTABLE3) { "[286 ISA] Compaq Portable III", ROM_PORTABLEIII, "portableiii", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO, 640,16384, 128, 127, machine_at_compaq_init, NULL, nvr_at_close }, #endif + { "[286 ISA] GW-286CT GEAR", ROM_GW286CT, "gw286ct", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_scat_init, NULL, nvr_at_close }, { "[286 ISA] Hyundai Super-286TR", ROM_SUPER286TR, "super286tr", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_scat_init, NULL, nvr_at_close }, { "[286 ISA] IBM AT", ROM_IBMAT, "ibmat", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibm_init, NULL, nvr_at_close }, { "[286 ISA] IBM PS/1 model 2011", ROM_IBMPS1_2011, "ibmps1es", {{"", cpus_ps1_m2011}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 512,16384, 512, 127, machine_ps1_m2011_init, NULL, nvr_at_close }, { "[286 ISA] IBM PS/2 model 30-286", ROM_IBMPS2_M30_286, "ibmps2_m30_286", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 16, 1, 127, machine_ps2_m30_286_init, NULL, nvr_at_close }, { "[286 ISA] IBM XT Model 286", ROM_IBMXT286, "ibmxt286", {{"", cpus_ibmxt286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibm_init, NULL, nvr_at_close }, { "[286 ISA] Samsung SPC-4200P", ROM_SPC4200P, "spc4200p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 512, 2048, 128, 127, machine_at_scat_init, NULL, nvr_at_close }, + { "[286 ISA] Samsung SPC-4216P", ROM_SPC4216P, "spc4216p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 1, 5, 1, 127, machine_at_scat_init, NULL, nvr_at_close }, #ifdef WALTJE { "[286 ISA] OpenAT 286", ROM_OPENAT, "open_at", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512, 4096, 128, 127, machine_at_init, NULL, nvr_at_close }, #endif @@ -90,6 +92,7 @@ machine_t machines[] = { { "[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, nvr_at_close }, { "[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, 127, machine_ps1_m2121_init, NULL, nvr_at_close }, { "[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, 127, machine_ps1_m2121_init, NULL, nvr_at_close }, + { "[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, nvr_at_close }, { "[386SX MCA] IBM PS/2 model 55SX", ROM_IBMPS2_M55SX, "ibmps2_m55sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 8, 1, 63, machine_ps2_model_55sx_init, NULL, nvr_at_close }, diff --git a/src/rom.c b/src/rom.c index 97bac6f83..d8ade5075 100644 --- a/src/rom.c +++ b/src/rom.c @@ -13,7 +13,7 @@ * - c386sx16 BIOS fails checksum * - the loadfont() calls should be done elsewhere * - * Version: @(#)rom.c 1.0.31 2018/03/02 + * Version: @(#)rom.c 1.0.32 2018/03/02 * * Authors: Sarah Walker, * Miran Grca, @@ -607,12 +607,32 @@ rom_load_bios(int rom_id) break; #endif + case ROM_GW286CT: + if (rom_load_linear( + L"roms/machines/gw286ct/2ctc001.bin", + 0x000000, 65536, 0, rom)) return(1); + break; + case ROM_SPC4200P: /* Samsung SPC-4200P */ if (rom_load_linear( L"roms/machines/spc4200p/u8.01", 0x000000, 65536, 0, rom)) return(1); break; + case ROM_SPC4216P: + if (! rom_load_interleaved( + L"roms/machines/spc4216p/7101.u8", + L"roms/machines/spc4216p/ac64.u10", + 0x000000, 65536, 0, rom)) break; + biosmask = 0x7fff; + return(1); + + case ROM_KMXC02: + if (rom_load_linear( + L"roms/machines/kmxc02/3ctm005.bin", + 0x000000, 65536, 0, rom)) return(1); + break; + case ROM_SUPER286TR: /* Hyundai Super-286TR */ if (rom_load_linear( L"roms/machines/super286tr/hyundai_award286.bin", diff --git a/src/rom.h b/src/rom.h index 1be17681c..936576844 100644 --- a/src/rom.h +++ b/src/rom.h @@ -8,7 +8,7 @@ * * Definitions for the ROM image handler. * - * Version: @(#)rom.h 1.0.14 2018/03/02 + * Version: @(#)rom.h 1.0.15 2018/03/02 * * Author: Fred N. van Kempen, * Copyright 2018 Fred N. van Kempen. @@ -76,12 +76,14 @@ enum { #if defined(DEV_BRANCH) && defined(USE_PORTABLE3) ROM_PORTABLEIII, #endif + ROM_GW286CT, ROM_SUPER286TR, /* Hyundai Super-286TR/SCAT/Award */ ROM_IBMAT, ROM_IBMPS1_2011, ROM_IBMPS2_M30_286, ROM_IBMXT286, ROM_SPC4200P, /* Samsung SPC-4200P/SCAT/Phoenix */ + ROM_SPC4216P, /* Samsung SPC-4216P/SCAT */ #ifdef WALTJE ROM_OPENAT, /* PC/AT clone with Open BIOS */ #endif @@ -89,6 +91,7 @@ enum { ROM_IBMPS2_M50, ROM_AMI386SX, + ROM_KMXC02, ROM_MEGAPC, ROM_AWARD386SX_OPTI495, #if defined(DEV_BRANCH) && defined(USE_PORTABLE3)