diff --git a/CMakeLists.txt b/CMakeLists.txt index f37195cc3..8664b1387 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,7 @@ CMAKE_DEPENDENT_OPTION(S3TRIO3D2X "S3 Trio3D/2X" ON "DEV_BRANCH" OFF) CMAKE_DEPENDENT_OPTION(SIO_DETECT "Super I/O Detection Helper" ON "DEV_BRANCH" OFF) CMAKE_DEPENDENT_OPTION(STPC "STPC machines" ON "DEV_BRANCH" OFF) CMAKE_DEPENDENT_OPTION(M1489 "ALi M1489" ON "DEV_BRANCH" OFF) +CMAKE_DEPENDENT_OPTION(M154X "ALi ALADDiN IV" ON "DEV_BRANCH" OFF) CMAKE_DEPENDENT_OPTION(M6117 "ALi M6117" ON "DEV_BRANCH" OFF) CMAKE_DEPENDENT_OPTION(VGAWONDER "ATI VGA Wonder (ATI-18800)" ON "DEV_BRANCH" OFF) CMAKE_DEPENDENT_OPTION(VNC "VNC renderer" ON "DEV_BRANCH" OFF) diff --git a/src/acpi.c b/src/acpi.c index 740d288df..d5201d1bf 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -97,7 +97,7 @@ acpi_raise_smi(void *priv) smi_line = 1; dev->regs.smi_active = 1; } - } else if (dev->vendor == VEN_INTEL) { + } else if ((dev->vendor == VEN_INTEL) || (dev->vendor == VEN_ALI)) { smi_line = 1; /* Clear bit 16 of GLBCTL. */ dev->regs.glbctl &= ~0x00010000; @@ -152,6 +152,72 @@ acpi_reg_read_common_regs(int size, uint16_t addr, void *p) return ret; } +static uint32_t +acpi_reg_read_ali(int size, uint16_t addr, void *p) +{ + acpi_t *dev = (acpi_t *) p; + uint32_t ret = 0x00000000; + int shift16, shift32; + + addr &= 0x3f; + shift16 = (addr & 1) << 3; + shift32 = (addr & 3) << 3; + + switch(addr) + { + case 0x10: case 0x11: case 0x12: case 0x13: + /* PCNTRL - Processor Control Register (IO) */ + ret = (dev->regs.pcntrl >> shift16) & 0xff; + break; + case 0x14: + /* LVL2 - Processor Level 2 Register */ + ret = dev->regs.plvl2; + break; + case 0x15: + /* LVL3 - Processor Level 3 Register */ + ret = dev->regs.plvl3; + break; + case 0x18: case 0x19: + /* GPE0_STS - General Purpose Event0 Status Register */ + ret = (dev->regs.gpsts >> shift16) & 0xff; + break; + case 0x1a: case 0x1b: + /* GPE0_EN - General Purpose Event0 Enable Register */ + ret = (dev->regs.gpen >> shift16) & 0xff; + break; + case 0x1d: case 0x1c: + /* GPE1_STS - General Purpose Event1 Status Register */ + ret = (dev->regs.gpsts >> shift16) & 0xff; + break; + case 0x1f: case 0x1e: + /* GPE1_EN - General Purpose Event1 Enable Register */ + ret = (dev->regs.gpen1 >> shift16) & 0xff; + break; + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + /* GPE1_CTL - General Purpose Event1 Control Register */ + ret = (dev->regs.gpcntrl >> shift32) & 0xff; + break; + case 0x30: + /* PM2_CNTRL - Power Management 2 Control Register( */ + ret = dev->regs.pmcntrl; + break; + default: + ret = acpi_reg_read_common_regs(size, addr, p); + break; + } +#ifdef ENABLE_ACPI_LOG + if (size != 1) + acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); +#endif + return ret; +} static uint32_t acpi_reg_read_intel(int size, uint16_t addr, void *p) @@ -518,6 +584,76 @@ acpi_reg_write_common_regs(int size, uint16_t addr, uint8_t val, void *p) } } +static void +acpi_reg_write_ali(int size, uint16_t addr, uint8_t val, void *p) +{ + acpi_t *dev = (acpi_t *) p; + int shift16, shift32; + + addr &= 0x3f; +#ifdef ENABLE_ACPI_LOG + if (size != 1) + acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val); +#endif + shift16 = (addr & 1) << 3; + shift32 = (addr & 3) << 3; + + switch (addr) { + case 0x10: case 0x11: case 0x12: case 0x13: + /* PCNTRL - Processor Control Register (IO) */ + dev->regs.pcntrl = ((dev->regs.pcntrl & ~(0xff << shift32)) | (val << shift32)) & 0x00023e1e; + break; + case 0x14: + /* LVL2 - Processor Level 2 Register */ + dev->regs.plvl2 = val; + break; + case 0x15: + /* LVL3 - Processor Level 3 Register */ + dev->regs.plvl3 = val; + break; + case 0x18: case 0x19: + /* GPE0_STS - General Purpose Event0 Status Register */ + dev->regs.gpsts &= ~((val << shift16) & 0x0d07); + break; + case 0x1a: case 0x1b: + /* GPE0_EN - General Purpose Event0 Enable Register */ + dev->regs.gpen = ((dev->regs.gpen & ~(0xff << shift16)) | (val << shift16)) & 0x0d07; + break; + case 0x1d: case 0x1c: + /* GPE1_STS - General Purpose Event1 Status Register */ + dev->regs.gpsts &= ~((val << shift16) & 0x0c01); + break; + case 0x1f: case 0x1e: + /* GPE1_EN - General Purpose Event1 Enable Register */ + dev->regs.gpen = ((dev->regs.gpen & ~(0xff << shift16)) | (val << shift16)) & 0x0c01; + break; + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + /* GPE1_CTL - General Purpose Event1 Control Register */ + dev->regs.gpcntrl = ((dev->regs.gpcntrl & ~(0xff << shift32)) | (val << shift32)) & 0x00000001; + break; + case 0x30: + /* PM2_CNTRL - Power Management 2 Control Register( */ + dev->regs.pmcntrl = val & 1; + break; + default: + acpi_reg_write_common_regs(size, addr, val, p); + /* Setting GBL_RLS also sets BIOS_STS and generates SMI. */ + if ((addr == 0x00) && !(dev->regs.pmsts & 0x20)) + dev->regs.glbctl &= ~0x0002; + else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { + dev->regs.glbsts |= 0x01; + if (dev->regs.glben & 0x02) + acpi_raise_smi(dev); + } + } +} static void acpi_reg_write_intel(int size, uint16_t addr, uint8_t val, void *p) @@ -823,7 +959,9 @@ acpi_reg_read_common(int size, uint16_t addr, void *p) acpi_t *dev = (acpi_t *) p; uint8_t ret = 0xff; - if (dev->vendor == VEN_VIA) + if (dev->vendor == VEN_ALI) + ret = acpi_reg_read_ali(size, addr, p); + else if (dev->vendor == VEN_VIA) ret = acpi_reg_read_via(size, addr, p); else if (dev->vendor == VEN_VIA_596B) ret = acpi_reg_read_via_596b(size, addr, p); @@ -841,6 +979,8 @@ acpi_reg_write_common(int size, uint16_t addr, uint8_t val, void *p) { acpi_t *dev = (acpi_t *) p; + if (dev->vendor == VEN_ALI) + acpi_reg_write_ali(size, addr, val, p); if (dev->vendor == VEN_VIA) acpi_reg_write_via(size, addr, val, p); else if (dev->vendor == VEN_VIA_596B) @@ -1021,6 +1161,7 @@ acpi_update_io_mapping(acpi_t *dev, uint32_t base, int chipset_en) int size; switch (dev->vendor) { + case VEN_ALI: case VEN_INTEL: default: size = 0x040; @@ -1173,7 +1314,7 @@ acpi_apm_out(uint16_t port, uint8_t val, void *p) if (port == 0x0000) { dev->apm->cmd = val; if (dev->apm->do_smi) { - if (dev->vendor == VEN_INTEL) + if ((dev->vendor == VEN_INTEL) || (dev->vendor == VEN_ALI)) dev->regs.glbsts |= 0x20; acpi_raise_smi(dev); } @@ -1285,7 +1426,7 @@ acpi_init(const device_t *info) dev->irq_line = 9; - if (dev->vendor == VEN_INTEL) { + if ((dev->vendor == VEN_INTEL) || (dev->vendor == VEN_ALI)) { dev->apm = device_add(&apm_pci_acpi_device); io_sethandler(0x00b2, 0x0002, acpi_apm_in, NULL, NULL, acpi_apm_out, NULL, NULL, dev); } else if (dev->vendor == VEN_VIA) { @@ -1301,6 +1442,19 @@ acpi_init(const device_t *info) return dev; } +const device_t acpi_ali_device = +{ + "ALi M7101 ACPI", + DEVICE_PCI, + VEN_ALI, + acpi_init, + acpi_close, + acpi_reset, + { NULL }, + acpi_speed_changed, + NULL, + NULL +}; const device_t acpi_intel_device = { diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 9b7cd39ad..c3a0b18e2 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -13,11 +13,11 @@ # Copyright 2020,2021 David Hrdlička. # -add_library(chipset OBJECT acc2168.c cs8230.c ali1429.c headland.c intel_82335.c +add_library(chipset OBJECT acc2168.c cs8230.c ali1217.c ali1429.c headland.c intel_82335.c cs4031.c intel_420ex.c intel_4x0.c intel_sio.c intel_piix.c ../ioapic.c neat.c opti495.c opti895.c opti5x7.c scamp.c scat.c via_vt82c49x.c via_vt82c505.c sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c - opti283.c opti291.c umc491.c via_apollo.c via_pipc.c wd76c10.c + opti283.c opti291.c via_apollo.c via_pipc.c wd76c10.c vl82c480.c) if(STPC) @@ -28,6 +28,11 @@ if(M1489) target_sources(chipset PRIVATE ali1489.c) endif() +if(M154X) + target_sources(chipset PRIVATE ali1531.c) + target_sources(chipset PRIVATE ali1543.c) +endif() + if(M6117) target_sources(chipset PRIVATE ali6117.c) endif() \ No newline at end of file diff --git a/src/chipset/ali1217.c b/src/chipset/ali1217.c new file mode 100644 index 000000000..878ed81df --- /dev/null +++ b/src/chipset/ali1217.c @@ -0,0 +1,152 @@ +/* + * 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 ALi M1217 chipset. + * + * Note: This chipset has no datasheet, everything were done via + * reverse engineering the BIOS of various machines using it. + * + * Authors: Tiseno100 + * + * Copyright 2021 Tiseno100 + * + */ + +#include +#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/mem.h> +#include <86box/port_92.h> +#include <86box/chipset.h> + +#ifdef ENABLE_ALI1217_LOG +int ali1217_do_log = ENABLE_ALI1217_LOG; +static void +ali1217_log(const char *fmt, ...) +{ + va_list ap; + + if (ali1217_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define ali1217_log(fmt, ...) +#endif + +typedef struct +{ + uint8_t index, regs[256]; + int cfg_locked; +} ali1217_t; + +static void ali1217_shadow_recalc(ali1217_t *dev) +{ + for (uint8_t i = 0; i < 4; i++) + { + mem_set_mem_state_both(0xc0000 + (i << 15), 0x8000, ((dev->regs[0x14] & (1 << (i * 2))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x14] & (1 << ((i * 2) + 1))) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); + mem_set_mem_state_both(0xe0000 + (i << 15), 0x8000, ((dev->regs[0x15] & (1 << (i * 2))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x15] & (1 << ((i * 2) + 1))) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); + } + + shadowbios = !!(dev->regs[0x15] & 5); + shadowbios_write = !!(dev->regs[0x15] & 0x0a); + + flushmmucache(); +} + +static void +ali1217_write(uint16_t addr, uint8_t val, void *priv) +{ + ali1217_t *dev = (ali1217_t *)priv; + + switch (addr) + { + case 0x22: + dev->index = val; + break; + case 0x23: + if (dev->index != 0x13) + ali1217_log("ALi M1217: dev->regs[%02x] = %02x\n", dev->index, val); + + if (dev->index == 0x13) + dev->cfg_locked = !(val == 0xc5); + + if (!dev->cfg_locked) + { + dev->regs[dev->index] = val; + + if ((dev->index == 0x14) || (dev->index == 0x15)) + ali1217_shadow_recalc(dev); + } + break; + } +} + +static uint8_t +ali1217_read(uint16_t addr, void *priv) +{ + ali1217_t *dev = (ali1217_t *)priv; + + return !(addr == 0x22) ? dev->regs[dev->index] : dev->index; +} + +static void +ali1217_close(void *priv) +{ + ali1217_t *dev = (ali1217_t *)priv; + + free(dev); +} + +static void * +ali1217_init(const device_t *info) +{ + ali1217_t *dev = (ali1217_t *)malloc(sizeof(ali1217_t)); + memset(dev, 0, sizeof(ali1217_t)); + + device_add(&port_92_device); + + dev->cfg_locked = 1; + + /* + + ALi M1217 Ports + + 22h Index Port + 23h Data Port + + */ + io_sethandler(0x0022, 0x0002, ali1217_read, NULL, NULL, ali1217_write, NULL, NULL, dev); + ali1217_shadow_recalc(dev); + + return dev; +} + +const device_t ali1217_device = { + "ALi M1217", + 0, + 0, + ali1217_init, + ali1217_close, + NULL, + {NULL}, + NULL, + NULL, + NULL}; diff --git a/src/chipset/ali1429.c b/src/chipset/ali1429.c index e9c83b0f7..0326a1471 100644 --- a/src/chipset/ali1429.c +++ b/src/chipset/ali1429.c @@ -101,17 +101,16 @@ ali1429_write(uint16_t addr, uint8_t val, void *priv) /* Don't log register unlock patterns */ if(dev->index != 0x03) - { ali1429_log("M1429: dev->regs[%02x] = %02x\n", dev->index, val); - } - - dev->regs[dev->index] = val; /* Unlock/Lock Registers */ - dev->cfg_locked = !(dev->regs[0x03] && 0xc5); + if(dev->index == 0x03) + dev->cfg_locked = !(val == 0xc5); - if(dev->cfg_locked == 0) + if(!dev->cfg_locked) { + dev->regs[dev->index] = val; + switch(dev->index){ /* Shadow RAM */ case 0x13: diff --git a/src/chipset/ali1531.c b/src/chipset/ali1531.c new file mode 100644 index 000000000..23a4f2564 --- /dev/null +++ b/src/chipset/ali1531.c @@ -0,0 +1,316 @@ +/* + * 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 ALi M1531B CPU-to-PCI Bridge. + * + * + * + * Authors: Tiseno100, + * + * Copyright 2021 Tiseno100. + * + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/timer.h> + +#include <86box/device.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/pci.h> +#include <86box/smram.h> +#include <86box/spd.h> + +#include <86box/chipset.h> + +typedef struct ali1531_t +{ + uint8_t pci_conf[256]; + + smram_t *smram; +} ali1531_t; + +void ali1531_shadow_recalc(ali1531_t *dev) +{ + for (uint32_t i = 0; i < 8; i++) + { + mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, (((dev->pci_conf[0x4c] >> i) & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | (((dev->pci_conf[0x4e] >> i) & 1) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); + mem_set_mem_state_both(0xe0000 + (i << 14), 0x4000, (((dev->pci_conf[0x4d] >> i) & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | (((dev->pci_conf[0x4f] >> i) & 1) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); + } + + shadowbios = !!(dev->pci_conf[0x4d] & 0xf0); + shadowbios_write = !!(dev->pci_conf[0x4f] & 0xf0); + + flushmmucache(); +} + +void ali1531_smm_recalc(uint8_t smm_state, ali1531_t *dev) +{ + if (!!(dev->pci_conf[0x48] & 1)) + { + switch (smm_state) + { + case 0: + smram_enable(dev->smram, 0xd0000, 0xb0000, 0x10000, 0, 1); + smram_map(1, 0xd0000, 0x10000, 1); + break; + case 1: + smram_enable(dev->smram, 0xd0000, 0xb0000, 0x10000, 1, 1); + smram_map(1, 0xd0000, 0x10000, 1); + break; + case 2: + smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, 0, 1); + smram_map(1, 0xa0000, 0x20000, (dev->pci_conf[0x48] & 0x10) ? 2 : 1); + break; + case 3: + smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, 1, 1); + smram_map(1, 0xa0000, 0x20000, (dev->pci_conf[0x48] & 0x10) ? 2 : 1); + break; + case 4: + smram_enable(dev->smram, 0x30000, 0xb0000, 0x10000, 0, 1); + smram_map(1, 0x30000, 0x10000, 1); + break; + case 5: + smram_enable(dev->smram, 0x30000, 0xb0000, 0x10000, 1, 1); + smram_map(1, 0x30000, 0x10000, 1); + break; + } + + } + else + smram_disable_all(); + + flushmmucache(); +} + +static void +ali1531_write(int func, int addr, uint8_t val, void *priv) +{ + ali1531_t *dev = (ali1531_t *)priv; + + switch (addr) + { + case 0x05: + dev->pci_conf[addr] = val & 1; + break; + + case 0x07: + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x0d: + dev->pci_conf[addr] = val & 0xf8; + break; + + case 0x40: + dev->pci_conf[addr] = val & 0xf1; + break; + + case 0x41: + dev->pci_conf[addr] = val & 0xdf; + break; + + case 0x42: /* L2 Cache */ + dev->pci_conf[addr] = val & 0xf7; + cpu_cache_ext_enabled = !!(val & 1); + cpu_update_waitstates(); + break; + + case 0x43: /* L1 Cache */ + dev->pci_conf[addr] = val; + cpu_cache_int_enabled = !!(val & 1); + cpu_update_waitstates(); + break; + + case 0x47: + dev->pci_conf[addr] = val & 0xfc; + + if (mem_size > 0xe00000) + mem_set_mem_state_both(0xe00000, 0x100000, !(val & 0x20) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + + if (mem_size > 0xf00000) + mem_set_mem_state_both(0xf00000, 0x100000, !(val & 0x10) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + + mem_set_mem_state_both(0xa0000, 0x20000, (val & 8) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + mem_set_mem_state_both(0x80000, 0x20000, (val & 4) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + break; + + case 0x48: /* SMRAM */ + dev->pci_conf[addr] = val; + ali1531_smm_recalc((val >> 1) & 7, dev); + break; + + case 0x49: + dev->pci_conf[addr] = val & 0x73; + break; + + case 0x4c: /* Shadow RAM */ + case 0x4d: + case 0x4e: + case 0x4f: + dev->pci_conf[addr] = val; + ali1531_shadow_recalc(dev); + break; + + case 0x57: /* H2PO */ + dev->pci_conf[addr] = val & 0x60; + if (!(val & 0x20)) + outb(0x92, 0x01); + break; + + case 0x58: + dev->pci_conf[addr] = val & 0x83; + break; + + case 0x5b: + dev->pci_conf[addr] = val & 0x4f; + break; + + case 0x5d: + dev->pci_conf[addr] = val & 0x53; + break; + + case 0x5f: + dev->pci_conf[addr] = val & 0x7f; + break; + + case 0x60: /* DRB's */ + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6a: + case 0x6b: + case 0x6c: + case 0x6d: + case 0x6e: + case 0x6f: + dev->pci_conf[addr] = val; + spd_write_drbs(dev->pci_conf, 0x60, 0x6f, 2); + break; + + case 0x72: + dev->pci_conf[addr] = val & 0xf; + break; + + case 0x74: + dev->pci_conf[addr] = val & 0x2b; + break; + + case 0x80: + dev->pci_conf[addr] = val & 0x84; + break; + + case 0x81: + dev->pci_conf[addr] = val & 0x81; + break; + + case 0x83: + dev->pci_conf[addr] = val & 0x10; + break; + + default: + dev->pci_conf[addr] = val; + break; + } +} + +static uint8_t +ali1531_read(int func, int addr, void *priv) +{ + ali1531_t *dev = (ali1531_t *)priv; + return dev->pci_conf[addr]; +} + +static void +ali1531_reset(void *priv) +{ + ali1531_t *dev = (ali1531_t *)priv; + + /* Default Registers */ + dev->pci_conf[0x00] = 0xb9; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x31; + dev->pci_conf[0x03] = 0x15; + dev->pci_conf[0x04] = 0x06; + dev->pci_conf[0x05] = 0x00; + dev->pci_conf[0x06] = 0x00; + dev->pci_conf[0x07] = 0x04; + dev->pci_conf[0x08] = 0xb0; + dev->pci_conf[0x09] = 0x00; + dev->pci_conf[0x0a] = 0x00; + dev->pci_conf[0x0b] = 0x06; + dev->pci_conf[0x0c] = 0x00; + dev->pci_conf[0x0d] = 0x20; + dev->pci_conf[0x0e] = 0x00; + dev->pci_conf[0x0f] = 0x00; + dev->pci_conf[0x2c] = 0xb9; + dev->pci_conf[0x2d] = 0x10; + dev->pci_conf[0x2e] = 0x31; + dev->pci_conf[0x2f] = 0x15; + dev->pci_conf[0x52] = 0xf0; + dev->pci_conf[0x54] = 0xff; + dev->pci_conf[0x55] = 0xff; + dev->pci_conf[0x59] = 0x20; + dev->pci_conf[0x5a] = 0x20; + dev->pci_conf[0x70] = 0x22; + + ali1531_write(0, 0x42, 0x00, dev); + ali1531_write(0, 0x43, 0x00, dev); + ali1531_write(0, 0x47, 0x00, dev); + ali1531_shadow_recalc(dev); + ali1531_write(0, 0x60, 0x08, dev); + ali1531_write(0, 0x61, 0x40, dev); +} + +static void +ali1531_close(void *priv) +{ + ali1531_t *dev = (ali1531_t *)priv; + + smram_del(dev->smram); + free(dev); +} + +static void * +ali1531_init(const device_t *info) +{ + ali1531_t *dev = (ali1531_t *)malloc(sizeof(ali1531_t)); + memset(dev, 0, sizeof(ali1531_t)); + + pci_add_card(PCI_ADD_NORTHBRIDGE, ali1531_read, ali1531_write, dev); + + dev->smram = smram_add(); + + ali1531_reset(dev); + + return dev; +} + +const device_t ali1531_device = { + "ALi M1531 CPU-to-PCI Bridge", + DEVICE_PCI, + 0, + ali1531_init, + ali1531_close, + ali1531_reset, + {NULL}, + NULL, + NULL, + NULL}; diff --git a/src/chipset/ali1543.c b/src/chipset/ali1543.c new file mode 100644 index 000000000..2014def33 --- /dev/null +++ b/src/chipset/ali1543.c @@ -0,0 +1,957 @@ +/* + * 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 ALi M1543 Desktop South Bridge. + * + * + * + * Authors: Tiseno100, + * + * Copyright 2021 Tiseno100. + * + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/timer.h> +#include <86box/device.h> +#include <86box/io.h> + +#include <86box/apm.h> +#include <86box/dma.h> +#include <86box/ddma.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/lpt.h> +#include <86box/mem.h> +#include <86box/nvr.h> +#include <86box/pci.h> +#include <86box/port_92.h> +#include <86box/serial.h> +#include <86box/smbus_piix4.h> +#include <86box/usb.h> + +#include <86box/acpi.h> + +#include <86box/chipset.h> + +#ifdef ENABLE_ALI1543_LOG +int ali1543_do_log = ENABLE_ALI1543_LOG; +static void +ali1543_log(const char *fmt, ...) +{ + va_list ap; + + if (ali1543_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define ali1543_log(fmt, ...) +#endif + +typedef struct ali1543_t +{ + uint8_t pci_conf[256], pmu_conf[256], usb_conf[256], ide_conf[256], + sio_regs[256], device_regs[8][256], sio_index, in_configuration_mode, + pci_slot, ide_slot, usb_slot, pmu_slot; + + apm_t *apm; + acpi_t *acpi; + ddma_t *ddma; + fdc_t *fdc_controller; + nvr_t *nvr; + port_92_t *port_92; + serial_t *uart[2]; + sff8038i_t *ide_controller[2]; + smbus_piix4_t *smbus; + usb_t *usb; + +} ali1543_t; + +/* + + Notes: + - Power Managment isn't functioning properly + - IDE isn't functioning properly + - 1543C differences have to be examined + - Some Chipset functionality might be missing + - Device numbers and types might be incorrect + - Code quality is abysmal and needs lot's of cleanup. + +*/ + +void ali1533_ddma_handler(ali1543_t *dev) +{ + for (uint8_t i = 0; i < 8; i++) + { + if (i != 4) + ddma_update_io_mapping(dev->ddma, i & 7, dev->pci_conf[0x73] & 0xf, dev->pci_conf[0x73] & 0xf0, dev->pci_conf[0x45] & 2); + } +} + +void ali5229_ide_handler(ali1543_t *dev); + +static void +ali1533_write(int func, int addr, uint8_t val, void *priv) +{ + ali1543_t *dev = (ali1543_t *)priv; + ali1543_log("M1533: dev->pci_conf[%02x] = %02x\n", addr, val); + switch (addr) + { + case 0x04: + if (dev->pci_conf[0x5f] & 8) + dev->pci_conf[addr] = val; + break; + + case 0x2c: /* Subsystem Vendor ID */ + case 0x2d: + case 0x2e: + case 0x2f: + if (dev->pci_conf[0x74] & 0x40) + dev->pci_conf[addr] = val; + break; + + case 0x40: + dev->pci_conf[addr] = val & 0x7f; + break; + + case 0x42: + dev->pci_conf[addr] = val & 0xcf; + break; + + case 0x43: + dev->pci_conf[addr] = val; + if (val & 0x80) + port_92_add(dev->port_92); + else + port_92_remove(dev->port_92); + break; + + case 0x44: /* Set IRQ Line for Primary IDE if it's on native mode */ + dev->pci_conf[addr] = 0xdf; + if (dev->ide_conf[0x09] & 1) + sff_set_irq_line(dev->ide_controller[0], val & 0x0f); + break; + + case 0x45: /* DDMA Enable */ + dev->pci_conf[addr] = 0xcf; + ali1533_ddma_handler(dev); + break; + + case 0x48: /* PCI IRQ Routing */ + case 0x49: + dev->pci_conf[addr] = val; + pci_set_irq_routing(((addr & 1) * 2) + 2, ((val & 0xf0) == 0) ? (val & 0xf0) : PCI_IRQ_DISABLED); + pci_set_irq_routing(((addr & 1) * 2) + 1, ((val & 0x0f) == 0) ? (val & 0x0f) : PCI_IRQ_DISABLED); + break; + + case 0x53: /* USB Enable */ + dev->pci_conf[addr] = val & 0xe7; + ohci_update_mem_mapping(dev->usb, 0x11, 0x12, 0x13, (dev->usb_conf[0x04] & 1) && (!(dev->pci_conf[0x53] & 0x40))); + break; + + case 0x54: /* USB Control ? */ + dev->pci_conf[addr] = val & 0xdf; + break; + + case 0x57: + dev->pci_conf[addr] = val & 0xc7; + break; + + case 0x58: /* IDE Enable */ + dev->pci_conf[addr] = val & 0x7f; + ali5229_ide_handler(dev); + break; + + case 0x59: + case 0x5a: + dev->pci_conf[addr] = val & 0x0e; + break; + + case 0x5b: + dev->pci_conf[addr] = val & 0x02; + break; + + case 0x5c: + dev->pci_conf[addr] = val & 0x7f; + break; + + case 0x5d: + dev->pci_conf[addr] = val & 0x02; + break; + + case 0x5e: + dev->pci_conf[addr] = val & 0xe0; + break; + + case 0x5f: + dev->pci_conf[addr] = val; + acpi_update_io_mapping(dev->acpi, (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0), (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); + smbus_piix4_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); + break; + + case 0x6d: + dev->pci_conf[addr] = val & 0xbf; + break; + + case 0x71: + case 0x72: + dev->pci_conf[addr] = val & 0xef; + break; + + case 0x73: /* DDMA Base Address */ + dev->pci_conf[addr] = val; + ali1533_ddma_handler(dev); + break; + + case 0x74: /* USB IRQ Routing */ + dev->pci_conf[addr] = val & 0xdf; + pci_set_irq_routing(dev->usb_slot, ((val & 0x0f) == 0) ? (val & 0x0f) : PCI_IRQ_DISABLED); + break; + + case 0x75: /* Set IRQ Line for Secondary IDE if it's on native mode */ + dev->pci_conf[addr] = val & 0x1f; + if (dev->ide_conf[0x09] & 8) + sff_set_irq_line(dev->ide_controller[1], val & 0x0f); + break; + + case 0x76: /* PMU IRQ Routing */ + dev->pci_conf[addr] = val & 0x1f; + acpi_set_irq_line(dev->acpi, val & 0x0f); + break; + + case 0x77: /* SMBus IRQ Routing */ + dev->pci_conf[addr] = val & 0x1f; + break; + + default: + dev->pci_conf[addr] = val; + break; + } +} + +static uint8_t +ali1533_read(int func, int addr, void *priv) +{ + ali1543_t *dev = (ali1543_t *)priv; + + if (((dev->pci_conf[0x42] & 0x80) && (addr >= 0x40)) || ((dev->pci_conf[0x5f] & 8) && (addr == 4))) + return 0; + else + return dev->pci_conf[addr]; +} + +void ali5229_ide_handler(ali1543_t *dev) +{ + uint16_t native_base_pri_addr = (dev->ide_conf[0x11] | dev->ide_conf[0x10] << 8); + uint16_t native_side_pri_addr = (dev->ide_conf[0x15] | dev->ide_conf[0x14] << 8); + uint16_t native_base_sec_addr = (dev->ide_conf[0x19] | dev->ide_conf[0x18] << 8); + uint16_t native_side_sec_addr = (dev->ide_conf[0x1c] | dev->ide_conf[0x1b] << 8); + + uint16_t comp_base_pri_addr = 0x01f0; + uint16_t comp_side_pri_addr = 0x03f6; + uint16_t comp_base_sec_addr = 0x0170; + uint16_t comp_side_sec_addr = 0x0376; + + uint16_t current_pri_base, current_pri_side, current_sec_base, current_sec_side; + + /* Primary Channel Programming */ + if (!(dev->ide_conf[0x52] & 0x10)) + { + current_pri_base = (!(dev->ide_conf[0x09] & 1)) ? comp_base_pri_addr : native_base_pri_addr; + current_pri_side = (!(dev->ide_conf[0x09] & 1)) ? comp_side_pri_addr : native_side_pri_addr; + } + else + { + current_pri_base = (!(dev->ide_conf[0x09] & 1)) ? comp_base_sec_addr : native_base_sec_addr; + current_pri_side = (!(dev->ide_conf[0x09] & 1)) ? comp_side_sec_addr : native_side_sec_addr; + } + + /* Secondary Channel Programming */ + if (!(dev->ide_conf[0x52] & 0x10)) + { + current_sec_base = (!(dev->ide_conf[0x09] & 4)) ? comp_base_sec_addr : native_base_sec_addr; + current_sec_side = (!(dev->ide_conf[0x09] & 4)) ? comp_side_sec_addr : native_side_sec_addr; + } + else + { + current_sec_base = (!(dev->ide_conf[0x09] & 4)) ? comp_base_pri_addr : native_base_pri_addr; + current_sec_side = (!(dev->ide_conf[0x09] & 4)) ? comp_side_pri_addr : native_side_pri_addr; + } + + /* Both channels use one port */ + if (dev->ide_conf[0x52] & 0x40) + { + current_pri_base = current_sec_base; + current_pri_side = current_sec_side; + } + + if (dev->ide_conf[0x52] & 0x20) + { + current_sec_base = current_pri_base; + current_sec_side = current_pri_side; + } + + ide_pri_disable(); + ide_sec_disable(); + + if (dev->pci_conf[0x58] & 0x40) + { + sff_set_irq_pin(dev->ide_controller[0], dev->ide_conf[0x3d] & 4); + sff_set_irq_pin(dev->ide_controller[1], dev->ide_conf[0x3d] & 4); + + /* Primary Channel Setup */ + if (dev->ide_conf[0x09] & 0x10) + { + if (!(dev->ide_conf[0x09] & 1)) + sff_set_irq_line(dev->ide_controller[0], dev->ide_conf[0x3c] & 0xf); + + ide_set_base(0, current_pri_base); + ide_set_side(0, current_pri_side); + + sff_bus_master_handler(dev->ide_controller[0], dev->ide_conf[0x09] & 0x80, (dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)); + ide_pri_enable(); + ali1543_log("M5229 PRI: BASE %04x SIDE %04x\n", current_pri_base, current_pri_side); + } + + /* Secondary Channel Setup */ + if (dev->ide_conf[0x09] & 8) + { + if (!(dev->ide_conf[0x09] & 4)) + sff_set_irq_line(dev->ide_controller[1], dev->ide_conf[0x3c] & 0xf); + + ide_set_base(1, current_sec_base); + ide_set_side(1, current_sec_side); + + sff_bus_master_handler(dev->ide_controller[1], dev->ide_conf[0x09] & 0x80, ((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)) + 8); + ide_sec_enable(); + ali1543_log("M5229 SEC: BASE %04x SIDE %04x\n", current_sec_base, current_sec_side); + } + } +} + +static void +ali5229_write(int func, int addr, uint8_t val, void *priv) +{ + ali1543_t *dev = (ali1543_t *)priv; + ali1543_log("M5229: dev->ide_conf[%02x] = %02x\n", addr, val); + + switch (addr) + { + case 0x09: /* Control */ + if (dev->ide_conf[0x4d] & 0x80) + dev->ide_conf[addr] |= val & 0x8f; + else + dev->ide_conf[addr] = val; + ali5229_ide_handler(dev); + break; + + case 0x10: /* Primary Base Address */ + case 0x11: + case 0x12: + case 0x13: + case 0x14: + + case 0x18: /* Secondary Base Address */ + case 0x19: + case 0x1a: + case 0x1b: + case 0x1c: + + case 0x20: /* Bus Mastering Base Address */ + case 0x21: + case 0x22: + case 0x23: + dev->ide_conf[addr] = val; + ali5229_ide_handler(dev); + break; + + /* The machines don't touch anything beyond that point so we avoid any programming */ + + case 0x2c: /* Subsystem Vendor */ + case 0x2d: + case 0x2e: + case 0x2f: + if (dev->ide_conf[0x53] & 0x80) + dev->ide_conf[addr] = val; + break; + + case 0x4d: + dev->ide_conf[addr] = val & 0x80; + break; + + case 0x4f: + dev->ide_conf[addr] = val & 0x3f; + break; + + case 0x50: /* Configuration */ + dev->ide_conf[addr] = val & 0x2b; + break; + + case 0x51: + dev->ide_conf[addr] = val & 0xf7; + break; + + case 0x53: /* Subsystem Vendor ID */ + dev->ide_conf[addr] = val & 0x8b; + break; + + case 0x58: + dev->ide_conf[addr] = val & 3; + break; + + case 0x59: + case 0x5a: + case 0x5b: + dev->ide_conf[addr] = val & 0x7f; + break; + + case 0x5c: + dev->ide_conf[addr] = val & 3; + break; + + case 0x5d: + case 0x5e: + case 0x5f: + dev->ide_conf[addr] = val & 0x7f; + break; + + default: + dev->ide_conf[addr] = val; + break; + } +} + +static uint8_t +ali5229_read(int func, int addr, void *priv) +{ + ali1543_t *dev = (ali1543_t *)priv; + return dev->ide_conf[addr]; +} + +static void +ali5237_write(int func, int addr, uint8_t val, void *priv) +{ + ali1543_t *dev = (ali1543_t *)priv; + ali1543_log("M5237: dev->usb_conf[%02x] = %02x\n", addr, val); + switch (addr) + { + case 0x04: /* USB Enable */ + dev->usb_conf[addr] = val; + ohci_update_mem_mapping(dev->usb, 0x10, 0x11, 0x12, (dev->usb_conf[0x04] & 1) && (!(dev->pci_conf[0x53] & 0x40))); + break; + + case 0x05: + dev->usb_conf[addr] = 0x03; + break; + + case 0x06: + dev->usb_conf[addr] = 0xc0; + break; + + case 0x11: + case 0x12: + case 0x13: /* USB Base I/O */ + dev->usb_conf[addr] = val; + ohci_update_mem_mapping(dev->usb, 0x11, 0x12, 0x13, (dev->usb_conf[0x04] & 1) && (!(dev->pci_conf[0x53] & 0x40))); + break; + + case 0x42: + dev->usb_conf[addr] = 0x10; + break; + + default: + dev->usb_conf[addr] = val; + break; + } +} + +static uint8_t +ali5237_read(int func, int addr, void *priv) +{ + ali1543_t *dev = (ali1543_t *)priv; + return dev->usb_conf[addr]; +} + +static void +ali7101_write(int func, int addr, uint8_t val, void *priv) +{ + ali1543_t *dev = (ali1543_t *)priv; + ali1543_log("M7101: dev->pmu_conf[%02x] = %02x\n", addr, val); + + switch (addr) + { + case 0x04: /* Enable PMU */ + dev->pmu_conf[addr] = val & 0x1f; + acpi_update_io_mapping(dev->acpi, (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0), (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); + smbus_piix4_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); + break; + + case 0x07: + dev->pmu_conf[addr] = val & 0xfe; + break; + + case 0x10: /* PMU Base I/O */ + case 0x11: + if (addr == 0x10) + dev->pmu_conf[addr] = (val & 0xe0) | 1; + else if (addr == 0x11) + dev->pmu_conf[addr] = val; + + acpi_update_io_mapping(dev->acpi, (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0), (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); + break; + + case 0x14: /* SMBus Base I/O */ + case 0x15: + dev->pmu_conf[addr] = val; + smbus_piix4_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); + break; + + case 0x2c: /* Subsystem Vendor ID */ + case 0x2d: + case 0x2e: + case 0x2f: + if (dev->pmu_conf[0xd8] & 0x10) + dev->pmu_conf[addr] = val; + + case 0x40: + dev->pmu_conf[addr] = val & 0x1f; + break; + + case 0x41: + dev->pmu_conf[addr] = val & 0x10; + break; + + case 0x45: + dev->pmu_conf[addr] = val & 0x9f; + break; + + case 0x46: + dev->pmu_conf[addr] = val & 0x18; + break; + + case 0x48: + dev->pmu_conf[addr] = val & 0x9f; + break; + + case 0x49: + dev->pmu_conf[addr] = val & 0x38; + break; + + case 0x4c: + dev->pmu_conf[addr] = val & 5; + break; + + case 0x4d: + dev->pmu_conf[addr] = val & 1; + break; + + case 0x4e: + dev->pmu_conf[addr] = val & 5; + break; + + case 0x4f: + dev->pmu_conf[addr] = val & 1; + break; + + case 0x55: /* APM Timer */ + dev->pmu_conf[addr] = val & 0x7f; + break; + + case 0x59: + dev->pmu_conf[addr] = val & 0x1f; + break; + + case 0x5b: /* ACPI/SMB Base I/O Control */ + dev->pmu_conf[addr] = val & 0x7f; + break; + + case 0x61: + dev->pmu_conf[addr] = val & 0x13; + break; + + case 0x62: + dev->pmu_conf[addr] = val & 0xf1; + break; + + case 0x63: + dev->pmu_conf[addr] = val & 3; + break; + + case 0x65: + dev->pmu_conf[addr] = val & 0x1f; + break; + + case 0x68: + dev->pmu_conf[addr] = val & 7; + break; + + case 0x6e: + dev->pmu_conf[addr] = val & 0xef; + break; + + case 0x6f: + dev->pmu_conf[addr] = val & 7; + break; + + /* Continue Further Later */ + case 0xc0: /* GPO Registers */ + case 0xc1: + case 0xc2: + case 0xc3: + dev->pmu_conf[addr] = val; + acpi_init_gporeg(dev->acpi, dev->pmu_conf[0xc0], dev->pmu_conf[0xc1], dev->pmu_conf[0xc2], dev->pmu_conf[0xc3]); + break; + + case 0xe0: + dev->pmu_conf[addr] = val; + smbus_piix4_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); + break; + + default: + dev->pmu_conf[addr] = val; + break; + } +} + +static uint8_t +ali7101_read(int func, int addr, void *priv) +{ + ali1543_t *dev = (ali1543_t *)priv; + return dev->pmu_conf[addr]; +} + +void ali1533_sio_fdc_handler(ali1543_t *dev) +{ + fdc_remove(dev->fdc_controller); + if (dev->device_regs[0][0x30] & 1) + { + fdc_set_base(dev->fdc_controller, dev->device_regs[0][0x61] | (dev->device_regs[0][0x60] << 8)); + fdc_set_irq(dev->fdc_controller, dev->device_regs[0][0x70] & 0xf); + fdc_set_dma_ch(dev->fdc_controller, dev->device_regs[0][0x74] & 0x07); + ali1543_log("M1543-SIO FDC: ADDR %04x IRQ %02x DMA %02x\n", dev->device_regs[0][0x61] | (dev->device_regs[0][0x60] << 8), dev->device_regs[0][0x70] & 0xf, dev->device_regs[0][0x74] & 0x07); + } +} + +void ali1533_sio_uart_handler(int num, ali1543_t *dev) +{ + serial_remove(dev->uart[num]); + if (dev->device_regs[num + 4][0x30] & 1) + { + serial_setup(dev->uart[num], dev->device_regs[num + 4][0x61] | (dev->device_regs[num + 4][0x60] << 8), dev->device_regs[num + 4][0x70] & 0xf); + ali1543_log("M1543-SIO UART%d: ADDR %04x IRQ %02x\n", num, dev->device_regs[num + 4][0x61] | (dev->device_regs[num + 4][0x60] << 8), dev->device_regs[num + 4][0x70] & 0xf); + } +} + +void ali1533_sio_lpt_handler(ali1543_t *dev) +{ + lpt1_remove(); + if (dev->device_regs[3][0x30] & 1) + { + lpt1_init(dev->device_regs[3][0x61] | (dev->device_regs[3][0x60] << 8)); + lpt1_irq(dev->device_regs[3][0x70] & 0xf); + ali1543_log("M1543-SIO LPT: ADDR %04x IRQ %02x\n", dev->device_regs[3][0x61] | (dev->device_regs[3][0x60] << 8), dev->device_regs[3][0x70] & 0xf); + } +} + +void ali1533_sio_ldn(uint16_t ldn, ali1543_t *dev) +{ + /* We don't include all LDN's */ + switch (ldn) + { + case 0: /* FDC */ + ali1533_sio_fdc_handler(dev); + break; + case 3: /* LPT */ + ali1533_sio_lpt_handler(dev); + break; + case 4: /* UART */ + case 5: + ali1533_sio_uart_handler(ldn - 4, dev); + break; + } +} + +static void +ali1533_sio_write(uint16_t addr, uint8_t val, void *priv) +{ + ali1543_t *dev = (ali1543_t *)priv; + + switch (addr) + { + case 0x3f0: + dev->sio_index = val; + if (dev->sio_index == 0x51) + { + dev->in_configuration_mode = 1; + } + else if (dev->sio_index == 0xbb) + dev->in_configuration_mode = 0; + break; + + case 0x3f1: + if (dev->in_configuration_mode) + { + switch (dev->sio_index) + { + case 0x07: + dev->sio_regs[dev->sio_index] = val & 0x7; + break; + + case 0x22: + dev->sio_regs[dev->sio_index] = val & 0x39; + break; + + case 0x23: + dev->sio_regs[dev->sio_index] = val & 0x38; + break; + + default: + if ((dev->sio_index < 0x30) || (dev->sio_index == 0x51) || (dev->sio_index == 0xbb)) + dev->sio_regs[dev->sio_index] = val; + else if (dev->sio_regs[0x07] <= 7) + dev->device_regs[dev->sio_regs[0x07]][dev->sio_index] = val; + break; + } + } + break; + } + + if ((!dev->in_configuration_mode) && (dev->sio_regs[0x07] <= 7) && (addr == 0x03f0)) + { + ali1533_sio_ldn(dev->sio_regs[0x07], dev); + } +} + +static uint8_t +ali1533_sio_read(uint16_t addr, void *priv) +{ + ali1543_t *dev = (ali1543_t *)priv; + if (dev->sio_index >= 0x30) + return dev->device_regs[dev->sio_regs[0x07]][dev->sio_index]; + else + return dev->sio_regs[dev->sio_index]; +} + +static void +ali1543_reset(void *priv) +{ + ali1543_t *dev = (ali1543_t *)priv; + + /* M1533 */ + dev->pci_conf[0x00] = 0xb9; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x33; + dev->pci_conf[0x03] = 0x15; + dev->pci_conf[0x04] = 0x0f; + dev->pci_conf[0x08] = 0xb4; + dev->pci_conf[0x0a] = 0x01; + dev->pci_conf[0x0b] = 0x06; + + ali1533_write(0, 0x48, 0x00, dev); // Disables all IRQ's + ali1533_write(0, 0x44, 0x00, dev); + ali1533_write(0, 0x74, 0x00, dev); + ali1533_write(0, 0x75, 0x00, dev); + ali1533_write(0, 0x76, 0x00, dev); + + /* M5229 */ + dev->ide_conf[0x00] = 0xb9; + dev->ide_conf[0x01] = 0x10; + dev->ide_conf[0x02] = 0x29; + dev->ide_conf[0x03] = 0x52; + dev->ide_conf[0x06] = 0x80; + dev->ide_conf[0x07] = 0x02; + dev->ide_conf[0x08] = 0x20; + dev->ide_conf[0x09] = 0xfa; + dev->ide_conf[0x0a] = 0x01; + dev->ide_conf[0x0b] = 0x01; + dev->ide_conf[0x10] = 0xf1; + dev->ide_conf[0x11] = 0x01; + dev->ide_conf[0x14] = 0xf5; + dev->ide_conf[0x15] = 0x03; + dev->ide_conf[0x18] = 0x71; + dev->ide_conf[0x19] = 0x01; + dev->ide_conf[0x1a] = 0x75; + dev->ide_conf[0x1b] = 0x03; + dev->ide_conf[0x20] = 0x01; + dev->ide_conf[0x23] = 0xf0; + dev->ide_conf[0x3d] = 0x01; + dev->ide_conf[0x3c] = 0x02; + dev->ide_conf[0x3d] = 0x03; + dev->ide_conf[0x54] = 0x55; + dev->ide_conf[0x55] = 0x55; + dev->ide_conf[0x63] = 0x01; + dev->ide_conf[0x64] = 0x02; + dev->ide_conf[0x67] = 0x01; + dev->ide_conf[0x78] = 0x21; + + sff_set_slot(dev->ide_controller[0], dev->ide_slot); + sff_set_slot(dev->ide_controller[1], dev->ide_slot); + sff_bus_master_reset(dev->ide_controller[0], (dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)); + sff_bus_master_reset(dev->ide_controller[1], ((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)) + 8); + ali5229_ide_handler(dev); + + /* M5237 */ + dev->usb_conf[0x00] = 0xb9; + dev->usb_conf[0x01] = 0x10; + dev->usb_conf[0x02] = 0x37; + dev->usb_conf[0x03] = 0x52; + dev->usb_conf[0x06] = 0x80; + dev->usb_conf[0x07] = 0x02; + dev->usb_conf[0x08] = 0x03; + dev->usb_conf[0x09] = 0x10; + dev->usb_conf[0x0a] = 0x03; + dev->usb_conf[0x0b] = 0x0c; + dev->usb_conf[0x3d] = 0x01; + + ali5237_write(0, 0x04, 0x00, dev); + + /* M7101 */ + dev->pmu_conf[0x00] = 0xb9; + dev->pmu_conf[0x01] = 0x10; + dev->pmu_conf[0x02] = 0x01; + dev->pmu_conf[0x03] = 0x71; + dev->pmu_conf[0x04] = 0x0f; + dev->pmu_conf[0x05] = 0x00; + dev->pmu_conf[0x0a] = 0x01; + dev->pmu_conf[0x0b] = 0x06; + + acpi_set_slot(dev->acpi, dev->pmu_slot); + acpi_set_nvr(dev->acpi, dev->nvr); + + ali7101_write(0, 0x04, 0x00, dev); + ali7101_write(0, 0xc0, 0x00, dev); + + /* M1543 Super I/O */ + dev->device_regs[0][0x60] = 0x03; + dev->device_regs[0][0x61] = 0xf0; + dev->device_regs[0][0x70] = 0x06; + dev->device_regs[0][0x74] = 0x02; + dev->device_regs[0][0xf0] = 0x08; + dev->device_regs[0][0xf2] = 0xff; + + dev->device_regs[3][0x60] = 0x03; + dev->device_regs[3][0x61] = 0x78; + dev->device_regs[3][0x70] = 0x05; + dev->device_regs[3][0x74] = 0x04; + dev->device_regs[3][0xf0] = 0x0c; + dev->device_regs[3][0xf1] = 0x05; + + dev->device_regs[4][0x60] = 0x03; + dev->device_regs[4][0x61] = 0xf8; + dev->device_regs[4][0x70] = 0x04; + dev->device_regs[4][0xf1] = 0x02; + dev->device_regs[4][0xf2] = 0x0c; + + dev->device_regs[5][0x60] = 0x02; + dev->device_regs[5][0x61] = 0xf8; + dev->device_regs[5][0x70] = 0x03; + dev->device_regs[5][0xf1] = 0x02; + dev->device_regs[5][0xf2] = 0x0c; + + dev->device_regs[7][0x70] = 0x01; + + ali1533_sio_fdc_handler(dev); + ali1533_sio_uart_handler(0, dev); + ali1533_sio_uart_handler(1, dev); + ali1533_sio_lpt_handler(dev); +} + +static void +ali1543_close(void *priv) +{ + ali1543_t *dev = (ali1543_t *)priv; + + free(dev); +} + +static void * +ali1543_init(const device_t *info) +{ + ali1543_t *dev = (ali1543_t *)malloc(sizeof(ali1543_t)); + memset(dev, 0, sizeof(ali1543_t)); + + /* Device 02: M1533 Southbridge */ + dev->pci_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, ali1533_read, ali1533_write, dev); + + /* Device 0B: M5229 IDE Controller*/ + dev->ide_slot = pci_add_card(PCI_ADD_IDE, ali5229_read, ali5229_write, dev); + + /* Device 0D: M5237 USB */ + dev->usb_slot = pci_add_card(PCI_ADD_NORMAL_NOBRIDGE, ali5237_read, ali5237_write, dev); + + /* Device 0C: M7101 Power Managment Controller */ + dev->pmu_slot = pci_add_card(PCI_ADD_BRIDGE, ali7101_read, ali7101_write, dev); + + /* Ports 3F0-1h: M1543 Super I/O */ + io_sethandler(0x03f0, 0x0002, ali1533_sio_read, NULL, NULL, ali1533_sio_write, NULL, NULL, dev); + + /* ACPI */ + dev->acpi = device_add(&acpi_ali_device); + dev->nvr = device_add(&at_nvr_device); // Generic NVR + + /* APM */ + dev->apm = device_add(&apm_pci_device); + + /* DMA */ + dma_alias_set(); + dma_high_page_init(); + + /* DDMA */ + dev->ddma = device_add(&ddma_device); + + /* Floppy Disk Controller */ + dev->fdc_controller = device_add(&fdc_at_device); + + /* IDE Controllers */ + dev->ide_controller[0] = device_add_inst(&sff8038i_device, 1); + dev->ide_controller[1] = device_add_inst(&sff8038i_device, 2); + + /* Port 92h */ + dev->port_92 = device_add(&port_92_pci_device); + + /* Serial NS16500 */ + dev->uart[0] = device_add_inst(&ns16550_device, 1); + dev->uart[1] = device_add_inst(&ns16550_device, 2); + + /* Standard SMBus */ + dev->smbus = device_add(&piix4_smbus_device); + + /* Super I/O Configuration Mechanism */ + dev->in_configuration_mode = 1; + + /* USB */ + dev->usb = device_add(&usb_device); + + ali1543_reset(dev); + + return dev; +} + +const device_t ali1543_device = { + "ALi M1543 Desktop South Bridge", + DEVICE_PCI, + 0, + ali1543_init, + ali1543_close, + ali1543_reset, + {NULL}, + NULL, + NULL, + NULL}; diff --git a/src/chipset/intel_82335.c b/src/chipset/intel_82335.c index f64da0330..edb8f266a 100644 --- a/src/chipset/intel_82335.c +++ b/src/chipset/intel_82335.c @@ -104,8 +104,8 @@ intel_82335_write(uint16_t addr, uint16_t val, void *priv) if (!EXTENDED_GRANULARITY_ENABLED) { - shadowbios = (dev->regs[0x22] & 0x01); - shadowbios_write = (dev->regs[0x22] & 0x01); + shadowbios = !!(dev->regs[0x22] & 0x01); + shadowbios_write = !!(dev->regs[0x22] & 0x01); /* Base System 512/640KB set */ mem_set_mem_state_both(0x80000, 0x20000, (dev->regs[0x22] & 0x08) ? ENABLE_TOP_128KB : DISABLE_TOP_128KB); diff --git a/src/chipset/sis_5571.c b/src/chipset/sis_5571.c index 69cc13ace..254aa5c4f 100644 --- a/src/chipset/sis_5571.c +++ b/src/chipset/sis_5571.c @@ -88,8 +88,8 @@ sis_5571_shadow_recalc(sis_5571_t *dev) can_read = (dev->pci_conf[0x76] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; can_write = (dev->pci_conf[0x76] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - shadowbios = (dev->pci_conf[0x76] & 0x80); - shadowbios_write = (dev->pci_conf[0x76] & 0x20); + shadowbios = !!(dev->pci_conf[0x76] & 0x80); + shadowbios_write = !!(dev->pci_conf[0x76] & 0x20); mem_set_mem_state_both(0xf0000, 0x10000, can_read | can_write); flushmmucache(); @@ -212,7 +212,7 @@ memory_pci_bridge_write(int func, int addr, uint8_t val, void *priv) case 0x51: /* Cache */ dev->pci_conf[addr] = val; - cpu_cache_ext_enabled = (val & 0x40); + cpu_cache_ext_enabled = !!(val & 0x40); cpu_update_waitstates(); break; diff --git a/src/chipset/via_apollo.c b/src/chipset/via_apollo.c index fbceb2fd8..b9a5d77bb 100644 --- a/src/chipset/via_apollo.c +++ b/src/chipset/via_apollo.c @@ -36,11 +36,11 @@ #include <86box/chipset.h> #include <86box/spd.h> -#define VIA_585 0x05850000 +#define VIA_585 0x05851000 #define VIA_595 0x05950000 #define VIA_597 0x05970100 #define VIA_598 0x05980000 -#define VIA_691 0x06910000 +#define VIA_691 0x06910600 #define VIA_693A 0x06914400 #define VIA_694 0x0691c200 #define VIA_8601 0x86010500 diff --git a/src/include/86box/acpi.h b/src/include/86box/acpi.h index 6cc98cefb..33044f49b 100644 --- a/src/include/86box/acpi.h +++ b/src/include/86box/acpi.h @@ -42,6 +42,7 @@ extern "C" { #define ACPI_ENABLE 0xf1 #define ACPI_DISABLE 0xf0 +#define VEN_ALI 0x010b9 #define VEN_INTEL 0x08086 #define VEN_SMC 0x01055 #define VEN_VIA 0x01106 @@ -56,8 +57,9 @@ typedef struct timer32, gpireg[3], gporeg[4]; uint16_t pmsts, pmen, - pmcntrl, gpsts, - gpen, gpscien, + pmcntrl, gpsts, gpsts1, + gpen, gpen1, gpscien, + gpcntrl, gpsmien, pscntrl, gpscists; int smi_lock, smi_active; @@ -91,13 +93,14 @@ typedef struct /* Global variables. */ extern int acpi_rtc_status; +extern const device_t acpi_ali_device; extern const device_t acpi_intel_device; extern const device_t acpi_smc_device; extern const device_t acpi_via_device; extern const device_t acpi_via_596b_device; -/* Functions. */ +/* Functions */ extern void acpi_update_io_mapping(acpi_t *dev, uint32_t base, int chipset_en); extern void acpi_update_aux_io_mapping(acpi_t *dev, uint32_t base, int chipset_en); extern void acpi_init_gporeg(acpi_t *dev, uint8_t val0, uint8_t val1, uint8_t val2, uint8_t val3); diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index 7b2923809..c2db87326 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -22,10 +22,15 @@ extern const device_t acc2168_device; /* ALi */ +extern const device_t ali1217_device; extern const device_t ali1429_device; #if defined(DEV_BRANCH) && defined(USE_M1489) extern const device_t ali1489_device; #endif +#if defined(DEV_BRANCH) && defined(USE_M154X) +extern const device_t ali1531_device; +extern const device_t ali1543_device; +#endif #if defined(DEV_BRANCH) && defined(USE_M6117) extern const device_t ali6117d_device; #endif @@ -110,9 +115,6 @@ extern const device_t stpc_serial_device; extern const device_t stpc_lpt_device; #endif -/* UMC */ -extern const device_t umc491_device; - /* VIA */ extern const device_t via_vt82c49x_device; extern const device_t via_vt82c49x_ide_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index b18e71934..0314ca425 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -267,6 +267,7 @@ extern int machine_at_commodore_sl386sx16_init(const machine_t *); extern int machine_at_commodore_sl386sx25_init(const machine_t *); extern int machine_at_spc6033p_init(const machine_t *); extern int machine_at_wd76c10_init(const machine_t *); +extern int machine_at_flytech386_init(const machine_t *); extern int machine_at_olim300_05_init(const machine_t *); extern int machine_at_olim300_10_init(const machine_t *); @@ -286,6 +287,7 @@ extern int machine_at_pja511m_init(const machine_t *); #ifdef EMU_DEVICE_H extern const device_t *at_ama932j_get_device(void); +extern const device_t *at_flytech386_get_device(void); extern const device_t *at_commodore_sl386sx25_get_device(void); extern const device_t *at_spc4620p_get_device(void); extern const device_t *at_spc6033p_get_device(void); @@ -298,7 +300,6 @@ extern int machine_at_acc386_init(const machine_t *); extern int machine_at_asus386_init(const machine_t *); extern int machine_at_ecs386_init(const machine_t *); extern int machine_at_spc6000a_init(const machine_t *); -extern int machine_at_ustechnologies386_init(const machine_t *); extern int machine_at_micronics386_init(const machine_t *); extern int machine_at_rycleopardlx_init(const machine_t *); @@ -349,6 +350,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 *); @@ -454,6 +456,10 @@ extern int machine_at_p5mms98_init(const machine_t *); extern int machine_at_r534f_init(const machine_t *); extern int machine_at_ms5146_init(const machine_t *); #endif +#if defined(DEV_BRANCH) && defined(USE_M154X) +extern int machine_at_m560_init(const machine_t *); +extern int machine_at_ms5164_init(const machine_t *); +#endif extern int machine_at_ficva502_init(const machine_t *); diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index dafef5e72..aac21111f 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -152,12 +152,14 @@ extern void thread_reset_event(event_t *arg); extern int thread_wait_event(event_t *arg, int timeout); extern void thread_destroy_event(event_t *arg); +#define MUTEX_DEFAULT_SPIN_COUNT 1024 + extern mutex_t *thread_create_mutex(void); +extern mutex_t *thread_create_mutex_with_spin_count(unsigned int spin_count); extern void thread_close_mutex(mutex_t *arg); extern int thread_wait_mutex(mutex_t *arg); extern int thread_release_mutex(mutex_t *mutex); - /* Other stuff. */ extern void startblit(void); extern void endblit(void); diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index c53e69e56..0bb49ac7b 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -50,6 +50,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; @@ -57,6 +59,7 @@ extern const device_t sio_detect_device; extern const device_t um8669f_device; extern const device_t via_vt82c686_sio_device; extern const device_t w83787f_device; +extern const device_t w83787f_ide_device; extern const device_t w83877f_device; extern const device_t w83877f_president_device; extern const device_t w83877tf_device; diff --git a/src/include/86box/vid_voodoo_common.h b/src/include/86box/vid_voodoo_common.h index 85b97c7d2..76b56e88f 100644 --- a/src/include/86box/vid_voodoo_common.h +++ b/src/include/86box/vid_voodoo_common.h @@ -489,6 +489,10 @@ typedef struct voodoo_t uint64_t time; int render_time[4]; + int force_blit_count; + int can_blit; + mutex_t* force_blit_mutex; + int use_recompiler; void *codegen_data; diff --git a/src/machine/CMakeLists.txt b/src/machine/CMakeLists.txt index 18a43eb03..7576ae130 100644 --- a/src/machine/CMakeLists.txt +++ b/src/machine/CMakeLists.txt @@ -50,6 +50,10 @@ if(M1489) target_compile_definitions(mch PRIVATE USE_M1489) endif() +if(M154X) + target_compile_definitions(mch PRIVATE USE_M154X) +endif() + if(M6117) target_compile_definitions(mch PRIVATE USE_M6117) endif() diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index fe8fd29ba..1c2b6526c 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -597,6 +597,34 @@ machine_at_awardsx_init(const machine_t *model) return ret; } +int +machine_at_flytech386_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/flytech386/FLYTECH.BIO", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&ali1217_device); + device_add(&w83787f_ide_device); + device_add(&keyboard_ps2_device); + + if (gfxcard == VID_INTERNAL) + device_add(&tvga8900d_device); + + return ret; +} + +const device_t * +at_flytech386_get_device(void) +{ + return &tvga8900d_device; +} #if defined(DEV_BRANCH) && defined(USE_M6117) int diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index e040e3128..a0f8494b3 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -185,27 +185,6 @@ machine_at_spc6000a_init(const machine_t *model) } -int -machine_at_ustechnologies386_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear(L"roms/machines/ustechnologies386/3umw003.bin", - 0x000f0000, 65536, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init(model); - - device_add(&umc491_device); - device_add(&keyboard_at_device); - device_add(&fdc_at_device); - - return ret; -} - - int machine_at_rycleopardlx_init(const machine_t *model) { @@ -971,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/m_at_socket7.c b/src/machine/m_at_socket7.c index acdb2278e..f81a6d28f 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -1032,6 +1032,75 @@ machine_at_p5mms98_init(const machine_t *model) return ret; } +#if defined(DEV_BRANCH) && defined(USE_M154X) +int +machine_at_m560_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/m560/5600410s.ami", + 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(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + 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); + pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_IDE, 1, 2, 3, 4); + pci_register_slot(0x0C, PCI_CARD_BRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL_NOBRIDGE, 1, 2, 3, 4); + device_add(&ali1531_device); + device_add(&ali1543_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sst_flash_29ee010_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 128); + + return ret; +} + +int +machine_at_ms5164_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/ms5164/W564MS43.005", + 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(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + 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); + pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_IDE, 1, 2, 3, 4); + pci_register_slot(0x0C, PCI_CARD_BRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL_NOBRIDGE, 1, 2, 3, 4); + + device_add(&ali1531_device); + device_add(&ali1543_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sst_flash_29ee010_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 128); + + return ret; +} +#endif + #if defined(DEV_BRANCH) && defined(USE_SIS_5571) int machine_at_r534f_init(const machine_t *model) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index de539f5e5..6c7928da4 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -157,6 +157,7 @@ const machine_t machines[] = { { "[ALi M6117D] Acrosser AR-B1375", "arb1375", MACHINE_TYPE_386SX, CPU_PKG_M6117, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768,1024, 127, machine_at_arb1375_init, NULL }, { "[ALi M6117D] Acrosser PJ-A511M", "pja511m", MACHINE_TYPE_386SX, CPU_PKG_M6117, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768,1024, 127, machine_at_pja511m_init, NULL }, #endif + { "[ALi M1217] Flytech 386", "flytech386", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 16384, 1024, 127, machine_at_flytech386_init, at_flytech386_get_device }, { "[HT18] AMA-932J", "ama932j", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_VIDEO, 512, 8192, 128, 127, machine_at_ama932j_init, at_ama932j_get_device }, { "[Intel 82335] ADI 386SX", "adi386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_adi386sx_init, NULL }, { "[Intel 82335] Shuttle 386SX", "shuttle386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_shuttle386sx_init, NULL }, @@ -181,7 +182,6 @@ const machine_t machines[] = { { "[ISA] Compaq Portable III (386)", "portableiii386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_VIDEO, 1024, 14336, 1024, 127, machine_at_portableiii386_init, at_cpqiii_get_device }, { "[ISA] Micronics 386 clone", "micronics386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_micronics386_init, NULL }, { "[SiS 310] ASUS ISA-386C", "asus386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_asus386_init, NULL }, - { "[UMC 491] US Technologies 386", "ustechnologies386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_ustechnologies386_init, NULL }, /* 386DX machines which utilize the VLB bus */ { "[OPTi 495] Award 386DX clone", "award386dx", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_init, NULL }, @@ -230,6 +230,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 }, @@ -346,6 +347,12 @@ const machine_t machines[] = { { "[SiS 5571] MSI MS-5146", "ms5146", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 393216, 8192, 127, machine_at_ms5146_init, NULL }, #endif + /* ALi ALADDiN IV */ +#if defined(DEV_BRANCH) && defined(USE_M154X) + { "[ALi ALADDiN IV] PC Chips M560", "m560", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_m560_init, NULL }, + { "[ALi ALADDiN IV] MSI MS-5164", "ms5164", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_ms5164_init, NULL }, +#endif + /* Super Socket 7 machines */ /* Apollo MVP3 */ { "[VIA MVP3] AOpen AX59 Pro", "ax59pro", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 1300, 3520, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_ax59pro_init, NULL }, diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index 2760d2623..0009b4430 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -182,10 +182,10 @@ ncr_log(const char *fmt, ...) #define SET_BUS_STATE(ncr, state) ncr->cur_bus = (ncr->cur_bus & ~(SCSI_PHASE_MESSAGE_IN)) | (state & (SCSI_PHASE_MESSAGE_IN)) static void -ncr_dma_send(ncr5380_t *ncr_dev, ncr_t *ncr); +ncr_dma_send(ncr5380_t *ncr_dev, ncr_t *ncr, scsi_device_t *dev); static void -ncr_dma_initiator_receive(ncr5380_t *ncr_dev, ncr_t *ncr); +ncr_dma_initiator_receive(ncr5380_t *ncr_dev, ncr_t *ncr, scsi_device_t *dev); static void ncr_callback(void *priv); @@ -249,9 +249,8 @@ ncr_timer_on(ncr5380_t *ncr_dev, ncr_t *ncr, int callback) if (ncr->data_wait & 2) ncr->data_wait &= ~2; - if (callback) { + if (callback) p *= 128.0; - } p += 1.0; @@ -619,7 +618,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv) ncr_log("Write: start DMA send register\n"); /*a Write 6/10 has occurred, start the timer when the block count is loaded*/ ncr->dma_mode = DMA_SEND; - if (ncr_dev->block_count_loaded && (ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) { + if ((ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) { ncr_timer_on(ncr_dev, ncr, 0); } break; @@ -628,7 +627,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv) ncr_log("Write: start DMA initiator receive register, dma? = %02x\n", ncr->mode & MODE_DMA); /*a Read 6/10 has occurred, start the timer when the block count is loaded*/ ncr->dma_mode = DMA_INITIATOR_RECEIVE; - if (ncr_dev->block_count_loaded && (ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) { + if ((ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) { ncr_timer_on(ncr_dev, ncr, 0); } break; @@ -888,10 +887,8 @@ memio_write(uint32_t addr, uint8_t val, void *priv) ncr_dev->block_count = val; ncr_dev->block_count_loaded = 1; - if (ncr->mode & MODE_DMA) { - ncr_log("Start timer, buffer not ready = %02x\n", !(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)); + if (ncr->mode & MODE_DMA) ncr_timer_on(ncr_dev, ncr, 0); - } if (ncr_dev->status_ctrl & CTRL_DATA_DIR) { ncr_dev->buffer_host_pos = 128; @@ -988,15 +985,15 @@ t130b_out(uint16_t port, uint8_t val, void *priv) } static void -ncr_dma_send(ncr5380_t *ncr_dev, ncr_t *ncr) +ncr_dma_send(ncr5380_t *ncr_dev, ncr_t *ncr, scsi_device_t *dev) { - scsi_device_t *dev = &scsi_devices[ncr->target_id]; - int bus, c = 0; uint8_t data; if (scsi_device_get_callback(dev) > 0.0) ncr_timer_on(ncr_dev, ncr, 1); + else + ncr_timer_on(ncr_dev, ncr, 0); for (c = 0; c < 10; c++) { ncr_bus_read(ncr_dev); @@ -1004,9 +1001,6 @@ ncr_dma_send(ncr5380_t *ncr_dev, ncr_t *ncr) break; } - if (c == 10) - return; - /* Data ready. */ data = ncr_dev->buffer[ncr_dev->buffer_pos]; bus = get_bus_host(ncr) & ~BUS_DATAMASK; @@ -1038,19 +1032,19 @@ ncr_dma_send(ncr5380_t *ncr_dev, ncr_t *ncr) } return; } - ncr_dma_send(ncr_dev, ncr); + ncr_dma_send(ncr_dev, ncr, dev); } static void -ncr_dma_initiator_receive(ncr5380_t *ncr_dev, ncr_t *ncr) +ncr_dma_initiator_receive(ncr5380_t *ncr_dev, ncr_t *ncr, scsi_device_t *dev) { - scsi_device_t *dev = &scsi_devices[ncr->target_id]; - int bus, c = 0; uint8_t temp; if (scsi_device_get_callback(dev) > 0.0) ncr_timer_on(ncr_dev, ncr, 1); + else + ncr_timer_on(ncr_dev, ncr, 0); for (c = 0; c < 10; c++) { ncr_bus_read(ncr_dev); @@ -1058,9 +1052,6 @@ ncr_dma_initiator_receive(ncr5380_t *ncr_dev, ncr_t *ncr) break; } - if (c == 10) - return; - /* Data ready. */ ncr_bus_read(ncr_dev); temp = BUS_GETDATA(ncr->cur_bus); @@ -1091,7 +1082,7 @@ ncr_dma_initiator_receive(ncr5380_t *ncr_dev, ncr_t *ncr) } return; } - ncr_dma_initiator_receive(ncr_dev, ncr); + ncr_dma_initiator_receive(ncr_dev, ncr, dev); } static void @@ -1103,8 +1094,9 @@ ncr_callback(void *priv) ncr_log("DMA mode=%d, status ctrl = %02x\n", ncr->dma_mode, ncr_dev->status_ctrl); - if (ncr->dma_mode != DMA_IDLE && (ncr->mode & MODE_DMA) && ncr_dev->block_count_loaded && scsi_device_get_callback(dev) <= 0.0) - timer_on_auto(&ncr_dev->timer, 10.0); + if (ncr->dma_mode != DMA_IDLE && (ncr->mode & MODE_DMA) && ncr_dev->block_count_loaded) { + ncr_timer_on(ncr_dev, ncr, 0); + } if (ncr->data_wait & 1) { ncr->clear_req = 3; @@ -1129,7 +1121,7 @@ ncr_callback(void *priv) if (!ncr_dev->block_count_loaded) break; - ncr_dma_send(ncr_dev, ncr); + ncr_dma_send(ncr_dev, ncr, dev); break; case DMA_INITIATOR_RECEIVE: @@ -1146,7 +1138,7 @@ ncr_callback(void *priv) if (!ncr_dev->block_count_loaded) break; - ncr_dma_initiator_receive(ncr_dev, ncr); + ncr_dma_initiator_receive(ncr_dev, ncr, dev); break; } diff --git a/src/sio/CMakeLists.txt b/src/sio/CMakeLists.txt index 93e084e11..62debb1b5 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_pc87310.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/sio/sio_w83787f.c b/src/sio/sio_w83787f.c index ed0f60a75..8bd2cd5c3 100644 --- a/src/sio/sio_w83787f.c +++ b/src/sio/sio_w83787f.c @@ -16,24 +16,43 @@ * Author: Miran Grca, * Copyright 2020 Miran Grca. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> #include <86box/io.h> #include <86box/timer.h> -#include <86box/pci.h> #include <86box/mem.h> -#include <86box/rom.h> #include <86box/lpt.h> #include <86box/serial.h> #include <86box/fdd.h> #include <86box/fdc.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> #include <86box/sio.h> +#ifdef ENABLE_W83787_LOG +int w83787_do_log = ENABLE_W83787_LOG; +static void +w83787_log(const char *fmt, ...) +{ + va_list ap; + + if (w83787_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define w83787_log(fmt, ...) +#endif #define FDDA_TYPE (dev->regs[7] & 3) #define FDDB_TYPE ((dev->regs[7] >> 2) & 3) @@ -52,13 +71,14 @@ #define HEFERE ((dev->regs[0xC] >> 5) & 1) +#define HAS_IDE_FUNCTIONALITY dev->ide_function typedef struct { uint8_t tries, regs[42]; uint16_t reg_init; int locked, rw_locked, cur_reg, - key; + key, ide_function; fdc_t *fdc; serial_t *uart[2]; } w83787f_t; @@ -187,6 +207,17 @@ w83787f_fdc_handler(w83787f_t *dev) fdc_set_base(dev->fdc, (dev->regs[0] & 0x10) ? 0x03f0 : 0x0370); } +static void +w83787f_ide_handler(w83787f_t *dev) +{ +ide_pri_disable(); +if(dev->regs[0] & 0x80) +{ + ide_set_base(0, (dev->regs[0] & 0x40) ? 0x1f0 : 0x170); + ide_set_side(0, (dev->regs[0] & 0x40) ? 0x3f6 : 0x376); + ide_pri_enable(); +} +} static void w83787f_write(uint16_t port, uint8_t val, void *priv) @@ -219,6 +250,8 @@ w83787f_write(uint16_t port, uint8_t val, void *priv) switch (dev->cur_reg) { case 0: + if ((valxor & 0xc0) && (HAS_IDE_FUNCTIONALITY)) + w83787f_ide_handler(dev); if (valxor & 0x30) w83787f_fdc_handler(dev); if (valxor & 0x0c) @@ -281,7 +314,7 @@ w83787f_write(uint16_t port, uint8_t val, void *priv) w83787f_lpt_handler(dev); break; case 0xB: - pclog("Writing %02X to CRB\n", val); + w83787_log("Writing %02X to CRB\n", val); break; case 0xC: if (valxor & 0x20) @@ -319,6 +352,14 @@ w83787f_reset(w83787f_t *dev) lpt1_init(0x378); lpt1_irq(7); + if(HAS_IDE_FUNCTIONALITY) + { + ide_pri_disable(); + ide_set_base(0, 0x1f0); + ide_set_side(0, 0x3f6); + ide_pri_enable(); + } + fdc_reset(dev->fdc); memset(dev->regs, 0, 0x2A); @@ -358,13 +399,17 @@ w83787f_init(const device_t *info) w83787f_t *dev = (w83787f_t *) malloc(sizeof(w83787f_t)); memset(dev, 0, sizeof(w83787f_t)); + HAS_IDE_FUNCTIONALITY = !!(info->local & 0x10); + dev->fdc = device_add(&fdc_at_winbond_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->reg_init = info->local; - + dev->reg_init = info->local & 0x0f; w83787f_reset(dev); return dev; @@ -379,3 +424,12 @@ const device_t w83787f_device = { { NULL }, NULL, NULL, NULL }; + +const device_t w83787f_ide_device = { + "Winbond W83787F/IF Super I/O with IDE functionality", + 0, + 0x19, + w83787f_init, w83787f_close, NULL, + { NULL }, NULL, NULL, + NULL +}; diff --git a/src/video/vid_voodoo.c b/src/video/vid_voodoo.c index c806bf243..72e82da5b 100644 --- a/src/video/vid_voodoo.c +++ b/src/video/vid_voodoo.c @@ -514,6 +514,12 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p) if (voodoo->initEnable & 0x01) { voodoo->fbiInit0 = val; + thread_wait_mutex(voodoo->force_blit_mutex); + voodoo->can_blit = (voodoo->fbiInit0 & FBIINIT0_VGA_PASS) ? 1 : 0; + if (!voodoo->can_blit) + voodoo->force_blit_count = 0; + thread_release_mutex(voodoo->force_blit_mutex); + if (voodoo->set->nr_cards == 2) svga_set_override(voodoo->svga, (voodoo->set->voodoos[0]->fbiInit0 | voodoo->set->voodoos[1]->fbiInit0) & 1); else @@ -877,6 +883,24 @@ static void voodoo_speed_changed(void *p) // voodoo_log("Voodoo read_time=%i write_time=%i burst_time=%i %08x %08x\n", voodoo->read_time, voodoo->write_time, voodoo->burst_time, voodoo->fbiInit1, voodoo->fbiInit4); } +static void voodoo_force_blit(void *p) +{ + voodoo_set_t *voodoo_set = (voodoo_set_t *)p; + + thread_wait_mutex(voodoo_set->voodoos[0]->force_blit_mutex); + if(voodoo_set->voodoos[0]->can_blit) { + voodoo_set->voodoos[0]->force_blit_count++; + } + thread_release_mutex(voodoo_set->voodoos[0]->force_blit_mutex); + if(voodoo_set->nr_cards == 2) { + thread_wait_mutex(voodoo_set->voodoos[1]->force_blit_mutex); + if(voodoo_set->voodoos[1]->can_blit) { + voodoo_set->voodoos[1]->force_blit_count++; + } + thread_release_mutex(voodoo_set->voodoos[1]->force_blit_mutex); + } +} + void *voodoo_card_init() { int c; @@ -1014,6 +1038,10 @@ void *voodoo_card_init() voodoo->disp_buffer = 0; voodoo->draw_buffer = 1; + + voodoo->force_blit_count = 0; + voodoo->can_blit = 0; + voodoo->force_blit_mutex = thread_create_mutex_with_spin_count(MUTEX_DEFAULT_SPIN_COUNT); return voodoo; } @@ -1128,6 +1156,10 @@ void *voodoo_2d3d_card_init(int type) voodoo->disp_buffer = 0; voodoo->draw_buffer = 1; + voodoo->force_blit_count = 0; + voodoo->can_blit = 0; + voodoo->force_blit_mutex = thread_create_mutex_with_spin_count(MUTEX_DEFAULT_SPIN_COUNT); + return voodoo; } @@ -1241,6 +1273,9 @@ void voodoo_card_close(voodoo_t *voodoo) free(voodoo->tex_mem[1]); free(voodoo->tex_mem[0]); } + + thread_close_mutex(voodoo->force_blit_mutex); + free(voodoo); } @@ -1386,6 +1421,6 @@ const device_t voodoo_device = NULL, { NULL }, voodoo_speed_changed, - NULL, + voodoo_force_blit, voodoo_config }; diff --git a/src/video/vid_voodoo_display.c b/src/video/vid_voodoo_display.c index 5d3ad6e81..bfee8554c 100644 --- a/src/video/vid_voodoo_display.c +++ b/src/video/vid_voodoo_display.c @@ -645,7 +645,16 @@ skip_draw: { if (voodoo->line == voodoo->v_disp) { - if (voodoo->dirty_line_high > voodoo->dirty_line_low) + int force_blit = 0; + thread_wait_mutex(voodoo->force_blit_mutex); + if(voodoo->force_blit_count) { + force_blit = 1; + if(--voodoo->force_blit_count < 0) + voodoo->force_blit_count = 0; + } + thread_release_mutex(voodoo->force_blit_mutex); + + if (voodoo->dirty_line_high > voodoo->dirty_line_low || force_blit) svga_doblit(0, voodoo->v_disp, voodoo->h_disp, voodoo->v_disp-1, voodoo->svga); if (voodoo->clutData_dirty) { diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 656b54649..241e0e2c2 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -81,6 +81,9 @@ ifeq ($(DEV_BUILD), y) ifndef M1489 M1489 := y endif + ifndef M154X + M154X := y + endif ifndef M6117 M6117 := y endif @@ -154,6 +157,9 @@ else ifndef M1489 M1489 := n endif + ifndef M154X + M154X := n + endif ifndef M6117 M6117 := n endif @@ -553,6 +559,11 @@ OPTS += -DUSE_M1489 DEVBROBJ += ali1489.o endif +ifeq ($(M1489), y) +OPTS += -DUSE_M154X +DEVBROBJ += ali1531.o ali1543.o +endif + ifeq ($(M6117), y) OPTS += -DUSE_M6117 DEVBROBJ += ali6117.o @@ -604,10 +615,10 @@ CPUOBJ := cpu.o cpu_table.o \ x86seg.o x87.o x87_timings.o \ $(DYNARECOBJ) -CHIPSETOBJ := acc2168.o cs8230.o ali1429.o headland.o intel_82335.o cs4031.o \ +CHIPSETOBJ := acc2168.o cs8230.o ali1217.o ali1429.o headland.o intel_82335.o cs4031.o \ intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \ neat.o opti495.o opti895.o opti5x7.o scamp.o scat.o via_vt82c49x.o via_vt82c505.o \ - sis_85c310.o sis_85c4xx.o sis_85c496.o sis_85c50x.o opti283.o opti291.o umc491.o \ + sis_85c310.o sis_85c4xx.o sis_85c496.o sis_85c50x.o opti283.o opti291.o \ via_apollo.o via_pipc.o wd76c10.o vl82c480.o MCHOBJ := machine.o machine_table.o \ @@ -641,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_pc87310.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 \ diff --git a/src/win/win_thread.c b/src/win/win_thread.c index 000c96706..1d4ae0d32 100644 --- a/src/win/win_thread.c +++ b/src/win/win_thread.c @@ -133,17 +133,23 @@ thread_destroy_event(event_t *arg) mutex_t * thread_create_mutex(void) -{ - return((mutex_t*)CreateMutex(NULL, FALSE, NULL)); +{ + mutex_t *mutex = malloc(sizeof(CRITICAL_SECTION)); + + InitializeCriticalSection(mutex); + + return mutex; } -void -thread_close_mutex(mutex_t *mutex) +mutex_t * +thread_create_mutex_with_spin_count(unsigned int spin_count) { - if (mutex == NULL) return; + mutex_t *mutex = malloc(sizeof(CRITICAL_SECTION)); - CloseHandle((HANDLE)mutex); + InitializeCriticalSectionAndSpinCount(mutex, spin_count); + + return mutex; } @@ -152,11 +158,11 @@ thread_wait_mutex(mutex_t *mutex) { if (mutex == NULL) return(0); - DWORD dwres = WaitForSingleObject((HANDLE)mutex, INFINITE); + LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION)mutex; - if (dwres == WAIT_OBJECT_0) return(1); + EnterCriticalSection(critsec); - return(0); + return 1; } @@ -165,5 +171,22 @@ thread_release_mutex(mutex_t *mutex) { if (mutex == NULL) return(0); - return(!!ReleaseMutex((HANDLE)mutex)); + LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION)mutex; + + LeaveCriticalSection(critsec); + + return 1; +} + + +void +thread_close_mutex(mutex_t *mutex) +{ + if (mutex == NULL) return; + + LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION)mutex; + + DeleteCriticalSection(critsec); + + free(critsec); }