diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 9ccba8dc6..6147a2ccf 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -92,5 +92,6 @@ add_library(chipset OBJECT via_apollo.c via_pipc.c vl82c480.c + vl82c59x.c wd76c10.c ) diff --git a/src/chipset/vl82c59x.c b/src/chipset/vl82c59x.c new file mode 100644 index 000000000..0ed6bb0db --- /dev/null +++ b/src/chipset/vl82c59x.c @@ -0,0 +1,644 @@ +/* + * 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. + * + * Implementation of the VLSI SuperCore and Wildcat chipsets. + * + * + * + * Authors: Miran Grca, + * win2kgamer + * + * Copyright 2020-2025 Miran Grca. + * Copyright 2025 win2kgamer + */ + +#ifdef ENABLE_VL82C59X_LOG +#include +#endif + +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/device.h> +#include <86box/io.h> +#include <86box/timer.h> +#include <86box/apm.h> +#include <86box/machine.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/pit_fast.h> +#include <86box/plat_unused.h> +#include <86box/mem.h> +#include <86box/nvr.h> +#include <86box/smram.h> +#include <86box/pci.h> +#include <86box/port_92.h> +#include <86box/spd.h> +#include <86box/keyboard.h> +#include <86box/chipset.h> +#include <86box/log.h> + +#ifdef ENABLE_VL82C59X_LOG +int vl82c59x_do_log = ENABLE_VL82C59X_LOG; + +static void +vl82c59x_log(void *priv, const char *fmt, ...) +{ + if (vl82c59x_do_log) { + va_list ap; + va_start(ap, fmt); + log_out(priv, fmt, ap); + va_end(ap); + } +} +#else +# define vl82c59x_log(fmt, ...) +#endif + +typedef struct vl82c59x_t { + uint8_t nb_slot; + uint8_t sb_slot; + uint8_t type; + uint8_t is_compaq; + + uint8_t pci_conf[256]; + uint8_t pci_conf_sb[256]; + + uint16_t pmio; + uint8_t pmio_set; + uint8_t pmreg; + + smram_t *smram[4]; + port_92_t *port_92; + nvr_t *nvr; + + void * log; /* New logging system */ +} vl82c59x_t; + +static int +vl82c59x_shflags(uint8_t access) +{ + int ret = MEM_READ_EXTANY | MEM_WRITE_EXTANY; + + switch (access) { + default: + case 0x00: + ret = MEM_READ_EXTANY | MEM_WRITE_EXTANY; + break; + case 0x01: + ret = MEM_READ_EXTANY | MEM_WRITE_INTERNAL; + break; + case 0x02: + ret = MEM_READ_INTERNAL | MEM_WRITE_EXTANY; + break; + case 0x03: + ret = MEM_READ_INTERNAL | MEM_WRITE_INTERNAL; + break; + } + + return ret; +} + +static void +vl82c59x_recalc(vl82c59x_t *dev) +{ + uint32_t base; + uint8_t access; + + shadowbios = 0; + shadowbios_write = 0; + + for (uint8_t i = 0; i < 4; i++) { + for (uint8_t j = 0; j < 8; j += 2) { + base = 0x000c0000 + (i << 16) + (j << 13); + access = (dev->pci_conf[0x66 + i] >> j) & 3; + mem_set_mem_state_both(base, 0x4000, vl82c59x_shflags(access)); + shadowbios |= ((base >= 0xe0000) && (access & 0x02)); + shadowbios_write |= ((base >= 0xe0000) && (access & 0x01)); + } + } + + flushmmucache(); +} + +static void +vl82c59x_smram(vl82c59x_t *dev) +{ + smram_disable_all(); + + /* A/B region SMRAM seems to not be controlled by 591 reg 0x7C/SMRAM enable */ + /* Dell Dimension BIOS breaks if A0000 region is controlled by SMRAM enable */ + if (dev->pci_conf[0x64] & 0x55) { + smram_enable(dev->smram[1], 0x000a0000, 0x000a0000, 0x10000, dev->pci_conf[0x64] & 0xAA, dev->pci_conf[0x64] & 0x55); + } + if (dev->pci_conf[0x65] & 0x55) { + smram_enable(dev->smram[2], 0x000b0000, 0x000b0000, 0x10000, dev->pci_conf[0x65] & 0xAA, dev->pci_conf[0x65] & 0x55); + } + + /* Handle E region SMRAM */ + if (dev->pci_conf[0x7C] & 0x80) { + if (dev->pci_conf[0x68] & 0x05) { + smram_enable(dev->smram[3], 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x68] & 0x0A, dev->pci_conf[0x68] & 0x05); + } + if (dev->pci_conf[0x68] & 0x50) { + smram_enable(dev->smram[4], 0x000e8000, 0x000e8000, 0x8000, dev->pci_conf[0x68] & 0xA0, dev->pci_conf[0x68] & 0x50); + } + } + + flushmmucache(); +} + +static void +vl82c59x_pm_write(uint16_t addr, uint8_t val, void *priv) +{ + vl82c59x_t *dev = (vl82c59x_t *) priv; + + vl82c59x_log(dev->log, "VL82c593 SMI I/O: [W] (%04X) = %02X\n", addr, val); + + /* Verify SMI Global Enable and Software SMI Enable are set */ + if ((dev->pci_conf_sb[0x6D] & 0x80) && (dev->pci_conf_sb[0x60] & 0x80)) { + dev->pci_conf_sb[0x61] = 0x80; + dev->pmreg = val; + smi_raise(); + } + +} + +static uint8_t +vl82c59x_pm_read(uint16_t addr, void *priv) +{ + vl82c59x_t *dev = (vl82c59x_t *) priv; + uint8_t ret = 0x00; + + ret = dev->pmreg; + vl82c59x_log(dev->log, "VL82c593 SMI I/O: [R] (%04X) = %02X\n", addr, ret); + + return ret; +} + +static void +vl82c59x_set_pm_io(void *priv) +{ + vl82c59x_t *dev = (vl82c59x_t *) priv; + uint8_t highbyte = dev->pci_conf_sb[0x62]; + uint8_t lowbyte = dev->pci_conf_sb[0x63]; + + /* Check for existing I/O mapping and remove it */ + if (dev->pmio_set == 1) { + vl82c59x_log(dev->log, "VL82c59x: Removing SMI IO handler for %04X\n", dev->pmio); + io_removehandler(dev->pmio, 0x0001, vl82c59x_pm_read, NULL, NULL, vl82c59x_pm_write, NULL, NULL, dev); + dev->pmio_set = 0; + } + + if ((highbyte != 0x00) | (lowbyte != 0x00)) { + dev->pmio = ((highbyte << 8) + lowbyte); + vl82c59x_log(dev->log, "VL82c59x: Adding SMI IO handler for %04X\n", dev->pmio); + io_sethandler(dev->pmio, 0x0001, vl82c59x_pm_read, NULL, NULL, vl82c59x_pm_write, NULL, NULL, dev); + dev->pmio_set = 1; + } + +} + +static void +vl82c59x_write(int func, int addr, uint8_t val, void *priv) +{ + vl82c59x_t *dev = (vl82c59x_t *) priv; + + vl82c59x_log(dev->log, "[%04X:%08X] VL82c591: [W] (%02X, %02X) = %02X\n", CS, cpu_state.pc, func, addr, val); + + if (func == 0x00) + switch (addr) { + case 0x04: + case 0x05: /* PCI Command Register */ + dev->pci_conf[addr] = val; + break; + case 0x54: /* Cache Control Register 1 */ + dev->pci_conf[addr] = val; + cpu_cache_ext_enabled = (val & 0xc0); + cpu_update_waitstates(); + break; + case 0x55: /* Cache Control Register 2 */ + dev->pci_conf[addr] = val; + cpu_cache_int_enabled = (val & 0x40); + cpu_update_waitstates(); + break; + case 0x58: /* RAMCFG0 */ + case 0x59: /* RAMCFG1 */ + dev->pci_conf[addr] = val; + break; + case 0x5A: /* Wildcat EDO RAM control */ + if (dev->type == 0x01) { + dev->pci_conf[addr] = val; + } + break; + case 0x5C: /* RAMCTL0 */ + case 0x5D: /* RAMCTL1 */ + case 0x5E: /* RAMCTL2 */ + case 0x5F: + case 0x60: + case 0x62: + /* Apricot XEN-PC Ruby/Jade BIOS requires bit 2 to be set or */ + /* CMOS setup hangs on subsequent runs after NVRAM is initialized */ + dev->pci_conf[addr] = val; + break; + case 0x64: /* A-B SMRAM regs */ + case 0x65: + dev->pci_conf[addr] = val; + vl82c59x_smram(dev); + break; + case 0x66: /* Shadow RAM */ + case 0x67: + case 0x68: + case 0x69: + dev->pci_conf[addr] = val; + vl82c59x_recalc(dev); + vl82c59x_smram(dev); + break; + case 0x6C: /* L2 Cacheability registers */ + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x74: /* Suspected PMRA registers */ + case 0x75: + case 0x76: + case 0x78: + case 0x79: + case 0x7A: + dev->pci_conf[addr] = val; + break; + case 0x7C: /* MISCSSET, bit 7 is SMRAM enable (for the E region) */ + /* io.c logging shows BIOSes setting Bit 7 here */ + dev->pci_conf[addr] = val; + vl82c59x_smram(dev); + break; + case 0x7D: /* Unknown but seems Wildcat-specific, Zeos and PB600 BIOSes hang if bit 3 is writable */ + if (dev->type == 0x01) { + dev->pci_conf[addr] = val & 0xf7; + } + break; + default: + if (addr > 0x3F) + vl82c59x_log(dev->log, "VL82c591: Unknown reg [W] (%02X, %02X) = %02X\n", func, addr, val); + break; + } + +} + +static uint8_t +vl82c59x_read(int func, int addr, void *priv) +{ + const vl82c59x_t *dev = (vl82c59x_t *) priv; + uint8_t ret = 0xff; + + if (func == 0x00) { + switch (addr) { + default: + ret = dev->pci_conf[addr]; + break; + } + } + + vl82c59x_log(dev->log, "[%04X:%08X] VL82c591: [R] (%02X, %02X) = %02X\n", CS, cpu_state.pc, func, addr, ret); + + return ret; +} + +static void +vl82c59x_sb_write(int func, int addr, uint8_t val, void *priv) +{ + vl82c59x_t *dev = (vl82c59x_t *) priv; + uint8_t irq; + const uint8_t irq_array[8] = { 3, 5, 9, 10, 11, 12, 14, 15 }; + + vl82c59x_log(dev->log, "[%04X:%08X] VL82c593: [W] (%02X, %02X) = %02X\n", CS, cpu_state.pc, func, addr, val); + + if (func == 0x00) + switch (addr) { + case 0x04: + case 0x05: /* PCI Command Register */ + dev->pci_conf_sb[addr] = val; + break; + case 0x50: /* MISCSETC */ + case 0x51: /* MISCSETB */ + case 0x52: /* MISCSETA */ + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5A: + /* Has at least one GPIO bit. Compaq Presario 700/900 586 BIOS */ + /* uses bit 2 as an output to set the onboard ES688's base I/O */ + /* address. Bit 2 cleared = 220, bit 2 set = 240 */ + case 0x5C: /* Interrupt Assertion Level Register */ + case 0x5D: + dev->pci_conf_sb[addr] = val; + break; + case 0x60: /* SMI Enable Register */ + dev->pci_conf_sb[addr] = val; + break; + case 0x61: /* SMI Status Register */ + dev->pci_conf_sb[addr] = 0x00; + break; + case 0x62: /* SMI I/O port high byte */ + case 0x63: /* SMI I/O port low byte */ + dev->pci_conf_sb[addr] = val; + vl82c59x_set_pm_io(dev); + break; + case 0x64: /* System Event Enable Register 1 */ + dev->pci_conf_sb[addr] = val; + break; + case 0x65: /* System Event Status Register 1 */ + dev->pci_conf_sb[addr] = 0x00; + break; + case 0x66: /* System Event Enable Register 2 */ + dev->pci_conf_sb[addr] = val; + break; + case 0x67: /* System Event Status Register 2 */ + dev->pci_conf_sb[addr] = 0x00; + break; + case 0x68: /* System Event Enable Register 3 */ + dev->pci_conf_sb[addr] = val; + break; + case 0x69: /* System Event Status Register 3 */ + dev->pci_conf_sb[addr] = 0x00; + break; + case 0x6A: /* PCI Activity Control Register */ + dev->pci_conf_sb[addr] = val & 0x0f; /* Top 4 bits are Read/Clear */ + break; + case 0x6B: /* Programmable I/O Range Register High Byte */ + dev->pci_conf_sb[addr] = val; + break; + case 0x6C: /* Programmable I/O Range Register Low Byte */ + dev->pci_conf_sb[addr] = val; + break; + case 0x6D: /* System Event Control Register/SMI Global Enable */ + dev->pci_conf_sb[addr] = val; + break; + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: /* GPIO */ + /* Compaq Presario and Prolinea use bits 6-4 for setting ECP DMA */ + /* 011 (0x03) = DMA 3 (Default) */ + /* 100 (0x04) = DMA 0 */ + /* 111 (0x07) = DMA disabled */ + case 0x73: /* GPIO */ + dev->pci_conf_sb[addr] = val; + break; + case 0x74: /* PCI Interrupt Connection Register (PCIINT0/1) */ + dev->pci_conf_sb[addr] = val; + irq = irq_array[val & 0x07]; + pci_set_irq_routing(PCI_INTA, (irq != 0) ? irq : PCI_IRQ_DISABLED); + irq = irq_array[(val & 0x70) >> 4]; + pci_set_irq_routing(PCI_INTB, (irq != 0) ? irq : PCI_IRQ_DISABLED); + break; + case 0x75: /* PCI Interrupt Connection Register (PCIINT2/3) */ + dev->pci_conf_sb[addr] = val; + irq = irq_array[val & 0x07]; + pci_set_irq_routing(PCI_INTC, (irq != 0) ? irq : PCI_IRQ_DISABLED); + irq = irq_array[(val & 0x70) >> 4]; + pci_set_irq_routing(PCI_INTD, (irq != 0) ? irq : PCI_IRQ_DISABLED); + break; + case 0x76: /* PCI Interrupt Connection Register (ISA/PCIINT) */ + dev->pci_conf_sb[addr] = val; + break; + case 0x77: + case 0x78: + dev->pci_conf_sb[addr] = val; + break; + default: + if (addr > 0x3F) + vl82c59x_log(dev->log, "VL82c593: Unknown reg [W] (%02X, %02X) = %02X\n", func, addr, val); + break; + } + +} + +static uint8_t +vl82c59x_sb_read(int func, int addr, void *priv) +{ + const vl82c59x_t *dev = (vl82c59x_t *) priv; + uint8_t ret = 0xff; + + if (func == 0x00) + switch (addr) { + case 0x69: /* Lower two bits are a CPU speed readout per Compaq's Prolinea E series TRG */ + /* Per the Prolinea TRG bits 5/3/1 of 593 reg 0x73 must be set to 1 to read the jumpers */ + if (dev->is_compaq && (dev->pci_conf_sb[0x73] & 0x2A)) { + /* Set bit 2 to 1 as this is required for the Prolinea E to be properly identified + in Compaq Computer Setup. */ + ret = (dev->pci_conf_sb[addr] | 0x04); + if (cpu_busspeed <= 50000000) + ret = (ret & 0xfd); /* 50MHz: Bit 1 = 0 */ + else + ret = (ret | 0x02); /* 60MHz: Bit 1 = 1 */ + + if (cpu_dmulti <= 1.5) + ret = (ret | 0x01); /* 1.5x mult: Bit 0 = 1 */ + else + ret = (ret & 0xfe); /* 2.0x mult: Bit 0 = 0 */ + } else { + ret = dev->pci_conf_sb[addr]; + } + break; + default: + ret = dev->pci_conf_sb[addr]; + break; + } + + vl82c59x_log(dev->log, "[%04X:%08X] VL82c593: [R] (%02X, %02X) = %02X\n", CS, cpu_state.pc, func, addr, ret); + + return ret; + +} + +static void +vl82c59x_reset(void *priv) +{ + vl82c59x_t *dev = (vl82c59x_t *) priv; + + /* Northbridge (VLSI VL82c591) */ + dev->pci_conf[0x00] = 0x04; + dev->pci_conf[0x01] = 0x10; + switch (dev->type) { + case 0: /* SuperCore */ + dev->pci_conf[0x02] = 0x05; + dev->pci_conf[0x03] = 0x00; + break; + case 1: /* Wildcat */ + dev->pci_conf[0x02] = 0x07; + dev->pci_conf[0x03] = 0x00; + break; + } + dev->pci_conf[0x08] = 0x00; + dev->pci_conf[0x09] = 0x00; + dev->pci_conf[0x0a] = 0x00; + dev->pci_conf[0x0b] = 0x06; + + /* Southbridge (VLSI VL82c593) */ + dev->pci_conf_sb[0x00] = 0x04; + dev->pci_conf_sb[0x01] = 0x10; + switch (dev->type) { + case 0: /* SuperCore */ + dev->pci_conf_sb[0x02] = 0x06; + dev->pci_conf_sb[0x03] = 0x00; + break; + case 1: /* Wildcat */ + dev->pci_conf_sb[0x02] = 0x08; + dev->pci_conf_sb[0x03] = 0x00; + break; + } + dev->pci_conf_sb[0x08] = 0x00; + dev->pci_conf_sb[0x09] = 0x00; + dev->pci_conf_sb[0x0a] = 0x01; + dev->pci_conf_sb[0x0b] = 0x06; + + /* Unsure on which register configures this (if any), per Compaq's + * Pentium-based Presario 700/900 Series and Prolinea E Series Desktop + * Technical Reference Guides the ISA bus runs at 8MHz while the + * Zeos Pantera Wildcat user manual says that the ISA bus runs at + * 7.5MHz on 90MHz (60MHz bus) systems and 8.25MHz on 100MHz (66MHz bus) + * systems. + */ + if (cpu_busspeed > 50000000) + cpu_set_isa_pci_div(4); + else + cpu_set_isa_pci_div(3); + + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + + vl82c59x_smram(dev); + + /* Reset SMI IO port */ + dev->pmio = 0x0000; + dev->pmio_set = 0; + + cpu_cache_int_enabled = 1; + cpu_cache_ext_enabled = 1; + cpu_update_waitstates(); +} + +static void +vl82c59x_close(void *priv) +{ + vl82c59x_t *dev = (vl82c59x_t *) priv; + + smram_del(dev->smram[1]); + smram_del(dev->smram[2]); + smram_del(dev->smram[3]); + smram_del(dev->smram[4]); + + if (dev->log != NULL) { + log_close(dev->log); + dev->log = NULL; + } + + free(dev); +} + +static void * +vl82c59x_init(UNUSED(const device_t *info)) +{ + vl82c59x_t *dev = (vl82c59x_t *) calloc(1, sizeof(vl82c59x_t)); + + dev->type = (info->local & 0x0f); + + dev->is_compaq = (info->local >> 4); + + dev->log = log_open("VL82c59x"); + + /* VL82c591 (Northbridge) */ + pci_add_card(PCI_ADD_NORTHBRIDGE, vl82c59x_read, vl82c59x_write, dev, &dev->nb_slot); + + /* VL82c593 (Southbridge) */ + pci_add_card(PCI_ADD_SOUTHBRIDGE, vl82c59x_sb_read, vl82c59x_sb_write, dev, &dev->sb_slot); + + dev->port_92 = device_add(&port_92_device); + + /* NVR */ + dev->nvr = device_add(&at_nvr_device); + + dev->smram[1] = smram_add(); + dev->smram[2] = smram_add(); + dev->smram[3] = smram_add(); + dev->smram[4] = smram_add(); + + vl82c59x_reset(dev); + + return dev; +} + +const device_t vl82c59x_device = { + .name = "VLSI VL82c59x (SuperCore)", + .internal_name = "vl82c59x", + .flags = DEVICE_PCI, + .local = 0, + .init = vl82c59x_init, + .close = vl82c59x_close, + .reset = vl82c59x_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t vl82c59x_compaq_device = { + .name = "VLSI VL82c59x (SuperCore with Compaq readout)", + .internal_name = "vl82c59x_compaq", + .flags = DEVICE_PCI, + .local = 0x10, + .init = vl82c59x_init, + .close = vl82c59x_close, + .reset = vl82c59x_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t vl82c59x_wildcat_device = { + .name = "VLSI VL82c59x (Wildcat)", + .internal_name = "vl82c59x_wildcat", + .flags = DEVICE_PCI, + .local = 1, + .init = vl82c59x_init, + .close = vl82c59x_close, + .reset = vl82c59x_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t vl82c59x_wildcat_compaq_device = { + .name = "VLSI VL82c59x (Wildcat with Compaq readout)", + .internal_name = "vl82c59x_wildcat_compaq", + .flags = DEVICE_PCI, + .local = 0x11, + .init = vl82c59x_init, + .close = vl82c59x_close, + .reset = vl82c59x_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index dcad64149..47330955a 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -18,6 +18,8 @@ add_library(dev OBJECT access_bus.c + ast_nvr.c + ast_readout.c bugger.c cartridge.c cassette.c diff --git a/src/device/ast_nvr.c b/src/device/ast_nvr.c new file mode 100644 index 000000000..21585dbe3 --- /dev/null +++ b/src/device/ast_nvr.c @@ -0,0 +1,180 @@ +/* + * 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. + * + * Implementation of the AST Bravo MS secondary NVR + * + * + * + * Authors: win2kgamer + * + * Copyright 2025 win2kgamer. + */ + +#ifdef ENABLE_AST_NVR_LOG +#include +#endif + +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/machine.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/timer.h> +#include <86box/nvr.h> +#include <86box/rom.h> +#include <86box/log.h> + +#ifdef ENABLE_AST_NVR_LOG +int ast_nvr_do_log = ENABLE_AST_NVR_LOG; + +static void +ast_nvr_log(void *priv, const char *fmt, ...) +{ + if (ast_nvr_do_log) { + va_list ap; + va_start(ap, fmt); + log_out(priv, fmt, ap); + va_end(ap); + } +} +#else +# define ast_nvr_log(fmt, ...) +#endif + +typedef struct ast_nvr_t { + int addr; + int bank; + + uint8_t *ram; + int size; + + char *fn; + + void * log; // New logging system +} ast_nvr_t; + +static uint8_t +ast_nvr_read(uint16_t port, void *priv) +{ + ast_nvr_t *nvr = (ast_nvr_t *) priv; + uint8_t ret = 0xff; + + switch (port) { + case 0x800 ... 0x8FF: + nvr->addr = ((nvr->bank << 8) + (port - 0x800)); + ret = nvr->ram[nvr->addr]; + break; + default: + break; + } + + ast_nvr_log(nvr->log, "AST NVR Read [%02X:%02X] = %02X\n", nvr->bank, port, ret); + + return ret; +} + +static void +ast_nvr_write(uint16_t port, uint8_t val, void *priv) +{ + ast_nvr_t *nvr = (ast_nvr_t *) priv; + + ast_nvr_log(nvr->log, "AST NVR Write [%02X:%02X] = %02X\n", nvr->bank, port, val); + + switch (port) { + case 0x800 ... 0x8FF: + nvr->addr = ((nvr->bank << 8) + (port - 0x800)); + nvr->ram[nvr->addr] = val; + break; + case 0xC00: + nvr->bank = val; + default: + break; + } + +} + +static void * +ast_nvr_init(const device_t *info) +{ + ast_nvr_t *nvr; + FILE *fp = NULL; + int c; + + nvr = (ast_nvr_t *) calloc(1, sizeof(ast_nvr_t)); + memset(nvr, 0x00, sizeof(ast_nvr_t)); + + nvr->log = log_open("ASTNVR"); + + nvr->size = 8192; + + /* Set up the NVR file's name */ + c = strlen(machine_get_internal_name()) + 9; + nvr->fn = (char *) calloc(1, (c + 1)); + sprintf(nvr->fn, "%s_sec.nvr", machine_get_internal_name()); + + io_sethandler(0x0800, 0x100, + ast_nvr_read, NULL, NULL, ast_nvr_write, NULL, NULL, nvr); + io_sethandler(0x0C00, 0x01, + ast_nvr_read, NULL, NULL, ast_nvr_write, NULL, NULL, nvr); + + fp = nvr_fopen(nvr->fn, "rb"); + + nvr->ram = (uint8_t *) calloc(1, nvr->size); + memset(nvr->ram, 0xff, nvr->size); + if (fp != NULL) { + if (fread(nvr->ram, 1, nvr->size, fp) != nvr->size) + fatal("ast_nvr_init(): Error reading EEPROM data\n"); + fclose(fp); + } + + return nvr; +} + +static void +ast_nvr_close (void *priv) +{ + ast_nvr_t *nvr = (ast_nvr_t *) priv; + FILE *fp = NULL; + + fp = nvr_fopen(nvr->fn, "wb"); + + if (fp != NULL) { + (void) fwrite(nvr->ram, nvr->size, 1, fp); + fclose(fp); + } + + if (nvr->ram != NULL) + free(nvr->ram); + + if (nvr->log != NULL) { + log_close(nvr->log); + nvr->log = NULL; + } + + free(nvr); +} + +const device_t ast_nvr_device = { + .name = "AST Secondary NVRAM for Bravo MS", + .internal_name = "ast_nvr", + .flags = 0, + .local = 0, + .init = ast_nvr_init, + .close = ast_nvr_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/device/ast_readout.c b/src/device/ast_readout.c new file mode 100644 index 000000000..e583ae34d --- /dev/null +++ b/src/device/ast_readout.c @@ -0,0 +1,198 @@ +/* + * 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. + * + * Implementation of the AST Bravo MS jumper readout. + * + * + * + * Authors: win2kgamer + * + * Copyright 2025 win2kgamer + */ + +#ifdef ENABLE_AST_READOUT_LOG +#include +#endif + +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/timer.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/chipset.h> +#include <86box/plat_unused.h> +#include <86box/lpt.h> +#include <86box/machine.h> +#include <86box/log.h> + +/* + The AST readout device has multiple indexed registers that handle + jumper readout, software ECP DMA configuration and other unknown functions. + + Register 0x00: + Bits 6-4 = ECP DMA configuration + 010 (0x02) = DMA 0 + 101 (0x05) = DMA 1 + 111 (0x07) = DMA 3 + + Register 0x03: + Bit 7 = Force flash + Bit 6 = Password disable + Bit 5 = Mono/Color primary video (0=Color/1=Mono) + Bit 4 = Setup disable (0=Enable Setup/1=Disable Setup) + Bit 3 = Enable onboard video (0=Enable/1=Disable) + Bit 2 = ???? + Bit 1 = ???? + Bit 0 = ???? +*/ + +typedef struct ast_readout_t { + uint8_t index; + uint8_t jumper[4]; + + void * log; // New logging system +} ast_readout_t; + +#ifdef ENABLE_AST_READOUT_LOG +int ast_readout_do_log = ENABLE_AST_READOUT_LOG; + +static void +ast_readout_log(void *priv, const char *fmt, ...) +{ + if (ast_readout_do_log) { + va_list ap; + va_start(ap, fmt); + log_out(priv, fmt, ap); + va_end(ap); + } +} +#else +# define ast_readout_log(fmt, ...) +#endif + +static void +ast_readout_write(uint16_t port, uint8_t val, void *priv) +{ + ast_readout_t *dev = (ast_readout_t *) priv; + switch (port) { + case 0xE0: + ast_readout_log(dev->log, "[%04X:%08X] AST Bravo Readout: Set Index %02X\n", CS, cpu_state.pc, val); + dev->index = val; + break; + case 0xE1: + ast_readout_log(dev->log, "[%04X:%08X] AST Bravo Readout: Write %02X:%02X\n", CS, cpu_state.pc, dev->index, val); + if ((dev->index == 0x00) && (!strcmp(machine_get_internal_name(), "bravoms586"))) { + uint8_t dmaval = ((val >> 4) & 0x07); + dev->jumper[dev->index] = val; + switch (dmaval) { + case 0x02: + ast_readout_log(dev->log, "ECP DMA set to 0\n"); + lpt1_dma(0); + break; + case 0x05: + ast_readout_log(dev->log, "ECP DMA set to 1\n"); + lpt1_dma(1); + break; + case 0x07: + ast_readout_log(dev->log, "ECP DMA set to 3\n"); + lpt1_dma(3); + break; + default: + ast_readout_log(dev->log, "Unknown ECP DMA!\n"); + break; + } + } else if (dev->index == 0x03) { + dev->jumper[dev->index] = (val & 0x07); + if (gfxcard[0] != 0x01) + dev->jumper[dev->index] |= 0x08; + } + else + dev->jumper[dev->index] = val; + break; + default: + break; + } +} + +static uint8_t +ast_readout_read(uint16_t port, void *priv) +{ + const ast_readout_t *dev = (ast_readout_t *) priv; + uint8_t ret = 0xff; + + switch (port) { + case 0xE0: + ast_readout_log(dev->log, "[%04X:%08X] AST Bravo Readout: Read Index %02X\n", CS, cpu_state.pc, dev->index); + ret = dev->index; + break; + case 0xE1: + ast_readout_log(dev->log, "[%04X:%08X] AST Bravo Readout: Read %02X:%02X\n", CS, cpu_state.pc, dev->index, dev->jumper[dev->index]); + ret = dev->jumper[dev->index]; + break; + default: + break; + } + return ret; +} + +static void +ast_readout_reset(void *priv) +{ + ast_readout_t *dev = (ast_readout_t *) priv; + + dev->jumper[0x03] = 0x06; + if (gfxcard[0] != 0x01) + dev->jumper[0x03] |= 0x08; +} + +static void +ast_readout_close(void *priv) +{ + ast_readout_t *dev = (ast_readout_t *) priv; + + if (dev->log != NULL) { + log_close(dev->log); + dev->log = NULL; + } + + free(dev); +} + +static void * +ast_readout_init(const device_t *info) +{ + ast_readout_t *dev = (ast_readout_t *) calloc(1, sizeof(ast_readout_t)); + + dev->log = log_open("AST Readout"); + + ast_readout_reset(dev); + + io_sethandler(0x00E0, 0x0002, ast_readout_read, NULL, NULL, ast_readout_write, NULL, NULL, dev); + + return dev; +} + +const device_t ast_readout_device = { + .name = "AST Bravo MS Readout", + .internal_name = "ast_readout", + .flags = 0, + .local = 0, + .init = ast_readout_init, + .close = ast_readout_close, + .reset = ast_readout_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/device/phoenix_486_jumper.c b/src/device/phoenix_486_jumper.c index 1b6270984..ed4349082 100644 --- a/src/device/phoenix_486_jumper.c +++ b/src/device/phoenix_486_jumper.c @@ -40,6 +40,18 @@ Bit 0 = ????. */ +/* + PB600 bit meanings: + Bit 7 = ???? (if 1 BIOS throws beep codes and won't POST) + Bit 6 = Super I/O chip: 1 = disabled, 0 = enabled + Bit 5 = ???? + Bit 4 = ???? + Bit 3 = ???? + Bit 2 = ???? + Bit 1 = Quick Boot: 1 = normal boot, 0 = quick boot/skip POST + Bit 0 = ???? +*/ + typedef struct phoenix_486_jumper_t { uint8_t type; uint8_t jumper; @@ -70,6 +82,8 @@ phoenix_486_jumper_write(UNUSED(uint16_t addr), uint8_t val, void *priv) phoenix_486_jumper_log("Phoenix 486 Jumper: Write %02x\n", val); if (dev->type == 1) dev->jumper = val & 0xbf; + else if (dev->type == 2) /* PB600 */ + dev->jumper = ((val & 0xbf) | 0x02); else dev->jumper = val; } @@ -90,6 +104,8 @@ phoenix_486_jumper_reset(void *priv) if (dev->type == 1) dev->jumper = 0x00; + else if (dev->type == 2) /* PB600 */ + dev->jumper = 0x02; else { dev->jumper = 0x9f; if (gfxcard[0] != 0x01) @@ -146,3 +162,17 @@ const device_t phoenix_486_jumper_pci_device = { .force_redraw = NULL, .config = NULL }; + +const device_t phoenix_486_jumper_pci_pb600_device = { + .name = "Phoenix 486 Jumper Readout (PB600)", + .internal_name = "phoenix_486_jumper_pci_pb600", + .flags = 0, + .local = 2, + .init = phoenix_486_jumper_init, + .close = phoenix_486_jumper_close, + .reset = phoenix_486_jumper_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/disk/hdc_ide_cmd640.c b/src/disk/hdc_ide_cmd640.c index dbdf32dcf..ea2a195d9 100644 --- a/src/disk/hdc_ide_cmd640.c +++ b/src/disk/hdc_ide_cmd640.c @@ -694,3 +694,18 @@ const device_t ide_cmd640_pci_single_channel_sec_device = { .force_redraw = NULL, .config = NULL }; + +const device_t ide_cmd640_pci_single_channel_legacy_only_device = { + .name = "CMD PCI-0640B PCI (Legacy Mode Only)", + .internal_name = "ide_cmd640_pci_single_channel_legacy_only", + .flags = DEVICE_PCI, + .local = 0x20000, + .init = cmd640_init, + .close = cmd640_close, + .reset = cmd640_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + diff --git a/src/disk/hdc_ide_rz1000.c b/src/disk/hdc_ide_rz1000.c index 6b7aa68e8..56568cc2c 100644 --- a/src/disk/hdc_ide_rz1000.c +++ b/src/disk/hdc_ide_rz1000.c @@ -51,6 +51,7 @@ typedef struct rz1000_t { int irq_mode[2]; int irq_pin; int irq_line; + uint8_t type; } rz1000_t; static int next_id = 0; @@ -197,9 +198,12 @@ rz1000_reset(void *priv) rz1000_log("dev->local = %08X\n", dev->local); + dev->type = ((dev->local >> 8) & 0x01); + rz1000_log("dev->type = %04X\n", dev->type); + dev->regs[0x00] = 0x42; /* PC Technology */ dev->regs[0x01] = 0x10; - dev->regs[0x02] = 0x00; /* RZ-1000 */ + dev->regs[0x02] = dev->type; /* RZ-1000/RZ-1001 */ dev->regs[0x03] = 0x10; dev->regs[0x04] = 0x00; dev->regs[0x07] = 0x02; /* DEVSEL timing: 01 medium */ @@ -296,3 +300,17 @@ const device_t ide_rz1000_pci_single_channel_device = { .force_redraw = NULL, .config = NULL }; + +const device_t ide_rz1001_pci_device = { + .name = "PC Technology RZ-1001 PCI", + .internal_name = "ide_rz1001_pci", + .flags = DEVICE_PCI, + .local = 0x60100, + .init = rz1000_init, + .close = rz1000_close, + .reset = rz1000_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index 9cd037d1f..66ae082ef 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -214,6 +214,10 @@ extern const device_t via_vt8231_device; /* VLSI */ extern const device_t vl82c480_device; extern const device_t vl82c486_device; +extern const device_t vl82c59x_device; +extern const device_t vl82c59x_compaq_device; +extern const device_t vl82c59x_wildcat_device; +extern const device_t vl82c59x_wildcat_compaq_device; extern const device_t vlsi_scamp_device; /* WD */ @@ -228,6 +232,10 @@ extern const device_t nec_mate_unk_device; extern const device_t phoenix_486_jumper_device; extern const device_t phoenix_486_jumper_pci_device; +extern const device_t phoenix_486_jumper_pci_pb600_device; + +extern const device_t ast_readout_device; +extern const device_t ast_nvr_device; extern const device_t radisys_config_device; diff --git a/src/include/86box/hdc.h b/src/include/86box/hdc.h index 214ed84e5..91a4c68cd 100644 --- a/src/include/86box/hdc.h +++ b/src/include/86box/hdc.h @@ -76,6 +76,7 @@ extern const device_t ide_cmd640_pci_device; /* CMD PCI-640B extern const device_t ide_cmd640_pci_legacy_only_device; /* CMD PCI-640B PCI (Legacy Mode Only) */ extern const device_t ide_cmd640_pci_single_channel_device; /* CMD PCI-640B PCI (Only primary channel) */ extern const device_t ide_cmd640_pci_single_channel_sec_device; /* CMD PCI-640B PCI (Only secondary channel) */ +extern const device_t ide_cmd640_pci_single_channel_legacy_only_device; /* CMD PCI-640B PCI (Legacy Mode Only/Only primary channel) */ extern const device_t ide_cmd646_device; /* CMD PCI-646 */ extern const device_t ide_cmd646_legacy_only_device; /* CMD PCI-646 (Legacy Mode Only) */ extern const device_t ide_cmd646_single_channel_device; /* CMD PCI-646 (Only primary channel) */ @@ -89,6 +90,7 @@ extern const device_t ide_opti611_vlb_sec_device; /* OPTi 82c611/6 extern const device_t ide_rz1000_pci_device; /* PC Technology RZ-1000 PCI */ extern const device_t ide_rz1000_pci_single_channel_device; /* PC Technology RZ-1000 PCI (Only primary channel) */ +extern const device_t ide_rz1001_pci_device; /* PC Technology RZ-1001 PCI */ extern const device_t ide_um8673f_device; /* UMC UM8673F */ extern const device_t ide_um8886af_device; /* UMC UM8886AF */ diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index b88d8f492..00562d455 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -301,6 +301,8 @@ enum { MACHINE_CHIPSET_VLSI_VL82C480, MACHINE_CHIPSET_VLSI_VL82C481, MACHINE_CHIPSET_VLSI_VL82C486, + MACHINE_CHIPSET_VLSI_SUPERCORE, + MACHINE_CHIPSET_VLSI_WILDCAT, MACHINE_CHIPSET_WD76C10, MACHINE_CHIPSET_ZYMOS_POACH, MACHINE_CHIPSET_MAX @@ -890,6 +892,9 @@ extern int machine_at_ecs50x_init(const machine_t *); /* OPTi 597 */ extern int machine_at_pci56001_init(const machine_t *); +/* VLSI SuperCore */ +extern int machine_at_celebris5xx_init(const machine_t *); + /* m_at_socket5.c */ /* i430NX */ extern int machine_at_p54np4_init(const machine_t *); @@ -930,6 +935,15 @@ extern int machine_at_torino_init(const machine_t *); /* UMC 889x */ extern int machine_at_hot539_init(const machine_t *); +/* VLSI SuperCore */ +extern int machine_at_bravoms586_init(const machine_t *); +extern int machine_at_g586vpmc_init(const machine_t *); +extern int machine_at_m54si_init(const machine_t *); +extern int machine_at_pb600_init(const machine_t *); + +/* VLSI Wildcat */ +extern int machine_at_globalyst620_init(const machine_t *); + /* m_at_socket7_3v.c */ /* i430FX */ #ifdef EMU_DEVICE_H @@ -976,6 +990,9 @@ extern int machine_at_ap5s_init(const machine_t *); extern int machine_at_pc140_6260_init(const machine_t *); extern int machine_at_ms5124_init(const machine_t *); +/* VLSI Wildcat */ +extern int machine_at_zeoswildcat_init(const machine_t *); + /* m_at_socket7.c */ /* i430HX */ extern int machine_at_acerm3a_init(const machine_t *); diff --git a/src/machine/m_at_socket4_5.c b/src/machine/m_at_socket4_5.c index 368f8397f..ccaf06050 100644 --- a/src/machine/m_at_socket4_5.c +++ b/src/machine/m_at_socket4_5.c @@ -70,3 +70,35 @@ machine_at_pci56001_init(const machine_t *model) return ret; } + +/* VLSI SuperCore */ +int +machine_at_celebris5xx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/celebris5xx/CELEBRIS.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_IDE, 4, 1, 2, 3); /* Onboard */ + pci_register_slot(0x09, PCI_CARD_VIDEO, 4, 1, 2, 3); /* Onboard */ + pci_register_slot(0x0B, PCI_CARD_NORMAL, 1, 3, 2, 1); /* Slot 01 */ + pci_register_slot(0x0C, PCI_CARD_NORMAL, 2, 1, 3, 2); /* Slot 02 */ + + device_add(&vl82c59x_device); + device_add(&intel_flash_bxt_device); + device_add_params(machine_get_kbc_device(machine), (void *) model->kbc_params); + device_add_params(&fdc37c6xx_device, (void *) FDC37C665); + device_add(&ide_cmd640_pci_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + +} diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index cb3803e0d..c61f4c8bb 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -765,3 +765,165 @@ machine_at_hot539_init(const machine_t *model) return ret; } + +/* VLSI SuperCore */ +int +machine_at_bravoms586_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/bravoms586/asttest.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_IDE, 2, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 4, 1, 2, 3); + + device_add(&vl82c59x_device); + device_add(&intel_flash_bxt_device); + device_add_params(machine_get_kbc_device(machine), (void *) model->kbc_params); + device_add_params(&fdc37c6xx_device, (void *) (FDC37C665 | FDC37C6XX_IDE_SEC)); + device_add(&ide_cmd640_pci_single_channel_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + device_add(&ast_readout_device); /* AST custom jumper readout */ + device_add(&ast_nvr_device); /* AST custom secondary NVR device */ + + return ret; +} + +int +machine_at_g586vpmc_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/g586vpmc/Vpm_c3.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x02, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x08, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0A, PCI_CARD_IDE, 0, 0, 0, 0); + device_add(&vl82c59x_device); + device_add(&sst_flash_29ee010_device); + device_add_params(machine_get_kbc_device(machine), (void *) model->kbc_params); + device_add_params(&pc873xx_device, (void *) (PC87332 | PCX730X_398)); + device_add(&ide_cmd646_device); + return ret; +} + +int +machine_at_m54si_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/m54si/M54SI.03", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_IDE, 0, 0, 0, 0); /* Onboard device */ + pci_register_slot(0x10, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + /* Slots are a guess since this BIOS won't work with pcireg */ + device_add(&vl82c59x_device); + device_add(&intel_flash_bxt_device); + device_add_params(machine_get_kbc_device(machine), (void *) model->kbc_params); + device_add_params(&fdc37c6xx_device, (void *) (FDC37C665 | FDC37C6XX_IDE_SEC)); + device_add(&ide_cmd640_pci_single_channel_device); + + return ret; +} + +int +machine_at_pb600_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/pb600/BIOS.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0A, PCI_CARD_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_IDE, 4, 0, 0, 0); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + device_add(&vl82c59x_device); + device_add(&intel_flash_bxt_device); + device_add_params(machine_get_kbc_device(machine), (void *) model->kbc_params); + device_add_params(&fdc37c6xx_device, (void *) FDC37C665); + device_add(&phoenix_486_jumper_pci_pb600_device); + device_add(&ide_cmd640_pci_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + return ret; +} + +/* VLSI Wildcat */ +int +machine_at_globalyst620_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/globalyst620/p107.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0F, PCI_CARD_VIDEO, 0, 0, 0, 0); /* Onboard device */ + pci_register_slot(0x10, PCI_CARD_IDE, 0, 0, 0, 0); /* Onboard device */ + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); /* Slot 04 */ + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); /* Slot 05 */ + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); /* Slot 06 */ + device_add(&vl82c59x_wildcat_device); + device_add(&intel_flash_bxt_device); + device_add_params(machine_get_kbc_device(machine), (void *) model->kbc_params); + device_add(&ide_cmd640_pci_single_channel_legacy_only_device); + device_add_params(&fdc37c6xx_device, (void *) (FDC37C665 | FDC37C6XX_IDE_SEC)); + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + return ret; +} diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index f289b2275..068782db7 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -1020,3 +1020,36 @@ machine_at_ms5124_init(const machine_t *model) return ret; } + +/* VLSI Wildcat */ +int +machine_at_zeoswildcat_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/zeoswildcat/003606.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_IDE, 1, 2, 0, 0); /* Onboard device */ + pci_register_slot(0x0E, PCI_CARD_SCSI, 1, 0, 0, 0); /* Onboard device */ + pci_register_slot(0x0F, PCI_CARD_NETWORK, 1, 0, 0, 0); /* Onboard device */ + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); /* Slot 03 */ + pci_register_slot(0x12, PCI_CARD_NORMAL, 4, 2, 3, 1); /* Slot 04 */ + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); /* Slot 05 */ + /* Per the machine's manual there was an option for AMD SCSI and/or LAN controllers */ + device_add(&vl82c59x_wildcat_device); + device_add(&intel_flash_bxt_device); + device_add_params(machine_get_kbc_device(machine), (void *) model->kbc_params); + device_add_params(&fdc37c6xx_device, (void *) FDC37C665); + device_add(&ide_rz1001_pci_device); + + return ret; +} diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 8c8dc6b91..9fa4ab81b 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -163,6 +163,8 @@ const machine_filter_t machine_chipsets[] = { { "VLSI VL82C480", MACHINE_CHIPSET_VLSI_VL82C480 }, { "VLSI VL82C481", MACHINE_CHIPSET_VLSI_VL82C481 }, { "VLSI VL82C486", MACHINE_CHIPSET_VLSI_VL82C486 }, + { "VLSI SuperCore", MACHINE_CHIPSET_VLSI_SUPERCORE }, + { "VLSI Wildcat", MACHINE_CHIPSET_VLSI_WILDCAT }, { "WD76C10", MACHINE_CHIPSET_WD76C10 } }; @@ -11939,6 +11941,51 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* VLSI SuperCore */ + /* This has Phoenix KBC firmware. */ + { + .name = "[VLSI SuperCore] DEC Celebris 5xx", + .internal_name = "celebris5xx", + .type = MACHINE_TYPE_SOCKET4_5, + .chipset = MACHINE_CHIPSET_VLSI_SUPERCORE, + .init = machine_at_celebris5xx_init, + .p1_handler = machine_generic_p1_handler, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET4 | CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK(CPU_Cx6x86), + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3520, + .max_voltage = 5000, + .min_multi = 1.0, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_VIDEO, + .ram = { + .min = 4096, + .max = 131072, + .step = 4096 + }, + .nvrmask = 127, + .jumpered_ecp_dma = MACHINE_DMA_3, + .default_jumpered_ecp_dma = 3, + .kbc_device = &kbc_at_device, + .kbc_params = KBC_VEN_PHOENIX | 0x00021400, /* Guess */ + .kbc_p1 = 0x00000cf0, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .kbd_device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &s3_phoenix_vision864_pci_device, + .snd_device = NULL, + .net_device = NULL + }, /* Socket 5 machines */ /* 430NX */ @@ -12879,6 +12926,232 @@ const machine_t machines[] = { .net_device = NULL }, + /* VLSI SuperCore */ + /* This has AST KBC firmware, likely a Phoenix variant since the BIOS */ + /* calls KBC command D5h to read the KBC revision. */ + { + .name = "[VLSI SuperCore] AST Bravo MS P/90", + .internal_name = "bravoms586", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_VLSI_SUPERCORE, + .init = machine_at_bravoms586_init, + .p1_handler = machine_generic_p1_handler, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK(CPU_Cx6x86), + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3520, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_VIDEO, + .ram = { + .min = 4096, + .max = 131072, + .step = 4096 + }, + .nvrmask = 127, + .jumpered_ecp_dma = MACHINE_DMA_USE_CONFIG, + .default_jumpered_ecp_dma = -1, + .kbc_device = &kbc_at_device, + .kbc_params = KBC_VEN_PHOENIX | 0x00021400, /* Guess */ + .kbc_p1 = 0x00000cf0, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .kbd_device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &gd5434_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL + }, + /* Has a VIA KBC chip */ + { + .name = "[VLSI SuperCore] DFI G586VPM Rev C", + .internal_name = "g586vpmc", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_VLSI_SUPERCORE, + .init = machine_at_g586vpmc_init, + .p1_handler = machine_generic_p1_handler, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3520, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 4096, + .max = 262144, + .step = 4096 + }, + .nvrmask = 127, + .jumpered_ecp_dma = MACHINE_DMA_1 | MACHINE_DMA_3, + .default_jumpered_ecp_dma = 1, + .kbc_device = &kbc_at_device, + .kbc_params = KBC_VEN_VIA | 0x00424600, /* Guess */ + .kbc_p1 = 0x00000cf0, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .kbd_device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* KBC firmware is unknown. No commands outside of the base PS/2 */ + /* KBC command set are used. */ + { + .name = "[VLSI SuperCore] Micronics M54Si", + .internal_name = "m54si", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_VLSI_SUPERCORE, + .init = machine_at_m54si_init, + .p1_handler = machine_generic_p1_handler, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK(CPU_Cx6x86), + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3520, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 4096, + .max = 131072, + .step = 4096 + }, + .nvrmask = 127, + .jumpered_ecp_dma = MACHINE_DMA_DISABLED | MACHINE_DMA_1 | MACHINE_DMA_3, + .default_jumpered_ecp_dma = 4, + .kbc_device = &kbc_at_device, + .kbc_params = KBC_VEN_PHOENIX | 0x00021400, /* Guess */ + .kbc_p1 = 0x00000cf0, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .kbd_device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* This has Phoenix KBC firmware. */ + { + .name = "[VLSI SuperCore] Packard Bell PB600", + .internal_name = "pb600", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_VLSI_SUPERCORE, + .init = machine_at_pb600_init, + .p1_handler = machine_generic_p1_handler, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3520, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_VIDEO, + .ram = { + .min = 8192, + .max = 139264, + .step = 4096 + }, + .nvrmask = 127, + .jumpered_ecp_dma = MACHINE_DMA_1 | MACHINE_DMA_3, + .default_jumpered_ecp_dma = 3, + .kbc_device = &kbc_at_device, + .kbc_params = KBC_VEN_PHOENIX | 0x00012900, /* Guess */ + .kbc_p1 = 0x00000cf0, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .kbd_device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &gd5430_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL + }, + + /* VLSI Wildcat */ + /* This has Phoenix KBC firmware. */ + { + .name = "[VLSI Wildcat] AT&T Globalyst 620/630 (NCR 3248/3348)", + .internal_name = "globalyst620", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_VLSI_WILDCAT, + .init = machine_at_globalyst620_init, + .p1_handler = machine_generic_p1_handler, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK(CPU_Cx6x86), + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3520, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_VIDEO, + .ram = { + .min = 4096, + .max = 196608, + .step = 4096 + }, + .nvrmask = 127, + .jumpered_ecp_dma = MACHINE_DMA_3, + .default_jumpered_ecp_dma = 3, + .kbc_device = &kbc_at_device, + .kbc_params = KBC_VEN_PHOENIX | 0x00012900, /* Guess */ + .kbc_p1 = 0x00000cf0, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .kbd_device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &s3_phoenix_trio64_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL + }, + /* Socket 7 (Single Voltage) machines */ /* 430FX */ /* This has an AMIKey-2, which is type 'H'. @@ -13736,6 +14009,53 @@ const machine_t machines[] = { .net_device = NULL }, + /* VLSI Wildcat */ + /* KBC firmware is unknown. No PS/2 port is present and no commands outside */ + /* of the base AT KBC command set are used. */ + { + .name = "[VLSI Wildcat] Zeos Pantera Wildcat", + .internal_name = "zeoswildcat", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_VLSI_WILDCAT, + .init = machine_at_zeoswildcat_init, + .p1_handler = machine_generic_p1_handler, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK(CPU_Cx6x86, CPU_PENTIUMMMX), + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3520, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 2.5 + }, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 4096, + .max = 393216, + .step = 4096 + }, + .nvrmask = 127, + .jumpered_ecp_dma = MACHINE_DMA_3, + .default_jumpered_ecp_dma = 3, + .kbc_device = &kbc_at_device, + .kbc_params = 0x00000000, + .kbc_p1 = 0x000004f0, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .kbd_device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Socket 7 (Dual Voltage) machines */ /* ALi ALADDiN IV+ */ /* Has the ALi M1543 southbridge with on-chip KBC. */