From b465a6a3ec61bb8df076270fc20852930e28b384 Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Wed, 20 Jan 2021 13:37:39 +0200 Subject: [PATCH] Added an AMI ALi M1489 board This includes also the Goldstar Prime3B Super I/O --- src/include/86box/machine.h | 1 + src/include/86box/sio.h | 2 + src/machine/m_at_386dx_486.c | 26 ++++ src/machine/machine_table.c | 1 + src/sio/CMakeLists.txt | 3 +- src/sio/sio_prime3b.c | 292 +++++++++++++++++++++++++++++++++++ src/win/Makefile.mingw | 2 +- 7 files changed, 325 insertions(+), 2 deletions(-) create mode 100644 src/sio/sio_prime3b.c diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 4379a4551..7107829dc 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -336,6 +336,7 @@ extern int machine_at_486vipio2_init(const machine_t *); #endif #if defined(DEV_BRANCH) && defined(USE_M1489) extern int machine_at_abpb4_init(const machine_t *); +extern int machine_at_win486pci_init(const machine_t *); #endif #if defined(DEV_BRANCH) && defined(USE_STPC) extern int machine_at_itoxstar_init(const machine_t *); diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index ec37b2609..6775b0bea 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -48,6 +48,8 @@ extern const device_t pc87311_ide_device; extern const device_t pc87332_device; extern const device_t pc87332_ps1_device; extern const device_t pc97307_device; +extern const device_t prime3b_device; +extern const device_t prime3b_ide_device; extern const device_t prime3c_device; extern const device_t prime3c_ide_device; extern const device_t ps1_m2133_sio; diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 6235316f3..a0f8494b3 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -950,6 +950,32 @@ machine_at_abpb4_init(const machine_t *model) return ret; } + +int +machine_at_win486pci_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/win486pci/v1hj3.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); + + device_add(&ali1489_device); + device_add(&prime3b_device); + device_add(&keyboard_at_ami_device); + + return ret; +} #endif diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index a9ca2aa32..d3a037b7e 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -224,6 +224,7 @@ const machine_t machines[] = { /* 486 machines which utilize the PCI bus */ #if defined(DEV_BRANCH) && defined(USE_M1489) { "[ALi M1489] ABIT AB-PB4", "abpb4", MACHINE_TYPE_486, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_abpb4_init, NULL }, + { "[ALi M1489] AMI WinBIOS 486 PCI", "win486pci", MACHINE_TYPE_486, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_win486pci_init, NULL }, #endif { "[i420EX] ASUS PVI-486AP4", "486ap4", MACHINE_TYPE_486, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_IDE_DUAL, 1024, 131072, 1024, 127, machine_at_486ap4_init, NULL }, { "[i420ZX] ASUS PCI/I-486SP3G", "486sp3g", MACHINE_TYPE_486, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 131072, 1024, 127, machine_at_486sp3g_init, NULL }, diff --git a/src/sio/CMakeLists.txt b/src/sio/CMakeLists.txt index 8dcb8416e..4cd1dcef1 100644 --- a/src/sio/CMakeLists.txt +++ b/src/sio/CMakeLists.txt @@ -16,7 +16,8 @@ add_library(sio OBJECT sio_acc3221.c sio_f82c710.c sio_82091aa.c sio_fdc37c661.c sio_fdc37c66x.c sio_fdc37c669.c sio_fdc37c93x.c sio_fdc37m60x.c sio_pc87306.c sio_pc87307.c sio_pc87309.c sio_pc87311.c sio_pc87332.c - sio_prime3c.c sio_w83787f.c sio_w83877f.c sio_w83977f.c sio_um8669f.c + sio_prime3b.c sio_prime3c.c + sio_w83787f.c sio_w83877f.c sio_w83977f.c sio_um8669f.c sio_vt82c686.c) if(SIO_DETECT) diff --git a/src/sio/sio_prime3b.c b/src/sio/sio_prime3b.c new file mode 100644 index 000000000..3277aa306 --- /dev/null +++ b/src/sio/sio_prime3b.c @@ -0,0 +1,292 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the Goldstar Prime3B Super I/O + * + * Authors: Tiseno100 + * Copyright 2021 Tiseno100 + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/timer.h> +#include <86box/device.h> +#include <86box/lpt.h> +#include <86box/serial.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/sio.h> + +#define FSR dev->regs[0xa0] +#define ASR dev->regs[0xa1] +#define PDR dev->regs[0xa2] +#define HAS_IDE_FUNCTIONALITY dev->ide_function + +#ifdef ENABLE_PRIME3B_LOG +int prime3b_do_log = ENABLE_PRIME3B_LOG; +static void +prime3b_log(const char *fmt, ...) +{ + va_list ap; + + if (prime3b_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define prime3b_log(fmt, ...) +#endif + +typedef struct +{ + uint8_t index, regs[256], cfg_lock, ide_function; + uint16_t com3_addr, com4_addr; + + fdc_t *fdc_controller; + serial_t *uart[2]; + +} prime3b_t; + +void prime3b_fdc_handler(prime3b_t *dev); +void prime3b_uart_handler(uint8_t num, prime3b_t *dev); +void prime3b_lpt_handler(prime3b_t *dev); +void prime3b_ide_handler(prime3b_t *dev); +void prime3b_enable(prime3b_t *dev); +void prime3b_powerdown(prime3b_t *dev); + +static void +prime3b_write(uint16_t addr, uint8_t val, void *priv) +{ + prime3b_t *dev = (prime3b_t *)priv; + + if (addr == 0x398) + { + dev->index = val; + + /* Enter/Escape Configuration Mode */ + if (val == 0x33) + dev->cfg_lock = 0; + else if (val == 0xcc) + dev->cfg_lock = 1; + } + else if ((addr == 0x399) && !dev->cfg_lock) + { + switch (dev->index) + { + case 0xa0: /* Function Selection Register (FSR) */ + FSR = val; + prime3b_enable(dev); + break; + case 0xa1: /* Address Selection Register (ASR) */ + ASR = val; + prime3b_enable(dev); + break; + case 0xa2: /* Power Down Register (PDR) */ + dev->regs[0xa2] = val; + break; + case 0xa3: /* Test Mode Register (TMR) */ + dev->regs[0xa3] = val; + break; + case 0xa4: /* Miscellaneous Function Register */ + dev->regs[0xa4] = val; + switch ((dev->regs[0xa4] >> 6) & 3) + { + case 0: + dev->com3_addr = 0x3e8; + dev->com4_addr = 0x2e8; + break; + case 1: + dev->com3_addr = 0x338; + dev->com4_addr = 0x238; + break; + case 2: + dev->com3_addr = 0x2e8; + dev->com4_addr = 0x2e0; + break; + case 3: + dev->com3_addr = 0x220; + dev->com4_addr = 0x228; + break; + } + break; + case 0xa5: /* ECP Register */ + dev->regs[0xa5] = val; + break; + } + } +} + +static uint8_t +prime3b_read(uint16_t addr, void *priv) +{ + prime3b_t *dev = (prime3b_t *)priv; + + return dev->regs[dev->index]; +} + +void prime3b_fdc_handler(prime3b_t *dev) +{ + uint16_t fdc_base = !(ASR & 0x40) ? 0x3f0 : 0x370; + fdc_remove(dev->fdc_controller); + fdc_set_base(dev->fdc_controller, fdc_base); + prime3b_log("Prime3B-FDC: Enabled with base %03x\n", fdc_base); +} + +void prime3b_uart_handler(uint8_t num, prime3b_t *dev) +{ + uint16_t uart_base; + if ((ASR >> (3 + 2 * num)) & 1) + uart_base = !((ASR >> (2 + 2 * num)) & 1) ? dev->com3_addr : dev->com4_addr; + else + uart_base = !((ASR >> (2 + 2 * num)) & 1) ? 0x3f8 : 0x2f8; + + serial_remove(dev->uart[num]); + serial_setup(dev->uart[num], uart_base, 4 - num); + prime3b_log("Prime3B-UART%d: Enabled with base %03x\n", num, uart_base); +} + +void prime3b_lpt_handler(prime3b_t *dev) +{ + uint16_t lpt_base = (ASR & 2) ? 0x3bc : (!(ASR & 1) ? 0x378 : 0x278); + lpt1_remove(); + lpt1_init(lpt_base); + lpt1_irq(7); + prime3b_log("Prime3B-LPT: Enabled with base %03x\n", lpt_base); +} + +void prime3b_ide_handler(prime3b_t *dev) +{ + ide_pri_disable(); + uint16_t ide_base = !(ASR & 0x80) ? 0x1f0 : 0x170; + ide_set_base(0, ide_base); + ide_set_side(0, ide_base + 0x206); + prime3b_log("Prime3B-IDE: Enabled with base %03x and side %03x\n", ide_base, ide_base + 0x206); +} + +void prime3b_enable(prime3b_t *dev) +{ + /* + Simulate a device enable/disable scenario + + Register A0: Function Selection Register (FSR) + Bit 7: Gameport + Bit 6: 4 FDD Enable + Bit 5: IDE + Bit 4: FDC + Bit 3: UART 2 + Bit 2: UART 1 + Bit 1/0: PIO (0/0 Bidirectional , 0/1 ECP, 1/0 EPP, 1/1 Disabled) + + Note: 86Box LPT is simplistic and can't do ECP or EPP. + */ + + !(FSR & 3) ? prime3b_lpt_handler(dev) : lpt1_remove(); + (FSR & 4) ? prime3b_uart_handler(0, dev) : serial_remove(dev->uart[0]); + (FSR & 8) ? prime3b_uart_handler(1, dev) : serial_remove(dev->uart[1]); + (FSR & 0x10) ? prime3b_fdc_handler(dev) : fdc_remove(dev->fdc_controller); + if (HAS_IDE_FUNCTIONALITY) + (FSR & 0x20) ? prime3b_ide_handler(dev) : ide_pri_disable(); +} + +void prime3b_powerdown(prime3b_t *dev) +{ + /* Note: It can be done more efficiently for sure */ + uint8_t old_base = PDR; + + if (PDR & 1) + PDR |= 0x1e; + + if (PDR & 0x40) + io_removehandler(0x0398, 0x0002, prime3b_read, NULL, NULL, prime3b_write, NULL, NULL, dev); + + if (PDR & 2) + fdc_remove(dev->fdc_controller); + + if (PDR & 4) + serial_remove(dev->uart[0]); + + if (PDR & 8) + serial_remove(dev->uart[1]); + + if (PDR & 0x10) + lpt1_remove(); + + if (PDR & 1) + PDR = old_base; +} + +static void +prime3b_close(void *priv) +{ + prime3b_t *dev = (prime3b_t *)priv; + + free(dev); +} + +static void * +prime3b_init(const device_t *info) +{ + prime3b_t *dev = (prime3b_t *)malloc(sizeof(prime3b_t)); + memset(dev, 0, sizeof(prime3b_t)); + + /* Avoid conflicting with machines that make no use of the Prime3B Internal IDE */ + HAS_IDE_FUNCTIONALITY = info->local; + + dev->regs[0xa0] = 3; + + dev->fdc_controller = device_add(&fdc_at_device); + dev->uart[0] = device_add_inst(&ns16550_device, 1); + dev->uart[1] = device_add_inst(&ns16550_device, 2); + if (HAS_IDE_FUNCTIONALITY) + device_add(&ide_isa_device); + + dev->com3_addr = 0x3e8; + dev->com4_addr = 0x2e8; + fdc_reset(dev->fdc_controller); + + prime3b_enable(dev); + + io_sethandler(0x0398, 0x0002, prime3b_read, NULL, NULL, prime3b_write, NULL, NULL, dev); + + return dev; +} + +const device_t prime3b_device = { + "Goldstar Prime3B", + 0, + 0, + prime3b_init, + prime3b_close, + NULL, + {NULL}, + NULL, + NULL, + NULL}; + +const device_t prime3b_ide_device = { + "Goldstar Prime3B with IDE functionality", + 0, + 1, + prime3b_init, + prime3b_close, + NULL, + {NULL}, + NULL, + NULL, + NULL}; diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 1c6fc5397..7b2488060 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -652,7 +652,7 @@ SIOOBJ := sio_acc3221.o \ sio_f82c710.o sio_82091aa.o \ sio_fdc37c661.o sio_fdc37c66x.o sio_fdc37c669.o sio_fdc37c93x.o sio_fdc37m60x.o \ sio_pc87306.o sio_pc87307.o sio_pc87309.o sio_pc87311.o sio_pc87332.o \ - sio_prime3c.o \ + sio_prime3b.o sio_prime3c.o \ sio_w83787f.o \ sio_w83877f.o sio_w83977f.o \ sio_um8669f.o \