diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index e5cd315d1..cc1ec7f8e 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,4 +1,5 @@ +blank_issues_enabled: false contact_links: - name: Question - url: https://discord.gg/QXK9XTv + url: https://github.com/86Box/86Box/discussions about: Please ask and answer questions here. 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/cs4031.c b/src/chipset/cs4031.c index 2765025d9..2d55ce90d 100644 --- a/src/chipset/cs4031.c +++ b/src/chipset/cs4031.c @@ -12,7 +12,7 @@ * * Authors: Tiseno100 * - * Copyright 2020 Tiseno100 + * Copyright 2021 Tiseno100 * */ @@ -28,19 +28,15 @@ #include <86box/timer.h> #include <86box/io.h> #include <86box/device.h> -#include <86box/keyboard.h> #include <86box/mem.h> -#include <86box/fdd.h> -#include <86box/fdc.h> #include <86box/port_92.h> #include <86box/chipset.h> - typedef struct { - uint8_t index, - regs[256]; - port_92_t * port_92; + uint8_t index, + regs[256]; + port_92_t *port_92; } cs4031_t; #ifdef ENABLE_CS4031_LOG @@ -50,10 +46,11 @@ cs4031_log(const char *fmt, ...) { va_list ap; - if (cs4031_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + if (cs4031_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else @@ -62,139 +59,130 @@ cs4031_log(const char *fmt, ...) static void cs4031_shadow_recalc(cs4031_t *dev) { + mem_set_mem_state_both(0xa0000, 0x10000, (dev->regs[0x18] & 0x01) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + mem_set_mem_state_both(0xb0000, 0x10000, (dev->regs[0x18] & 0x02) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); -uint32_t romc0000, romc4000, romc8000, romcc000, romd0000, rome0000, romf0000; - -/* Register 18h */ -if(dev->regs[0x18] & 0x01) -mem_set_mem_state_both(0xa0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); -else -mem_set_mem_state_both(0xa0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - -if(dev->regs[0x18] & 0x02) -mem_set_mem_state_both(0xb0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); -else -mem_set_mem_state_both(0xb0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - - -/* Register 19h-1ah-1bh*/ - -shadowbios = (dev->regs[0x19] & 0x40); -shadowbios_write = (dev->regs[0x1a] & 0x40); - -/* ROMCS only functions if shadow write is disabled */ -romc0000 = ((dev->regs[0x1b] & 0x80) && (dev->regs[0x1b] & 0x01)) ? MEM_WRITE_DISABLED : MEM_WRITE_EXTANY; -romc4000 = ((dev->regs[0x1b] & 0x80) && (dev->regs[0x1b] & 0x02)) ? MEM_WRITE_DISABLED : MEM_WRITE_EXTANY; -romc8000 = ((dev->regs[0x1b] & 0x80) && (dev->regs[0x1b] & 0x04)) ? MEM_WRITE_DISABLED : MEM_WRITE_EXTANY; -romcc000 = ((dev->regs[0x1b] & 0x80) && (dev->regs[0x1b] & 0x08)) ? MEM_WRITE_DISABLED : MEM_WRITE_EXTANY; -romd0000 = ((dev->regs[0x1b] & 0x80) && (dev->regs[0x1b] & 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_EXTANY; -rome0000 = ((dev->regs[0x1b] & 0x80) && (dev->regs[0x1b] & 0x20)) ? MEM_WRITE_DISABLED : MEM_WRITE_EXTANY; -romf0000 = ((dev->regs[0x1b] & 0x80) && (dev->regs[0x1b] & 0x40)) ? MEM_WRITE_DISABLED : MEM_WRITE_EXTANY; - - -mem_set_mem_state_both(0xc0000, 0x4000, ((dev->regs[0x19] & 0x01) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x1a] & 0x01) ? MEM_WRITE_INTERNAL : romc0000)); -mem_set_mem_state_both(0xc4000, 0x4000, ((dev->regs[0x19] & 0x02) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x1a] & 0x02) ? MEM_WRITE_INTERNAL : romc4000)); -mem_set_mem_state_both(0xc8000, 0x4000, ((dev->regs[0x19] & 0x04) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x1a] & 0x04) ? MEM_WRITE_INTERNAL : romc8000)); -mem_set_mem_state_both(0xcc000, 0x4000, ((dev->regs[0x19] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x1a] & 0x08) ? MEM_WRITE_INTERNAL : romcc000)); -mem_set_mem_state_both(0xd0000, 0x10000, ((dev->regs[0x19] & 0x10) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x1a] & 0x10) ? MEM_WRITE_INTERNAL : romd0000)); -mem_set_mem_state_both(0xe0000, 0x10000, ((dev->regs[0x19] & 0x20) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x1a] & 0x20) ? MEM_WRITE_INTERNAL : rome0000)); -mem_set_mem_state_both(0xf0000, 0x10000, ((dev->regs[0x19] & 0x40) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x1a] & 0x40) ? MEM_WRITE_INTERNAL : romf0000)); - - + for (uint32_t i = 0; i < 7; i++) + { + if (i < 4) + mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, ((dev->regs[0x19] & (1 << i)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x1a] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); + else + mem_set_mem_state_both(0xd0000 + ((i - 4) << 16), 0x10000, ((dev->regs[0x19] & (1 << i)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x1a] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); + } + shadowbios = !!(dev->regs[0x19] & 0x40); + shadowbios_write = !!(dev->regs[0x1a] & 0x40); } static void cs4031_write(uint16_t addr, uint8_t val, void *priv) { - cs4031_t *dev = (cs4031_t *) priv; + cs4031_t *dev = (cs4031_t *)priv; - switch (addr) { - case 0x22: - dev->index = val; - break; - case 0x23: + switch (addr) + { + case 0x22: + dev->index = val; + break; + case 0x23: cs4031_log("CS4031: dev->regs[%02x] = %02x\n", dev->index, val); - dev->regs[dev->index] = val; - - switch(dev->index){ - case 0x06: - cpu_update_waitstates(); + switch (dev->index) + { + case 0x05: + dev->regs[dev->index] = val & 0x3f; break; - case 0x18: - case 0x19: - case 0x1a: - case 0x1b: + case 0x06: + dev->regs[dev->index] = val & 0xbc; + break; + + case 0x07: + dev->regs[dev->index] = val & 0x0f; + break; + + case 0x10: + dev->regs[dev->index] = val & 0x3d; + break; + + case 0x11: + dev->regs[dev->index] = val & 0x8d; + break; + + case 0x12: + case 0x13: + dev->regs[dev->index] = val & 0x8d; + break; + + case 0x14: + case 0x15: + case 0x16: + case 0x17: + dev->regs[dev->index] = val & 0x7f; + break; + + case 0x18: + dev->regs[dev->index] = val & 0xf3; cs4031_shadow_recalc(dev); break; - case 0x1c: - - if(dev->regs[0x1c] & 0x20) - port_92_add(dev->port_92); - else - port_92_remove(dev->port_92); - + case 0x19: + case 0x1a: + dev->regs[dev->index] = val & 0x7f; + cs4031_shadow_recalc(dev); + break; + + case 0x1b: + dev->regs[dev->index] = val; + break; + + case 0x1c: + dev->regs[dev->index] = val & 0xb3; + port_92_set_features(dev->port_92, val & 0x10, val & 0x20); break; - } - break; + break; } } - static uint8_t cs4031_read(uint16_t addr, void *priv) { - uint8_t ret = 0xff; - cs4031_t *dev = (cs4031_t *) priv; + cs4031_t *dev = (cs4031_t *)priv; - switch (addr) { - case 0x23: - ret = dev->regs[dev->index]; - break; - } - - return ret; + return (addr == 0x23) ? dev->regs[dev->index] : 0xff; } - static void cs4031_close(void *priv) { - cs4031_t *dev = (cs4031_t *) priv; + cs4031_t *dev = (cs4031_t *)priv; free(dev); } - static void * cs4031_init(const device_t *info) { - cs4031_t *dev = (cs4031_t *) malloc(sizeof(cs4031_t)); + cs4031_t *dev = (cs4031_t *)malloc(sizeof(cs4031_t)); memset(dev, 0, sizeof(cs4031_t)); dev->port_92 = device_add(&port_92_device); - io_sethandler(0x022, 0x0001, cs4031_read, NULL, NULL, cs4031_write, NULL, NULL, dev); - io_sethandler(0x023, 0x0001, cs4031_read, NULL, NULL, cs4031_write, NULL, NULL, dev); - dev->regs[0x05] = 0x05; - dev->regs[0x18] = 0x00; - dev->regs[0x19] = 0x00; - dev->regs[0x1a] = 0x00; dev->regs[0x1b] = 0x60; - cs4031_shadow_recalc(dev); - + + io_sethandler(0x0022, 0x0002, cs4031_read, NULL, NULL, cs4031_write, NULL, NULL, dev); + return dev; } - const device_t cs4031_device = { "Chips & Technogies CS4031", 0, 0, - cs4031_init, cs4031_close, NULL, - { NULL }, NULL, NULL, - NULL -}; + cs4031_init, + cs4031_close, + NULL, + {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/opti283.c b/src/chipset/opti283.c index dc1d74599..be2343bff 100644 --- a/src/chipset/opti283.c +++ b/src/chipset/opti283.c @@ -12,7 +12,7 @@ * * Authors: Tiseno100 * - * Copyright 2020 Tiseno100 + * Copyright 2021 Tiseno100 * */ @@ -28,144 +28,125 @@ #include <86box/timer.h> #include <86box/io.h> #include <86box/device.h> -#include <86box/keyboard.h> #include <86box/mem.h> -#include <86box/fdd.h> -#include <86box/fdc.h> -#include <86box/port_92.h> #include <86box/chipset.h> -#define disabled_shadow (MEM_READ_EXTANY | MEM_WRITE_EXTANY) +#ifdef ENABLE_OPTI283_LOG +int opti283_do_log = ENABLE_OPTI283_LOG; +static void +opti283_log(const char *fmt, ...) +{ + va_list ap; + if (opti283_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define opti283_log(fmt, ...) +#endif typedef struct { - uint8_t index, - regs[256]; + uint8_t index, + regs[256]; } opti283_t; static void opti283_shadow_recalc(opti283_t *dev) { -uint32_t base, i; -uint32_t shflagsc, shflagsd, shflagse, shflagsf; + mem_set_mem_state_both(0xf0000, 0x10000, (dev->regs[0x11] & 0x80) ? (MEM_READ_EXTANY | MEM_WRITE_INTERNAL) : (MEM_READ_INTERNAL | ((dev->regs[0x14] & 0x80) ? MEM_WRITE_INTERNAL : MEM_WRITE_DISABLED))); -shadowbios = !(dev->regs[0x11] & 0x80); -shadowbios_write = (dev->regs[0x11] & 0x80); + for (uint32_t i = 0; i < 4; i++) + { + if (dev->regs[0x11] & 0x40) + mem_set_mem_state_both(0xe0000 + (i << 14), 0x4000, (dev->regs[0x12] & (1 << (4 + i))) ? (MEM_READ_INTERNAL | ((dev->regs[0x11] & 4) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + mem_set_mem_state_both(0xe0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); -if(dev->regs[0x11] & 0x10){ - shflagsc = MEM_READ_INTERNAL; - shflagsc |= (dev->regs[0x11] & 0x08) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; -} else shflagsc = disabled_shadow; - -if(dev->regs[0x11] & 0x20){ - shflagsd = MEM_READ_INTERNAL; - shflagsd |= (dev->regs[0x11] & 0x08) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; -} else shflagsd = disabled_shadow; - -if(dev->regs[0x11] & 0x40){ - shflagse = MEM_READ_INTERNAL; - shflagse |= (dev->regs[0x11] & 0x08) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; -} else shflagse = disabled_shadow; - -if(!(dev->regs[0x11] & 0x80)){ - shflagsf = MEM_READ_INTERNAL | MEM_WRITE_DISABLED; -} else shflagsf = MEM_READ_EXTANY | MEM_WRITE_INTERNAL; - -mem_set_mem_state_both(0xf0000, 0x10000, shflagsf); - -for(i = 4; i < 8; i++){ -base = 0xc0000 + ((i-4) << 14); -mem_set_mem_state_both(base, 0x4000, (dev->regs[0x13] & (1 << i)) ? shflagsc : disabled_shadow); -} - -for(i = 0; i < 4; i++){ -base = 0xd0000 + (i << 14); -mem_set_mem_state_both(base, 0x4000, (dev->regs[0x12] & (1 << i)) ? shflagsd : disabled_shadow); -} - -for(i = 4; i < 8; i++){ -base = 0xe0000 + ((i-4) << 14); -mem_set_mem_state_both(base, 0x4000, (dev->regs[0x12] & (1 << i)) ? shflagse : disabled_shadow); -} + if (dev->regs[0x11] & 0x20) + mem_set_mem_state_both(0xd0000 + (i << 14), 0x4000, (dev->regs[0x12] & (1 << i)) ? (MEM_READ_INTERNAL | ((dev->regs[0x11] & 2) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + else + mem_set_mem_state_both(0xd0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + if (dev->regs[0x11] & 0x10) + mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, (dev->regs[0x13] & (1 << (4 + i))) ? (MEM_READ_INTERNAL | ((dev->regs[0x11] & 1) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + else + mem_set_mem_state_both(0xc0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + } } static void opti283_write(uint16_t addr, uint8_t val, void *priv) { - opti283_t *dev = (opti283_t *) priv; + opti283_t *dev = (opti283_t *)priv; - switch (addr) { - case 0x22: - dev->index = val; - break; - case 0x24: - /* pclog("OPTi 283: dev->regs[%02x] = %02x\n", dev->index, val); */ - dev->regs[dev->index] = val; + switch (addr) + { + case 0x22: + dev->index = val; + break; + case 0x24: + opti283_log("OPTi 283: dev->regs[%02x] = %02x\n", dev->index, val); - switch(dev->index){ - case 0x10: - cpu_update_waitstates(); + switch (dev->index) + { + case 0x10: + dev->regs[dev->index] = val; break; - case 0x11: - case 0x12: - case 0x13: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + dev->regs[dev->index] = val; opti283_shadow_recalc(dev); break; } - break; + break; } } - static uint8_t opti283_read(uint16_t addr, void *priv) { - uint8_t ret = 0xff; - opti283_t *dev = (opti283_t *) priv; - - switch (addr) { - case 0x24: - ret = dev->regs[dev->index]; - break; - } - - return ret; + opti283_t *dev = (opti283_t *)priv; + return (addr == 0x24) ? dev->regs[dev->index] : 0xff; } - static void opti283_close(void *priv) { - opti283_t *dev = (opti283_t *) priv; + opti283_t *dev = (opti283_t *)priv; free(dev); } - static void * opti283_init(const device_t *info) { - opti283_t *dev = (opti283_t *) malloc(sizeof(opti283_t)); + opti283_t *dev = (opti283_t *)malloc(sizeof(opti283_t)); memset(dev, 0, sizeof(opti283_t)); - io_sethandler(0x022, 0x0001, opti283_read, NULL, NULL, opti283_write, NULL, NULL, dev); - io_sethandler(0x024, 0x0001, opti283_read, NULL, NULL, opti283_write, NULL, NULL, dev); + io_sethandler(0x0022, 0x0001, opti283_read, NULL, NULL, opti283_write, NULL, NULL, dev); + io_sethandler(0x0024, 0x0001, opti283_read, NULL, NULL, opti283_write, NULL, NULL, dev); dev->regs[0x10] = 0x3f; dev->regs[0x11] = 0xf0; opti283_shadow_recalc(dev); - + return dev; } - const device_t opti283_device = { "OPTi 82C283", 0, 0, - opti283_init, opti283_close, NULL, - { NULL }, NULL, NULL, - NULL -}; + opti283_init, + opti283_close, + NULL, + {NULL}, + NULL, + NULL, + NULL}; diff --git a/src/chipset/sis_5571.c b/src/chipset/sis_5571.c index 69cc13ace..2594dbb3c 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(); @@ -210,9 +210,9 @@ memory_pci_bridge_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf[addr] = val & 0xec; break; - case 0x51: /* Cache */ + case 0x51: /* L2 Cache */ dev->pci_conf[addr] = val; - cpu_cache_ext_enabled = (val & 0x40); + cpu_cache_ext_enabled = !!(val & 0x40); cpu_update_waitstates(); break; @@ -263,7 +263,7 @@ memory_pci_bridge_write(int func, int addr, uint8_t val, void *priv) case 0x83: dev->pci_conf[addr] = val; - port_92_set_features(dev->port_92, (val & 0x40), (val & 0x80)); + port_92_set_features(dev->port_92, !!(val & 0x40), !!(val & 0x80)); break; case 0x87: @@ -272,7 +272,9 @@ memory_pci_bridge_write(int func, int addr, uint8_t val, void *priv) case 0x93: /* APM SMI */ dev->pci_conf[addr] = val; - apm_set_do_smi(dev->apm, ((dev->pci_conf[0x9b] & 0x01) && (val & 0x02))); + apm_set_do_smi(dev->apm, !!((dev->pci_conf[0x9b] & 0x01) && (val & 0x02))); + if (val & 0x02) + dev->pci_conf[0x9d] |= 1; break; case 0x94: @@ -326,7 +328,7 @@ pci_isa_bridge_write(int func, int addr, uint8_t val, void *priv) case 0x43: case 0x44: dev->pci_conf_sb[0][addr] = val & 0x8f; - pci_set_irq_routing(PCI_INTA + (val & 0x07), !(val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED); + pci_set_irq_routing((addr & 0x07), !(val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED); break; case 0x45: @@ -415,7 +417,7 @@ pci_isa_bridge_write(int func, int addr, uint8_t val, void *priv) } sis_5571_log("IDE Controller: dev->pci_conf[%02x] = %02x\n", addr, val); - if ((addr == 0x09) || ((addr >= 0x10) && (addr <= 0x23)) || (addr == 0x4a)) + if (((addr >= 0x09) && (addr <= 0x23)) || (addr == 0x4a)) sis_5571_ide_handler(dev); break; @@ -593,7 +595,6 @@ sis_5571_init(const device_t *info) pci_add_card(PCI_ADD_NORTHBRIDGE, memory_pci_bridge_read, memory_pci_bridge_write, dev); dev->sb_pci_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, pci_isa_bridge_read, pci_isa_bridge_write, dev); - pci_enable_mirq(1); /* APM */ dev->apm = device_add(&apm_pci_device); @@ -601,16 +602,19 @@ sis_5571_init(const device_t *info) /* DMA */ dma_alias_set(); + /* MIRQ */ + pci_enable_mirq(0); + + /* Port 92 & SMRAM */ + dev->port_92 = device_add(&port_92_pci_device); + dev->smram = smram_add(); + /* SFF IDE */ dev->bm[0] = device_add_inst(&sff8038i_device, 1); dev->bm[1] = device_add_inst(&sff8038i_device, 2); dev->program_status_pri = 0; dev->program_status_sec = 0; - /* Port 92 & SMRAM */ - dev->port_92 = device_add(&port_92_pci_device); - dev->smram = smram_add(); - /* USB */ dev->usb = device_add(&usb_device); diff --git a/src/chipset/umc491.c b/src/chipset/umc491.c deleted file mode 100644 index 26aeec985..000000000 --- a/src/chipset/umc491.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * 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 UMC 491/493 chipset. - * - * - * - * Authors: Tiseno100 - * - * Copyright 2020 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_UMC491_LOG -int ali1429_do_log = ENABLE_UMC491_LOG; -static void -umc491_log(const char *fmt, ...) -{ - va_list ap; - - if (umc491_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -#define umc491_log(fmt, ...) -#endif - -typedef struct -{ - uint8_t index, - regs[256]; -} umc491_t; - -static void umc491_shadow_recalc(umc491_t *dev) -{ - -shadowbios = (dev->regs[0xcc] & 0x40); -shadowbios_write = (dev->regs[0xcc] & 0x80); - -mem_set_mem_state_both(0xc0000, 0x4000, ((dev->regs[0xcd] & 0x40) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0xcd] & 0x80) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); -mem_set_mem_state_both(0xc4000, 0x4000, ((dev->regs[0xcd] & 0x10) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0xcd] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); -mem_set_mem_state_both(0xc8000, 0x4000, ((dev->regs[0xcd] & 0x04) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0xcd] & 0x08) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); -mem_set_mem_state_both(0xcc000, 0x4000, ((dev->regs[0xcd] & 0x01) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0xcd] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); - -mem_set_mem_state_both(0xd0000, 0x4000, ((dev->regs[0xce] & 0x40) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0xce] & 0x80) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); -mem_set_mem_state_both(0xd4000, 0x4000, ((dev->regs[0xce] & 0x10) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0xce] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); -mem_set_mem_state_both(0xd8000, 0x4000, ((dev->regs[0xce] & 0x04) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0xce] & 0x08) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); -mem_set_mem_state_both(0xdc000, 0x4000, ((dev->regs[0xce] & 0x01) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0xce] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); - -/* -Our machine has the E segment into parts although most AMI machines treat it as one. -Probably a flaw by the BIOS as only one register gets enabled for it anyways. -*/ -mem_set_mem_state_both(0xe0000, 0x10000, ((dev->regs[0xcc] & 0x10) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0xcc] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); - -mem_set_mem_state_both(0xf0000, 0x10000, ((dev->regs[0xcc] & 0x40) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0xcc] & 0x80) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); - -flushmmucache(); -} - -static void -umc491_write(uint16_t addr, uint8_t val, void *priv) -{ - umc491_t *dev = (umc491_t *) priv; - - switch (addr) { - case 0x8022: - dev->index = val; - break; - case 0x8024: - umc491_log("UMC 491: dev->regs[%02x] = %02x\n", dev->index, val); - dev->regs[dev->index] = val; - - switch(dev->index) - { - case 0xcc: - case 0xcd: - case 0xce: - umc491_shadow_recalc(dev); - break; - - case 0xd0: - cpu_update_waitstates(); - break; - - case 0xd1: - cpu_cache_ext_enabled = (val & 0x01); - break; - } - break; - } -} - - -static uint8_t -umc491_read(uint16_t addr, void *priv) -{ - uint8_t ret = 0xff; - umc491_t *dev = (umc491_t *) priv; - - switch (addr) { - case 0x8024: - ret = dev->regs[dev->index]; - break; - } - - return ret; -} - - -static void -umc491_close(void *priv) -{ - umc491_t *dev = (umc491_t *) priv; - - free(dev); -} - - -static void * -umc491_init(const device_t *info) -{ - umc491_t *dev = (umc491_t *) malloc(sizeof(umc491_t)); - memset(dev, 0, sizeof(umc491_t)); - - device_add(&port_92_device); - -/* - -UMC 491/493 Ports - -8022h Index Port -8024h Data Port - -*/ - io_sethandler(0x8022, 0x0001, umc491_read, NULL, NULL, umc491_write, NULL, NULL, dev); - io_sethandler(0x8024, 0x0001, umc491_read, NULL, NULL, umc491_write, NULL, NULL, dev); - - dev->regs[0xcc] = 0x00; - dev->regs[0xcd] = 0x00; - dev->regs[0xce] = 0x00; - umc491_shadow_recalc(dev); - - return dev; -} - - -const device_t umc491_device = { - "UMC 491/493", - 0, - 0, - umc491_init, umc491_close, NULL, - { NULL }, NULL, NULL, - NULL -}; 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/chipset/wd76c10.c b/src/chipset/wd76c10.c index 6233177ba..3be448267 100644 --- a/src/chipset/wd76c10.c +++ b/src/chipset/wd76c10.c @@ -6,234 +6,424 @@ * * This file is part of the 86Box distribution. * - * Implementation of the WD76C10 System Controller chip. + * Implementation of the Western Digital WD76C10 chipset. * + * Note: This chipset has no datasheet, everything were done via + * reverse engineering the BIOS of various machines using it. * + * Authors: Tiseno100 * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, + * Copyright 2021 Tiseno100 * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. */ + +#include #include #include #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> -#include <86box/device.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/io.h> -#include <86box/keyboard.h> +#include <86box/device.h> +#include <86box/dma.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/hdd.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/lpt.h> #include <86box/mem.h> #include <86box/port_92.h> #include <86box/serial.h> -#include <86box/fdd.h> -#include <86box/fdc.h> -#include <86box/video.h> #include <86box/chipset.h> +/* Lock/Unlock Procedures */ +#define LOCK dev->lock +#define UNLOCKED !dev->lock -typedef struct { - int type; +#define ENABLE_WD76C10_LOG 1 - uint16_t reg_0092; - uint16_t reg_2072; - uint16_t reg_2872; - uint16_t reg_5872; +#ifdef ENABLE_WD76C10_LOG +int wd76c10_do_log = ENABLE_WD76C10_LOG; +static void +wd76c10_log(const char *fmt, ...) +{ + va_list ap; - uint16_t reg_f872; + if (wd76c10_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define wd76c10_log(fmt, ...) +#endif - serial_t *uart[2]; +typedef struct +{ + uint16_t lock_reg, oscillator_40mhz, cache_flush, ems_page_reg, + ems_page_reg_pointer, port_shadow, pmc_interrupt, + high_mem_protect_boundry, delay_line, diagnostic, + nmi_status, pmc_input, pmc_timer, + pmc_output, ems_control_low_address_boundry, shadow_ram, + split_addr, bank32staddr, bank10staddr, + non_page_mode_dram_timing, mem_control, + refresh_control, disk_chip_select, prog_chip_sel_addr, + bus_timing_power_down_ctl, clk_control; - fdc_t *fdc; + int lock; - mem_mapping_t extram_mapping; - uint8_t extram[65536]; + fdc_t *fdc_controller; + mem_mapping_t *mem_mapping; + serial_t *uart[2]; } wd76c10_t; +static void wd76c10_refresh_control(wd76c10_t *dev) +{ + serial_remove(dev->uart[1]); + /* Serial B */ + switch ((dev->refresh_control >> 1) & 7) + { + case 1: + serial_setup(dev->uart[1], 0x3f8, 3); + break; + case 2: + serial_setup(dev->uart[1], 0x2f8, 3); + break; + case 3: + serial_setup(dev->uart[1], 0x3e8, 3); + break; + case 4: + serial_setup(dev->uart[1], 0x2e8, 3); + break; + } + + serial_remove(dev->uart[0]); + /* Serial A */ + switch ((dev->refresh_control >> 5) & 7) + { + case 1: + serial_setup(dev->uart[0], 0x3f8, 4); + break; + case 2: + serial_setup(dev->uart[0], 0x2f8, 4); + break; + case 3: + serial_setup(dev->uart[0], 0x3e8, 4); + break; + case 4: + serial_setup(dev->uart[0], 0x2e8, 4); + break; + } + + lpt1_remove(); + /* LPT */ + switch ((dev->refresh_control >> 9) & 3) + { + case 1: + lpt1_init(0x3bc); + lpt1_irq(7); + break; + case 2: + lpt1_init(0x378); + lpt1_irq(7); + break; + case 3: + lpt1_init(0x278); + lpt1_irq(7); + break; + } +} + +static void wd76c10_split_addr(wd76c10_t *dev) +{ + switch ((dev->split_addr >> 8) & 3) + { + case 1: + if (((dev->shadow_ram >> 8) & 3) == 2) + mem_remap_top(256); + break; + case 2: + if (((dev->shadow_ram >> 8) & 3) == 1) + mem_remap_top(320); + break; + case 3: + if (((dev->shadow_ram >> 8) & 3) == 3) + mem_remap_top(384); + break; + } +} + +static void wd76c10_disk_chip_select(wd76c10_t *dev) +{ + ide_pri_disable(); + if (!(dev->disk_chip_select & 1)) + { + ide_set_base(0, !(dev->disk_chip_select & 0x0010) ? 0x1f0 : 0x170); + ide_set_side(0, !(dev->disk_chip_select & 0x0010) ? 0x3f6 : 0x376); + } + ide_pri_enable(); + + fdc_remove(dev->fdc_controller); + if (!(dev->disk_chip_select & 2)) + fdc_set_base(dev->fdc_controller, !(dev->disk_chip_select & 0x0010) ? 0x3f0 : 0x370); +} + +static void wd76c10_shadow_recalc(wd76c10_t *dev) +{ + switch ((dev->shadow_ram >> 14) & 3) + { + case 0: + mem_set_mem_state_both(0x20000, 0x80000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + case 1: + mem_set_mem_state_both(0x80000, 0x20000, MEM_READ_DISABLED | MEM_WRITE_DISABLED); + break; + case 2: + mem_set_mem_state_both(0x40000, 0x60000, MEM_READ_DISABLED | MEM_WRITE_DISABLED); + break; + case 3: + mem_set_mem_state_both(0x20000, 0x80000, MEM_READ_DISABLED | MEM_WRITE_DISABLED); + break; + } + + switch ((dev->shadow_ram >> 8) & 3) + { + case 0: + mem_set_mem_state_both(0xe0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + mem_set_mem_state_both(0xc0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + break; + case 1: + mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_INTERNAL | (!!(dev->shadow_ram & 0x1000) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)); + break; + case 2: + mem_set_mem_state_both(0xe0000, 0x20000, MEM_READ_INTERNAL | (!!(dev->shadow_ram & 0x1000) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)); + break; + case 3: + mem_set_mem_state_both(0x20000, 0x80000, MEM_READ_DISABLED | (!!(dev->shadow_ram & 0x1000) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)); + break; + } +} + +static void +wd76c10_write(uint16_t addr, uint16_t val, void *priv) +{ + wd76c10_t *dev = (wd76c10_t *)priv; + + if (UNLOCKED) + { + switch (addr) + { + case 0x1072: + dev->clk_control = val; + break; + + case 0x1872: + dev->bus_timing_power_down_ctl = val; + break; + + case 0x2072: + dev->refresh_control = val; + wd76c10_refresh_control(dev); + break; + + case 0x2872: + dev->disk_chip_select = val; + wd76c10_disk_chip_select(dev); + break; + + case 0x3072: + dev->prog_chip_sel_addr = val; + break; + + case 0x3872: + dev->non_page_mode_dram_timing = val; + break; + + case 0x4072: + dev->mem_control = val; + break; + + case 0x4872: + dev->bank10staddr = val; + break; + + case 0x5072: + dev->bank32staddr = val; + break; + + case 0x5872: + dev->split_addr = val; + wd76c10_split_addr(dev); + break; + + case 0x6072: + dev->shadow_ram = val & 0xffbf; + wd76c10_shadow_recalc(dev); + break; + + case 0x6872: + dev->ems_control_low_address_boundry = val & 0xecff; + break; + + case 0x7072: + dev->pmc_output = (val >> 8) & 0x00ff; + break; + + case 0x7872: + dev->pmc_output = val & 0xff00; + break; + + case 0x8072: + dev->pmc_timer = val; + break; + + case 0x8872: + dev->pmc_input = val; + break; + + case 0x9072: + dev->nmi_status = val & 0x00fc; + break; + + case 0x9872: + dev->diagnostic = val & 0xfdff; + break; + + case 0xa072: + dev->delay_line = val; + break; + + case 0xc872: + dev->pmc_interrupt = val & 0xfcfc; + break; + + case 0xf072: + dev->oscillator_40mhz = 0; + break; + + case 0xf472: + dev->oscillator_40mhz = 1; + break; + + case 0xf872: + dev->cache_flush = val; + flushmmucache(); + break; + } + wd76c10_log("WD76C10: dev->regs[%04x] = %04x\n", addr, val); + } + + switch (addr) + { + case 0xe072: + dev->ems_page_reg_pointer = val & 0x003f; + break; + + case 0xe872: + dev->ems_page_reg = val & 0x8fff; + break; + + case 0xf073: + dev->lock_reg = val & 0x00ff; + LOCK = !(val && 0x00da); + break; + } +} static uint16_t -wd76c10_read(uint16_t port, void *priv) +wd76c10_read(uint16_t addr, void *priv) { wd76c10_t *dev = (wd76c10_t *)priv; - int16_t ret = 0xffff; + wd76c10_log("WD76C10: R dev->regs[%04x]\n", addr); + switch (addr) + { + case 0x1072: + return dev->clk_control; - switch (port) { - case 0x2072: - ret = dev->reg_2072; - break; + case 0x1872: + return dev->bus_timing_power_down_ctl; - case 0x2872: - ret = dev->reg_2872; - break; + case 0x2072: + return dev->refresh_control; - case 0x5872: - ret = dev->reg_5872; - break; + case 0x2872: + return dev->disk_chip_select; - case 0xf872: - ret = dev->reg_f872; - break; - } + case 0x3072: + return dev->prog_chip_sel_addr; - return(ret); -} + case 0x3872: + return dev->non_page_mode_dram_timing; + case 0x4072: + return dev->mem_control; -static void -wd76c10_write(uint16_t port, uint16_t val, void *priv) -{ - wd76c10_t *dev = (wd76c10_t *)priv; + case 0x4872: + return dev->bank10staddr; - switch (port) { - case 0x2072: - dev->reg_2072 = val; + case 0x5072: + return dev->bank32staddr; - serial_remove(dev->uart[0]); - if (!(val & 0x10)) - { - switch ((val >> 5) & 7) - { - case 1: serial_setup(dev->uart[0], 0x3f8, 4); break; - case 2: serial_setup(dev->uart[0], 0x2f8, 4); break; - case 3: serial_setup(dev->uart[0], 0x3e8, 4); break; - case 4: serial_setup(dev->uart[0], 0x2e8, 4); break; - default: break; - } - } - serial_remove(dev->uart[1]); - if (!(val & 0x01)) - { - switch ((val >> 1) & 7) - { - case 1: serial_setup(dev->uart[1], 0x3f8, 3); break; - case 2: serial_setup(dev->uart[1], 0x2f8, 3); break; - case 3: serial_setup(dev->uart[1], 0x3e8, 3); break; - case 4: serial_setup(dev->uart[1], 0x2e8, 3); break; - default: break; - } - } - break; + case 0x5872: + return dev->split_addr; - case 0x2872: - dev->reg_2872 = val; + case 0x6072: + return dev->shadow_ram; - fdc_remove(dev->fdc); - if (! (val & 1)) - fdc_set_base(dev->fdc, 0x03f0); - break; + case 0x6872: + return dev->ems_control_low_address_boundry; - case 0x5872: - dev->reg_5872 = val; - break; + case 0x7072: + return (dev->pmc_output << 8) & 0xff00; - case 0xf872: - dev->reg_f872 = val; - switch (val & 3) { - case 0: - mem_set_mem_state(0xd0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - break; - case 1: - mem_set_mem_state(0xd0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); - break; - case 2: - mem_set_mem_state(0xd0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); - break; - case 3: - mem_set_mem_state(0xd0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - } - flushmmucache_nopc(); - if (val & 4) - mem_mapping_enable(&dev->extram_mapping); - else - mem_mapping_disable(&dev->extram_mapping); - flushmmucache_nopc(); - break; + case 0x7872: + return (dev->pmc_output) & 0xff00; + + case 0x8072: + return dev->pmc_timer; + + case 0x8872: + return dev->pmc_input; + + case 0x9072: + return dev->nmi_status; + + case 0x9872: + return dev->diagnostic; + + case 0xa072: + return dev->delay_line; + + case 0xb872: + return (inb(0x040b) << 8) | inb(0x04d6); + + case 0xc872: + return dev->pmc_interrupt; + + case 0xd072: + return dev->port_shadow; + + case 0xe072: + return dev->ems_page_reg_pointer; + + case 0xe872: + return dev->ems_page_reg; + + case 0xfc72: + return 0x0ff0; + + default: + return 0xffff; } } - -static uint8_t -wd76c10_readb(uint16_t port, void *priv) -{ - if (port & 1) - return(wd76c10_read(port & ~1, priv) >> 8); - - return(wd76c10_read(port, priv) & 0xff); -} - - -static void -wd76c10_writeb(uint16_t port, uint8_t val, void *priv) -{ - uint16_t temp = wd76c10_read(port, priv); - - if (port & 1) - wd76c10_write(port & ~1, (temp & 0x00ff) | (val << 8), priv); - else - wd76c10_write(port , (temp & 0xff00) | val, priv); -} - - -uint8_t -wd76c10_read_extram(uint32_t addr, void *priv) -{ - wd76c10_t *dev = (wd76c10_t *)priv; - - return dev->extram[addr & 0xffff]; -} - - -uint16_t -wd76c10_read_extramw(uint32_t addr, void *priv) -{ - wd76c10_t *dev = (wd76c10_t *)priv; - - return *(uint16_t *)&dev->extram[addr & 0xffff]; -} - - -uint32_t -wd76c10_read_extraml(uint32_t addr, void *priv) -{ - wd76c10_t *dev = (wd76c10_t *)priv; - - return *(uint32_t *)&dev->extram[addr & 0xffff]; -} - - -void -wd76c10_write_extram(uint32_t addr, uint8_t val, void *priv) -{ - wd76c10_t *dev = (wd76c10_t *)priv; - - dev->extram[addr & 0xffff] = val; -} - - -void -wd76c10_write_extramw(uint32_t addr, uint16_t val, void *priv) -{ - wd76c10_t *dev = (wd76c10_t *)priv; - - *(uint16_t *)&dev->extram[addr & 0xffff] = val; -} - - -void -wd76c10_write_extraml(uint32_t addr, uint32_t val, void *priv) -{ - wd76c10_t *dev = (wd76c10_t *)priv; - - *(uint32_t *)&dev->extram[addr & 0xffff] = val; -} - - static void wd76c10_close(void *priv) { @@ -242,51 +432,119 @@ wd76c10_close(void *priv) free(dev); } - static void * wd76c10_init(const device_t *info) { - wd76c10_t *dev; + wd76c10_t *dev = (wd76c10_t *)malloc(sizeof(wd76c10_t)); + memset(dev, 0, sizeof(wd76c10_t)); - dev = (wd76c10_t *) malloc(sizeof(wd76c10_t)); - memset(dev, 0x00, sizeof(wd76c10_t)); - dev->type = info->local; + device_add(&port_92_inv_device); + dev->uart[0] = device_add_inst(&ns16450_device, 1); + dev->uart[1] = device_add_inst(&ns16450_device, 2); + dev->fdc_controller = device_add(&fdc_at_device); + device_add(&ide_isa_device); - dev->fdc = (fdc_t *)device_add(&fdc_at_device); + /* Lock Configuration */ + LOCK = 1; - dev->uart[0] = device_add_inst(&i8250_device, 1); - dev->uart[1] = device_add_inst(&i8250_device, 2); + /* Clock Control */ + io_sethandler(0x1072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); - device_add(&port_92_word_device); + /* Bus Timing & Power Down Control */ + io_sethandler(0x1872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); - io_sethandler(0x2072, 2, - wd76c10_readb,wd76c10_read,NULL, - wd76c10_writeb,wd76c10_write,NULL, dev); - io_sethandler(0x2872, 2, - wd76c10_readb,wd76c10_read,NULL, - wd76c10_writeb,wd76c10_write,NULL, dev); - io_sethandler(0x5872, 2, - wd76c10_readb,wd76c10_read,NULL, - wd76c10_writeb,wd76c10_write,NULL, dev); - io_sethandler(0xf872, 2, - wd76c10_readb,wd76c10_read,NULL, - wd76c10_writeb,wd76c10_write,NULL, dev); + /* Refresh Control(Serial & Parallel) */ + io_sethandler(0x2072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); - mem_mapping_add(&dev->extram_mapping, 0xd0000, 0x10000, - wd76c10_read_extram,wd76c10_read_extramw,wd76c10_read_extraml, - wd76c10_write_extram,wd76c10_write_extramw,wd76c10_write_extraml, - dev->extram, MEM_MAPPING_EXTERNAL, dev); - mem_mapping_disable(&dev->extram_mapping); + /* Disk Chip Select */ + io_sethandler(0x2872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); - return(dev); + /* Programmable Chip Select Address(Needs more further examination!) */ + io_sethandler(0x3072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + + /* Bank 1 & 0 Start Address */ + io_sethandler(0x4872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + + /* Bank 3 & 2 Start Address */ + io_sethandler(0x5072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + + /* Split Address */ + io_sethandler(0x5872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + + /* EMS Control & EMS Low level boundry */ + io_sethandler(0x6072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + + /* EMS Control & EMS Low level boundry */ + io_sethandler(0x6872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + + /* PMC Output */ + io_sethandler(0x7072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + + /* PMC Output */ + io_sethandler(0x7872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + + /* PMC Status */ + io_sethandler(0x8072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + + /* PMC Status */ + io_sethandler(0x8872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + + /* NMI Status (Needs further checkup) */ + io_sethandler(0x9072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + + /* Diagnostics */ + io_sethandler(0x9872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + + /* Delay Line */ + io_sethandler(0xa072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + + /* DMA Mode Shadow(Needs Involvement on the DMA code) */ + io_sethandler(0xb872, 1, NULL, wd76c10_read, NULL, NULL, NULL, NULL, dev); + + /* High Memory Protection Boundry */ + io_sethandler(0xc072, 1, NULL, wd76c10_read, NULL, NULL, NULL, NULL, dev); + + /* PMC Interrupt Enable */ + io_sethandler(0xc872, 1, NULL, wd76c10_read, NULL, NULL, NULL, NULL, dev); + + /* Port Shadow (Needs further lookup) */ + io_sethandler(0xd072, 1, NULL, wd76c10_read, NULL, NULL, NULL, NULL, dev); + + /* EMS Page Register Pointer */ + io_sethandler(0xe072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + + /* EMS Page Register */ + io_sethandler(0xe872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + + /* Lock/Unlock Configuration */ + io_sethandler(0xf073, 1, NULL, NULL, NULL, NULL, wd76c10_write, NULL, dev); + + /* 40Mhz Oscillator Enable Disable */ + io_sethandler(0xf072, 1, NULL, NULL, NULL, NULL, wd76c10_write, NULL, dev); + io_sethandler(0xf472, 1, NULL, NULL, NULL, NULL, wd76c10_write, NULL, dev); + + /* Lock Status */ + io_sethandler(0xfc72, 1, NULL, wd76c10_read, NULL, NULL, NULL, NULL, dev); + + /* Cache Flush */ + io_sethandler(0xf872, 1, NULL, wd76c10_read, NULL, NULL, NULL, NULL, dev); + + dma_ext_mode_init(); + + wd76c10_shadow_recalc(dev); + wd76c10_refresh_control(dev); + wd76c10_disk_chip_select(dev); + return dev; } - const device_t wd76c10_device = { - "WD 76C10", + "Western Digital WD76C10", 0, 0, - wd76c10_init, wd76c10_close, NULL, - { NULL }, NULL, NULL, - NULL -}; + wd76c10_init, + wd76c10_close, + NULL, + {NULL}, + NULL, + NULL, + NULL}; 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 c6d228ddc..9767e7681 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 31baeee20..7107829dc 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -261,6 +261,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_olim290_init(const machine_t *); extern int machine_at_ncrpc8_init(const machine_t *); @@ -274,6 +275,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); @@ -284,7 +286,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 *); @@ -335,6 +336,7 @@ extern int machine_at_486vipio2_init(const machine_t *); #endif #if defined(DEV_BRANCH) && defined(USE_M1489) extern int machine_at_abpb4_init(const machine_t *); +extern int machine_at_win486pci_init(const machine_t *); #endif #if defined(DEV_BRANCH) && defined(USE_STPC) extern int machine_at_itoxstar_init(const machine_t *); @@ -440,6 +442,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 81dc8976e..6775b0bea 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -48,6 +48,8 @@ extern const device_t pc87311_ide_device; extern const device_t pc87332_device; extern const device_t pc87332_ps1_device; extern const device_t pc97307_device; +extern const device_t prime3b_device; +extern const device_t prime3b_ide_device; extern const device_t prime3c_device; extern const device_t prime3c_ide_device; extern const device_t ps1_m2133_sio; @@ -55,6 +57,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 ef2de1226..9aac75d6a 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -474,7 +474,7 @@ machine_at_wd76c10_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_ide_init(model); + machine_at_common_init(model); device_add(&keyboard_ps2_quadtel_device); @@ -596,6 +596,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 f9ea44d54..d3a037b7e 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -154,6 +154,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 }, @@ -175,7 +176,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 }, @@ -224,6 +224,7 @@ const machine_t machines[] = { /* 486 machines which utilize the PCI bus */ #if defined(DEV_BRANCH) && defined(USE_M1489) { "[ALi M1489] ABIT AB-PB4", "abpb4", MACHINE_TYPE_486, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_abpb4_init, NULL }, + { "[ALi M1489] AMI WinBIOS 486 PCI", "win486pci", MACHINE_TYPE_486, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_win486pci_init, NULL }, #endif { "[i420EX] ASUS PVI-486AP4", "486ap4", MACHINE_TYPE_486, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_IDE_DUAL, 1024, 131072, 1024, 127, machine_at_486ap4_init, NULL }, { "[i420ZX] ASUS PCI/I-486SP3G", "486sp3g", MACHINE_TYPE_486, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 131072, 1024, 127, machine_at_486sp3g_init, NULL }, @@ -340,6 +341,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 8dcb8416e..4cd1dcef1 100644 --- a/src/sio/CMakeLists.txt +++ b/src/sio/CMakeLists.txt @@ -16,7 +16,8 @@ add_library(sio OBJECT sio_acc3221.c sio_f82c710.c sio_82091aa.c sio_fdc37c661.c sio_fdc37c66x.c sio_fdc37c669.c sio_fdc37c93x.c sio_fdc37m60x.c sio_pc87306.c sio_pc87307.c sio_pc87309.c sio_pc87311.c sio_pc87332.c - sio_prime3c.c sio_w83787f.c sio_w83877f.c sio_w83977f.c sio_um8669f.c + sio_prime3b.c sio_prime3c.c + sio_w83787f.c sio_w83877f.c sio_w83977f.c sio_um8669f.c sio_vt82c686.c) if(SIO_DETECT) diff --git a/src/sio/sio_prime3b.c b/src/sio/sio_prime3b.c new file mode 100644 index 000000000..3277aa306 --- /dev/null +++ b/src/sio/sio_prime3b.c @@ -0,0 +1,292 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the Goldstar Prime3B Super I/O + * + * Authors: Tiseno100 + * Copyright 2021 Tiseno100 + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/timer.h> +#include <86box/device.h> +#include <86box/lpt.h> +#include <86box/serial.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/sio.h> + +#define FSR dev->regs[0xa0] +#define ASR dev->regs[0xa1] +#define PDR dev->regs[0xa2] +#define HAS_IDE_FUNCTIONALITY dev->ide_function + +#ifdef ENABLE_PRIME3B_LOG +int prime3b_do_log = ENABLE_PRIME3B_LOG; +static void +prime3b_log(const char *fmt, ...) +{ + va_list ap; + + if (prime3b_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define prime3b_log(fmt, ...) +#endif + +typedef struct +{ + uint8_t index, regs[256], cfg_lock, ide_function; + uint16_t com3_addr, com4_addr; + + fdc_t *fdc_controller; + serial_t *uart[2]; + +} prime3b_t; + +void prime3b_fdc_handler(prime3b_t *dev); +void prime3b_uart_handler(uint8_t num, prime3b_t *dev); +void prime3b_lpt_handler(prime3b_t *dev); +void prime3b_ide_handler(prime3b_t *dev); +void prime3b_enable(prime3b_t *dev); +void prime3b_powerdown(prime3b_t *dev); + +static void +prime3b_write(uint16_t addr, uint8_t val, void *priv) +{ + prime3b_t *dev = (prime3b_t *)priv; + + if (addr == 0x398) + { + dev->index = val; + + /* Enter/Escape Configuration Mode */ + if (val == 0x33) + dev->cfg_lock = 0; + else if (val == 0xcc) + dev->cfg_lock = 1; + } + else if ((addr == 0x399) && !dev->cfg_lock) + { + switch (dev->index) + { + case 0xa0: /* Function Selection Register (FSR) */ + FSR = val; + prime3b_enable(dev); + break; + case 0xa1: /* Address Selection Register (ASR) */ + ASR = val; + prime3b_enable(dev); + break; + case 0xa2: /* Power Down Register (PDR) */ + dev->regs[0xa2] = val; + break; + case 0xa3: /* Test Mode Register (TMR) */ + dev->regs[0xa3] = val; + break; + case 0xa4: /* Miscellaneous Function Register */ + dev->regs[0xa4] = val; + switch ((dev->regs[0xa4] >> 6) & 3) + { + case 0: + dev->com3_addr = 0x3e8; + dev->com4_addr = 0x2e8; + break; + case 1: + dev->com3_addr = 0x338; + dev->com4_addr = 0x238; + break; + case 2: + dev->com3_addr = 0x2e8; + dev->com4_addr = 0x2e0; + break; + case 3: + dev->com3_addr = 0x220; + dev->com4_addr = 0x228; + break; + } + break; + case 0xa5: /* ECP Register */ + dev->regs[0xa5] = val; + break; + } + } +} + +static uint8_t +prime3b_read(uint16_t addr, void *priv) +{ + prime3b_t *dev = (prime3b_t *)priv; + + return dev->regs[dev->index]; +} + +void prime3b_fdc_handler(prime3b_t *dev) +{ + uint16_t fdc_base = !(ASR & 0x40) ? 0x3f0 : 0x370; + fdc_remove(dev->fdc_controller); + fdc_set_base(dev->fdc_controller, fdc_base); + prime3b_log("Prime3B-FDC: Enabled with base %03x\n", fdc_base); +} + +void prime3b_uart_handler(uint8_t num, prime3b_t *dev) +{ + uint16_t uart_base; + if ((ASR >> (3 + 2 * num)) & 1) + uart_base = !((ASR >> (2 + 2 * num)) & 1) ? dev->com3_addr : dev->com4_addr; + else + uart_base = !((ASR >> (2 + 2 * num)) & 1) ? 0x3f8 : 0x2f8; + + serial_remove(dev->uart[num]); + serial_setup(dev->uart[num], uart_base, 4 - num); + prime3b_log("Prime3B-UART%d: Enabled with base %03x\n", num, uart_base); +} + +void prime3b_lpt_handler(prime3b_t *dev) +{ + uint16_t lpt_base = (ASR & 2) ? 0x3bc : (!(ASR & 1) ? 0x378 : 0x278); + lpt1_remove(); + lpt1_init(lpt_base); + lpt1_irq(7); + prime3b_log("Prime3B-LPT: Enabled with base %03x\n", lpt_base); +} + +void prime3b_ide_handler(prime3b_t *dev) +{ + ide_pri_disable(); + uint16_t ide_base = !(ASR & 0x80) ? 0x1f0 : 0x170; + ide_set_base(0, ide_base); + ide_set_side(0, ide_base + 0x206); + prime3b_log("Prime3B-IDE: Enabled with base %03x and side %03x\n", ide_base, ide_base + 0x206); +} + +void prime3b_enable(prime3b_t *dev) +{ + /* + Simulate a device enable/disable scenario + + Register A0: Function Selection Register (FSR) + Bit 7: Gameport + Bit 6: 4 FDD Enable + Bit 5: IDE + Bit 4: FDC + Bit 3: UART 2 + Bit 2: UART 1 + Bit 1/0: PIO (0/0 Bidirectional , 0/1 ECP, 1/0 EPP, 1/1 Disabled) + + Note: 86Box LPT is simplistic and can't do ECP or EPP. + */ + + !(FSR & 3) ? prime3b_lpt_handler(dev) : lpt1_remove(); + (FSR & 4) ? prime3b_uart_handler(0, dev) : serial_remove(dev->uart[0]); + (FSR & 8) ? prime3b_uart_handler(1, dev) : serial_remove(dev->uart[1]); + (FSR & 0x10) ? prime3b_fdc_handler(dev) : fdc_remove(dev->fdc_controller); + if (HAS_IDE_FUNCTIONALITY) + (FSR & 0x20) ? prime3b_ide_handler(dev) : ide_pri_disable(); +} + +void prime3b_powerdown(prime3b_t *dev) +{ + /* Note: It can be done more efficiently for sure */ + uint8_t old_base = PDR; + + if (PDR & 1) + PDR |= 0x1e; + + if (PDR & 0x40) + io_removehandler(0x0398, 0x0002, prime3b_read, NULL, NULL, prime3b_write, NULL, NULL, dev); + + if (PDR & 2) + fdc_remove(dev->fdc_controller); + + if (PDR & 4) + serial_remove(dev->uart[0]); + + if (PDR & 8) + serial_remove(dev->uart[1]); + + if (PDR & 0x10) + lpt1_remove(); + + if (PDR & 1) + PDR = old_base; +} + +static void +prime3b_close(void *priv) +{ + prime3b_t *dev = (prime3b_t *)priv; + + free(dev); +} + +static void * +prime3b_init(const device_t *info) +{ + prime3b_t *dev = (prime3b_t *)malloc(sizeof(prime3b_t)); + memset(dev, 0, sizeof(prime3b_t)); + + /* Avoid conflicting with machines that make no use of the Prime3B Internal IDE */ + HAS_IDE_FUNCTIONALITY = info->local; + + dev->regs[0xa0] = 3; + + dev->fdc_controller = device_add(&fdc_at_device); + dev->uart[0] = device_add_inst(&ns16550_device, 1); + dev->uart[1] = device_add_inst(&ns16550_device, 2); + if (HAS_IDE_FUNCTIONALITY) + device_add(&ide_isa_device); + + dev->com3_addr = 0x3e8; + dev->com4_addr = 0x2e8; + fdc_reset(dev->fdc_controller); + + prime3b_enable(dev); + + io_sethandler(0x0398, 0x0002, prime3b_read, NULL, NULL, prime3b_write, NULL, NULL, dev); + + return dev; +} + +const device_t prime3b_device = { + "Goldstar Prime3B", + 0, + 0, + prime3b_init, + prime3b_close, + NULL, + {NULL}, + NULL, + NULL, + NULL}; + +const device_t prime3b_ide_device = { + "Goldstar Prime3B with IDE functionality", + 0, + 1, + prime3b_init, + prime3b_close, + NULL, + {NULL}, + NULL, + NULL, + NULL}; diff --git a/src/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_ht216.c b/src/video/vid_ht216.c index 083de1f26..7d5ec5452 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -48,9 +48,8 @@ typedef struct ht216_t int clk_sel; uint8_t read_bank_reg[2], write_bank_reg[2]; - uint32_t read_bank[2], write_bank[2]; - uint8_t misc, pad; - uint16_t id; + uint16_t id, misc; + uint32_t read_banks[2], write_banks[2]; uint8_t bg_latch[8]; @@ -60,7 +59,7 @@ typedef struct ht216_t #define HT_MISC_PAGE_SEL (1 << 5) -/*Shifts CPU VRAM read address by 3 bits, for use with fat pixel colour expansion*/ +/*Shifts CPU VRAM read address by 3 bits, for use with fat pixel color expansion*/ #define HT_REG_C8_MOVSB (1 << 0) #define HT_REG_C8_E256 (1 << 4) #define HT_REG_C8_XLAM (1 << 6) @@ -132,11 +131,12 @@ ht216_out(uint16_t addr, uint8_t val, void *p) switch (addr) { case 0x3c2: ht216->clk_sel = (ht216->clk_sel & ~3) | ((val & 0x0c) >> 2); - ht216->misc = val; - ht216->read_bank_reg[0] = (ht216->read_bank_reg[0] & ~0x20) | ((val & HT_MISC_PAGE_SEL) ? 0x20 : 0); - ht216->write_bank_reg[0] = (ht216->write_bank_reg[0] & ~0x20) | ((val & HT_MISC_PAGE_SEL) ? 0x20 : 0); + /*Bit 17 of the display memory address, only active on odd/even modes, has no effect on graphics modes.*/ + ht216->misc = val; + ht216_log("HT216 misc val = %02x\n", val); ht216_remap(ht216); - svga_recalctimings(&ht216->svga); + svga->fullchange = changeframecount; + svga_recalctimings(svga); break; case 0x3c5: @@ -182,49 +182,58 @@ ht216_out(uint16_t addr, uint8_t val, void *p) case 0xa4: ht216->clk_sel = (val >> 2) & 0xf; svga->miscout = (svga->miscout & ~0xc) | ((ht216->clk_sel & 3) << 2); + svga->fullchange = changeframecount; + svga_recalctimings(svga); break; case 0xa5: - svga->hwcursor.ena = val & 0x80; + svga->hwcursor.ena = !!(val & 0x80); break; case 0xc8: - if ((old ^ val) & 0x10) { + if ((old ^ val) & HT_REG_C8_E256) { svga->fullchange = changeframecount; svga_recalctimings(svga); } break; + /*Bank registers*/ case 0xe8: - ht216->read_bank_reg[0] = val; - ht216->write_bank_reg[0] = val; - break; case 0xe9: - ht216->read_bank_reg[1] = val; - ht216->write_bank_reg[1] = val; + ht216_remap(ht216); break; + case 0xf6: svga->vram_display_mask = (val & 0x40) ? ht216->vram_mask : 0x3ffff; - ht216->read_bank_reg[0] = (ht216->read_bank_reg[0] & ~0xc0) | ((val & 0xc) << 4); - ht216->write_bank_reg[0] = (ht216->write_bank_reg[0] & ~0xc0) | ((val & 0x3) << 6); + /*Bits 18 and 19 of the display memory address*/ + ht216_log("HT216 reg 0xf6 write = %02x, vram mask = %08x\n", val & 0x40, svga->vram_display_mask); + ht216_remap(ht216); + svga->fullchange = changeframecount; + svga_recalctimings(svga); break; + case 0xf9: - ht216->read_bank_reg[0] = (ht216->read_bank_reg[0] & ~0x10) | ((val & 1) ? 0x10 : 0); - ht216->write_bank_reg[0] = (ht216->write_bank_reg[0] & ~0x10) | ((val & 1) ? 0x10 : 0); + /*Bit 16 of the display memory address, only active when in chain4 mode and 256 color mode.*/ + ht216_log("HT216 reg 0xf9 write = %02x\n", val & HT_REG_F9_XPSEL); + ht216_remap(ht216); break; + + case 0xfc: + svga->fullchange = changeframecount; + svga_recalctimings(svga); + break; + case 0xff: svga->hwcursor.addr = ((ht216->ht_regs[0x94] << 6) | (3 << 14) | ((val & 0x60) << 11)) << 2; break; } switch (svga->seqaddr & 0xff) { - case 0xa4: case 0xf6: case 0xfc: - svga->fullchange = changeframecount; - svga_recalctimings(&ht216->svga); - break; - } - switch (svga->seqaddr & 0xff) { - case 0xc8: case 0xc9: case 0xcf: - case 0xe0: case 0xe8: case 0xe9: - case 0xf6: case 0xf9: + case 0xc8: case 0xc9: case 0xcf: case 0xe0: + if ((svga->seqaddr & 0xff) == 0xc8) { + svga->adv_flags = 0; + if (val & HT_REG_C8_MOVSB) { + svga->adv_flags = FLAG_ADDR_BY8; + } + } ht216_remap(ht216); break; } @@ -233,12 +242,12 @@ ht216_out(uint16_t addr, uint8_t val, void *p) break; case 0x3cf: - if (svga->gdcaddr == 6) { - if (val & 8) - svga->banked_mask = 0x7fff; - else - svga->banked_mask = 0xffff; - } + if (svga->gdcaddr == 6) { + if (val & 8) + svga->banked_mask = 0x7fff; + else + svga->banked_mask = 0xffff; + } break; case 0x3D4: @@ -263,11 +272,11 @@ ht216_out(uint16_t addr, uint8_t val, void *p) case 0x46e8: io_removehandler(0x03c0, 0x0020, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); - mem_mapping_disable(&ht216->svga.mapping); + mem_mapping_disable(&svga->mapping); mem_mapping_disable(&ht216->linear_mapping); if (val & 8) { io_sethandler(0x03c0, 0x0020, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); - mem_mapping_enable(&ht216->svga.mapping); + mem_mapping_enable(&svga->mapping); ht216_remap(ht216); } break; @@ -335,42 +344,141 @@ void ht216_remap(ht216_t *ht216) { svga_t *svga = &ht216->svga; + uint8_t bank = ht216->ht_regs[0xf6] & 0x0f; mem_mapping_disable(&ht216->linear_mapping); if (ht216->ht_regs[0xc8] & HT_REG_C8_XLAM) { - uint32_t linear_base = ((ht216->ht_regs[0xc9] & 0xf) << 20) | (ht216->ht_regs[0xcf] << 24); - - mem_mapping_set_addr(&ht216->linear_mapping, linear_base, 0x100000); - /*Linear mapping enabled*/ + uint32_t linear_base = ((ht216->ht_regs[0xc9] & 0xf) << 20) | (ht216->ht_regs[0xcf] << 24); + mem_mapping_disable(&svga->mapping); + mem_mapping_set_addr(&ht216->linear_mapping, linear_base, 0x100000); } else { - uint8_t read_bank_reg[2] = {ht216->read_bank_reg[0], ht216->read_bank_reg[1]}; - uint8_t write_bank_reg[2] = {ht216->write_bank_reg[0], ht216->write_bank_reg[1]}; - - if (!svga->chain4 || !(ht216->ht_regs[0xfc] & HT_REG_FC_ECOLRE)) { - read_bank_reg[0] &= ~0x30; - read_bank_reg[1] &= ~0x30; - write_bank_reg[0] &= ~0x30; - write_bank_reg[1] &= ~0x30; - } - - ht216->read_bank[0] = read_bank_reg[0] << 12; - ht216->write_bank[0] = write_bank_reg[0] << 12; if (ht216->ht_regs[0xe0] & HT_REG_E0_SBAE) { - /*Split bank*/ - ht216->read_bank[1] = read_bank_reg[1] << 12; - ht216->write_bank[1] = write_bank_reg[1] << 12; + /*Split bank: two banks used*/ + /*Windows 3.1 always touches the misc register when split banks are enabled.*/ + if (!(ht216->misc & HT_MISC_PAGE_SEL)) { + ht216->read_banks[0] = ht216->ht_regs[0xe8] << 12; + ht216->write_banks[0] = ht216->ht_regs[0xe8] << 12; + ht216->read_banks[1] = ht216->ht_regs[0xe9] << 12; + ht216->write_banks[1] = ht216->ht_regs[0xe9] << 12; + + if (!svga->chain4) { + if (ht216->ht_regs[0xe8] == 0x40) { + ht216->read_banks[0] = 0x10000; + ht216->write_banks[0] = 0x10000; + } + if (ht216->ht_regs[0xe9] == 0x40) { + ht216->read_banks[1] = 0x10000; + ht216->write_banks[1] = 0x10000; + } + + if (ht216->ht_regs[0xe8] == 0x48) { + ht216->read_banks[0] = 0x18000; + ht216->write_banks[0] = 0x18000; + } + if (ht216->ht_regs[0xe9] == 0x48) { + ht216->read_banks[1] = 0x18000; + ht216->write_banks[1] = 0x18000; + } + + if (ht216->ht_regs[0xe8] == 0x80) { + ht216->read_banks[0] = 0x20000; + ht216->write_banks[0] = 0x20000; + } + if (ht216->ht_regs[0xe9] == 0x80) { + ht216->read_banks[1] = 0x20000; + ht216->write_banks[1] = 0x20000; + } + + if (ht216->ht_regs[0xe8] == 0x88) { + ht216->read_banks[0] = 0x28000; + ht216->write_banks[0] = 0x28000; + } + if (ht216->ht_regs[0xe9] == 0x88) { + ht216->read_banks[1] = 0x28000; + ht216->write_banks[1] = 0x28000; + } + + if (ht216->ht_regs[0xe9] == 0xc0) { + ht216->read_banks[1] = 0x30000; + ht216->write_banks[1] = 0x30000; + } + } + } } else { - ht216->read_bank[1] = ht216->read_bank[0] + (svga->chain4 ? 0x8000 : 0x20000); - ht216->write_bank[1] = ht216->write_bank[0] + (svga->chain4 ? 0x8000 : 0x20000); - } + /*One bank used*/ + /*Bit 17 of the video memory address*/ + if (ht216->misc & HT_MISC_PAGE_SEL) { + ht216->read_bank_reg[0] |= 0x20; + ht216->write_bank_reg[0] |= 0x20; + } else { + ht216->read_bank_reg[0] &= ~0x20; + ht216->write_bank_reg[0] &= ~0x20; + } - if (!svga->chain4) { - ht216->read_bank[0] >>= 2; - ht216->read_bank[1] >>= 2; - ht216->write_bank[0] >>= 2; - ht216->write_bank[1] >>= 2; + if (!(ht216->ht_regs[0xfc] & HT_REG_FC_ECOLRE)) { + if (bank & 2) { + bank &= ~2; + bank |= 1; + } + if (bank & 8) { + bank &= ~8; + bank |= 4; + } + } + + /*Bit 18 and 19 of the video memory address*/ + if (bank & 1) + ht216->write_bank_reg[0] |= 0x40; + else + ht216->write_bank_reg[0] &= ~0x40; + + if (bank & 2) + ht216->write_bank_reg[0] |= 0x80; + else + ht216->write_bank_reg[0] &= ~0x80; + + if (bank & 4) + ht216->read_bank_reg[0] |= 0x40; + else + ht216->read_bank_reg[0] &= ~0x40; + + if (bank & 8) + ht216->read_bank_reg[0] |= 0x80; + else + ht216->read_bank_reg[0] &= ~0x80; + + if (svga->chain4) { + /*Bit 16 of the video memory address*/ + if (ht216->ht_regs[0xf9] & HT_REG_F9_XPSEL) { + ht216->read_bank_reg[0] |= 0x10; + ht216->write_bank_reg[0] |= 0x10; + } else { + ht216->read_bank_reg[0] &= ~0x10; + ht216->write_bank_reg[0] &= ~0x10; + } + } + + if (!svga->chain4) { + /*In linear modes, bits 4 and 5 are ignored*/ + ht216->read_bank_reg[0] &= ~0x30; + ht216->write_bank_reg[0] &= ~0x30; + } + + ht216->read_banks[0] = ht216->read_bank_reg[0] << 12; + ht216->write_banks[0] = ht216->write_bank_reg[0] << 12; + ht216->read_banks[1] = ht216->read_banks[0] + (svga->chain4 ? 0x8000 : 0x20000); + ht216->write_banks[1] = ht216->write_banks[0] + (svga->chain4 ? 0x8000 : 0x20000); + + if (!svga->chain4) { + ht216->read_banks[0] >>= 2; + ht216->read_banks[1] >>= 2; + ht216->write_banks[0] >>= 2; + ht216->write_banks[1] >>= 2; + } } + + ht216_log("ReadBank0 = %06x, ReadBank1 = %06x, Misc Page Sel = %02x, F6 reg = %02x, F9 Sel = %02x, FC = %02x, E0 split = %02x, E8 = %02x, E9 = %02x, chain4 = %02x, banked mask = %04x\n", ht216->read_banks[0], ht216->read_banks[1], ht216->misc & HT_MISC_PAGE_SEL, bank, ht216->ht_regs[0xf9] & HT_REG_F9_XPSEL, ht216->ht_regs[0xfc] & (HT_REG_FC_ECOLRE | 2), ht216->ht_regs[0xe0] & HT_REG_E0_SBAE, ht216->ht_regs[0xe8], ht216->ht_regs[0xe9], svga->chain4, svga->banked_mask); } } @@ -386,11 +494,14 @@ ht216_recalctimings(svga_t *svga) case 10: svga->clock = (cpuclock * (double)(1ull << 32)) / 80000000.0; break; } svga->lowres = !(ht216->ht_regs[0xc8] & HT_REG_C8_E256); + svga->ma_latch |= ((ht216->ht_regs[0xf6] & 0x30) << 12); + svga->interlace = ht216->ht_regs[0xe0] & 1; - if ((svga->bpp == 8) && !svga->lowres) + if ((svga->bpp == 8) && !svga->lowres) { svga->render = svga_render_8bpp_highres; + } } @@ -399,7 +510,7 @@ ht216_hwcursor_draw(svga_t *svga, int displine) { int x; uint32_t dat[2]; - int offset = svga->hwcursor_latch.x + svga->x_add; + int offset = svga->hwcursor_latch.x + svga->hwcursor_latch.xoff; if (svga->interlace && svga->hwcursor_oddeven) svga->hwcursor_latch.addr += 4; @@ -415,9 +526,9 @@ ht216_hwcursor_draw(svga_t *svga, int displine) for (x = 0; x < 32; x++) { if (!(dat[0] & 0x80000000)) - ((uint32_t *)buffer32->line[displine])[offset + x] = 0; + ((uint32_t *)buffer32->line[displine])[svga->x_add + offset + x] = 0; if (dat[1] & 0x80000000) - ((uint32_t *)buffer32->line[displine])[offset + x] ^= 0xffffff; + ((uint32_t *)buffer32->line[displine])[svga->x_add + offset + x] ^= 0xffffff; dat[0] <<= 1; dat[1] <<= 1; @@ -461,15 +572,23 @@ static void ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_unexpanded) { svga_t *svga = &ht216->svga; - uint8_t vala, valb, valc, vald, wm = svga->writemask; - int writemask2 = svga->writemask; + int writemask2 = svga->writemask, reset_wm = 0; + latch_t vall; + uint8_t wm = svga->writemask; + uint8_t count, i; uint8_t fg_data[4] = {0, 0, 0, 0}; + if (svga->adv_flags & FLAG_ADDR_BY8) + writemask2 = svga->seqregs[2]; + if (!(svga->gdcreg[6] & 1)) svga->fullchange = 2; - if (svga->chain4 || svga->fb_only) { - writemask2=1<<(addr&3); - addr&=~3; + + if ((svga->adv_flags & FLAG_ADDR_BY8) && (svga->writemode < 4)) + addr <<= 3; + else if ((svga->chain4 || svga->fb_only) && (svga->writemode < 4)) { + writemask2 = 1 << (addr & 3); + addr &= ~3; } else if (svga->chain2_write) { writemask2 &= ~0xa; if (addr & 1) @@ -477,185 +596,166 @@ ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_u addr &= ~1; addr <<= 2; } else - addr<<=2; + addr <<= 2; + if (addr >= svga->vram_max) return; - svga->changedvram[addr >> 12]=changeframecount; + addr &= svga->decode_mask; + + if (addr >= svga->vram_max) + return; + + addr &= svga->vram_mask; + + svga->changedvram[addr >> 12] = changeframecount; + + count = 4; switch (ht216->ht_regs[0xfe] & HT_REG_FE_FBMC) { case 0x00: - fg_data[0] = fg_data[1] = fg_data[2] = fg_data[3] = cpu_dat; + for (i = 0; i < count; i++) + fg_data[i] = cpu_dat; break; case 0x04: if (ht216->ht_regs[0xfe] & HT_REG_FE_FBRC) { if (addr & 4) { - fg_data[0] = (cpu_dat_unexpanded & (1 << (((addr + 4) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[1] = (cpu_dat_unexpanded & (1 << (((addr + 5) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[2] = (cpu_dat_unexpanded & (1 << (((addr + 6) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[3] = (cpu_dat_unexpanded & (1 << (((addr + 7) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; + for (i = 0; i < count; i++) { + fg_data[i] = (cpu_dat_unexpanded & (1 << (((addr + i + 4) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; + } } else { - fg_data[0] = (cpu_dat_unexpanded & (1 << (((addr + 0) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[1] = (cpu_dat_unexpanded & (1 << (((addr + 1) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[2] = (cpu_dat_unexpanded & (1 << (((addr + 2) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[3] = (cpu_dat_unexpanded & (1 << (((addr + 3) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; + for (i = 0; i < count; i++) { + fg_data[i] = (cpu_dat_unexpanded & (1 << (((addr + i) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; + } } } else { if (addr & 4) { - fg_data[0] = (ht216->ht_regs[0xf5] & (1 << (((addr + 4) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[1] = (ht216->ht_regs[0xf5] & (1 << (((addr + 5) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[2] = (ht216->ht_regs[0xf5] & (1 << (((addr + 6) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[3] = (ht216->ht_regs[0xf5] & (1 << (((addr + 7) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; + for (i = 0; i < count; i++) + fg_data[i] = (ht216->ht_regs[0xf5] & (1 << (((addr + i + 4) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; } else { - fg_data[0] = (ht216->ht_regs[0xf5] & (1 << (((addr + 0) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[1] = (ht216->ht_regs[0xf5] & (1 << (((addr + 1) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[2] = (ht216->ht_regs[0xf5] & (1 << (((addr + 2) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; - fg_data[3] = (ht216->ht_regs[0xf5] & (1 << (((addr + 3) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; + for (i = 0; i < count; i++) + fg_data[i] = (ht216->ht_regs[0xf5] & (1 << (((addr + i) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb]; } } break; case 0x08: - fg_data[0] = ht216->ht_regs[0xec]; - fg_data[1] = ht216->ht_regs[0xed]; - fg_data[2] = ht216->ht_regs[0xee]; - fg_data[3] = ht216->ht_regs[0xef]; - break; case 0x0c: - fg_data[0] = ht216->ht_regs[0xec]; - fg_data[1] = ht216->ht_regs[0xed]; - fg_data[2] = ht216->ht_regs[0xee]; - fg_data[3] = ht216->ht_regs[0xef]; + for (i = 0; i < count; i++) + fg_data[i] = ht216->ht_regs[0xec + i]; break; } switch (svga->writemode) { - case 1: - if (writemask2 & 1) svga->vram[addr] = svga->latch.b[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = svga->latch.b[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = svga->latch.b[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = svga->latch.b[3]; - break; case 0: - if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && - (!svga->gdcreg[1] || svga->set_reset_disabled)) { - if (writemask2 & 1) svga->vram[addr] = fg_data[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = fg_data[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = fg_data[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = fg_data[3]; + if ((svga->gdcreg[8] == 0xff) && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { + for (i = 0; i < count; i++) { + if (svga->adv_flags & FLAG_ADDR_BY8) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = fg_data[i]; + } else { + if (writemask2 & (1 << i)) { + svga->vram[addr | i] = fg_data[i]; + } + } + } + return; } else { - if (svga->gdcreg[1] & 1) vala = (svga->gdcreg[0] & 1) ? 0xff : 0; - else vala = fg_data[0]; - if (svga->gdcreg[1] & 2) valb = (svga->gdcreg[0] & 2) ? 0xff : 0; - else valb = fg_data[1]; - if (svga->gdcreg[1] & 4) valc = (svga->gdcreg[0] & 4) ? 0xff : 0; - else valc = fg_data[2]; - if (svga->gdcreg[1] & 8) vald = (svga->gdcreg[0] & 8) ? 0xff : 0; - else vald = fg_data[3]; - - switch (svga->gdcreg[3] & 0x18) { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->latch.b[0] & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->latch.b[1] & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->latch.b[2] & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->latch.b[3] & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->latch.b[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->latch.b[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->latch.b[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->latch.b[3]; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->latch.b[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->latch.b[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->latch.b[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->latch.b[3]; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->latch.b[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->latch.b[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->latch.b[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->latch.b[3]; - break; + for (i = 0; i < count; i++) { + if (svga->gdcreg[1] & (1 << i)) + vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; + else + vall.b[i] = fg_data[i]; } } break; - case 2: - if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { - if (writemask2 & 1) svga->vram[addr] = (((cpu_dat & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->latch.b[0] & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (((cpu_dat & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->latch.b[1] & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (((cpu_dat & 4) ? 0xff : 0) & svga->gdcreg[8]) | (svga->latch.b[2] & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (((cpu_dat & 8) ? 0xff : 0) & svga->gdcreg[8]) | (svga->latch.b[3] & ~svga->gdcreg[8]); - } else { - vala = ((cpu_dat & 1) ? 0xff : 0); - valb = ((cpu_dat & 2) ? 0xff : 0); - valc = ((cpu_dat & 4) ? 0xff : 0); - vald = ((cpu_dat & 8) ? 0xff : 0); - switch (svga->gdcreg[3] & 0x18) { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->latch.b[0] & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->latch.b[1] & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->latch.b[2] & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->latch.b[3] & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->latch.b[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->latch.b[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->latch.b[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->latch.b[3]; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->latch.b[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->latch.b[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->latch.b[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->latch.b[3]; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->latch.b[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->latch.b[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->latch.b[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->latch.b[3]; - break; + case 1: + for (i = 0; i < count; i++) { + if (svga->adv_flags & FLAG_ADDR_BY8) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = svga->latch.b[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = svga->latch.b[i]; } } + return; + case 2: + for (i = 0; i < count; i++) + vall.b[i] = !!(cpu_dat & (1 << i)) * 0xff; + + if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { + for (i = 0; i < count; i++) { + if (svga->adv_flags & FLAG_ADDR_BY8) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } + } + return; + } break; case 3: - wm = svga->gdcreg[8]; - svga->gdcreg[8] &= cpu_dat; + wm = svga->gdcreg[8]; + svga->gdcreg[8] &= cpu_dat; - vala = (svga->gdcreg[0] & 1) ? 0xff : 0; - valb = (svga->gdcreg[0] & 2) ? 0xff : 0; - valc = (svga->gdcreg[0] & 4) ? 0xff : 0; - vald = (svga->gdcreg[0] & 8) ? 0xff : 0; - switch (svga->gdcreg[3] & 0x18) { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->latch.b[0] & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->latch.b[1] & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->latch.b[2] & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->latch.b[3] & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->latch.b[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->latch.b[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->latch.b[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->latch.b[3]; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->latch.b[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->latch.b[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->latch.b[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->latch.b[3]; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->latch.b[0]; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->latch.b[1]; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->latch.b[2]; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->latch.b[3]; - break; + for (i = 0; i < count; i++) + vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; + + reset_wm = 1; + break; + } + + switch (svga->gdcreg[3] & 0x18) { + case 0x00: /* Set */ + for (i = 0; i < count; i++) { + if (svga->adv_flags & FLAG_ADDR_BY8) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } + } + break; + case 0x08: /* AND */ + for (i = 0; i < count; i++) { + if (svga->adv_flags & FLAG_ADDR_BY8) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] | ~svga->gdcreg[8]) & svga->latch.b[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] | ~svga->gdcreg[8]) & svga->latch.b[i]; + } + } + break; + case 0x10: /* OR */ + for (i = 0; i < count; i++) { + if (svga->adv_flags & FLAG_ADDR_BY8) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | svga->latch.b[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | svga->latch.b[i]; + } + } + break; + case 0x18: /* XOR */ + for (i = 0; i < count; i++) { + if (svga->adv_flags & FLAG_ADDR_BY8) { + if (writemask2 & (0x80 >> i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) ^ svga->latch.b[i]; + } else { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) ^ svga->latch.b[i]; + } } - svga->gdcreg[8] = wm; break; } + + if (reset_wm) + svga->gdcreg[8] = wm; } @@ -709,6 +809,68 @@ ht216_dm_extalu_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t bi svga->changedvram[addr >> 12] = changeframecount; } +static void +ht216_dm_masked_write(ht216_t *ht216, uint32_t addr, uint8_t val, uint8_t bit_mask) +{ + svga_t *svga = &ht216->svga; + int writemask2 = svga->writemask; + uint8_t count, i; + + if (svga->adv_flags & FLAG_ADDR_BY8) + writemask2 = svga->seqregs[2]; + + if (!(svga->gdcreg[6] & 1)) + svga->fullchange = 2; + + if ((svga->adv_flags & FLAG_ADDR_BY8) && (svga->writemode < 4)) + addr <<= 3; + else if ((svga->chain4 || svga->fb_only) && (svga->writemode < 4)) { + writemask2 = 1 << (addr & 3); + addr &= ~3; + } else if (svga->chain2_write) { + writemask2 &= ~0xa; + if (addr & 1) + writemask2 <<= 1; + addr &= ~1; + addr <<= 2; + } else + addr <<= 2; + + if (addr >= svga->vram_max) + return; + + addr &= svga->decode_mask; + + if (addr >= svga->vram_max) + return; + + addr &= svga->vram_mask; + + svga->changedvram[addr >> 12] = changeframecount; + + count = 4; + + if (bit_mask == 0xff) { + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) { + svga->vram[addr | i] = val; + } + } + } else { + if (writemask2 == 0x0f) { + for (i = 0; i < count; i++) { + svga->vram[addr | i] = (svga->latch.b[i] & bit_mask) | (svga->vram[addr | i] & ~bit_mask); + } + } else { + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) { + svga->vram[addr | i] = (val & bit_mask) | (svga->vram[addr | i] & ~bit_mask); + } + } + } + } +} + static void ht216_write_common(ht216_t *ht216, uint32_t addr, uint8_t val) @@ -727,6 +889,7 @@ ht216_write_common(ht216_t *ht216, uint32_t addr, uint8_t val) 1x = (3C4:F5) */ svga_t *svga = &ht216->svga; + int i; uint8_t bit_mask = 0, rop_select = 0; cycles -= video_timing_write_b; @@ -735,7 +898,7 @@ ht216_write_common(ht216_t *ht216, uint32_t addr, uint8_t val) addr &= 0xfffff; - val = svga_rotate[svga->gdcreg[3] & 7][val]; + val = ((val >> (svga->gdcreg[3] & 7)) | (val << (8 - (svga->gdcreg[3] & 7)))); if (ht216->ht_regs[0xcd] & HT_REG_CD_EXALU) { /*Extended ALU*/ @@ -761,32 +924,27 @@ ht216_write_common(ht216_t *ht216, uint32_t addr, uint8_t val) bit_mask = ht216->ht_regs[0xf5]; break; } - + if (ht216->ht_regs[0xcd] & HT_REG_CD_FP8PCEXP) { /*1->8 bit expansion*/ addr = (addr << 3) & 0xfffff; - ht216_dm_extalu_write(ht216, addr, (val & 0x80) ? 0xff : 0, (bit_mask & 0x80) ? 0xff : 0, val, (rop_select & 0x80) ? 0xff : 0); - ht216_dm_extalu_write(ht216, addr + 1, (val & 0x40) ? 0xff : 0, (bit_mask & 0x40) ? 0xff : 0, val, (rop_select & 0x40) ? 0xff : 0); - ht216_dm_extalu_write(ht216, addr + 2, (val & 0x20) ? 0xff : 0, (bit_mask & 0x20) ? 0xff : 0, val, (rop_select & 0x20) ? 0xff : 0); - ht216_dm_extalu_write(ht216, addr + 3, (val & 0x10) ? 0xff : 0, (bit_mask & 0x10) ? 0xff : 0, val, (rop_select & 0x10) ? 0xff : 0); - ht216_dm_extalu_write(ht216, addr + 4, (val & 0x08) ? 0xff : 0, (bit_mask & 0x08) ? 0xff : 0, val, (rop_select & 0x08) ? 0xff : 0); - ht216_dm_extalu_write(ht216, addr + 5, (val & 0x04) ? 0xff : 0, (bit_mask & 0x04) ? 0xff : 0, val, (rop_select & 0x04) ? 0xff : 0); - ht216_dm_extalu_write(ht216, addr + 6, (val & 0x02) ? 0xff : 0, (bit_mask & 0x02) ? 0xff : 0, val, (rop_select & 0x02) ? 0xff : 0); - ht216_dm_extalu_write(ht216, addr + 7, (val & 0x01) ? 0xff : 0, (bit_mask & 0x01) ? 0xff : 0, val, (rop_select & 0x01) ? 0xff : 0); - } else + for (i = 0; i < 8; i++) + ht216_dm_extalu_write(ht216, addr + i, (val & (0x80 >> i)) ? 0xff : 0, (bit_mask & (0x80 >> i)) ? 0xff : 0, val, (rop_select & (0x80 >> i)) ? 0xff : 0); + } else { ht216_dm_extalu_write(ht216, addr, val, bit_mask, val, rop_select); + } + } else if (ht216->ht_regs[0xf3]) { + if (ht216->ht_regs[0xf3] & 2) { + ht216_dm_masked_write(ht216, addr, val, val); + } else + ht216_dm_masked_write(ht216, addr, val, ht216->ht_regs[0xf4]); } else { if (ht216->ht_regs[0xcd] & HT_REG_CD_FP8PCEXP) { /*1->8 bit expansion*/ addr = (addr << 3) & 0xfffff; - ht216_dm_write(ht216, addr, (val & 0x80) ? 0xff : 0, val); - ht216_dm_write(ht216, addr + 1, (val & 0x40) ? 0xff : 0, val); - ht216_dm_write(ht216, addr + 2, (val & 0x20) ? 0xff : 0, val); - ht216_dm_write(ht216, addr + 3, (val & 0x10) ? 0xff : 0, val); - ht216_dm_write(ht216, addr + 4, (val & 0x08) ? 0xff : 0, val); - ht216_dm_write(ht216, addr + 5, (val & 0x04) ? 0xff : 0, val); - ht216_dm_write(ht216, addr + 6, (val & 0x02) ? 0xff : 0, val); - ht216_dm_write(ht216, addr + 7, (val & 0x01) ? 0xff : 0, val); - } else + for (i = 0; i < 8; i++) + ht216_dm_write(ht216, addr + i, (val & (0x80 >> i)) ? 0xff : 0, val); + } else { ht216_dm_write(ht216, addr, val, val); + } } } @@ -798,10 +956,10 @@ ht216_write(uint32_t addr, uint8_t val, void *p) svga_t *svga = &ht216->svga; addr &= svga->banked_mask; - addr = (addr & 0x7fff) + ht216->write_bank[(addr >> 15) & 1]; + addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1]; - if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe]) - svga_write_linear(addr, val, &ht216->svga); + if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3]) + svga_write_linear(addr, val, svga); else ht216_write_common(ht216, addr, val); } @@ -812,11 +970,12 @@ ht216_writew(uint32_t addr, uint16_t val, void *p) { ht216_t *ht216 = (ht216_t *)p; svga_t *svga = &ht216->svga; - + addr &= svga->banked_mask; - addr = (addr & 0x7fff) + ht216->write_bank[(addr >> 15) & 1]; - if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe]) - svga_writew_linear(addr, val, &ht216->svga); + addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1]; + + if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3]) + svga_writew_linear(addr, val, svga); else { ht216_write_common(ht216, addr, val); ht216_write_common(ht216, addr+1, val >> 8); @@ -831,9 +990,10 @@ ht216_writel(uint32_t addr, uint32_t val, void *p) svga_t *svga = &ht216->svga; addr &= svga->banked_mask; - addr = (addr & 0x7fff) + ht216->write_bank[(addr >> 15) & 1]; - if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe]) - svga_writel_linear(addr, val, &ht216->svga); + addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1]; + + if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe] && !ht216->ht_regs[0xf3]) + svga_writel_linear(addr, val, svga); else { ht216_write_common(ht216, addr, val); ht216_write_common(ht216, addr+1, val >> 8); @@ -853,7 +1013,7 @@ ht216_write_linear(uint32_t addr, uint8_t val, void *p) addr = (addr & 0xffff) | ((addr & 0xc0000) >> 2); if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe]) - svga_write_linear(addr, val, &ht216->svga); + svga_write_linear(addr, val, svga); else ht216_write_common(ht216, addr, val); } @@ -869,7 +1029,7 @@ ht216_writew_linear(uint32_t addr, uint16_t val, void *p) addr = (addr & 0xffff) | ((addr & 0xc0000) >> 2); if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe]) - svga_writew_linear(addr, val, &ht216->svga); + svga_writew_linear(addr, val, svga); else { ht216_write_common(ht216, addr, val); ht216_write_common(ht216, addr+1, val >> 8); @@ -887,7 +1047,7 @@ ht216_writel_linear(uint32_t addr, uint32_t val, void *p) addr = (addr & 0xffff) | ((addr & 0xc0000) >> 2); if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe]) - svga_writel_linear(addr, val, &ht216->svga); + svga_writel_linear(addr, val, svga); else { ht216_write_common(ht216, addr, val); ht216_write_common(ht216, addr+1, val >> 8); @@ -901,37 +1061,39 @@ static uint8_t ht216_read_common(ht216_t *ht216, uint32_t addr) { svga_t *svga = &ht216->svga; - uint8_t temp, temp2, temp3, temp4, or; + uint32_t latch_addr = 0; int readplane = svga->readplane; + uint8_t or, count, i; + uint8_t plane, pixel; + uint8_t temp, ret; int offset; - uint32_t latch_addr; - if (ht216->ht_regs[0xc8] & HT_REG_C8_MOVSB) - addr <<= 3; - - addr &= 0xfffff; + if (svga->adv_flags & FLAG_ADDR_BY8) { + readplane = svga->gdcreg[4] & 7; + } cycles -= video_timing_read_b; egareads++; + + addr &= 0xfffff; - if (svga->chain4 || svga->fb_only) { + count = 2; + + latch_addr = (addr << count) & svga->decode_mask; + count = (1 << count); + + if (svga->adv_flags & FLAG_ADDR_BY8) + addr <<= 3; + else if (svga->chain4 || svga->fb_only) { addr &= svga->decode_mask; if (addr >= svga->vram_max) return 0xff; - latch_addr = (addr & svga->vram_mask) & ~7; if (ht216->ht_regs[0xcd] & HT_REG_CD_ASTODE) latch_addr += (svga->gdcreg[3] & 7); - ht216->bg_latch[0] = svga->vram[latch_addr]; - ht216->bg_latch[1] = svga->vram[latch_addr + 1]; - ht216->bg_latch[2] = svga->vram[latch_addr + 2]; - ht216->bg_latch[3] = svga->vram[latch_addr + 3]; - ht216->bg_latch[4] = svga->vram[latch_addr + 4]; - ht216->bg_latch[5] = svga->vram[latch_addr + 5]; - ht216->bg_latch[6] = svga->vram[latch_addr + 6]; - ht216->bg_latch[7] = svga->vram[latch_addr + 7]; - + for (i = 0; i < 8; i++) + ht216->bg_latch[i] = svga->vram[latch_addr | i]; return svga->vram[addr & svga->vram_mask]; } else if (svga->chain2_read) { readplane = (readplane & 2) | (addr & 1); @@ -950,45 +1112,34 @@ ht216_read_common(ht216_t *ht216, uint32_t addr) latch_addr = addr & ~7; if (ht216->ht_regs[0xcd] & HT_REG_CD_ASTODE) { offset = addr & 7; - - ht216->bg_latch[0] = svga->vram[latch_addr | offset]; - ht216->bg_latch[1] = svga->vram[latch_addr | ((offset + 1) & 7)]; - ht216->bg_latch[2] = svga->vram[latch_addr | ((offset + 2) & 7)]; - ht216->bg_latch[3] = svga->vram[latch_addr | ((offset + 3) & 7)]; - ht216->bg_latch[4] = svga->vram[latch_addr | ((offset + 4) & 7)]; - ht216->bg_latch[5] = svga->vram[latch_addr | ((offset + 5) & 7)]; - ht216->bg_latch[6] = svga->vram[latch_addr | ((offset + 6) & 7)]; - ht216->bg_latch[7] = svga->vram[latch_addr | ((offset + 7) & 7)]; + for (i = 0; i < 8; i++) + ht216->bg_latch[i] = svga->vram[latch_addr | ((offset + i) & 7)]; } else { - ht216->bg_latch[0] = svga->vram[latch_addr]; - ht216->bg_latch[1] = svga->vram[latch_addr | 1]; - ht216->bg_latch[2] = svga->vram[latch_addr | 2]; - ht216->bg_latch[3] = svga->vram[latch_addr | 3]; - ht216->bg_latch[4] = svga->vram[latch_addr | 4]; - ht216->bg_latch[5] = svga->vram[latch_addr | 5]; - ht216->bg_latch[6] = svga->vram[latch_addr | 6]; - ht216->bg_latch[7] = svga->vram[latch_addr | 7]; + for (i = 0; i < 8; i++) + ht216->bg_latch[i] = svga->vram[latch_addr | i]; } + or = addr & 4; svga->latch.d[0] = ht216->bg_latch[0 | or] | (ht216->bg_latch[1 | or] << 8) | (ht216->bg_latch[2 | or] << 16) | (ht216->bg_latch[3 | or] << 24); if (svga->readmode) { - temp = svga->latch.b[0]; - temp ^= (svga->colourcompare & 1) ? 0xff : 0; - temp &= (svga->colournocare & 1) ? 0xff : 0; - temp2 = svga->latch.b[1]; - temp2 ^= (svga->colourcompare & 2) ? 0xff : 0; - temp2 &= (svga->colournocare & 2) ? 0xff : 0; - temp3 = svga->latch.b[2]; - temp3 ^= (svga->colourcompare & 4) ? 0xff : 0; - temp3 &= (svga->colournocare & 4) ? 0xff : 0; - temp4 = svga->latch.b[3]; - temp4 ^= (svga->colourcompare & 8) ? 0xff : 0; - temp4 &= (svga->colournocare & 8) ? 0xff : 0; - return ~(temp | temp2 | temp3 | temp4); - } + temp = 0xff; + + for (pixel = 0; pixel < 8; pixel++) { + for (plane = 0; plane < 4; plane++) { + if (svga->colournocare & (1 << plane)) { + /* If we care about a plane, and the pixel has a mismatch on it, clear its bit. */ + if (((svga->latch.b[plane] >> pixel) & 1) != ((svga->colourcompare >> plane) & 1)) + temp &= ~(1 << pixel); + } + } + } - return svga->vram[addr | readplane]; + ret = temp; + } else + ret = svga->vram[addr | readplane]; + + return ret; } @@ -997,14 +1148,13 @@ ht216_read(uint32_t addr, void *p) { ht216_t *ht216 = (ht216_t *)p; svga_t *svga = &ht216->svga; - + addr &= svga->banked_mask; - addr = (addr & 0x7fff) + ht216->read_bank[(addr >> 15) & 1]; - + addr = (addr & 0x7fff) + ht216->read_banks[(addr >> 15) & 1]; + return ht216_read_common(ht216, addr); } - static uint8_t ht216_read_linear(uint32_t addr, void *p) { @@ -1040,7 +1190,7 @@ void else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_v7vga_isa); - svga_init(info, &ht216->svga, ht216, mem_size, + svga_init(info, svga, ht216, mem_size, ht216_recalctimings, ht216_in, ht216_out, ht216_hwcursor_draw, @@ -1050,19 +1200,24 @@ void svga->decode_mask = mem_size - 1; if (info->flags & DEVICE_VLB) { - mem_mapping_set_handler(&ht216->svga.mapping, ht216_read, NULL, NULL, ht216_write, ht216_writew, ht216_writel); - mem_mapping_add(&ht216->linear_mapping, 0, 0, ht216_read_linear, NULL, NULL, ht216_write_linear, ht216_writew_linear, ht216_writel_linear, NULL, MEM_MAPPING_EXTERNAL, &ht216->svga); + mem_mapping_set_handler(&svga->mapping, ht216_read, NULL, NULL, ht216_write, ht216_writew, ht216_writel); + mem_mapping_add(&ht216->linear_mapping, 0, 0, ht216_read_linear, NULL, NULL, ht216_write_linear, ht216_writew_linear, ht216_writel_linear, NULL, MEM_MAPPING_EXTERNAL, svga); } else { - mem_mapping_set_handler(&ht216->svga.mapping, ht216_read, NULL, NULL, ht216_write, ht216_writew, NULL); - mem_mapping_add(&ht216->linear_mapping, 0, 0, ht216_read_linear, NULL, NULL, ht216_write_linear, ht216_writew_linear, NULL, NULL, MEM_MAPPING_EXTERNAL, &ht216->svga); + mem_mapping_set_handler(&svga->mapping, ht216_read, NULL, NULL, ht216_write, ht216_writew, NULL); + mem_mapping_add(&ht216->linear_mapping, 0, 0, ht216_read_linear, NULL, NULL, ht216_write_linear, ht216_writew_linear, NULL, NULL, MEM_MAPPING_EXTERNAL, svga); } - mem_mapping_set_p(&ht216->svga.mapping, ht216); + mem_mapping_set_p(&svga->mapping, ht216); + mem_mapping_disable(&ht216->linear_mapping); svga->bpp = 8; svga->miscout = 1; - ht216->ht_regs[0xb4] = 0x08; /*32-bit DRAM bus*/ ht216->id = info->local; + + if (ht216->id == 0x7861) + ht216->ht_regs[0xb4] = 0x08; /*32-bit DRAM bus*/ + + svga->adv_flags = 0; return ht216; } @@ -1094,7 +1249,6 @@ ht216_pb410a_init(const device_t *info) return ht216; } - static int g2_gc205_available(void) { @@ -1108,7 +1262,6 @@ v7_vga_1024i_available(void) return rom_present(BIOS_VIDEO7_VGA_1024I_PATH); } - void ht216_close(void *p) { @@ -1159,6 +1312,27 @@ static const device_config_t v7_vga_1024i_config[] = } }; +static const device_config_t ht216_config[] = +{ + { + "memory", "Memory size", CONFIG_SELECTION, "", 1024, "", { 0 }, + { + { + "512 kB", 512 + }, + { + "1 MB", 1024 + }, + { + "" + } + } + }, + { + "", "", -1 + } +}; + const device_t g2_gc205_device = { "G2 GC205", @@ -1196,5 +1370,6 @@ const device_t ht216_32_pb410a_device = NULL, { NULL }, ht216_speed_changed, - ht216_force_redraw + ht216_force_redraw, + ht216_config }; 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 84482185b..7b2488060 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_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); }