From 9dbedefc5f83e003d932bfb9bf7eddcc4ae11e37 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sun, 20 Aug 2017 21:49:33 +0100 Subject: [PATCH] Improvements to Acermate 386SX25/N : - Implemented serial & parallel port configuration - Implemented shadow RAM - OTI-067 now configured as on-board device rather than separate card --- src/acer386sx.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++- src/acer386sx.h | 1 + src/vid_oti067.c | 21 ++++++-- src/vid_oti067.h | 2 + src/video.c | 2 +- 5 files changed, 147 insertions(+), 6 deletions(-) diff --git a/src/acer386sx.c b/src/acer386sx.c index 77a7ef2..456ef35 100644 --- a/src/acer386sx.c +++ b/src/acer386sx.c @@ -1,22 +1,92 @@ #include "ibm.h" +#include "device.h" #include "io.h" #include "cpu.h" +#include "lpt.h" +#include "mem.h" +#include "serial.h" +#include "vid_oti067.h" #include "acer386sx.h" static int acer_index = 0; static uint8_t acer_regs[256]; +static uint8_t acer_last_write; +static int acer_locked; +static void *acer_oti067; + +void acer386sx_set_oti067(void *oti067) +{ + acer_oti067 = oti067; +} void acer386sx_write(uint16_t addr, uint8_t val, void *priv) { if (addr & 1) - acer_regs[acer_index] = val; + { + if (acer_locked) + { + if (acer_last_write == 0x14 && val == 0x09) + acer_locked = 0; + + acer_last_write = val; + return; + } + + if (acer_index == 0xff && val == 0xff) + acer_locked = 1; + else + { + pclog("Write ACER reg %02x %02x %08x\n", acer_index, val, cs); + acer_regs[acer_index] = val; + + switch (acer_index) + { + case 0xa: + switch ((val >> 4) & 3) + { + case 0: + mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + case 1: + mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + case 2: + mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + break; + case 3: + mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + } + break; + case 0xb: + switch ((val >> 4) & 3) + { + case 0: + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + case 1: + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + case 2: + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + break; + case 3: + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + } + break; + } + } + } else - acer_index = val; + acer_index = val; } uint8_t acer386sx_read(uint16_t addr, void *priv) { + if (acer_locked) + return 0xff; if (addr & 1) { if ((acer_index >= 0xc0 || acer_index == 0x20) && cpu_iscyrix) @@ -27,7 +97,60 @@ uint8_t acer386sx_read(uint16_t addr, void *priv) return acer_index; } +static uint8_t acer386sx_37f = 0, acer386sx_io = 0; +void acer386sx_io_write(uint16_t addr, uint8_t val, void *priv) +{ + switch (addr) + { + case 0x37f: + acer386sx_37f = val; + if (val & 4) + oti067_enable_disable(acer_oti067, 0); + else + oti067_enable_disable(acer_oti067, 1); + break; + + case 0x3f3: + acer386sx_io = val; + serial1_remove(); + serial2_remove(); + lpt1_remove(); + lpt2_remove(); + + switch (val & 3) + { + case 0: lpt1_init(0x378); break; + case 1: lpt1_init(0x3bc); break; + case 2: lpt1_init(0x278); break; + } + if (!(val & 0x04)) + serial1_set(0x3f8, 4); + if (!(val & 0x08)) + serial2_set(0x2f8, 3); + break; + } +} + +uint8_t acer386sx_io_read(uint16_t addr, void *priv) +{ + switch (addr) + { + case 0x37f: + return acer386sx_37f; + + case 0x3f3: + return acer386sx_io; + } + + return 0xff; +} + void acer386sx_init() { io_sethandler(0x0022, 0x0002, acer386sx_read, NULL, NULL, acer386sx_write, NULL, NULL, NULL); + io_sethandler(0x037f, 0x0001, acer386sx_io_read, NULL, NULL, acer386sx_io_write, NULL, NULL, NULL); + io_sethandler(0x03f3, 0x0001, acer386sx_io_read, NULL, NULL, acer386sx_io_write, NULL, NULL, NULL); + + acer386sx_io = 0; + acer386sx_37f = 0; } diff --git a/src/acer386sx.h b/src/acer386sx.h index 12d98f1..3d91d5c 100644 --- a/src/acer386sx.h +++ b/src/acer386sx.h @@ -1 +1,2 @@ void acer386sx_init(); +void acer386sx_set_oti067(void *oti067); diff --git a/src/vid_oti067.c b/src/vid_oti067.c index 7088bbf..e528e01 100644 --- a/src/vid_oti067.c +++ b/src/vid_oti067.c @@ -8,6 +8,7 @@ #include "video.h" #include "vid_oti067.h" #include "vid_svga.h" +#include "acer386sx.h" typedef struct oti067_t { @@ -171,6 +172,21 @@ void *oti067_common_init(char *bios_fn, int vram_size) return oti067; } +void oti067_enable_disable(void *p, int enable) +{ + oti067_t *oti067 = (oti067_t *)p; + + mem_mapping_disable(&oti067->bios_rom.mapping); + io_removehandler(0x03c0, 0x0020, oti067_in, NULL, NULL, oti067_out, NULL, NULL, oti067); + io_removehandler(0x46e8, 0x0001, oti067_pos_in, NULL, NULL, oti067_pos_out, NULL, NULL, oti067); + if (enable) + { + mem_mapping_enable(&oti067->bios_rom.mapping); + io_sethandler(0x03c0, 0x0020, oti067_in, NULL, NULL, oti067_out, NULL, NULL, oti067); + io_sethandler(0x46e8, 0x0001, oti067_pos_in, NULL, NULL, oti067_pos_out, NULL, NULL, oti067); + } +} + void *oti067_init() { int vram_size = device_get_config_int("memory"); @@ -181,9 +197,8 @@ void *oti067_acer386_init() { oti067_t *oti067 = oti067_common_init("acer386/oti067.bin", 512); - if (oti067) - oti067->bios_rom.rom[0x5d] = 0x74; - + acer386sx_set_oti067(oti067); + return oti067; } diff --git a/src/vid_oti067.h b/src/vid_oti067.h index 81d4358..cf1fa1b 100644 --- a/src/vid_oti067.h +++ b/src/vid_oti067.h @@ -1,2 +1,4 @@ extern device_t oti067_device; extern device_t oti067_acer386_device; + +void oti067_enable_disable(void *p, int enable); diff --git a/src/video.c b/src/video.c index df3a2cc..e7567e5 100644 --- a/src/video.c +++ b/src/video.c @@ -297,7 +297,7 @@ void video_init() return; case ROM_ACER386: - device_add(&oti067_device); + device_add(&oti067_acer386_device); return; case ROM_IBMPS1_2011: