From 5c3069c561980869699ba64755c72cc440d8c19a Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 9 Nov 2020 21:50:42 +0000 Subject: [PATCH] Add W83977TF SuperIO chip for Gigabyte GA686BX. --- src/Makefile.am | 2 +- src/Makefile.mingw-wx-sdl2 | 2 +- src/Makefile.mingw-wx-sdl2-network | 2 +- src/model.c | 3 +- src/w83977tf.c | 197 +++++++++++++++++++++++++++++ src/w83977tf.h | 1 + 6 files changed, 203 insertions(+), 4 deletions(-) create mode 100644 src/w83977tf.c create mode 100644 src/w83977tf.h diff --git a/src/Makefile.am b/src/Makefile.am index d514a98..ca69439 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -51,7 +51,7 @@ vid_stg_ramdac.c vid_svga.c vid_svga_render.c vid_t1000.c vid_t3100e.c vid_tandy vid_tkd8001_ramdac.c vid_tvga.c vid_unk_ramdac.c vid_vga.c vid_voodoo.c vid_voodoo_banshee.c vid_voodoo_banshee_blitter.c \ vid_voodoo_blitter.c vid_voodoo_display.c vid_voodoo_fb.c vid_voodoo_fifo.c vid_voodoo_reg.c \ vid_voodoo_render.c vid_voodoo_setup.c vid_voodoo_texture.c video.c wd76c10.c vid_wy700.c vt82c586b.c \ -vl82c480.c w83877tf.c x86seg.c x87.c x87_timings.c xi8088.c xtide.c sound_dbopl.cc sound_resid.cc +vl82c480.c w83877tf.c w83977tf.c x86seg.c x87.c x87_timings.c xi8088.c xtide.c sound_dbopl.cc sound_resid.cc # DOSBox pcem_SOURCES += dosbox/cdrom_image.cpp dosbox/dbopl.cpp dosbox/nukedopl.cpp dosbox/vid_cga_comp.c diff --git a/src/Makefile.mingw-wx-sdl2 b/src/Makefile.mingw-wx-sdl2 index 2926e83..790468e 100644 --- a/src/Makefile.mingw-wx-sdl2 +++ b/src/Makefile.mingw-wx-sdl2 @@ -39,7 +39,7 @@ OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o 82091aa.o acc203 vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o vid_voodoo.o vid_voodoo_banshee.o vid_voodoo_banshee_blitter.o \ vid_voodoo_blitter.o vid_voodoo_display.o vid_voodoo_fb.o vid_voodoo_fifo.o vid_voodoo_reg.o \ vid_voodoo_render.o vid_voodoo_setup.o vid_voodoo_texture.o vid_wy700.o video.o vl82c480.o \ - vt82c586b.o w83877tf.o wd76c10.o x86seg.o x87.o x87_timings.o xi8088.c xtide.o win-midi.o wx-main.o \ + vt82c586b.o w83877tf.o w83977tf.o wd76c10.o x86seg.o x87.o x87_timings.o xi8088.c xtide.o win-midi.o wx-main.o \ wx-config_sel.o wx-dialogbox.o wx-utils.o wx-app.o wx-sdl2-joystick.o wx-sdl2-mouse.o \ wx-sdl2-keyboard.o wx-sdl2-video.o wx-sdl2.o wx-config.o wx-deviceconfig.o wx-status.o \ wx-sdl2-status.o wx-resources.o wx-thread.o wx-common.o wx-sdl2-display-win.o \ diff --git a/src/Makefile.mingw-wx-sdl2-network b/src/Makefile.mingw-wx-sdl2-network index fd03280..6952573 100644 --- a/src/Makefile.mingw-wx-sdl2-network +++ b/src/Makefile.mingw-wx-sdl2-network @@ -39,7 +39,7 @@ OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o 82091aa.o acc203 vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o vid_voodoo.o vid_voodoo_banshee.o vid_voodoo_banshee_blitter.o \ vid_voodoo_blitter.o vid_voodoo_display.o vid_voodoo_fb.o vid_voodoo_fifo.o vid_voodoo_reg.o \ vid_voodoo_render.o vid_voodoo_setup.o vid_voodoo_texture.o vid_wy700.o video.o vl82c480.o \ - vt82c586b.o w83877tf.o wd76c10.o x86seg.o x87.o x87_timings.o xi8088.c xtide.o win-midi.o wx-main.o \ + vt82c586b.o w83877tf.o w83977tf.o wd76c10.o x86seg.o x87.o x87_timings.o xi8088.c xtide.o win-midi.o wx-main.o \ wx-config_sel.o wx-dialogbox.o wx-hostconfig.o wx-utils.o wx-app.o wx-sdl2-joystick.o wx-sdl2-mouse.o \ wx-sdl2-keyboard.o wx-sdl2-video.o wx-sdl2.o wx-config.o wx-deviceconfig.o wx-status.o \ wx-sdl2-status.o wx-resources.o wx-thread.o wx-common.o wx-sdl2-display-win.o \ diff --git a/src/model.c b/src/model.c index 55e9177..fd10cb5 100644 --- a/src/model.c +++ b/src/model.c @@ -78,6 +78,7 @@ #include "vl82c480.h" #include "vt82c586b.h" #include "w83877tf.h" +#include "w83977tf.h" #include "wd76c10.h" #include "xi8088.h" #include "zenith.h" @@ -847,7 +848,7 @@ void at_ga686bx_init() pci_slot(0xb); i440bx_init(); piix4_init(7, 0x8, 0x9, 0xa, 0xb, i440bx_reset); - w83877tf_init(0x250, 0x89); + w83977tf_init(0x3f0, 0x87); device_add(&intel_flash_28f002bc_device); } diff --git a/src/w83977tf.c b/src/w83977tf.c new file mode 100644 index 0000000..520b4ed --- /dev/null +++ b/src/w83977tf.c @@ -0,0 +1,197 @@ +#include "ibm.h" + +#include "fdc.h" +#include "io.h" +#include "lpt.h" +#include "serial.h" +#include "w83977tf.h" + +typedef struct winbond_t +{ + int cur_reg; + int cur_device; + int index; + + uint8_t unlock_key; + uint8_t key[2]; + int enable_regs; + + struct + { + int enable; + uint16_t addr; + int irq; + int dma; + } dev[11]; +} winbond_t; + +static winbond_t winbond_global; + +#define DEV_FDC 0x0 +#define DEV_LPT 0x1 +#define DEV_COM1 0x2 +#define DEV_COM2 0x3 +#define DEV_KBC 0x5 +#define DEV_GPIO 0x7 +#define DEV_GPIO_II 0x8 +#define DEV_GPIO_III 0x9 +#define DEV_ACPI 0xa + +#define REG_DEVICE 0x07 +#define REG_DEVICE_ID 0x20 +#define REG_DEVICE_REV 0x21 +#define REG_ENABLE 0x30 +#define REG_ADDRHI 0x60 +#define REG_ADDRLO 0x61 +#define REG_IRQ 0x70 +#define REG_DMA 0x74 + +void winbond_write_reg(winbond_t *winbond, int index, uint8_t val) +{ + if (index == REG_DEVICE) + winbond->cur_device = val & 0xf; + else + { +// pclog("Write winbond %02x [%02x] %02x\n", winbond->cur_reg, winbond->cur_device, val); + switch (index) + { + case REG_ENABLE: + if (winbond->cur_device <= DEV_ACPI) + winbond->dev[winbond->cur_device].enable = val; + break; + case REG_ADDRLO: + if (winbond->cur_device <= DEV_ACPI) + winbond->dev[winbond->cur_device].addr = (winbond->dev[winbond->cur_device].addr & 0xff00) | val; + break; + case REG_ADDRHI: + if (winbond->cur_device <= DEV_ACPI) + winbond->dev[winbond->cur_device].addr = (winbond->dev[winbond->cur_device].addr & 0x00ff) | (val << 8); + break; + case REG_IRQ: + if (winbond->cur_device <= DEV_ACPI) + winbond->dev[winbond->cur_device].irq = val; + break; + case REG_DMA: + if (winbond->cur_device <= DEV_ACPI) + winbond->dev[winbond->cur_device].dma = val; + break; + } + + switch (winbond->cur_device) + { + case DEV_FDC: + fdc_remove(); + if (winbond->dev[DEV_FDC].enable & 1) + fdc_add(); + break; + case DEV_COM1: + serial1_remove(); + if (winbond->dev[DEV_COM1].enable & 1) + serial1_set(winbond->dev[DEV_COM1].addr, winbond->dev[DEV_COM1].irq); + break; + case DEV_COM2: + serial2_remove(); + if (winbond->dev[DEV_COM2].enable & 1) + serial2_set(winbond->dev[DEV_COM2].addr, winbond->dev[DEV_COM2].irq); + break; + case DEV_LPT: + lpt1_remove(); + lpt2_remove(); + if (winbond->dev[DEV_LPT].enable & 1) + lpt1_init(winbond->dev[DEV_LPT].addr); + break; + } + } +} + +uint8_t winbond_read_reg(winbond_t *winbond, int index) +{ +// pclog("Read winbond %02x\n", winbond->cur_reg); + + switch (index) + { + case REG_DEVICE: + return winbond->cur_device; + case REG_DEVICE_ID: + return 0x97; + case REG_DEVICE_REV: + return 0x73; + case REG_ENABLE: + return winbond->dev[winbond->cur_device].enable; + case REG_ADDRLO: + return winbond->dev[winbond->cur_device].addr & 0xff; + case REG_ADDRHI: + return winbond->dev[winbond->cur_device].addr >> 8; + case REG_IRQ: + return winbond->dev[winbond->cur_device].irq; + case REG_DMA: + return winbond->dev[winbond->cur_device].dma; + } + + return 0xff; +} + +static void winbond_write_3fx(uint16_t port, uint8_t val, void *p) +{ + winbond_t *winbond = (winbond_t *)p; + +// pclog("winbond_write: port=%04x val=%02x\n", port, val); + + switch (port) + { + case 0x3f0: /*Enable/index register*/ + if (val == 0xaa) + { + fdc_3f1_enable(1); + winbond->enable_regs = 0; + } + else if (!winbond->enable_regs) + { + winbond->key[1] = winbond->key[0]; + winbond->key[0] = val; + winbond->enable_regs = (winbond->key[0] == winbond->unlock_key && winbond->key[1] == winbond->unlock_key); + /*The FDC conflicts with the 3fx config registers, so disable + it when enabling config registers*/ + if (winbond->enable_regs) + fdc_3f1_enable(0); + } + else + winbond->index = val; + break; + case 0x3f1: /*Data*/ + if (winbond->enable_regs) + winbond_write_reg(winbond, winbond->index, val); + break; + } +} + +static uint8_t winbond_read_3fx(uint16_t port, void *p) +{ + winbond_t *winbond = (winbond_t *)p; + uint8_t ret = 0xff; + + switch (port) + { + case 0x3f0: /*Index*/ + if (winbond->enable_regs) + ret = winbond->index; + break; + + case 0x3f1: /*Data*/ + if (winbond->enable_regs) + ret = winbond_read_reg(winbond, winbond->index); + break; + } + +// pclog("winbond_read: port=%04x val=%02x\n", port, ret); + + return ret; +} + +void w83977tf_init(uint16_t base, uint8_t key) +{ + memset(&winbond_global, 0, sizeof(winbond_t)); + + winbond_global.unlock_key = key; + io_sethandler(base, 0x0002, winbond_read_3fx, NULL, NULL, winbond_write_3fx, NULL, NULL, &winbond_global); +} diff --git a/src/w83977tf.h b/src/w83977tf.h new file mode 100644 index 0000000..290f571 --- /dev/null +++ b/src/w83977tf.h @@ -0,0 +1 @@ +void w83977tf_init(uint16_t base, uint8_t key);