diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index b76c2c260..fd81701a7 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -16,6 +16,8 @@ on: jobs: msys2: + # Negative condition disables the job + if: false name: "Win32 GUI, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }}" runs-on: windows-2022 @@ -92,7 +94,6 @@ jobs: rtmidi:p libslirp:p fluidsynth:p - libvncserver:p - name: Checkout repository uses: actions/checkout@v4 diff --git a/.github/workflows/cmake_linux.yml b/.github/workflows/cmake_linux.yml index c09789bfc..12cb21303 100644 --- a/.github/workflows/cmake_linux.yml +++ b/.github/workflows/cmake_linux.yml @@ -80,7 +80,6 @@ jobs: libopenal-dev libslirp-dev libfluidsynth-dev - libvncserver-dev ${{ matrix.ui.packages }} - name: Checkout repository diff --git a/.github/workflows/cmake_macos.yml b/.github/workflows/cmake_macos.yml index 7a6edcde9..e51c652a4 100644 --- a/.github/workflows/cmake_macos.yml +++ b/.github/workflows/cmake_macos.yml @@ -82,7 +82,6 @@ jobs: rtmidi openal-soft fluidsynth - libvncserver ${{ matrix.ui.packages }} - name: Checkout repository diff --git a/.github/workflows/cmake_windows_msys2.yml b/.github/workflows/cmake_windows_msys2.yml index 48503cc27..c7d77307c 100644 --- a/.github/workflows/cmake_windows_msys2.yml +++ b/.github/workflows/cmake_windows_msys2.yml @@ -57,9 +57,6 @@ jobs: new: on slug: -NDR ui: - - name: Win32 GUI - qt: off - static: on - name: Qt GUI qt: on static: on @@ -107,7 +104,6 @@ jobs: rtmidi:p libslirp:p fluidsynth:p - libvncserver:p ${{ matrix.ui.packages }} - name: Checkout repository diff --git a/.github/workflows/codeql_linux.yml b/.github/workflows/codeql_linux.yml index a97951abf..d92d11767 100644 --- a/.github/workflows/codeql_linux.yml +++ b/.github/workflows/codeql_linux.yml @@ -83,7 +83,6 @@ jobs: libopenal-dev libslirp-dev libfluidsynth-dev - libvncserver-dev ${{ matrix.ui.packages }} - name: Checkout repository diff --git a/.github/workflows/codeql_macos.yml b/.github/workflows/codeql_macos.yml index 724bdc6f6..cef8c4828 100644 --- a/.github/workflows/codeql_macos.yml +++ b/.github/workflows/codeql_macos.yml @@ -76,7 +76,6 @@ jobs: rtmidi openal-soft fluidsynth - libvncserver ${{ matrix.ui.packages }} - name: Checkout repository diff --git a/.github/workflows/codeql_windows_msys2.yml b/.github/workflows/codeql_windows_msys2.yml index 5b0c2485f..dc18544c7 100644 --- a/.github/workflows/codeql_windows_msys2.yml +++ b/.github/workflows/codeql_windows_msys2.yml @@ -110,7 +110,6 @@ jobs: rtmidi:p libslirp:p fluidsynth:p - libvncserver:p ${{ matrix.ui.packages }} - name: Checkout repository diff --git a/CMakeLists.txt b/CMakeLists.txt index a6b50baf3..196952cb4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -155,6 +155,7 @@ cmake_dependent_option(ISAMEM_BRAT "BocaRAM/AT" cmake_dependent_option(LASERXT "VTech Laser XT" ON "DEV_BRANCH" OFF) cmake_dependent_option(OLIVETTI "Olivetti M290" ON "DEV_BRANCH" OFF) cmake_dependent_option(OPEN_AT "OpenAT" ON "DEV_BRANCH" OFF) +cmake_dependent_option(OPL4ML "OPL4-ML daughterboard" ON "DEV_BRANCH" OFF) cmake_dependent_option(PAS16 "Pro Audio Spectrum 16" ON "DEV_BRANCH" OFF) cmake_dependent_option(SIO_DETECT "Super I/O Detection Helper" ON "DEV_BRANCH" OFF) cmake_dependent_option(VGAWONDER "ATI VGA Wonder (ATI-18800)" ON "DEV_BRANCH" OFF) diff --git a/src/86box.c b/src/86box.c index f72b066a5..8218c208c 100644 --- a/src/86box.c +++ b/src/86box.c @@ -30,10 +30,10 @@ #include #include #include +#include #ifndef _WIN32 # include -# include #endif #ifdef __APPLE__ # include @@ -1048,6 +1048,7 @@ pc_send_ca(uint16_t sc) keyboard_input(1, 0x1D); /* Ctrl key pressed */ keyboard_input(1, 0x38); /* Alt key pressed */ keyboard_input(1, sc); + usleep(50000); keyboard_input(0, sc); keyboard_input(0, 0x38); /* Alt key released */ keyboard_input(0, 0x1D); /* Ctrl key released */ diff --git a/src/acpi.c b/src/acpi.c index 782062d4a..a2b061837 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -42,6 +42,10 @@ #include <86box/machine.h> #include <86box/i2c.h> #include <86box/video.h> +#include <86box/smbus.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/sis_55xx.h> int acpi_rtc_status = 0; atomic_int acpi_pwrbut_pressed = 0; @@ -49,7 +53,9 @@ int acpi_enabled = 0; static double cpu_to_acpi; -static int acpi_power_on = 0; +static int acpi_power_on = 0; +static uint64_t acpi_last_clock = 0ULL; +static int acpi_count = 0; #ifdef ENABLE_ACPI_LOG int acpi_do_log = ENABLE_ACPI_LOG; @@ -85,23 +91,43 @@ acpi_timer_get(acpi_t *dev) return clock & 0xffffff; } +static uint8_t +acpi_gp_timer_get(acpi_t *dev) +{ + uint64_t clock = acpi_clock_get(); + clock -= acpi_last_clock; + if (clock >= acpi_count) + clock = 0x00; + else + clock &= 0xff; + return clock; +} + static double acpi_get_overflow_period(acpi_t *dev) { uint64_t timer = acpi_clock_get(); uint64_t overflow_time; - if (dev->regs.timer32) { + if (dev->regs.timer32) overflow_time = (timer + 0x80000000LL) & ~0x7fffffffLL; - } else { + else overflow_time = (timer + 0x800000LL) & ~0x7fffffLL; - } uint64_t time_to_overflow = overflow_time - timer; return ((double) time_to_overflow / (double) ACPI_TIMER_FREQ) * 1000000.0; } +static void +acpi_timer_update(acpi_t *dev, bool enable) +{ + if (enable) + timer_on_auto(&dev->timer, acpi_get_overflow_period(dev)); + else + timer_stop(&dev->timer); +} + static void acpi_timer_overflow(void *priv) { @@ -109,7 +135,7 @@ acpi_timer_overflow(void *priv) int sci_en = dev->regs.pmcntrl & 1; dev->regs.pmsts |= TMROF_STS; - +/* if (dev->regs.pmen & 1) /* Timer Overflow Interrupt Enable */ { acpi_log("ACPI: Overflow detected. Provoking an %s\n", sci_en ? "SCI" : "SMI"); @@ -119,42 +145,111 @@ acpi_timer_overflow(void *priv) else acpi_raise_smi(dev, 1); } +*/ + acpi_update_irq(dev); + acpi_timer_update(dev, (dev->regs.pmen & TMROF_EN) && !(dev->regs.pmsts & TMROF_STS)); } static void -acpi_timer_update(acpi_t *dev, bool enable) +acpi_gp_timer_update(acpi_t *dev, bool enable, int count) { if (enable) { - timer_on_auto(&dev->timer, acpi_get_overflow_period(dev)); - } else { + acpi_last_clock = acpi_clock_get(); + acpi_count = count; + timer_on_auto(&dev->gp_timer, (1000000.0 / (double) ACPI_TIMER_FREQ) * ((double) count)); + } else timer_stop(&dev->timer); +} + +void +acpi_sis5595_smi_raise(void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + if (dev->regs.leg_en & 0x20) { + dev->regs.leg_sts |= 0x20; + smi_raise(); } } +static void +acpi_gp_timer(void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + if (dev->vendor == VEN_SIS_5595_1997) { + dev->regs.gpe_sts |= 0x20000000; + dev->regs.leg_sts |= 0x20; + acpi_gp_timer_update(dev, (dev->regs.gpe_en & 0x20000000), acpi_count); + acpi_sis5595_smi_raise(dev); + } else if (dev->vendor == VEN_SIS_5595) { + dev->regs.gpe_sts |= 0x00000400; + dev->regs.leg_sts |= 0x20; + acpi_gp_timer_update(dev, (dev->regs.gpe_en & 0x00000400), acpi_count); + acpi_sis5595_smi_raise(dev); + } else { + dev->regs.reg_14 |= 0x2000; + acpi_gp_timer_update(dev, (dev->regs.reg_16 & 0x2000), acpi_count); + smi_raise(); + } +} + +static void +acpi_per_timer(void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + if (dev->vendor >= VEN_SIS_5595_1997) { + dev->regs.leg_sts |= 0x04; + acpi_sis5595_smi_raise(dev); + } else { + dev->regs.reg_25 |= 0x04; + smi_raise(); + } + timer_on_auto(&dev->per_timer, 16000000.0); +} + void acpi_update_irq(acpi_t *dev) { int sci_level = (dev->regs.pmsts & dev->regs.pmen) & (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN); - if (dev->vendor == VEN_SMC) - sci_level |= (dev->regs.pmsts & BM_STS); + sis_55xx_common_t *sis = (sis_55xx_common_t *) dev->priv; - if ((dev->regs.pmcntrl & 0x01) && sci_level) { - if (dev->irq_mode == 1) - pci_set_irq(dev->slot, dev->irq_pin, &dev->irq_state); - else if (dev->irq_mode == 2) - pci_set_mirq(5, dev->mirq_is_level, &dev->irq_state); - else - picintlevel(1 << dev->irq_line, &dev->irq_state); - } else { - if (dev->irq_mode == 1) - pci_clear_irq(dev->slot, dev->irq_pin, &dev->irq_state); - else if (dev->irq_mode == 2) - pci_clear_mirq(5, dev->mirq_is_level, &dev->irq_state); - else - picintclevel(1 << dev->irq_line, &dev->irq_state); + switch (dev->vendor) { + case VEN_SMC: + sci_level |= (dev->regs.pmsts & BM_STS); + break; + case VEN_SIS_5595_1997: + case VEN_SIS_5595: + if ((sis != NULL) && (sis->pmu_regs != NULL)) { + sci_level |= (sis->pmu_regs[0x80] | sis->pmu_regs[0x81] | + sis->pmu_regs[0x82] | sis->pmu_regs[0x83]); + } + break; } - acpi_timer_update(dev, (dev->regs.pmen & TMROF_EN) && !(dev->regs.pmsts & TMROF_STS)); + if ((dev->regs.pmcntrl & 0x01) && sci_level) switch (dev->irq_mode) { + default: + picintlevel(1 << dev->irq_line, &dev->irq_state); + break; + case 1: + pci_set_irq(dev->slot, dev->irq_pin, &dev->irq_state); + break; + case 2: + pci_set_mirq(5, dev->mirq_is_level, &dev->irq_state); + break; + case -1: + break; + } else switch (dev->irq_mode) { + default: + picintclevel(1 << dev->irq_line, &dev->irq_state); + break; + case 1: + pci_clear_irq(dev->slot, dev->irq_pin, &dev->irq_state); + break; + case 2: + pci_clear_mirq(5, dev->mirq_is_level, &dev->irq_state); + break; + case -1: + break; + } } void @@ -773,6 +868,230 @@ acpi_aux_reg_read_smc(UNUSED(int size), uint16_t addr, void *priv) return ret; } +static uint32_t +acpi_reg_read_sis_5582(int size, uint16_t addr, void *priv) +{ + const acpi_t *dev = (acpi_t *) priv; + uint32_t ret = 0x00000000; + int shift16; + int shift32; + + addr &= 0x3f; + shift16 = (addr & 1) << 3; + shift32 = (addr & 3) << 3; + + switch (addr) { + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + ret = (dev->regs.reg_0c >> shift32) & 0xff; + break; + case 0x10: + ret = dev->regs.enter_c2_ps; + break; + case 0x11: + ret = dev->regs.enter_c3_ps; + break; + case 0x12: + ret = dev->regs.reg_12; + break; + case 0x13: + ret = acpi_gp_timer_get((acpi_t *) dev) & 0xff; +#ifdef USE_DYNAREC + if (cpu_use_dynarec) + update_tsc(); +#endif + break; + case 0x14: + case 0x15: + ret = (dev->regs.reg_14 >> shift16) & 0xff; + break; + case 0x16: + case 0x17: + ret = (dev->regs.reg_16 >> shift16) & 0xff; + break; + case 0x18: + case 0x19: + ret = (dev->regs.reg_18 >> shift16) & 0xff; + break; + case 0x1a: + case 0x1b: + ret = (dev->regs.reg_18 >> shift16) & 0xff; + break; + case 0x1c: + case 0x1d: + ret = (dev->regs.reg_1c >> shift16) & 0xff; + break; + case 0x20: + ret = dev->regs.smi_cmd; + break; + case 0x24: + ret = dev->regs.reg_24; + break; + case 0x25: + ret = dev->regs.reg_25; + break; + case 0x26: + ret = dev->regs.reg_26; + break; + case 0x28: + ret = dev->regs.smi_en_val; + break; + case 0x29: + ret = dev->regs.smi_dis_val; + break; + case 0x2a: + ret = dev->regs.mail_box; + break; + case 0x2b: + ret = dev->regs.reg_2b; + break; + default: + ret = acpi_reg_read_common_regs(size, addr, priv); + 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_sis_5595(int size, uint16_t addr, void *priv) +{ + const acpi_t *dev = (acpi_t *) priv; + uint32_t ret = 0x00000000; + int shift16; + int shift32; + + addr &= 0x3f; + shift16 = (addr & 1) << 3; + shift32 = (addr & 3) << 3; + + switch (addr) { + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + ret = (dev->regs.reg_0c >> shift32) & 0xff; + break; + case 0x10: + ret = dev->regs.enter_c2_ps; + break; + case 0x11: + ret = dev->regs.enter_c3_ps; + break; + case 0x12: + ret = dev->regs.reg_12; + break; + case 0x13: + ret = dev->regs.reg_13; + break; + case 0x14: + case 0x15: + case 0x16: + case 0x17: + ret = (dev->regs.gpe_sts >> shift32) & 0xff; + break; + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + ret = (dev->regs.gpe_en >> shift32) & 0xff; + break; + case 0x1c: + case 0x1d: + case 0x1e: + ret = (dev->regs.gpe_pin >> shift32) & 0xff; + break; + case 0x1f: + ret = acpi_gp_timer_get((acpi_t *) dev) & 0xff; +#ifdef USE_DYNAREC + if (cpu_use_dynarec) + update_tsc(); +#endif + break; + case 0x20: + case 0x21: + case 0x22: + case 0x23: + ret = (dev->regs.gpe_io >> shift32) & 0xff; + break; + case 0x24: + case 0x25: + case 0x26: + case 0x27: + ret = (dev->regs.gpe_pol >> shift32) & 0xff; + break; + case 0x28: + case 0x29: + ret = (dev->regs.gpe_mul >> shift16) & 0xff; + break; + case 0x2a: + case 0x2b: + ret = (dev->regs.gpe_ctl >> shift16) & 0xff; + break; + case 0x2c: + case 0x2d: + ret = (dev->regs.gpe_smi >> shift16) & 0xff; + break; + case 0x2e: + case 0x2f: + ret = (dev->regs.gpe_rl >> shift16) & 0xff; + break; + case 0x30: + ret = dev->regs.leg_sts; + break; + case 0x31: + ret = dev->regs.leg_en; + break; + case 0x32: + if (dev->vendor == VEN_SIS_5595_1997) + ret = dev->regs.smi_cmd; + else + ret = 0x00; + break; + case 0x33: + ret = dev->regs.tst_ctl; + break; + case 0x34: + if (dev->vendor == VEN_SIS_5595_1997) + ret = dev->regs.smi_en_val; + else + ret = dev->regs.reg_34; + break; + case 0x35: + if (dev->vendor == VEN_SIS_5595_1997) + ret = dev->regs.smi_dis_val; + else + ret = dev->regs.smi_cmd; + break; + case 0x36: + ret = dev->regs.mail_box; + break; + case 0x38: + if (dev->vendor == VEN_SIS_5595) + ret = smbus_sis5595_read_index(dev->smbus); + break; + case 0x39: + if (dev->vendor == VEN_SIS_5595) + ret = smbus_sis5595_read_data(dev->smbus); + break; + default: + ret = acpi_reg_read_common_regs(size, addr, priv); + 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 void acpi_reg_write_common_regs(UNUSED(int size), uint16_t addr, uint8_t val, void *priv) { @@ -1438,12 +1757,382 @@ acpi_aux_reg_write_smc(UNUSED(int size), uint16_t addr, uint8_t val, void *priv) } } +void +acpi_sis5582_pmu_event(void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + + dev->regs.reg_25 |= 0x02; + if (dev->regs.reg_26 & 0x02) + smi_raise(); +} + +static void +acpi_reg_write_sis_5582(int size, uint16_t addr, uint8_t val, void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + int shift16; + int shift32; + uint8_t old; + + 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 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + dev->regs.reg_0c &= ~((val << shift32) & 0x007e); + break; + case 0x10: + dev->regs.enter_c2_ps = val; + break; + case 0x11: + dev->regs.enter_c3_ps = val; + break; + case 0x12: + dev->regs.reg_12 = val & 0x01; + break; + case 0x13: + dev->regs.reg_13 = val; + acpi_gp_timer_update(dev, (val != 0x00) && (dev->regs.reg_16 & 0x2000), val); + break; + case 0x14: + case 0x15: + dev->regs.reg_14 &= ~((val << shift32) & 0xff9f); + break; + case 0x16: + case 0x17: + dev->regs.reg_16 = ((dev->regs.reg_16 & ~(0xff << shift16)) | (val << shift16)) & 0xff1f; + break; + case 0x18: + case 0x19: + dev->regs.reg_18 = ((dev->regs.reg_18 & ~(0xff << shift16)) | (val << shift16)) & 0x07ff; + break; + case 0x1a: + case 0x1b: + dev->regs.reg_1a = ((dev->regs.reg_1a & ~(0xff << shift16)) | (val << shift16)) & 0x0387; + break; + case 0x1c: + case 0x1d: + dev->regs.reg_1c = ((dev->regs.reg_1c & ~(0xff << shift16)) | (val << shift16)) & 0x3f7f; + /* Setting BIOS_RLS also sets GBL_STS and generates SMI. */ + if (dev->regs.reg_1c & 0x0400) { + dev->regs.pmsts |= 0x20; + if (dev->regs.pmen & 0x20) + acpi_update_irq(dev); + } + break; + case 0x20: + /* SMI Command Port */ + dev->regs.smi_cmd = val; + if (val == dev->regs.smi_en_val) { + dev->regs.reg_25 |= 0x08; + if (dev->regs.reg_26 & 0x08) + smi_raise(); + } else if (val == dev->regs.smi_dis_val) { + dev->regs.reg_25 |= 0x10; + if (dev->regs.reg_26 & 0x10) + smi_raise(); + } + break; + case 0x24: + dev->regs.reg_24 = val & 0x43; + break; + case 0x25: + dev->regs.reg_25 &= ~(val & 0x1f); + break; + case 0x26: + old = dev->regs.reg_26; + dev->regs.reg_26 = val & 0x3f; + if (!(old & 0x04) && (val & 0x04)) + timer_on_auto(&dev->per_timer, 16000000.0); + else if ((old & 0x04) && !(val & 0x04)) + timer_stop(&dev->per_timer); + break; + case 0x28: + dev->regs.smi_en_val = val; + break; + case 0x29: + dev->regs.smi_dis_val = val; + break; + case 0x2a: + dev->regs.mail_box = val; + break; + case 0x2b: + dev->regs.reg_2b = val & 0x01; + break; + default: + acpi_reg_write_common_regs(size, addr, val, priv); + /* Setting GBL_RLS also sets BIOS_STS and generates SMI. */ + if ((addr == 0x00) && !(dev->regs.pmsts & 0x20)) + dev->regs.reg_1c &= ~0x0400; + else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { + dev->regs.reg_25 |= 0x01; + if (dev->regs.reg_26 & 0x01) + acpi_raise_smi(dev, 1); + } + break; + } +} + +void +acpi_sis5595_pmu_event(void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + + if (dev->vendor == VEN_SIS_5595_1997) + acpi_sis5595_smi_raise(dev); + else if (dev->regs.gpe_en & 0x00001000) { + dev->regs.gpe_sts |= 0x00001000; + acpi_sis5595_smi_raise(dev); + } +} + +void +acpi_sis5595_smbus_event(void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + + if (dev->regs.gpe_en & 0x00000800) { + dev->regs.gpe_sts |= 0x00000800; + acpi_sis5595_smi_raise(dev); + } +} + +void +acpi_sis5595_software_smi(void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + + if (dev->regs.leg_en & 0x01) { + dev->regs.leg_sts |= 0x01; + acpi_sis5595_smi_raise(dev); + } +} + +static void +acpi_reg_write_sis_5595(int size, uint16_t addr, uint8_t val, void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + int shift16; + int shift32; + uint8_t old; + uint8_t do_smi = 0; + + 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 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + dev->regs.reg_0c &= ~((val << shift32) & 0x001e); + break; + case 0x10: + dev->regs.enter_c2_ps = val; + break; + case 0x11: + dev->regs.enter_c3_ps = val; + break; + case 0x12: + dev->regs.reg_12 = val & 0x01; + break; + case 0x13: + dev->regs.reg_13 = val; + /* Setting BIOS_RLS also sets GBL_STS and generates SMI. */ + if (dev->regs.reg_13 & 0x02) { + dev->regs.pmsts |= 0x20; + if (dev->regs.pmen & 0x20) + acpi_update_irq(dev); + } + break; + case 0x14: + case 0x15: + case 0x16: + case 0x17: + if (dev->vendor == VEN_SIS_5595_1997) + dev->regs.gpe_sts &= ~((val << shift32) & 0xff03ffbf); + else + dev->regs.gpe_sts &= ~((val << shift32) & 0xff83ffff); + break; + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + if (dev->vendor == VEN_SIS_5595_1997) + dev->regs.gpe_en = ((dev->regs.gpe_en & ~(0xff << shift32)) | (val << shift32)); + else + dev->regs.gpe_en = ((dev->regs.gpe_en & ~(0xff << shift32)) | + (val << shift32)) & 0xff83ffff; + break; + case 0x1c: + dev->regs.gpe_pin = ((dev->regs.gpe_pin & ~(0xff << shift32)) | ((val & 0xff) << shift32)); + break; + case 0x1d: + dev->regs.gpe_pin = ((dev->regs.gpe_pin & ~(0x0f << shift32)) | ((val & 0x0f) << shift32)); + break; + case 0x1e: + dev->regs.gpe_pin = ((dev->regs.gpe_pin & ~(0x03 << shift32)) | ((val & 0x03) << shift32)); + break; + case 0x1f: + dev->regs.gp_tmr = val; + acpi_gp_timer_update(dev, (val != 0x00) && (dev->regs.gpe_en & 0x00000400), val); + break; + case 0x20: + dev->regs.gpe_io = ((dev->regs.gpe_io & ~(0x9f << shift32)) | ((val & 0x9f) << shift32)); + break; + case 0x21: + dev->regs.gpe_io = ((dev->regs.gpe_io & ~(0x0f << shift32)) | ((val & 0x0f) << shift32)); + break; + case 0x22: + dev->regs.gpe_io = ((dev->regs.gpe_io & ~(0x03 << shift32)) | ((val & 0x03) << shift32)); + break; + case 0x24: + dev->regs.gpe_pol = ((dev->regs.gpe_pol & ~(0xbf << shift32)) | ((val & 0xbf) << shift32)); + break; + case 0x25: + dev->regs.gpe_pol = ((dev->regs.gpe_pol & ~(0x0f << shift32)) | ((val & 0x0f) << shift32)); + break; + case 0x26: + dev->regs.gpe_pol = ((dev->regs.gpe_pol & ~(0x03 << shift32)) | ((val & 0x03) << shift32)); + break; + case 0x27: + dev->regs.gpe_pol = ((dev->regs.gpe_pol & ~(0x10 << shift32)) | ((val & 0x10) << shift32)); + break; + case 0x28: + dev->regs.gpe_mul = ((dev->regs.gpe_mul & ~(0xf9 << shift16)) | ((val & 0xf9) << shift16)); + break; + case 0x29: + dev->regs.gpe_mul = ((dev->regs.gpe_mul & ~(0x13 << shift16)) | ((val & 0x13) << shift16)); + break; + case 0x2a: + case 0x2b: + dev->regs.gpe_ctl = ((dev->regs.gpe_ctl & ~(0xff << shift16)) | ((val & 0xff) << shift16)); + break; + case 0x2c: + case 0x2d: + dev->regs.gpe_smi = ((dev->regs.gpe_smi & ~(0xff << shift16)) | ((val & 0xff) << shift16)); + break; + case 0x2e: + case 0x2f: + dev->regs.gpe_rl = ((dev->regs.gpe_rl & ~(0xff << shift16)) | ((val & 0xff) << shift16)); + break; + case 0x30: + dev->regs.leg_sts &= ~val; + break; + case 0x31: + old = dev->regs.leg_en; + dev->regs.leg_en = val; + if (!(old & 0x04) && (val & 0x04)) + timer_on_auto(&dev->per_timer, 16000000.0); + else if ((old & 0x04) && !(val & 0x04)) + timer_stop(&dev->per_timer); + break; + case 0x32: + if (dev->vendor == VEN_SIS_5595_1997) { + /* SMI Command Port */ + dev->regs.smi_cmd = val; + if (val == dev->regs.smi_en_val) { + dev->regs.leg_sts |= 0x08; + if (dev->regs.leg_en & 0x08) + acpi_sis5595_smi_raise(dev); + } else if (val == dev->regs.smi_dis_val) { + dev->regs.leg_sts |= 0x10; + if (dev->regs.leg_en & 0x10) + acpi_sis5595_smi_raise(dev); + } + } + break; + case 0x33: + dev->regs.tst_ctl = val & 0x01; + break; + case 0x34: + if (dev->vendor == VEN_SIS_5595_1997) + dev->regs.smi_en_val = val; + else + dev->regs.reg_34 = val; + break; + case 0x35: + if (dev->vendor == VEN_SIS_5595_1997) + dev->regs.smi_dis_val = val; + else { + /* SMI Command Port */ + dev->regs.smi_cmd = val; + dev->regs.leg_sts |= 0x10; + if (dev->regs.leg_en & 0x10) + acpi_sis5595_smi_raise(dev); + } + break; + case 0x36: + dev->regs.mail_box = val; + break; + case 0x38: + if (dev->vendor == VEN_SIS_5595) { + dev->regs.index = val; + smbus_sis5595_write_index(dev->smbus, val); + } + break; + case 0x39: + if (dev->vendor == VEN_SIS_5595) { + dev->regs.reg_ff = val & 0x3f; + smbus_sis5595_write_data(dev->smbus, val); + if (val & 0x20) { /* Set GPIO5_STS of GPE_STS */ + dev->regs.gpe_sts |= 0x00000008; + do_smi |= (dev->regs.gpe_en & 0x00000004); + } else if (val & 0x10) { /* Set GPIO10_STS of GPE_STS */ + dev->regs.gpe_sts |= 0x00000004; + do_smi |= (dev->regs.gpe_en & 0x00000008); + } else if (val & 0x08) { /* Set RI_STS in GPE_STS */ + dev->regs.gpe_sts |= 0x00000002; + do_smi |= (dev->regs.gpe_en & 0x00000002); + } else if (val & 0x04) /* Set WAK_STS of PM1_STS */ + dev->regs.pmsts |= 0x8000; + else if (val & 0x02) { /* Set RTC_STS of PM1_STS */ + dev->regs.pmsts |= 0x0400; + do_smi |= (dev->regs.pmen & 0x0400); + } else if (val & 0x01) { /* Set PWRBTN_STS of PM1_STS */ + dev->regs.pmsts |= 0x0100; + do_smi |= (dev->regs.pmen & 0x0100); + } + + if (do_smi) + acpi_sis5595_smi_raise(dev); + } + break; + default: + acpi_reg_write_common_regs(size, addr, val, priv); + /* Setting GBL_RLS also sets BIOS_STS and generates SMI. */ + if ((addr == 0x00) && !(dev->regs.pmsts & 0x20)) + dev->regs.reg_13 &= ~0x02; + else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { + dev->regs.leg_sts |= 0x01; + if (dev->regs.leg_en & 0x01) + acpi_sis5595_smi_raise(dev); + } + break; + } +} + static uint32_t acpi_reg_read_common(int size, uint16_t addr, void *priv) { const acpi_t *dev = (acpi_t *) priv; uint8_t ret = 0xff; +/* if (dev->vendor == VEN_ALI) ret = acpi_reg_read_ali(size, addr, priv); else if (dev->vendor == VEN_VIA) @@ -1456,6 +2145,31 @@ acpi_reg_read_common(int size, uint16_t addr, void *priv) ret = acpi_reg_read_intel_ich2(size, addr, priv); else if (dev->vendor == VEN_SMC) ret = acpi_reg_read_smc(size, addr, priv); +*/ + switch (dev->vendor) { + case VEN_ALI: + ret = acpi_reg_read_ali(size, addr, priv); + break; + case VEN_VIA: + ret = acpi_reg_read_via(size, addr, priv); + break; + case VEN_VIA_596B: + ret = acpi_reg_read_via_596b(size, addr, priv); + break; + case VEN_INTEL: + ret = acpi_reg_read_intel(size, addr, priv); + break; + case VEN_SMC: + ret = acpi_reg_read_smc(size, addr, priv); + break; + case VEN_SIS_5582: + ret = acpi_reg_read_sis_5582(size, addr, priv); + break; + case VEN_SIS_5595_1997: + case VEN_SIS_5595: + ret = acpi_reg_read_sis_5595(size, addr, priv); + break; + } return ret; } @@ -1465,6 +2179,7 @@ acpi_reg_write_common(int size, uint16_t addr, uint8_t val, void *priv) { const acpi_t *dev = (acpi_t *) priv; +/* if (dev->vendor == VEN_ALI) acpi_reg_write_ali(size, addr, val, priv); else if (dev->vendor == VEN_VIA) @@ -1477,6 +2192,31 @@ acpi_reg_write_common(int size, uint16_t addr, uint8_t val, void *priv) acpi_reg_write_intel_ich2(size, addr, val, priv); else if (dev->vendor == VEN_SMC) acpi_reg_write_smc(size, addr, val, priv); +*/ + switch (dev->vendor) { + case VEN_ALI: + acpi_reg_write_ali(size, addr, val, priv); + break; + case VEN_VIA: + acpi_reg_write_via(size, addr, val, priv); + break; + case VEN_VIA_596B: + acpi_reg_write_via_596b(size, addr, val, priv); + break; + case VEN_INTEL: + acpi_reg_write_intel(size, addr, val, priv); + break; + case VEN_SMC: + acpi_reg_write_smc(size, addr, val, priv); + break; + case VEN_SIS_5582: + acpi_reg_write_sis_5582(size, addr, val, priv); + break; + case VEN_SIS_5595_1997: + case VEN_SIS_5595: + acpi_reg_write_sis_5595(size, addr, val, priv); + break; + } } static uint32_t @@ -1645,6 +2385,9 @@ acpi_update_io_mapping(acpi_t *dev, uint32_t base, int chipset_en) default: case VEN_ALI: case VEN_INTEL: + case VEN_SIS_5582: + case VEN_SIS_5595_1997: + case VEN_SIS_5595: size = 0x040; break; case VEN_SMC: @@ -1928,10 +2671,28 @@ acpi_reset(void *priv) acpi_power_on = 0; } + /* The Gateway Tomahawk requires the LID polarity bit to be set. */ + if (!strcmp(machine_get_internal_name(), "tomahawk")) + dev->regs.glbctl |= 0x02000000; + acpi_rtc_status = 0; acpi_update_irq(dev); dev->irq_state = 0; + + timer_disable(&dev->gp_timer); + + acpi_last_clock = 0ULL; + acpi_count = 0; + + timer_disable(&dev->per_timer); + + if ((dev->vendor == VEN_SIS_5595_1997) || (dev->vendor == VEN_SIS_5595)) { + dev->regs.reg_13 = 0x20; + dev->regs.gp_tmr = 0xff; + dev->regs.gpe_io = 0x00030b9f; + dev->regs.gpe_mul = 0x1001; + } } static void @@ -1944,6 +2705,33 @@ acpi_speed_changed(void *priv) if (timer_enabled) timer_on_auto(&dev->timer, acpi_get_overflow_period(dev)); + + if ((dev->vendor & 0xffff) == 0x1039) { + if (timer_is_on(&dev->gp_timer)) { + timer_stop(&dev->gp_timer); + + if (dev->vendor == VEN_SIS_5595_1997) + acpi_gp_timer_update(dev, (dev->regs.gpe_en & 0x20000000), acpi_count); + else if (dev->vendor == VEN_SIS_5595) + acpi_gp_timer_update(dev, (dev->regs.gpe_en & 0x00000400), acpi_count); + else + acpi_gp_timer_update(dev, (dev->regs.reg_16 & 0x2000), acpi_count); + } + + if (timer_is_on(&dev->per_timer)) { + timer_stop(&dev->per_timer); + + timer_on_auto(&dev->per_timer, 16000000.0); + } + } +} + +void * +acpi_get_smbus(void *priv) +{ + acpi_t *dev = (acpi_t *) priv; + + return dev->smbus; } static void @@ -2029,6 +2817,28 @@ acpi_init(const device_t *info) dev->suspend_types[7] = SUS_POWER_OFF; break; + case VEN_SIS_5582: + dev->suspend_types[0] = SUS_SUSPEND; /* S1 */ + dev->suspend_types[4] = SUS_POWER_OFF; /* S5 */ + + timer_add(&dev->gp_timer, acpi_gp_timer, dev, 0); + timer_add(&dev->per_timer, acpi_per_timer, dev, 0); + break; + + case VEN_SIS_5595_1997: + case VEN_SIS_5595: + dev->suspend_types[1] = SUS_SUSPEND; + dev->suspend_types[2] = SUS_SUSPEND; + dev->suspend_types[3] = SUS_SUSPEND | SUS_NVR | SUS_RESET_CPU | SUS_RESET_PCI; + dev->suspend_types[4] = SUS_POWER_OFF; + dev->suspend_types[5] = SUS_POWER_OFF; + + timer_add(&dev->gp_timer, acpi_gp_timer, dev, 0); + timer_add(&dev->per_timer, acpi_per_timer, dev, 0); + + dev->smbus = device_add(&sis5595_smbus_device); + break; + default: break; } @@ -2130,3 +2940,45 @@ const device_t acpi_smc_device = { .force_redraw = NULL, .config = NULL }; + +const device_t acpi_sis_5582_device = { + .name = "SiS 5582 ACPI", + .internal_name = "acpi_sis_5582", + .flags = DEVICE_PCI, + .local = VEN_SIS_5582, + .init = acpi_init, + .close = acpi_close, + .reset = acpi_reset, + { .available = NULL }, + .speed_changed = acpi_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t acpi_sis_5595_1997_device = { + .name = "SiS 5595 (1997) ACPI", + .internal_name = "acpi_sis_5595_1997", + .flags = DEVICE_PCI, + .local = VEN_SIS_5595_1997, + .init = acpi_init, + .close = acpi_close, + .reset = acpi_reset, + { .available = NULL }, + .speed_changed = acpi_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +const device_t acpi_sis_5595_device = { + .name = "SiS 5595 ACPI", + .internal_name = "acpi_sis_5595", + .flags = DEVICE_PCI, + .local = VEN_SIS_5595, + .init = acpi_init, + .close = acpi_close, + .reset = acpi_reset, + { .available = NULL }, + .speed_changed = acpi_speed_changed, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index c5755709d..ea025de2a 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -442,7 +442,7 @@ cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len) { int ret = 1; - if (!dev->sound_on || (dev->cd_status != CD_STATUS_PLAYING)) { + if (!dev->sound_on || (dev->cd_status != CD_STATUS_PLAYING) || dev->audio_muted_soft) { cdrom_log("CD-ROM %i: Audio callback while not playing\n", dev->id); if (dev->cd_status == CD_STATUS_PLAYING) dev->seek_pos += (len >> 11); @@ -557,6 +557,7 @@ cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf) len += pos; } + dev->audio_muted_soft = 0; /* Do this at this point, since it's at this point that we know the actual LBA position to start playing from. */ if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) { @@ -578,6 +579,7 @@ cdrom_audio_track_search(cdrom_t *dev, uint32_t pos, int type, uint8_t playbit) int m = 0; int s = 0; int f = 0; + uint32_t pos2 = 0; if (dev->cd_status == CD_STATUS_DATA_ONLY) return 0; @@ -614,14 +616,21 @@ cdrom_audio_track_search(cdrom_t *dev, uint32_t pos, int type, uint8_t playbit) break; } + pos2 = pos - 1; + if (pos2 == 0xffffffff) + pos2 = pos + 1; + /* Do this at this point, since it's at this point that we know the actual LBA position to start playing from. */ - if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) { - cdrom_log("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos); - cdrom_stop(dev); - return 0; - } + if (!(dev->ops->track_type(dev, pos2) & CD_TRACK_AUDIO)) { + cdrom_log("CD-ROM %i: Track Search: LBA %08X not on an audio track\n", dev->id, pos); + dev->audio_muted_soft = 1; + if (dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO) + dev->audio_muted_soft = 0; + } else + dev->audio_muted_soft = 0; + cdrom_log("Track Search Toshiba: Muted?=%d, LBA=%08X.\n", dev->audio_muted_soft, pos); dev->cd_buflen = 0; dev->cd_status = playbit ? CD_STATUS_PLAYING : CD_STATUS_PAUSED; return 1; @@ -647,6 +656,7 @@ cdrom_audio_track_search_pioneer(cdrom_t *dev, uint32_t pos, uint8_t playbit) dev->seek_pos = pos; + dev->audio_muted_soft = 0; /* Do this at this point, since it's at this point that we know the actual LBA position to start playing from. */ if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) { @@ -676,6 +686,7 @@ cdrom_audio_play_pioneer(cdrom_t *dev, uint32_t pos) pos = MSFtoLBA(m, s, f) - 150; dev->cd_end = pos; + dev->audio_muted_soft = 0; dev->cd_buflen = 0; dev->cd_status = CD_STATUS_PLAYING; return 1; @@ -717,16 +728,7 @@ cdrom_audio_play_toshiba(cdrom_t *dev, uint32_t pos, int type) break; } - cdrom_log("Toshiba/NEC Play Audio: MSF = %06x, type = %02x, cdstatus = %02x\n", pos, type, dev->cd_status); - - /* Do this at this point, since it's at this point that we know the - actual LBA position to start playing from. */ - if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) { - cdrom_log("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos); - cdrom_stop(dev); - return 0; - } - + cdrom_log("Toshiba Play Audio: Muted?=%d, LBA=%08X.\n", dev->audio_muted_soft, pos); dev->cd_buflen = 0; dev->cd_status = CD_STATUS_PLAYING; return 1; @@ -770,6 +772,7 @@ cdrom_audio_scan(cdrom_t *dev, uint32_t pos, int type) break; } + dev->audio_muted_soft = 0; /* Do this at this point, since it's at this point that we know the actual LBA position to start playing from. */ if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) { @@ -1007,6 +1010,11 @@ cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b) else ret = (dev->cd_status == CD_STATUS_PLAYING) ? 0x00 : dev->audio_op; + /*If a valid audio track is detected with audio on, unmute it.*/ + if (dev->ops->track_type(dev, dev->seek_pos) & CD_TRACK_AUDIO) + dev->audio_muted_soft = 0; + + cdrom_log("SubCodeQ: Play Status: Seek LBA=%08x, CDEND=%08x, mute=%d.\n", dev->seek_pos, dev->cd_end, dev->audio_muted_soft); b[0] = subc.attr; b[1] = bin2bcd(subc.track); b[2] = bin2bcd(subc.index); @@ -1952,8 +1960,18 @@ cdrom_hard_reset(void) dev->cd_status = CD_STATUS_EMPTY; - if (dev->host_drive == 200) + if (dev->host_drive == 200) { +#ifdef _WIN32 + if ((strlen(dev->image_path) >= 1) && (dev->image_path[strlen(dev->image_path) - 1] == '/')) + dev->image_path[strlen(dev->image_path) - 1] = '\\'; +#else + if ((strlen(dev->image_path) >= 1) && + (dev->image_path[strlen(dev->image_path) - 1] == '\\')) + dev->image_path[strlen(dev->image_path) - 1] = '/'; +#endif + cdrom_image_open(dev, dev->image_path); + } } } @@ -2042,6 +2060,15 @@ cdrom_reload(uint8_t id) if (dev->prev_host_drive == 200) { /* Reload a previous image. */ strcpy(dev->image_path, dev->prev_image_path); + +#ifdef _WIN32 + if ((strlen(dev->image_path) >= 1) && (dev->image_path[strlen(dev->image_path) - 1] == '/')) + dev->image_path[strlen(dev->image_path) - 1] = '\\'; +#else + if ((strlen(dev->image_path) >= 1) && (dev->image_path[strlen(dev->image_path) - 1] == '\\')) + dev->image_path[strlen(dev->image_path) - 1] = '/'; +#endif + cdrom_image_open(dev, dev->image_path); cdrom_insert(id); diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 708354926..9a0fd00ab 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -18,9 +18,11 @@ add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1429.c ali1435.c ali14 compaq_386.c contaq_82c59x.c cs4031.c intel_420ex.c intel_4x0.c intel_i450kx.c intel_815ep.c intel_ich2.c intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c opti495.c opti602.c opti822.c opti895.c opti5x7.c scamp.c scat.c sis_85c310.c sis_85c4xx.c - sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c via_vt82c49x.c via_vt82c505.c - gc100.c stpc.c umc_8886.c umc_hb4.c - via_apollo.c via_pipc.c vl82c480.c wd76c10.c) + sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c sis_5581.c sis_5591.c sis_5600.c + sis_5511_h2p.c sis_5571_h2p.c sis_5581_h2p.c sis_5591_h2p.c sis_5600_h2p.c + sis_5513_p2i.c sis_5513_ide.c sis_5572_usb.c sis_5595_pmu.c sis_55xx.c via_vt82c49x.c + via_vt82c505.c sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c stpc.c + umc_8886.c umc_hb4.c umc_8890.c via_apollo.c via_pipc.c vl82c480.c wd76c10.c) if(OLIVETTI) target_sources(chipset PRIVATE olivetti_eva.c) diff --git a/src/chipset/contaq_82c59x.c b/src/chipset/contaq_82c59x.c index ec7050b1e..5c2910227 100644 --- a/src/chipset/contaq_82c59x.c +++ b/src/chipset/contaq_82c59x.c @@ -311,8 +311,10 @@ contaq_82c59x_close(void *priv) { contaq_82c59x_t *dev = (contaq_82c59x_t *) priv; - smram_del(dev->smram[1]); - smram_del(dev->smram[0]); + if (dev->green) { + smram_del(dev->smram[1]); + smram_del(dev->smram[0]); + } free(dev); } diff --git a/src/chipset/intel_4x0.c b/src/chipset/intel_4x0.c index 1e4158b94..a1f923e49 100644 --- a/src/chipset/intel_4x0.c +++ b/src/chipset/intel_4x0.c @@ -1522,6 +1522,8 @@ i4x0_read(int func, int addr, void *priv) with the addition of bits 3 and 0. */ if ((func == 0) && (addr == 0x93) && ((dev->type == INTEL_440FX) || (dev->type == INTEL_440LX) || (dev->type == INTEL_440EX))) ret = (ret & 0xf9) | (pci_read(0x0cf9, NULL) & 0x06); + else if ((func == 0) && (addr == 0x52) && (dev->type == INTEL_430TX) && !strcmp(machine_get_internal_name(), "tomahawk")) + ret = 0xb2; } return ret; diff --git a/src/chipset/intel_i450kx.c b/src/chipset/intel_i450kx.c index 90b807a6d..2f6547309 100644 --- a/src/chipset/intel_i450kx.c +++ b/src/chipset/intel_i450kx.c @@ -8,19 +8,14 @@ * * Implementation of the Intel 450KX Mars Chipset. * + * i450GX is way more popular of an option but needs more stuff. * + * Authors: Miran Grca, + * Tiseno100, * - * Authors: Tiseno100 - * + * Copyright 2021-2024 Miran Grca. * Copyright 2021 Tiseno100. */ - -/* -Note: i450KX PB manages PCI memory access with MC manages DRAM memory access. -Due to 86Box limitations we can't manage them seperately thus it is dev branch till then. - -i450GX is way more popular of an option but needs more stuff. -*/ #include #include #include @@ -97,17 +92,18 @@ i450kx_smram_recalc(i450kx_t *dev, int bus) const uint8_t *regs = bus ? dev->pb_pci_conf : dev->mc_pci_conf; uint32_t addr; uint32_t size; + int enable = bus ? !(regs[0x57] & 0x08) : (regs[0x57] & 0x08); smram_disable(dev->smram[bus]); addr = ((uint32_t) regs[0xb8] << 16) | ((uint32_t) regs[0xb9] << 24); size = (((uint32_t) ((regs[0xbb] >> 4) & 0x0f)) << 16) + 0x00010000; - if ((addr != 0x00000000) && !!(regs[0x57] & 0x08)) { + if ((addr != 0x00000000) && enable) { if (bus) - smram_enable_ex(dev->smram[bus], addr, addr, size, 0, !!(regs[0x57] & 8), 0, 1); + smram_enable_ex(dev->smram[bus], addr, addr, size, 0, 0, 0, enable); else - smram_enable_ex(dev->smram[bus], addr, addr, size, !!(regs[0x57] & 8), 0, 1, 0); + smram_enable_ex(dev->smram[bus], addr, addr, size, 0, 0, enable, 0); } flushmmucache(); @@ -118,10 +114,8 @@ i450kx_vid_buf_recalc(i450kx_t *dev, int bus) { const uint8_t *regs = bus ? dev->pb_pci_conf : dev->mc_pci_conf; -#if 0 - // int state = (regs[0x58] & 0x02) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_DISABLED | MEM_WRITE_DISABLED); -#endif - int state = (regs[0x58] & 0x02) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY); + int state = (regs[0x58] & 0x02) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : + (MEM_READ_EXTANY | MEM_WRITE_EXTANY); if (bus) mem_set_mem_state_bus_both(0x000a0000, 0x00020000, state); @@ -136,10 +130,10 @@ pb_write(int func, int addr, uint8_t val, void *priv) { i450kx_t *dev = (i450kx_t *) priv; - // pclog("i450KX-PB: [W] dev->pb_pci_conf[%02X] = %02X POST: %02X\n", addr, val, inb(0x80)); - i450kx_log("i450KX-PB: [W] dev->pb_pci_conf[%02X] = %02X POST: %02X\n", addr, val, inb(0x80)); + if (func == 0) { + i450kx_log("[%04X:%08X] i450KX-PB: [W] dev->pb_pci_conf[%02X] = %02X\n", CS, cpu_state.pc, + addr, val); - if (func == 0) switch (addr) { case 0x04: dev->pb_pci_conf[addr] = (dev->pb_pci_conf[addr] & 0x04) | (val & 0x53); @@ -373,6 +367,7 @@ pb_write(int func, int addr, uint8_t val, void *priv) default: break; } + } } static uint8_t @@ -381,10 +376,12 @@ pb_read(int func, int addr, void *priv) const i450kx_t *dev = (i450kx_t *) priv; uint8_t ret = 0xff; - if (func == 0) + if (func == 0) { ret = dev->pb_pci_conf[addr]; - // pclog("i450KX-PB: [R] dev->pb_pci_conf[%02X] = %02X POST: %02X\n", addr, ret, inb(0x80)); + i450kx_log("[%04X:%08X] i450KX-PB: [R] dev->pb_pci_conf[%02X] = %02X\n", CS, cpu_state.pc, + addr, ret); + } return ret; } @@ -407,10 +404,10 @@ mc_write(int func, int addr, uint8_t val, void *priv) { i450kx_t *dev = (i450kx_t *) priv; - // pclog("i450KX-MC: [W] dev->mc_pci_conf[%02X] = %02X POST: %02X\n", addr, val, inb(0x80)); - i450kx_log("i450KX-MC: [W] dev->mc_pci_conf[%02X] = %02X POST: %02X\n", addr, val, inb(0x80)); + if (func == 0) { + i450kx_log("[%04X:%08X] i450KX-MC: [W] dev->mc_pci_conf[%02X] = %02X\n", CS, cpu_state.pc, + addr, val); - if (func == 0) switch (addr) { case 0x4c: dev->mc_pci_conf[addr] = val & 0xdf; @@ -600,6 +597,7 @@ mc_write(int func, int addr, uint8_t val, void *priv) default: break; } + } } static uint8_t @@ -608,10 +606,12 @@ mc_read(int func, int addr, void *priv) const i450kx_t *dev = (i450kx_t *) priv; uint8_t ret = 0xff; - if (func == 0) + if (func == 0) { ret = dev->mc_pci_conf[addr]; - // pclog("i450KX-MC: [R] dev->mc_pci_conf[%02X] = %02X POST: %02X\n", addr, ret, inb(0x80)); + i450kx_log("[%04X:%08X] i450KX-MC: [R] dev->mc_pci_conf[%02X] = %02X\n", CS, cpu_state.pc, + addr, ret); + } return ret; } @@ -622,10 +622,6 @@ i450kx_reset(void *priv) i450kx_t *dev = (i450kx_t *) priv; uint32_t i; -#if 0 - // pclog("i450KX: i450kx_reset()\n"); -#endif - /* Defaults PB */ dev->pb_pci_conf[0x00] = 0x86; dev->pb_pci_conf[0x01] = 0x80; diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index 49d720d8b..1f95c28b3 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -1578,7 +1578,16 @@ piix_init(const device_t *info) dev->acpi = device_add(&acpi_intel_device); acpi_set_slot(dev->acpi, dev->pci_slot); acpi_set_nvr(dev->acpi, dev->nvr); - acpi_set_gpireg2_default(dev->acpi, (dev->type > 4) ? 0xf1 : 0xdd); + /* + TriGem Richmond: + - Bit 5: Manufacturing jumper, must be set; + - Bit 4: CMOS clear jumper, must be clear; + - Bit 0: Password switch, must be clear. + */ + if (!strcmp(machine_get_internal_name(), "richmond")) + acpi_set_gpireg2_default(dev->acpi, 0xee); + else + acpi_set_gpireg2_default(dev->acpi, (dev->type > 4) ? 0xf1 : 0xdd); acpi_set_trap_update(dev->acpi, piix_trap_update, dev); dev->ddma = device_add(&ddma_device); diff --git a/src/chipset/sis_5511.c b/src/chipset/sis_5511.c index e58066c95..aa841ed9c 100644 --- a/src/chipset/sis_5511.c +++ b/src/chipset/sis_5511.c @@ -25,9 +25,10 @@ #include <86box/device.h> #include <86box/io.h> #include <86box/timer.h> - #include <86box/mem.h> #include <86box/nvr.h> +#include <86box/apm.h> +#include <86box/acpi.h> #include <86box/hdd.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> @@ -41,7 +42,7 @@ #include <86box/port_92.h> #include <86box/smram.h> #include <86box/spd.h> - +#include <86box/sis_55xx.h> #include <86box/chipset.h> #ifdef ENABLE_SIS_5511_LOG @@ -63,573 +64,53 @@ sis_5511_log(const char *fmt, ...) #endif typedef struct sis_5511_t { - uint8_t index; - uint8_t nb_slot; - uint8_t sb_slot; - uint8_t pad; + uint8_t nb_slot; + uint8_t sb_slot; - uint8_t regs[16]; - uint8_t states[7]; + void *h2p; - uint8_t slic_regs[4096]; + void *p2i; + void *ide; - uint8_t pci_conf[256]; - uint8_t pci_conf_sb[2][256]; - - mem_mapping_t slic_mapping; - - sff8038i_t *bm[2]; - smram_t *smram; - port_92_t *port_92; - void *pit; - nvr_t *nvr; - - uint8_t (*pit_read_reg)(void *priv, uint8_t reg); + sis_55xx_common_t *sis; } sis_5511_t; static void -sis_5511_shadow_recalc(sis_5511_t *dev) +sis_5511_write(int func, int addr, uint8_t val, void *priv) { - int state; - uint32_t base; - - for (uint8_t i = 0x80; i <= 0x86; i++) { - if (i == 0x86) { - if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) { - state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - mem_set_mem_state_both(0xf0000, 0x10000, state); - sis_5511_log("000F0000-000FFFFF\n"); - } - } else { - base = ((i & 0x07) << 15) + 0xc0000; - - if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) { - state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - mem_set_mem_state_both(base, 0x4000, state); - sis_5511_log("%08X-%08X\n", base, base + 0x3fff); - } - - if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0x0a) { - state = (dev->pci_conf[i] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - state |= (dev->pci_conf[i] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - mem_set_mem_state_both(base + 0x4000, 0x4000, state); - sis_5511_log("%08X-%08X\n", base + 0x4000, base + 0x7fff); - } - } - - dev->states[i & 0x0f] = dev->pci_conf[i]; - } - - flushmmucache_nopc(); -} - -static void -sis_5511_smram_recalc(sis_5511_t *dev) -{ - smram_disable_all(); - - switch (dev->pci_conf[0x65] >> 6) { - case 0: - smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1); - break; - case 1: - smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1); - break; - case 2: - smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1); - break; - - default: - break; - } - - flushmmucache(); -} - -static void -sis_5511_write(UNUSED(int func), int addr, uint8_t val, void *priv) -{ - sis_5511_t *dev = (sis_5511_t *) priv; + const sis_5511_t *dev = (sis_5511_t *) priv; sis_5511_log("SiS 5511: [W] dev->pci_conf[%02X] = %02X\n", addr, val); - if (func == 0x00) switch (addr) { - case 0x07: /* Status - High Byte */ - dev->pci_conf[addr] &= 0xb0; - break; - - case 0x50: - dev->pci_conf[addr] = val; - cpu_cache_ext_enabled = !!(val & 0x40); - cpu_update_waitstates(); - break; - - case 0x51: - dev->pci_conf[addr] = val & 0xfe; - break; - - case 0x52: - dev->pci_conf[addr] = val & 0x3f; - break; - - case 0x53: - case 0x54: - dev->pci_conf[addr] = val; - break; - - case 0x55: - dev->pci_conf[addr] = val & 0xf8; - break; - - case 0x56 ... 0x59: - dev->pci_conf[addr] = val; - break; - - case 0x5a: - /* TODO: Fast Gate A20 Emulation and Fast Reset Emulation on the KBC. - The former (bit 7) means the chipset intercepts D1h to 64h and 00h to 60h. - The latter (bit 6) means the chipset intercepts all odd FXh to 64h. - Bit 5 sets fast reset latency. This should be fixed on the other SiS - chipsets as well. */ - dev->pci_conf[addr] = val; - break; - - case 0x5b: - dev->pci_conf[addr] = val & 0xf7; - break; - - case 0x5c: - dev->pci_conf[addr] = val & 0xcf; - break; - - case 0x5d: - dev->pci_conf[addr] = val; - break; - - case 0x5e: - dev->pci_conf[addr] = val & 0xfe; - break; - - case 0x5f: - dev->pci_conf[addr] = val & 0xfe; - break; - - case 0x60: - dev->pci_conf[addr] = val & 0x3e; - if ((dev->pci_conf[0x68] & 1) && (val & 2)) { - smi_raise(); - dev->pci_conf[0x69] |= 1; - } - break; - - case 0x61 ... 0x64: - dev->pci_conf[addr] = val; - break; - - case 0x65: - dev->pci_conf[addr] = val & 0xd0; - sis_5511_smram_recalc(dev); - break; - - case 0x66: - dev->pci_conf[addr] = val & 0x7f; - break; - - case 0x67: - case 0x68: - dev->pci_conf[addr] = val; - break; - - case 0x69: - dev->pci_conf[addr] &= val; - break; - - case 0x6a ... 0x6e: - dev->pci_conf[addr] = val; - break; - - case 0x6f: - dev->pci_conf[addr] = val & 0x3f; - break; - - case 0x70: /* DRAM Bank Register 0-0 */ - case 0x72: /* DRAM Bank Register 0-1 */ - case 0x74: /* DRAM Bank Register 1-0 */ - case 0x76: /* DRAM Bank Register 1-1 */ - case 0x78: /* DRAM Bank Register 2-0 */ - case 0x7a: /* DRAM Bank Register 2-1 */ - case 0x7c: /* DRAM Bank Register 3-0 */ - case 0x7e: /* DRAM Bank Register 3-1 */ - spd_write_drbs(dev->pci_conf, 0x70, 0x7e, 0x82); - break; - - case 0x71: /* DRAM Bank Register 0-0 */ - dev->pci_conf[addr] = val; - break; - - case 0x75: /* DRAM Bank Register 1-0 */ - case 0x79: /* DRAM Bank Register 2-0 */ - case 0x7d: /* DRAM Bank Register 3-0 */ - dev->pci_conf[addr] = val & 0x7f; - break; - - case 0x73: /* DRAM Bank Register 0-1 */ - case 0x77: /* DRAM Bank Register 1-1 */ - case 0x7b: /* DRAM Bank Register 2-1 */ - case 0x7f: /* DRAM Bank Register 3-1 */ - dev->pci_conf[addr] = val & 0x83; - break; - - case 0x80 ... 0x85: - dev->pci_conf[addr] = val & 0xee; - sis_5511_shadow_recalc(dev); - break; - case 0x86: - dev->pci_conf[addr] = val & 0xe8; - sis_5511_shadow_recalc(dev); - break; - - case 0x90 ... 0x93: /* 5512 General Purpose Register Index */ - dev->pci_conf[addr] = val; - break; - - default: - break; - } -} - -static void -sis_5511_slic_write(uint32_t addr, uint8_t val, void *priv) -{ - sis_5511_t *dev = (sis_5511_t *) priv; - - addr &= 0x00000fff; - - switch (addr) { - case 0x00000000: - case 0x00000008: /* 0x00000008 is a SiS 5512 register. */ - dev->slic_regs[addr] = val; - break; - case 0x00000010: - case 0x00000018: - case 0x00000028: - case 0x00000038: - dev->slic_regs[addr] = val & 0x01; - break; - case 0x00000030: - dev->slic_regs[addr] = val & 0x0f; - mem_mapping_set_addr(&dev->slic_mapping, - (((uint32_t) (val & 0x0f)) << 28) | 0x0fc00000, 0x00001000); - break; - } + if (func == 0x00) + sis_5511_host_to_pci_write(addr, val, dev->h2p); } static uint8_t -sis_5511_read(UNUSED(int func), int addr, void *priv) +sis_5511_read(int func, int addr, void *priv) { const sis_5511_t *dev = (sis_5511_t *) priv; uint8_t ret = 0xff; if (func == 0x00) - ret = dev->pci_conf[addr]; + ret = sis_5511_host_to_pci_read(addr, dev->h2p); sis_5511_log("SiS 5511: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); return ret; } -static uint8_t -sis_5511_slic_read(uint32_t addr, void *priv) -{ - sis_5511_t *dev = (sis_5511_t *) priv; - uint8_t ret = 0xff; - - addr &= 0x00000fff; - - switch (addr) { - case 0x00000008: /* 0x00000008 is a SiS 5512 register. */ - ret = dev->slic_regs[addr]; - break; - } - - return ret; -} - -void -sis_5513_pci_to_isa_write(int addr, uint8_t val, sis_5511_t *dev) -{ - sis_5511_log("SiS 5513 P2I: [W] dev->pci_conf_sb[0][%02X] = %02X\n", addr, val); - - switch (addr) { - case 0x04: /* Command */ - dev->pci_conf_sb[0][addr] = val & 0x0f; - break; - - case 0x07: /* Status */ - dev->pci_conf_sb[0][addr] = (dev->pci_conf_sb[0][addr] & 0x06) & ~(val & 0x30); - break; - - case 0x40: /* BIOS Control Register */ - dev->pci_conf_sb[0][addr] = val & 0x3f; - break; - - case 0x41: /* INTA# Remapping Control Register */ - case 0x42: /* INTB# Remapping Control Register */ - case 0x43: /* INTC# Remapping Control Register */ - case 0x44: /* INTD# Remapping Control Register */ - dev->pci_conf_sb[0][addr] = val & 0x8f; - pci_set_irq_routing(addr & 0x07, (val & 0x80) ? PCI_IRQ_DISABLED : (val & 0x0f)); - break; - - case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */ - case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */ - case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */ - case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */ - dev->pci_conf_sb[0][addr] = val; - break; - - case 0x60: /* MIRQ0 Remapping Control Register */ - case 0x61: /* MIRQ1 Remapping Control Register */ - sis_5511_log("Set MIRQ routing: MIRQ%i -> %02X\n", addr & 0x01, val); - dev->pci_conf_sb[0][addr] = val & 0xcf; - if (val & 0x80) - pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), PCI_IRQ_DISABLED); - else - pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), val & 0xf); - break; - - case 0x62: /* On-board Device DMA Control Register */ - dev->pci_conf_sb[0][addr] = val; - break; - - case 0x63: /* IDEIRQ Remapping Control Register */ - sis_5511_log("Set MIRQ routing: IDEIRQ -> %02X\n", val); - dev->pci_conf_sb[0][addr] = val & 0x8f; - if (val & 0x80) - pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); - else - pci_set_mirq_routing(PCI_MIRQ2, val & 0xf); - break; - - case 0x64: /* GPIO0 Control Register */ - dev->pci_conf_sb[0][addr] = val & 0xef; - break; - - case 0x65: - dev->pci_conf_sb[0][addr] = val & 0x80; - break; - - case 0x66: /* GPIO0 Output Mode Control Register */ - case 0x67: /* GPIO0 Output Mode Control Register */ - dev->pci_conf_sb[0][addr] = val; - break; - - case 0x6a: /* GPIO Status Register */ - dev->pci_conf_sb[0][addr] |= (val & 0x10); - dev->pci_conf_sb[0][addr] &= ~(val & 0x01); - break; - - default: - break; - } -} - -static void -sis_5513_ide_irq_handler(sis_5511_t *dev) -{ - if (dev->pci_conf_sb[1][0x09] & 0x01) { - /* Primary IDE is native. */ - sis_5511_log("Primary IDE IRQ mode: Native, Native\n"); - sff_set_irq_mode(dev->bm[0], IRQ_MODE_SIS_551X); - } else { - /* Primary IDE is legacy. */ - sis_5511_log("Primary IDE IRQ mode: IRQ14, IRQ15\n"); - sff_set_irq_mode(dev->bm[0], IRQ_MODE_LEGACY); - } - - if (dev->pci_conf_sb[1][0x09] & 0x04) { - /* Secondary IDE is native. */ - sis_5511_log("Secondary IDE IRQ mode: Native, Native\n"); - sff_set_irq_mode(dev->bm[1], IRQ_MODE_SIS_551X); - } else { - /* Secondary IDE is legacy. */ - sis_5511_log("Secondary IDE IRQ mode: IRQ14, IRQ15\n"); - sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY); - } -} - -static void -sis_5513_ide_handler(sis_5511_t *dev) -{ - uint8_t ide_io_on = dev->pci_conf_sb[1][0x04] & 0x01; - - uint16_t native_base_pri_addr = (dev->pci_conf_sb[1][0x11] | dev->pci_conf_sb[1][0x10] << 8) & 0xfffe; - uint16_t native_side_pri_addr = (dev->pci_conf_sb[1][0x15] | dev->pci_conf_sb[1][0x14] << 8) & 0xfffe; - uint16_t native_base_sec_addr = (dev->pci_conf_sb[1][0x19] | dev->pci_conf_sb[1][0x18] << 8) & 0xfffe; - uint16_t native_side_sec_addr = (dev->pci_conf_sb[1][0x1c] | dev->pci_conf_sb[1][0x1b] << 8) & 0xfffe; - - uint16_t current_pri_base; - uint16_t current_pri_side; - uint16_t current_sec_base; - uint16_t current_sec_side; - - /* Primary Channel Programming */ - current_pri_base = (!(dev->pci_conf_sb[1][0x09] & 1)) ? 0x01f0 : native_base_pri_addr; - current_pri_side = (!(dev->pci_conf_sb[1][0x09] & 1)) ? 0x03f6 : native_side_pri_addr; - - /* Secondary Channel Programming */ - current_sec_base = (!(dev->pci_conf_sb[1][0x09] & 4)) ? 0x0170 : native_base_sec_addr; - current_sec_side = (!(dev->pci_conf_sb[1][0x09] & 4)) ? 0x0376 : native_side_sec_addr; - - sis_5511_log("sis_5513_ide_handler(): Disabling primary IDE...\n"); - ide_pri_disable(); - sis_5511_log("sis_5513_ide_handler(): Disabling secondary IDE...\n"); - ide_sec_disable(); - - if (ide_io_on) { - /* Primary Channel Setup */ - if (dev->pci_conf_sb[1][0x4a] & 0x02) { - sis_5511_log("sis_5513_ide_handler(): Primary IDE base now %04X...\n", current_pri_base); - ide_set_base(0, current_pri_base); - sis_5511_log("sis_5513_ide_handler(): Primary IDE side now %04X...\n", current_pri_side); - ide_set_side(0, current_pri_side); - - sis_5511_log("sis_5513_ide_handler(): Enabling primary IDE...\n"); - ide_pri_enable(); - - sis_5511_log("SiS 5513 PRI: BASE %04x SIDE %04x\n", current_pri_base, current_pri_side); - } - - /* Secondary Channel Setup */ - if (dev->pci_conf_sb[1][0x4a] & 0x04) { - sis_5511_log("sis_5513_ide_handler(): Secondary IDE base now %04X...\n", current_sec_base); - ide_set_base(1, current_sec_base); - sis_5511_log("sis_5513_ide_handler(): Secondary IDE side now %04X...\n", current_sec_side); - ide_set_side(1, current_sec_side); - - sis_5511_log("sis_5513_ide_handler(): Enabling secondary IDE...\n"); - ide_sec_enable(); - - sis_5511_log("SiS 5513: BASE %04x SIDE %04x\n", current_sec_base, current_sec_side); - } - } - - sff_bus_master_handler(dev->bm[0], ide_io_on, - ((dev->pci_conf_sb[1][0x20] & 0xf0) | (dev->pci_conf_sb[1][0x21] << 8)) + 0); - sff_bus_master_handler(dev->bm[1], ide_io_on, - ((dev->pci_conf_sb[1][0x20] & 0xf0) | (dev->pci_conf_sb[1][0x21] << 8)) + 8); -} - -void -sis_5513_ide_write(int addr, uint8_t val, sis_5511_t *dev) -{ - sis_5511_log("SiS 5513 IDE: [W] dev->pci_conf_sb[1][%02X] = %02X\n", addr, val); - - switch (addr) { - case 0x04: /* Command low byte */ - dev->pci_conf_sb[1][addr] = val & 0x05; - sis_5513_ide_handler(dev); - break; - case 0x06: /* Status low byte */ - dev->pci_conf_sb[1][addr] = val & 0x20; - break; - case 0x07: /* Status high byte */ - dev->pci_conf_sb[1][addr] = (dev->pci_conf_sb[1][addr] & 0x06) & ~(val & 0x38); - break; - case 0x09: /* Programming Interface Byte */ - dev->pci_conf_sb[1][addr] = (dev->pci_conf_sb[1][addr] & 0x8a) | (val & 0x05); - sis_5513_ide_irq_handler(dev); - sis_5513_ide_handler(dev); - break; - case 0x0d: /* Latency Timer */ - dev->pci_conf_sb[1][addr] = val; - break; - - /* Primary Base Address */ - case 0x10: - case 0x11: - case 0x14: - case 0x15: - fallthrough; - - /* Secondary Base Address */ - case 0x18: - case 0x19: - case 0x1c: - case 0x1d: - fallthrough; - - /* Bus Mastering Base Address */ - case 0x20: - case 0x21: - if (addr == 0x20) - dev->pci_conf_sb[1][addr] = (val & 0xe0) | 0x01; - else - dev->pci_conf_sb[1][addr] = val; - sis_5513_ide_handler(dev); - break; - - case 0x30: /* Expansion ROM Base Address */ - case 0x31: /* Expansion ROM Base Address */ - case 0x32: /* Expansion ROM Base Address */ - case 0x33: /* Expansion ROM Base Address */ - dev->pci_conf_sb[1][addr] = val; - break; - - case 0x40: /* IDE Primary Channel/Master Drive Data Recovery Time Control */ - case 0x42: /* IDE Primary Channel/Slave Drive Data Recovery Time Control */ - case 0x44: /* IDE Secondary Channel/Master Drive Data Recovery Time Control */ - case 0x46: /* IDE Secondary Channel/Slave Drive Data Recovery Time Control */ - case 0x48: /* IDE Command Recovery Time Control */ - dev->pci_conf_sb[1][addr] = val & 0x0f; - break; - - case 0x41: /* IDE Primary Channel/Master Drive DataActive Time Control */ - case 0x43: /* IDE Primary Channel/Slave Drive Data Active Time Control */ - case 0x45: /* IDE Secondary Channel/Master Drive Data Active Time Control */ - case 0x47: /* IDE Secondary Channel/Slave Drive Data Active Time Control */ - case 0x49: /* IDE Command Active Time Control */ - dev->pci_conf_sb[1][addr] = val & 0x07; - break; - - case 0x4a: /* IDE General Control Register 0 */ - dev->pci_conf_sb[1][addr] = val & 0x9e; - sis_5513_ide_handler(dev); - break; - - case 0x4b: /* IDE General Control Register 1 */ - dev->pci_conf_sb[1][addr] = val & 0xef; - break; - - case 0x4c: /* Prefetch Count of Primary Channel (Low Byte) */ - case 0x4d: /* Prefetch Count of Primary Channel (High Byte) */ - case 0x4e: /* Prefetch Count of Secondary Channel (Low Byte) */ - case 0x4f: /* Prefetch Count of Secondary Channel (High Byte) */ - dev->pci_conf_sb[1][addr] = val; - break; - - default: - break; - } -} - static void sis_5513_write(int func, int addr, uint8_t val, void *priv) { - sis_5511_t *dev = (sis_5511_t *) priv; + const sis_5511_t *dev = (sis_5511_t *) priv; - switch (func) { - default: - break; - case 0: - sis_5513_pci_to_isa_write(addr, val, dev); - break; - case 1: - sis_5513_ide_write(addr, val, dev); - break; - } + sis_5511_log("SiS 5513: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + if (func == 0x00) + sis_5513_pci_to_isa_write(addr, val, dev->p2i); + else if (func == 0x01) + sis_5513_ide_write(addr, val, dev->ide); } static uint8_t @@ -638,281 +119,21 @@ sis_5513_read(int func, int addr, void *priv) const sis_5511_t *dev = (sis_5511_t *) priv; uint8_t ret = 0xff; - if (func == 0x00) { - switch (addr) { - default: - ret = dev->pci_conf_sb[func][addr]; - break; - case 0x4c ... 0x4f: - ret = pic_read_icw(0, addr & 0x03); - break; - case 0x50 ... 0x53: - ret = pic_read_icw(1, addr & 0x03); - break; - case 0x54 ... 0x55: - ret = pic_read_ocw(0, addr & 0x01); - break; - case 0x56 ... 0x57: - ret = pic_read_ocw(1, addr & 0x01); - break; - case 0x58 ... 0x5f: - ret = dev->pit_read_reg(dev->pit, addr & 0x07); - break; - } + if (func == 0x00) + ret = sis_5513_pci_to_isa_read(addr, dev->p2i); + else if (func == 0x01) + ret = sis_5513_ide_read(addr, dev->ide); - sis_5511_log("SiS 5513 P2I: [R] dev->pci_conf_sb[0][%02X] = %02X\n", addr, ret); - } else if (func == 0x01) { - if (addr == 0x3d) - ret = (((dev->pci_conf_sb[0x01][0x4b] & 0xc0) == 0xc0) || - (dev->pci_conf_sb[0x01][0x09] & 0x05)) ? PCI_INTA : 0x00; - else - ret = dev->pci_conf_sb[func][addr]; - - sis_5511_log("SiS 5513 IDE: [R] dev->pci_conf_sb[1][%02X] = %02X\n", addr, ret); - } + sis_5511_log("SiS 5513: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); return ret; } -static void -sis_5513_isa_write(uint16_t addr, uint8_t val, void *priv) -{ - sis_5511_t *dev = (sis_5511_t *) priv; - - switch (addr) { - case 0x22: - dev->index = val - 0x50; - break; - case 0x23: - sis_5511_log("SiS 5513 ISA: [W] dev->regs[%02X] = %02X\n", dev->index + 0x50, val); - - switch (dev->index) { - case 0x00: - dev->regs[dev->index] = val & 0xed; - switch (val >> 6) { - case 0: - cpu_set_isa_speed(7159091); - break; - case 1: - cpu_set_isa_pci_div(4); - break; - case 2: - cpu_set_isa_pci_div(3); - break; - - default: - break; - } - nvr_bank_set(0, !!(val & 0x08), dev->nvr); - break; - case 0x01: - dev->regs[dev->index] = val & 0xf4; - break; - case 0x03: - dev->regs[dev->index] = val & 3; - break; - case 0x04: /* BIOS Register */ - dev->regs[dev->index] = val; - break; - case 0x05: - dev->regs[dev->index] = val; - outb(0x70, val); - break; - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - dev->regs[dev->index] = val; - break; - - default: - break; - } - break; - - default: - break; - } -} - -static uint8_t -sis_5513_isa_read(uint16_t addr, void *priv) -{ - const sis_5511_t *dev = (sis_5511_t *) priv; - uint8_t ret = 0xff; - - if (addr == 0x23) { - if (dev->index == 0x05) - ret = inb(0x70); - else - ret = dev->regs[dev->index]; - - sis_5511_log("SiS 5513 ISA: [R] dev->regs[%02X] = %02X\n", dev->index + 0x50, ret); - } - - return ret; -} - -static void -sis_5511_reset(void *priv) -{ - sis_5511_t *dev = (sis_5511_t *) priv; - - /* SiS 5511 */ - dev->pci_conf[0x00] = 0x39; - dev->pci_conf[0x01] = 0x10; - dev->pci_conf[0x02] = 0x11; - dev->pci_conf[0x03] = 0x55; - dev->pci_conf[0x04] = 0x07; - dev->pci_conf[0x05] = dev->pci_conf[0x06] = 0x00; - dev->pci_conf[0x07] = 0x02; - dev->pci_conf[0x08] = 0x00; - dev->pci_conf[0x09] = dev->pci_conf[0x0a] = 0x00; - dev->pci_conf[0x0b] = 0x06; - dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x00; - dev->pci_conf[0x52] = 0x20; - dev->pci_conf[0x53] = dev->pci_conf[0x54] = 0x00; - dev->pci_conf[0x55] = dev->pci_conf[0x56] = 0x00; - dev->pci_conf[0x57] = dev->pci_conf[0x58] = 0x00; - dev->pci_conf[0x59] = dev->pci_conf[0x5a] = 0x00; - dev->pci_conf[0x5b] = dev->pci_conf[0x5c] = 0x00; - dev->pci_conf[0x5d] = dev->pci_conf[0x5e] = 0x00; - dev->pci_conf[0x5f] = dev->pci_conf[0x60] = 0x00; - dev->pci_conf[0x61] = dev->pci_conf[0x62] = 0xff; - dev->pci_conf[0x63] = 0xff; - dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00; - dev->pci_conf[0x66] = 0x00; - dev->pci_conf[0x67] = 0xff; - dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00; - dev->pci_conf[0x6a] = 0x00; - dev->pci_conf[0x6b] = dev->pci_conf[0x6c] = 0xff; - dev->pci_conf[0x6d] = dev->pci_conf[0x6e] = 0xff; - dev->pci_conf[0x6f] = 0x00; - dev->pci_conf[0x70] = dev->pci_conf[0x72] = 0x04; - dev->pci_conf[0x74] = dev->pci_conf[0x76] = 0x04; - dev->pci_conf[0x78] = dev->pci_conf[0x7a] = 0x04; - dev->pci_conf[0x7c] = dev->pci_conf[0x7e] = 0x04; - dev->pci_conf[0x71] = dev->pci_conf[0x75] = 0x00; - dev->pci_conf[0x73] = dev->pci_conf[0x77] = 0x80; - dev->pci_conf[0x79] = dev->pci_conf[0x7d] = 0x00; - dev->pci_conf[0x7b] = dev->pci_conf[0x7f] = 0x80; - dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00; - dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00; - dev->pci_conf[0x84] = dev->pci_conf[0x85] = 0x00; - dev->pci_conf[0x86] = 0x00; - - cpu_cache_ext_enabled = 0; - cpu_update_waitstates(); - - sis_5511_smram_recalc(dev); - sis_5511_shadow_recalc(dev); - - flushmmucache(); - - memset(dev->slic_regs, 0x00, 4096 * sizeof(uint8_t)); - dev->slic_regs[0x18] = 0x0f; - - mem_mapping_set_addr(&dev->slic_mapping, 0xffc00000, 0x00001000); - - /* SiS 5513 */ - dev->pci_conf_sb[0][0x00] = 0x39; - dev->pci_conf_sb[0][0x01] = 0x10; - dev->pci_conf_sb[0][0x02] = 0x08; - dev->pci_conf_sb[0][0x03] = 0x00; - dev->pci_conf_sb[0][0x04] = 0x07; - dev->pci_conf_sb[0][0x05] = dev->pci_conf_sb[0][0x06] = 0x00; - dev->pci_conf_sb[0][0x07] = 0x02; - dev->pci_conf_sb[0][0x08] = dev->pci_conf_sb[0][0x09] = 0x00; - dev->pci_conf_sb[0][0x0a] = 0x01; - dev->pci_conf_sb[0][0x0b] = 0x06; - dev->pci_conf_sb[0][0x0e] = 0x80; - dev->pci_conf_sb[0][0x40] = 0x00; - dev->pci_conf_sb[0][0x41] = dev->pci_conf_sb[0][0x42] = 0x80; - dev->pci_conf_sb[0][0x43] = dev->pci_conf_sb[0][0x44] = 0x80; - dev->pci_conf_sb[0][0x48] = dev->pci_conf_sb[0][0x49] = 0x00; - dev->pci_conf_sb[0][0x4a] = dev->pci_conf_sb[0][0x4b] = 0x00; - dev->pci_conf_sb[0][0x60] = dev->pci_conf_sb[0][0x61] = 0x80; - dev->pci_conf_sb[0][0x62] = 0x00; - dev->pci_conf_sb[0][0x63] = 0x80; - dev->pci_conf_sb[0][0x64] = 0x00; - dev->pci_conf_sb[0][0x65] = 0x00; - dev->pci_conf_sb[0][0x66] = dev->pci_conf_sb[0][0x67] = 0x00; - dev->pci_conf_sb[0][0x68] = dev->pci_conf_sb[0][0x69] = 0x00; - dev->pci_conf_sb[0][0x6a] = 0x04; - - pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); - - pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); - pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); - pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); - - dev->regs[0x00] = dev->regs[0x01] = 0x00; - dev->regs[0x03] = dev->regs[0x04] = 0x00; - dev->regs[0x05] = 0x00; - dev->regs[0x08] = dev->regs[0x09] = 0x00; - dev->regs[0x0a] = dev->regs[0x0b] = 0x00; - - cpu_set_isa_speed(7159091); - nvr_bank_set(0, 0, dev->nvr); - - /* SiS 5513 IDE Controller */ - dev->pci_conf_sb[1][0x00] = 0x39; - dev->pci_conf_sb[1][0x01] = 0x10; - dev->pci_conf_sb[1][0x02] = 0x13; - dev->pci_conf_sb[1][0x03] = 0x55; - dev->pci_conf_sb[1][0x04] = dev->pci_conf_sb[1][0x05] = 0x00; - dev->pci_conf_sb[1][0x06] = dev->pci_conf_sb[1][0x07] = 0x00; - dev->pci_conf_sb[1][0x08] = 0x00; - dev->pci_conf_sb[1][0x09] = 0x8a; - dev->pci_conf_sb[1][0x0a] = dev->pci_conf_sb[1][0x0b] = 0x01; - dev->pci_conf_sb[1][0x0c] = dev->pci_conf_sb[1][0x0d] = 0x00; - dev->pci_conf_sb[1][0x0e] = 0x80; - dev->pci_conf_sb[1][0x0f] = 0x00; - dev->pci_conf_sb[1][0x10] = 0xf1; - dev->pci_conf_sb[1][0x11] = 0x01; - dev->pci_conf_sb[1][0x14] = 0xf5; - dev->pci_conf_sb[1][0x15] = 0x03; - dev->pci_conf_sb[1][0x18] = 0x71; - dev->pci_conf_sb[1][0x19] = 0x01; - dev->pci_conf_sb[1][0x1c] = 0x75; - dev->pci_conf_sb[1][0x1d] = 0x03; - dev->pci_conf_sb[1][0x20] = 0x01; - dev->pci_conf_sb[1][0x21] = 0xf0; - dev->pci_conf_sb[1][0x22] = dev->pci_conf_sb[1][0x23] = 0x00; - dev->pci_conf_sb[1][0x24] = dev->pci_conf_sb[1][0x25] = 0x00; - dev->pci_conf_sb[1][0x26] = dev->pci_conf_sb[1][0x27] = 0x00; - dev->pci_conf_sb[1][0x28] = dev->pci_conf_sb[1][0x29] = 0x00; - dev->pci_conf_sb[1][0x2a] = dev->pci_conf_sb[1][0x2b] = 0x00; - dev->pci_conf_sb[1][0x2c] = dev->pci_conf_sb[1][0x2d] = 0x00; - dev->pci_conf_sb[1][0x2e] = dev->pci_conf_sb[1][0x2f] = 0x00; - dev->pci_conf_sb[1][0x30] = dev->pci_conf_sb[1][0x31] = 0x00; - dev->pci_conf_sb[1][0x32] = dev->pci_conf_sb[1][0x33] = 0x00; - dev->pci_conf_sb[1][0x40] = dev->pci_conf_sb[1][0x41] = 0x00; - dev->pci_conf_sb[1][0x42] = dev->pci_conf_sb[1][0x43] = 0x00; - dev->pci_conf_sb[1][0x44] = dev->pci_conf_sb[1][0x45] = 0x00; - dev->pci_conf_sb[1][0x46] = dev->pci_conf_sb[1][0x47] = 0x00; - dev->pci_conf_sb[1][0x48] = dev->pci_conf_sb[1][0x49] = 0x00; - dev->pci_conf_sb[1][0x4a] = 0x06; - dev->pci_conf_sb[1][0x4b] = 0x00; - dev->pci_conf_sb[1][0x4c] = dev->pci_conf_sb[1][0x4d] = 0x00; - dev->pci_conf_sb[1][0x4e] = dev->pci_conf_sb[1][0x4f] = 0x00; - - sis_5513_ide_irq_handler(dev); - sis_5513_ide_handler(dev); - - sff_bus_master_reset(dev->bm[0]); - sff_bus_master_reset(dev->bm[1]); -} - static void sis_5511_close(void *priv) { sis_5511_t *dev = (sis_5511_t *) priv; - smram_del(dev->smram); free(dev); } @@ -920,53 +141,18 @@ static void * sis_5511_init(UNUSED(const device_t *info)) { sis_5511_t *dev = (sis_5511_t *) calloc(1, sizeof(sis_5511_t)); - uint8_t pit_is_fast = (((pit_mode == -1) && is486) || (pit_mode == 1)); /* Device 0: SiS 5511 */ pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5511_read, sis_5511_write, dev, &dev->nb_slot); /* Device 1: SiS 5513 */ pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5513_read, sis_5513_write, dev, &dev->sb_slot); - /* SLiC Memory Mapped Registers */ - mem_mapping_add(&dev->slic_mapping, - 0xffc00000, 0x00001000, - sis_5511_slic_read, - NULL, - NULL, - sis_5511_slic_write, - NULL, - NULL, - NULL, MEM_MAPPING_EXTERNAL, - dev); + dev->sis = device_add(&sis_55xx_common_device); - /* Ports 22h-23h: SiS 5513 ISA */ - io_sethandler(0x0022, 0x0002, sis_5513_isa_read, NULL, NULL, sis_5513_isa_write, NULL, NULL, dev); + dev->h2p = device_add_linked(&sis_5511_h2p_device, dev->sis); - /* MIRQ */ - pci_enable_mirq(0); - pci_enable_mirq(1); - - /* IDEIRQ */ - pci_enable_mirq(2); - - /* Port 92h */ - dev->port_92 = device_add(&port_92_device); - - /* SFF IDE */ - dev->bm[0] = device_add_inst(&sff8038i_device, 1); - dev->bm[1] = device_add_inst(&sff8038i_device, 2); - - /* SMRAM */ - dev->smram = smram_add(); - - /* PIT */ - dev->pit = device_find_first_priv(DEVICE_PIT); - dev->pit_read_reg = pit_is_fast ? pitf_read_reg : pit_read_reg; - - /* NVR */ - dev->nvr = device_add(&at_mb_nvr_device); - - sis_5511_reset(dev); + dev->p2i = device_add_linked(&sis_5513_p2i_device, dev->sis); + dev->ide = device_add_linked(&sis_5513_ide_device, dev->sis); return dev; } @@ -978,7 +164,7 @@ const device_t sis_5511_device = { .local = 0, .init = sis_5511_init, .close = sis_5511_close, - .reset = sis_5511_reset, + .reset = NULL, { .available = NULL }, .speed_changed = NULL, .force_redraw = NULL, diff --git a/src/chipset/sis_5511_h2p.c b/src/chipset/sis_5511_h2p.c new file mode 100644 index 000000000..7916d6ae2 --- /dev/null +++ b/src/chipset/sis_5511_h2p.c @@ -0,0 +1,461 @@ +/* + * 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 SiS 5511 Host to PCI bridge. + * + * Authors: Miran Grca, + * + * Copyright 2024 Miran Grca. + */ +#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/dma.h> +#include <86box/mem.h> +#include <86box/nvr.h> +#include <86box/hdd.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/pci.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/pit_fast.h> +#include <86box/plat.h> +#include <86box/plat_unused.h> +#include <86box/port_92.h> +#include <86box/smram.h> +#include <86box/spd.h> +#include <86box/apm.h> +#include <86box/ddma.h> +#include <86box/acpi.h> +#include <86box/smbus.h> +#include <86box/spd.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> +#include <86box/usb.h> +#include <86box/agpgart.h> + +#ifdef ENABLE_SIS_5511_HOST_TO_PCI_LOG +int sis_5511_host_to_pci_do_log = ENABLE_SIS_5511_HOST_TO_PCI_LOG; + +static void +sis_5511_host_to_pci_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5511_host_to_pci_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5511_host_to_pci_log(fmt, ...) +#endif + +typedef struct sis_5511_host_to_pci_t { + uint8_t pci_conf[256]; + uint8_t states[7]; + + uint8_t slic_regs[4096]; + + sis_55xx_common_t *sis; + + smram_t *smram; + + mem_mapping_t slic_mapping; +} sis_5511_host_to_pci_t; + +static void +sis_5511_shadow_recalc(sis_5511_host_to_pci_t *dev) +{ + int state; + uint32_t base; + + for (uint8_t i = 0x80; i <= 0x86; i++) { + if (i == 0x86) { + if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) { + state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_both(0xf0000, 0x10000, state); + sis_5511_host_to_pci_log("000F0000-000FFFFF\n"); + } + } else { + base = ((i & 0x07) << 15) + 0xc0000; + + if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) { + state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_both(base, 0x4000, state); + sis_5511_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff); + } + + if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0x0a) { + state = (dev->pci_conf[i] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[i] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_both(base + 0x4000, 0x4000, state); + sis_5511_host_to_pci_log("%08X-%08X\n", base + 0x4000, base + 0x7fff); + } + } + + dev->states[i & 0x0f] = dev->pci_conf[i]; + } + + flushmmucache_nopc(); +} + +static void +sis_5511_smram_recalc(sis_5511_host_to_pci_t *dev) +{ + smram_disable_all(); + + switch (dev->pci_conf[0x65] >> 6) { + case 0: + smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1); + break; + case 1: + smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1); + break; + case 2: + smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1); + break; + + default: + break; + } + + flushmmucache(); +} + +void +sis_5511_host_to_pci_write(int addr, uint8_t val, void *priv) +{ + sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv; + + sis_5511_host_to_pci_log("SiS 5511 H2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (addr) { + default: + break; + + case 0x07: /* Status - High Byte */ + dev->pci_conf[addr] &= 0xb0; + break; + + case 0x50: + dev->pci_conf[addr] = val; + cpu_cache_ext_enabled = !!(val & 0x40); + cpu_update_waitstates(); + break; + + case 0x51: + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x52: + dev->pci_conf[addr] = val & 0x3f; + break; + + case 0x53: + case 0x54: + dev->pci_conf[addr] = val; + break; + + case 0x55: + dev->pci_conf[addr] = val & 0xf8; + break; + + case 0x56 ... 0x59: + dev->pci_conf[addr] = val; + break; + + case 0x5a: + /* TODO: Fast Gate A20 Emulation and Fast Reset Emulation on the KBC. + The former (bit 7) means the chipset intercepts D1h to 64h and 00h to 60h. + The latter (bit 6) means the chipset intercepts all odd FXh to 64h. + Bit 5 sets fast reset latency. This should be fixed on the other SiS + chipsets as well. */ + dev->pci_conf[addr] = val; + break; + + case 0x5b: + dev->pci_conf[addr] = val & 0xf7; + break; + + case 0x5c: + dev->pci_conf[addr] = val & 0xcf; + break; + + case 0x5d: + dev->pci_conf[addr] = val; + break; + + case 0x5e: + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x5f: + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x60: + dev->pci_conf[addr] = val & 0x3e; + if ((dev->pci_conf[0x68] & 1) && (val & 2)) { + smi_raise(); + dev->pci_conf[0x69] |= 1; + } + break; + + case 0x61 ... 0x64: + dev->pci_conf[addr] = val; + break; + + case 0x65: + dev->pci_conf[addr] = val & 0xd0; + sis_5511_smram_recalc(dev); + break; + + case 0x66: + dev->pci_conf[addr] = val & 0x7f; + break; + + case 0x67: + case 0x68: + dev->pci_conf[addr] = val; + break; + + case 0x69: + dev->pci_conf[addr] &= val; + break; + + case 0x6a ... 0x6e: + dev->pci_conf[addr] = val; + break; + + case 0x6f: + dev->pci_conf[addr] = val & 0x3f; + break; + + case 0x70: /* DRAM Bank Register 0-0 */ + case 0x72: /* DRAM Bank Register 0-1 */ + case 0x74: /* DRAM Bank Register 1-0 */ + case 0x76: /* DRAM Bank Register 1-1 */ + case 0x78: /* DRAM Bank Register 2-0 */ + case 0x7a: /* DRAM Bank Register 2-1 */ + case 0x7c: /* DRAM Bank Register 3-0 */ + case 0x7e: /* DRAM Bank Register 3-1 */ + spd_write_drbs(dev->pci_conf, 0x70, 0x7e, 0x82); + break; + + case 0x71: /* DRAM Bank Register 0-0 */ + dev->pci_conf[addr] = val; + break; + + case 0x75: /* DRAM Bank Register 1-0 */ + case 0x79: /* DRAM Bank Register 2-0 */ + case 0x7d: /* DRAM Bank Register 3-0 */ + dev->pci_conf[addr] = val & 0x7f; + break; + + case 0x73: /* DRAM Bank Register 0-1 */ + case 0x77: /* DRAM Bank Register 1-1 */ + case 0x7b: /* DRAM Bank Register 2-1 */ + case 0x7f: /* DRAM Bank Register 3-1 */ + dev->pci_conf[addr] = val & 0x83; + break; + + case 0x80 ... 0x85: + dev->pci_conf[addr] = val & 0xee; + sis_5511_shadow_recalc(dev); + break; + case 0x86: + dev->pci_conf[addr] = val & 0xe8; + sis_5511_shadow_recalc(dev); + break; + + case 0x90 ... 0x93: /* 5512 General Purpose Register Index */ + dev->pci_conf[addr] = val; + break; + } +} + +uint8_t +sis_5511_host_to_pci_read(int addr, void *priv) +{ + const sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv; + uint8_t ret = 0xff; + + ret = dev->pci_conf[addr]; + + sis_5511_host_to_pci_log("SiS 5511 H2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5511_slic_write(uint32_t addr, uint8_t val, void *priv) +{ + sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv; + + addr &= 0x00000fff; + + switch (addr) { + case 0x00000000: + case 0x00000008: /* 0x00000008 is a SiS 5512 register. */ + dev->slic_regs[addr] = val; + break; + case 0x00000010: + case 0x00000018: + case 0x00000028: + case 0x00000038: + dev->slic_regs[addr] = val & 0x01; + break; + case 0x00000030: + dev->slic_regs[addr] = val & 0x0f; + mem_mapping_set_addr(&dev->slic_mapping, + (((uint32_t) (val & 0x0f)) << 28) | 0x0fc00000, 0x00001000); + break; + } +} + +static uint8_t +sis_5511_slic_read(uint32_t addr, void *priv) +{ + sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv; + uint8_t ret = 0xff; + + addr &= 0x00000fff; + + switch (addr) { + case 0x00000008: /* 0x00000008 is a SiS 5512 register. */ + ret = dev->slic_regs[addr]; + break; + } + + return ret; +} + +static void +sis_5511_host_to_pci_reset(void *priv) +{ + sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv; + + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x11; + dev->pci_conf[0x03] = 0x55; + dev->pci_conf[0x04] = 0x07; + dev->pci_conf[0x05] = dev->pci_conf[0x06] = 0x00; + dev->pci_conf[0x07] = 0x02; + dev->pci_conf[0x08] = 0x00; + dev->pci_conf[0x09] = dev->pci_conf[0x0a] = 0x00; + dev->pci_conf[0x0b] = 0x06; + dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x00; + dev->pci_conf[0x52] = 0x20; + dev->pci_conf[0x53] = dev->pci_conf[0x54] = 0x00; + dev->pci_conf[0x55] = dev->pci_conf[0x56] = 0x00; + dev->pci_conf[0x57] = dev->pci_conf[0x58] = 0x00; + dev->pci_conf[0x59] = dev->pci_conf[0x5a] = 0x00; + dev->pci_conf[0x5b] = dev->pci_conf[0x5c] = 0x00; + dev->pci_conf[0x5d] = dev->pci_conf[0x5e] = 0x00; + dev->pci_conf[0x5f] = dev->pci_conf[0x60] = 0x00; + dev->pci_conf[0x61] = dev->pci_conf[0x62] = 0xff; + dev->pci_conf[0x63] = 0xff; + dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00; + dev->pci_conf[0x66] = 0x00; + dev->pci_conf[0x67] = 0xff; + dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00; + dev->pci_conf[0x6a] = 0x00; + dev->pci_conf[0x6b] = dev->pci_conf[0x6c] = 0xff; + dev->pci_conf[0x6d] = dev->pci_conf[0x6e] = 0xff; + dev->pci_conf[0x6f] = 0x00; + dev->pci_conf[0x70] = dev->pci_conf[0x72] = 0x04; + dev->pci_conf[0x74] = dev->pci_conf[0x76] = 0x04; + dev->pci_conf[0x78] = dev->pci_conf[0x7a] = 0x04; + dev->pci_conf[0x7c] = dev->pci_conf[0x7e] = 0x04; + dev->pci_conf[0x71] = dev->pci_conf[0x75] = 0x00; + dev->pci_conf[0x73] = dev->pci_conf[0x77] = 0x80; + dev->pci_conf[0x79] = dev->pci_conf[0x7d] = 0x00; + dev->pci_conf[0x7b] = dev->pci_conf[0x7f] = 0x80; + dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00; + dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00; + dev->pci_conf[0x84] = dev->pci_conf[0x85] = 0x00; + dev->pci_conf[0x86] = 0x00; + + cpu_cache_ext_enabled = 0; + cpu_update_waitstates(); + + sis_5511_smram_recalc(dev); + sis_5511_shadow_recalc(dev); + + flushmmucache(); + + memset(dev->slic_regs, 0x00, 4096 * sizeof(uint8_t)); + dev->slic_regs[0x18] = 0x0f; + + mem_mapping_set_addr(&dev->slic_mapping, 0xffc00000, 0x00001000); +} + +static void +sis_5511_host_to_pci_close(void *priv) +{ + sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv; + + smram_del(dev->smram); + free(dev); +} + +static void * +sis_5511_host_to_pci_init(UNUSED(const device_t *info)) +{ + sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) calloc(1, sizeof(sis_5511_host_to_pci_t)); + + dev->sis = device_get_common_priv(); + + /* SLiC Memory Mapped Registers */ + mem_mapping_add(&dev->slic_mapping, + 0xffc00000, 0x00001000, + sis_5511_slic_read, + NULL, + NULL, + sis_5511_slic_write, + NULL, + NULL, + NULL, MEM_MAPPING_EXTERNAL, + dev); + + /* SMRAM */ + dev->smram = smram_add(); + + sis_5511_host_to_pci_reset(dev); + + return dev; +} + +const device_t sis_5511_h2p_device = { + .name = "SiS 5511 Host to PCI bridge", + .internal_name = "sis_5511_host_to_pci", + .flags = DEVICE_PCI, + .local = 0x00, + .init = sis_5511_host_to_pci_init, + .close = sis_5511_host_to_pci_close, + .reset = sis_5511_host_to_pci_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5513_ide.c b/src/chipset/sis_5513_ide.c new file mode 100644 index 000000000..130f2abd5 --- /dev/null +++ b/src/chipset/sis_5513_ide.c @@ -0,0 +1,501 @@ +/* + * 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 SiS 5513 IDE controller. + * + * Authors: Miran Grca, + * + * Copyright 2024 Miran Grca. + */ +#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/dma.h> +#include <86box/mem.h> +#include <86box/nvr.h> +#include <86box/hdd.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/pci.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/pit_fast.h> +#include <86box/plat.h> +#include <86box/plat_unused.h> +#include <86box/port_92.h> +#include <86box/smram.h> +#include <86box/spd.h> +#include <86box/apm.h> +#include <86box/ddma.h> +#include <86box/acpi.h> +#include <86box/smbus.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> + +#ifdef ENABLE_SIS_5513_IDE_LOG +int sis_5513_ide_do_log = ENABLE_SIS_5513_IDE_LOG; + +static void +sis_5513_ide_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5513_ide_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5513_ide_log(fmt, ...) +#endif + +typedef struct sis_5513_ide_t { + uint8_t rev; + + uint8_t pci_conf[256]; + + sis_55xx_common_t *sis; +} sis_5513_ide_t; + +static void +sis_5513_ide_irq_handler(sis_5513_ide_t *dev) +{ + if (dev->pci_conf[0x09] & 0x01) { + /* Primary IDE is native. */ + sis_5513_ide_log("Primary IDE IRQ mode: Native, Native\n"); + sff_set_irq_mode(dev->sis->bm[0], IRQ_MODE_SIS_551X); + } else { + /* Primary IDE is legacy. */ + sis_5513_ide_log("Primary IDE IRQ mode: IRQ14, IRQ15\n"); + sff_set_irq_mode(dev->sis->bm[0], IRQ_MODE_LEGACY); + } + + if (dev->pci_conf[0x09] & 0x04) { + /* Secondary IDE is native. */ + sis_5513_ide_log("Secondary IDE IRQ mode: Native, Native\n"); + sff_set_irq_mode(dev->sis->bm[1], IRQ_MODE_SIS_551X); + } else { + /* Secondary IDE is legacy. */ + sis_5513_ide_log("Secondary IDE IRQ mode: IRQ14, IRQ15\n"); + sff_set_irq_mode(dev->sis->bm[1], IRQ_MODE_LEGACY); + } +} + +static void +sis_5513_ide_handler(sis_5513_ide_t *dev) +{ + uint8_t ide_io_on = dev->pci_conf[0x04] & 0x01; + + uint16_t native_base_pri_addr = (dev->pci_conf[0x11] | dev->pci_conf[0x10] << 8) & 0xfffe; + uint16_t native_side_pri_addr = (dev->pci_conf[0x15] | dev->pci_conf[0x14] << 8) & 0xfffe; + uint16_t native_base_sec_addr = (dev->pci_conf[0x19] | dev->pci_conf[0x18] << 8) & 0xfffe; + uint16_t native_side_sec_addr = (dev->pci_conf[0x1c] | dev->pci_conf[0x1b] << 8) & 0xfffe; + + uint16_t current_pri_base; + uint16_t current_pri_side; + uint16_t current_sec_base; + uint16_t current_sec_side; + + /* Primary Channel Programming */ + current_pri_base = (!(dev->pci_conf[0x09] & 1)) ? 0x01f0 : native_base_pri_addr; + current_pri_side = (!(dev->pci_conf[0x09] & 1)) ? 0x03f6 : native_side_pri_addr; + + /* Secondary Channel Programming */ + current_sec_base = (!(dev->pci_conf[0x09] & 4)) ? 0x0170 : native_base_sec_addr; + current_sec_side = (!(dev->pci_conf[0x09] & 4)) ? 0x0376 : native_side_sec_addr; + + sis_5513_ide_log("sis_5513_ide_handler(): Disabling primary IDE...\n"); + ide_pri_disable(); + sis_5513_ide_log("sis_5513_ide_handler(): Disabling secondary IDE...\n"); + ide_sec_disable(); + + if (ide_io_on) { + /* Primary Channel Setup */ + if (dev->pci_conf[0x4a] & 0x02) { + sis_5513_ide_log("sis_5513_ide_handler(): Primary IDE base now %04X...\n", current_pri_base); + ide_set_base(0, current_pri_base); + sis_5513_ide_log("sis_5513_ide_handler(): Primary IDE side now %04X...\n", current_pri_side); + ide_set_side(0, current_pri_side); + + sis_5513_ide_log("sis_5513_ide_handler(): Enabling primary IDE...\n"); + ide_pri_enable(); + + sis_5513_ide_log("SiS 5513 PRI: BASE %04x SIDE %04x\n", current_pri_base, current_pri_side); + } + + /* Secondary Channel Setup */ + if (dev->pci_conf[0x4a] & 0x04) { + sis_5513_ide_log("sis_5513_ide_handler(): Secondary IDE base now %04X...\n", current_sec_base); + ide_set_base(1, current_sec_base); + sis_5513_ide_log("sis_5513_ide_handler(): Secondary IDE side now %04X...\n", current_sec_side); + ide_set_side(1, current_sec_side); + + sis_5513_ide_log("sis_5513_ide_handler(): Enabling secondary IDE...\n"); + ide_sec_enable(); + + sis_5513_ide_log("SiS 5513: BASE %04x SIDE %04x\n", current_sec_base, current_sec_side); + } + } + + sff_bus_master_handler(dev->sis->bm[0], ide_io_on, + ((dev->pci_conf[0x20] & 0xf0) | (dev->pci_conf[0x21] << 8)) + 0); + sff_bus_master_handler(dev->sis->bm[1], ide_io_on, + ((dev->pci_conf[0x20] & 0xf0) | (dev->pci_conf[0x21] << 8)) + 8); +} + +void +sis_5513_ide_write(int addr, uint8_t val, void *priv) +{ + sis_5513_ide_t *dev = (sis_5513_ide_t *) priv; + + sis_5513_ide_log("SiS 5513 IDE: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (addr) { + case 0x04: /* Command low byte */ + dev->pci_conf[addr] = val & 0x05; + sis_5513_ide_handler(dev); + break; + case 0x06: /* Status low byte */ + dev->pci_conf[addr] = val & 0x20; + break; + case 0x07: /* Status high byte */ + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x06) & ~(val & 0x38); + break; + case 0x09: /* Programming Interface Byte */ + switch (dev->rev) { + case 0xd0: + if (dev->sis->ide_bits_1_3_writable) + val |= 0x0a; + fallthrough; + case 0x00: + case 0xd1: + val &= 0xbf; + fallthrough; + case 0xc0: + switch (val & 0x0a) { + case 0x00: + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x85) | (val & 0x4a); + break; + case 0x02: + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x84) | (val & 0x4b); + break; + case 0x08: + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x81) | (val & 0x4e); + break; + case 0x0a: + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x80) | (val & 0x4f); + break; + } + break; + } + sis_5513_ide_irq_handler(dev); + sis_5513_ide_handler(dev); + break; + case 0x0d: /* Latency Timer */ + dev->pci_conf[addr] = val; + break; + + /* Primary Base Address */ + case 0x10 ... 0x11: + case 0x14 ... 0x15: + fallthrough; + + /* Secondary Base Address */ + case 0x18 ... 0x19: + case 0x1c ... 0x1d: + fallthrough; + + /* Bus Mastering Base Address */ + case 0x20 ... 0x21: + if (addr == 0x20) + dev->pci_conf[addr] = (val & 0xe0) | 0x01; + else + dev->pci_conf[addr] = val; + sis_5513_ide_handler(dev); + break; + + case 0x2c ... 0x2f: + if (dev->rev >= 0xd0) + dev->pci_conf[addr] = val; + break; + + case 0x30 ... 0x33: /* Expansion ROM Base Address */ +#ifdef DATASHEET + dev->pci_conf[addr] = val; +#else + if (dev->rev == 0x00) + dev->pci_conf[addr] = val; +#endif + break; + + case 0x40: /* IDE Primary Channel/Master Drive Data Recovery Time Control */ + if (dev->rev >= 0xd0) + dev->pci_conf[addr] = val & 0xcf; + else + dev->pci_conf[addr] = val & 0x0f; + break; + + case 0x42: /* IDE Primary Channel/Slave Drive Data Recovery Time Control */ + case 0x44: /* IDE Secondary Channel/Master Drive Data Recovery Time Control */ + case 0x46: /* IDE Secondary Channel/Slave Drive Data Recovery Time Control */ + case 0x48: /* IDE Command Recovery Time Control */ + dev->pci_conf[addr] = val & 0x0f; + break; + + case 0x41: /* IDE Primary Channel/Master Drive DataActive Time Control */ + case 0x43: /* IDE Primary Channel/Slave Drive Data Active Time Control */ + case 0x45: /* IDE Secondary Channel/Master Drive Data Active Time Control */ + case 0x47: /* IDE Secondary Channel/Slave Drive Data Active Time Control */ + if (dev->rev >= 0xd0) + dev->pci_conf[addr] = val & 0xe7; + else + dev->pci_conf[addr] = val & 0x07; + break; + + case 0x49: /* IDE Command Active Time Control */ + dev->pci_conf[addr] = val & 0x07; + break; + + case 0x4a: /* IDE General Control Register 0 */ + switch (dev->rev) { + case 0x00: + dev->pci_conf[addr] = val & 0x9e; + break; + case 0xc0: + dev->pci_conf[addr] = val & 0xaf; + break; + case 0xd0: + dev->pci_conf[addr] = val; + break; + } + sis_5513_ide_handler(dev); + break; + + case 0x4b: /* IDE General Control Register 1 */ + if (dev->rev >= 0xc0) + dev->pci_conf[addr] = val; + else + dev->pci_conf[addr] = val & 0xef; + break; + + case 0x4c: /* Prefetch Count of Primary Channel (Low Byte) */ + case 0x4d: /* Prefetch Count of Primary Channel (High Byte) */ + case 0x4e: /* Prefetch Count of Secondary Channel (Low Byte) */ + case 0x4f: /* Prefetch Count of Secondary Channel (High Byte) */ + dev->pci_conf[addr] = val; + break; + + case 0x50: + case 0x51: + if (dev->rev >= 0xd0) + dev->pci_conf[addr] = val; + break; + + case 0x52: + if (dev->rev >= 0xd0) + dev->pci_conf[addr] = val & 0x0f; + break; + + default: + break; + } +} + +uint8_t +sis_5513_ide_read(int addr, void *priv) +{ + const sis_5513_ide_t *dev = (sis_5513_ide_t *) priv; + uint8_t ret = 0xff; + + switch (addr) { + default: + ret = dev->pci_conf[addr]; + break; + case 0x09: + ret = dev->pci_conf[addr]; + if (dev->rev >= 0xc0) { + if (dev->pci_conf[0x09] & 0x40) + ret |= ((dev->pci_conf[0x4a] & 0x06) << 3); + if ((dev->rev == 0xd0) && dev->sis->ide_bits_1_3_writable) + ret |= 0x0a; + } + break; + case 0x3d: + if (dev->rev >= 0xc0) + ret = (dev->pci_conf[0x09] & 0x05) ? PCI_INTA : 0x00; + else + ret = (((dev->pci_conf[0x4b] & 0xc0) == 0xc0) || + (dev->pci_conf[0x09] & 0x05)) ? PCI_INTA : 0x00; + break; + } + + sis_5513_ide_log("SiS 5513 IDE: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5513_ide_reset(void *priv) +{ + sis_5513_ide_t *dev = (sis_5513_ide_t *) priv; + + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x13; + dev->pci_conf[0x03] = 0x55; + dev->pci_conf[0x04] = dev->pci_conf[0x05] = 0x00; + dev->pci_conf[0x06] = dev->pci_conf[0x07] = 0x00; + dev->pci_conf[0x08] = (dev->rev == 0xd1) ? 0xd0 : dev->rev; + dev->pci_conf[0x09] = 0x8a; + dev->pci_conf[0x0a] = dev->pci_conf[0x0b] = 0x01; + dev->pci_conf[0x0c] = dev->pci_conf[0x0d] = 0x00; + dev->pci_conf[0x0e] = 0x80; + dev->pci_conf[0x0f] = 0x00; + dev->pci_conf[0x10] = 0xf1; + dev->pci_conf[0x11] = 0x01; + dev->pci_conf[0x14] = 0xf5; + dev->pci_conf[0x15] = 0x03; + dev->pci_conf[0x18] = 0x71; + dev->pci_conf[0x19] = 0x01; + dev->pci_conf[0x1c] = 0x75; + dev->pci_conf[0x1d] = 0x03; + dev->pci_conf[0x20] = 0x01; + dev->pci_conf[0x21] = 0xf0; + dev->pci_conf[0x22] = dev->pci_conf[0x23] = 0x00; + dev->pci_conf[0x24] = dev->pci_conf[0x25] = 0x00; + dev->pci_conf[0x26] = dev->pci_conf[0x27] = 0x00; + dev->pci_conf[0x28] = dev->pci_conf[0x29] = 0x00; + dev->pci_conf[0x2a] = dev->pci_conf[0x2b] = 0x00; + switch (dev->rev) { + case 0x00: + case 0xd0: + case 0xd1: + dev->pci_conf[0x2c] = dev->pci_conf[0x2d] = 0x00; + break; + case 0xc0: +#ifdef DATASHEET + dev->pci_conf[0x2c] = dev->pci_conf[0x2d] = 0x00; +#else + /* The only Linux lspci listing I could find of this chipset, + shows a subsystem of 0058:0000. */ + dev->pci_conf[0x2c] = 0x58; + dev->pci_conf[0x2d] = 0x00; +#endif + break; + } + dev->pci_conf[0x2e] = dev->pci_conf[0x2f] = 0x00; + dev->pci_conf[0x30] = dev->pci_conf[0x31] = 0x00; + dev->pci_conf[0x32] = dev->pci_conf[0x33] = 0x00; + dev->pci_conf[0x40] = dev->pci_conf[0x41] = 0x00; + dev->pci_conf[0x42] = dev->pci_conf[0x43] = 0x00; + dev->pci_conf[0x44] = dev->pci_conf[0x45] = 0x00; + dev->pci_conf[0x46] = dev->pci_conf[0x47] = 0x00; + dev->pci_conf[0x48] = dev->pci_conf[0x49] = 0x00; + dev->pci_conf[0x4a] = 0x06; + dev->pci_conf[0x4b] = 0x00; + dev->pci_conf[0x4c] = dev->pci_conf[0x4d] = 0x00; + dev->pci_conf[0x4e] = dev->pci_conf[0x4f] = 0x00; + + sis_5513_ide_irq_handler(dev); + sis_5513_ide_handler(dev); + + sff_bus_master_reset(dev->sis->bm[0]); + sff_bus_master_reset(dev->sis->bm[1]); +} + +static void +sis_5513_ide_close(void *priv) +{ + sis_5513_ide_t *dev = (sis_5513_ide_t *) priv; + + free(dev); +} + +static void * +sis_5513_ide_init(UNUSED(const device_t *info)) +{ + sis_5513_ide_t *dev = (sis_5513_ide_t *) calloc(1, sizeof(sis_5513_ide_t)); + + dev->rev = info->local; + + dev->sis = device_get_common_priv(); + + /* SFF IDE */ + dev->sis->bm[0] = device_add_inst(&sff8038i_device, 1); + dev->sis->bm[1] = device_add_inst(&sff8038i_device, 2); + + sis_5513_ide_reset(dev); + + return dev; +} + +const device_t sis_5513_ide_device = { + .name = "SiS 5513 IDE controller", + .internal_name = "sis_5513_ide", + .flags = DEVICE_PCI, + .local = 0x00, + .init = sis_5513_ide_init, + .close = sis_5513_ide_close, + .reset = sis_5513_ide_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5572_ide_device = { + .name = "SiS 5572 IDE controller", + .internal_name = "sis_5572_ide", + .flags = DEVICE_PCI, + .local = 0xc0, + .init = sis_5513_ide_init, + .close = sis_5513_ide_close, + .reset = sis_5513_ide_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5582_ide_device = { + .name = "SiS 5582 IDE controller", + .internal_name = "sis_5582_ide", + .flags = DEVICE_PCI, + .local = 0xd0, + .init = sis_5513_ide_init, + .close = sis_5513_ide_close, + .reset = sis_5513_ide_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5591_5600_ide_device = { + .name = "SiS 5591/(5)600 IDE controller", + .internal_name = "sis_5591_5600_ide", + .flags = DEVICE_PCI, + .local = 0xd1, /* D0, but we need to distinguish them. */ + .init = sis_5513_ide_init, + .close = sis_5513_ide_close, + .reset = sis_5513_ide_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5513_p2i.c b/src/chipset/sis_5513_p2i.c new file mode 100644 index 000000000..df18cc4b3 --- /dev/null +++ b/src/chipset/sis_5513_p2i.c @@ -0,0 +1,1354 @@ +/* + * 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 SiS 5513 PCI to ISA bridge. + * + * Authors: Miran Grca, + * + * Copyright 2024 Miran Grca. + */ +#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/dma.h> +#include <86box/mem.h> +#include <86box/nvr.h> +#include <86box/hdd.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/pci.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/pit_fast.h> +#include <86box/plat.h> +#include <86box/plat_unused.h> +#include <86box/port_92.h> +#include <86box/smram.h> +#include <86box/spd.h> +#include <86box/apm.h> +#include <86box/ddma.h> +#include <86box/acpi.h> +#include <86box/smbus.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> + +#ifdef ENABLE_SIS_5513_PCI_TO_ISA_LOG +int sis_5513_pci_to_isa_do_log = ENABLE_SIS_5513_PCI_TO_ISA_LOG; + +static void +sis_5513_pci_to_isa_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5513_pci_to_isa_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5513_pci_to_isa_log(fmt, ...) +#endif + +typedef struct sis_5513_pci_to_isa_t { + uint8_t rev; + uint8_t index; + uint8_t dam_index; + uint8_t irq_state; + uint8_t dam_enable; + uint8_t dam_irq_enable; + uint8_t ddma_enable; + uint8_t pci_conf[256]; + uint8_t regs[16]; + uint8_t dam_regs[256]; + uint8_t apc_regs[256]; + + uint16_t dam_base; + uint16_t ddma_base; + uint16_t acpi_io_base; + + sis_55xx_common_t *sis; + port_92_t *port_92; + void *pit; + nvr_t *nvr; + ddma_t *ddma; + acpi_t *acpi; + void *smbus; + + uint8_t (*pit_read_reg)(void *priv, uint8_t reg); +} sis_5513_pci_to_isa_t; + +static void +sis_5595_acpi_recalc(sis_5513_pci_to_isa_t *dev) +{ + dev->acpi_io_base = (dev->pci_conf[0x91] << 8) | (dev->pci_conf[0x90] & 0xc0); + acpi_update_io_mapping(dev->sis->acpi, dev->acpi_io_base, (dev->pci_conf[0x40] & 0x80)); +} + +static void +sis_5513_apc_reset(sis_5513_pci_to_isa_t *dev) +{ + memset(dev->apc_regs, 0x00, sizeof(dev->apc_regs)); + + if (dev->rev == 0b0) { + dev->apc_regs[0x03] = 0x80; + dev->apc_regs[0x04] = 0x38; + dev->apc_regs[0x07] = 0x01; + } else + dev->apc_regs[0x04] = 0x08; +} + +static void +sis_5513_apc_write(uint16_t addr, uint8_t val, void *priv) +{ + sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; + uint8_t nvr_index = nvr_get_index(dev->nvr, 0); + + sis_5513_pci_to_isa_log("SiS 5595 APC: [W] %04X = %02X\n", addr, val); + + switch (nvr_index) { + case 0x02 ... 0x04: + dev->apc_regs[nvr_index] = val; + break; + case 0x05: + case 0x07 ... 0x08: + if (dev->rev == 0xb0) + dev->apc_regs[nvr_index] = val; + break; + } +} + +static uint8_t +sis_5513_apc_read(uint16_t addr, void *priv) +{ + sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; + uint8_t nvr_index = nvr_get_index(dev->nvr, 0); + uint8_t ret = 0xff; + + ret = dev->apc_regs[nvr_index]; + + if (nvr_index == 0x06) + dev->apc_regs[nvr_index] = 0x00; + + sis_5513_pci_to_isa_log("SiS 5595 APC: [R] %04X = %02X\n", addr, ret); + + return ret; +} + +void +sis_5513_apc_recalc(sis_5513_pci_to_isa_t *dev, uint8_t apc_on) +{ + nvr_at_data_port(!apc_on, dev->nvr); + io_removehandler(0x0071, 0x0001, + sis_5513_apc_read, NULL, NULL, sis_5513_apc_write, NULL, NULL, dev); + + if (apc_on) + io_removehandler(0x0071, 0x0001, + sis_5513_apc_read, NULL, NULL, sis_5513_apc_write, NULL, NULL, dev); +} + +static void +sis_5595_do_nmi(sis_5513_pci_to_isa_t *dev, int set) +{ + if (set) + nmi_raise(); + + dev->irq_state = set; +} + +static void +sis_5595_dam_reset(sis_5513_pci_to_isa_t *dev) +{ + if (dev->irq_state) { + if (dev->dam_regs[0x40] & 0x20) + sis_5595_do_nmi(dev, 0); + else if (dev->dam_irq_enable) + pci_clear_mirq(6, 1, &dev->irq_state); + } + + memset(dev->dam_regs, 0x00, sizeof(dev->dam_regs)); + + dev->dam_regs[0x40] = 0x08; + dev->dam_regs[0x47] = 0x50; +} + +static void +sis_5595_dam_write(uint16_t addr, uint8_t val, void *priv) +{ + sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; + uint16_t reg = addr - dev->dam_base; + uint8_t old; + + sis_5513_pci_to_isa_log("SiS 5595 DAM: [W] %04X = %02X\n", addr, val); + + switch (reg) { + case 0x05: + dev->dam_index = (dev->index & 0x80) | (val & 0x7f); + break; + case 0x06: + switch (dev->dam_index) { + case 0x40: + old = dev->dam_regs[0x40]; + dev->dam_regs[0x40] = val & 0xef; + if (val & 0x80) { + sis_5595_dam_reset(dev); + return; + } + if (dev->irq_state) { + if (!(old & 0x20) && (val & 0x20)) { + if (dev->dam_irq_enable) + pci_clear_mirq(6, 1, &dev->irq_state); + sis_5595_do_nmi(dev, 1); + } else if ((old & 0x20) && !(val & 0x20)) { + sis_5595_do_nmi(dev, 0); + if (dev->dam_irq_enable) + pci_set_mirq(6, 1, &dev->irq_state); + } + } + if ((val & 0x08) && dev->dam_irq_enable) + pci_clear_mirq(6, 1, &dev->irq_state); + break; + case 0x43 ... 0x47: + dev->dam_regs[dev->dam_index] = val; + break; + case 0x2b ... 0x34: + case 0x6b ... 0x74: + case 0x3b ... 0x3c: + case 0x7b ... 0x7c: + dev->dam_regs[dev->dam_index & 0x3f] = val; + break; + } + break; + } +} + +static uint8_t +sis_5595_dam_read(uint16_t addr, void *priv) +{ + sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; + uint16_t reg = addr - dev->dam_base; + uint8_t ret = 0xff; + + switch (reg) { + case 0x05: + ret = dev->dam_index; + break; + case 0x06: + switch (dev->dam_index) { + default: + ret = dev->dam_regs[dev->dam_index]; + break; + case 0x20 ... 0x29: + case 0x2b ... 0x3f: + ret = dev->dam_regs[dev->dam_index & 0x3f]; + break; + case 0x2a: + case 0x6a: + ret = dev->pci_conf[0x78]; + break; + } + break; + } + + sis_5513_pci_to_isa_log("SiS 5595 DAM: [R] %04X = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5595_dam_recalc(sis_5513_pci_to_isa_t *dev) +{ + if (dev->dam_enable && (dev->dam_base != 0x0000)) + io_removehandler(dev->dam_base, 0x0008, + sis_5595_dam_read, NULL, NULL, sis_5595_dam_write, NULL, NULL, dev); + + dev->dam_base = dev->pci_conf[0x68] | (dev->pci_conf[0x69] << 16); + dev->dam_enable = !!(dev->pci_conf[0x7b] & 0x80); + + if (dev->dam_enable && (dev->dam_base != 0x0000)) + io_sethandler(dev->dam_base, 0x0008, + sis_5595_dam_read, NULL, NULL, sis_5595_dam_write, NULL, NULL, dev); +} + +static void +sis_5595_ddma_recalc(sis_5513_pci_to_isa_t *dev) +{ + uint16_t ch_base; + + dev->ddma_base = (dev->pci_conf[0x80] & 0xf0) | (dev->pci_conf[0x81] << 16); + dev->ddma_enable = !!(dev->pci_conf[0x80] & 0x01); + + for (uint8_t i = 0; i < 8; i++) { + ch_base = dev->ddma_base + (i << 4); + ddma_update_io_mapping(dev->ddma, i, ch_base & 0xff, (ch_base >> 8), + dev->ddma_enable && (dev->pci_conf[0x84] & (1 << i)) && + (dev->ddma_base != 0x0000)); + } +} + +static void +sis_5513_00_pci_to_isa_write(int addr, uint8_t val, sis_5513_pci_to_isa_t *dev) +{ + switch (addr) { + case 0x60: /* MIRQ0 Remapping Control Register */ + case 0x61: /* MIRQ1 Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: MIRQ%i -> %02X\n", addr & 0x01, val); + dev->pci_conf[addr] = val & 0xcf; + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), val & 0xf); + break; + + case 0x62: /* On-board Device DMA Control Register */ + dev->pci_conf[addr] = val; + break; + + case 0x63: /* IDEIRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: IDEIRQ -> %02X\n", val); + dev->pci_conf[addr] = val & 0x8f; + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ2, val & 0xf); + break; + + case 0x64: /* GPIO0 Control Register */ + dev->pci_conf[addr] = val & 0xef; + break; + + case 0x65: + dev->pci_conf[addr] = val & 0x80; + break; + + case 0x66: /* GPIO0 Output Mode Control Register */ + case 0x67: /* GPIO0 Output Mode Control Register */ + dev->pci_conf[addr] = val; + break; + + case 0x6a: /* GPIO Status Register */ + dev->pci_conf[addr] |= (val & 0x10); + dev->pci_conf[addr] &= ~(val & 0x01); + break; + + default: + break; + } +} + +static void +sis_5513_01_pci_to_isa_write(int addr, uint8_t val, sis_5513_pci_to_isa_t *dev) +{ + uint8_t old; + + switch (addr) { + /* Simply skip MIRQ0, so we can reuse the SiS 551x IDEIRQ infrastructure. */ + case 0x61: /* MIRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: MIRQ%i -> %02X\n", addr & 0x01, val); + dev->pci_conf[addr] = val & 0xcf; + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), val & 0xf); + break; + + case 0x62: /* On-board Device DMA Control Register */ + dev->pci_conf[addr] = val; + break; + + case 0x63: /* IDEIRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: IDEIRQ -> %02X\n", val); + dev->pci_conf[addr] = val & 0x8f; + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ2, val & 0xf); + break; + + case 0x64: /* GPIO Control Register */ + dev->pci_conf[addr] = val & 0xef; + break; + + case 0x65: + dev->pci_conf[addr] = val & 0x1b; + break; + + case 0x66: /* GPIO Output Mode Control Register */ + case 0x67: /* GPIO Output Mode Control Register */ + dev->pci_conf[addr] = val; + break; + + case 0x68: /* USBIRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: USBIRQ -> %02X\n", val); + dev->pci_conf[addr] = val & 0xcf; + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ3, val & 0xf); + break; + + case 0x69: + dev->pci_conf[addr] = val; + break; + + case 0x6a: + dev->pci_conf[addr] = val & 0xfc; + break; + + case 0x6b: + dev->pci_conf[addr] = val; + break; + + case 0x6c: + dev->pci_conf[addr] = val & 0x02; + break; + + case 0x6e: /* Software-Controlled Interrupt Request, Channels 7-0 */ + old = dev->pci_conf[addr]; + picint((val ^ old) & val); + picintc((val ^ old) & ~val); + dev->pci_conf[addr] = val; + break; + + case 0x6f: /* Software-Controlled Interrupt Request, channels 15-8 */ + old = dev->pci_conf[addr]; + picint(((val ^ old) & val) << 8); + picintc(((val ^ old) & ~val) << 8); + dev->pci_conf[addr] = val; + break; + + case 0x70: + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x02) | (val & 0xdc); + break; + + case 0x71: /* Type-F DMA Control Register */ + dev->pci_conf[addr] = val & 0xef; + break; + + case 0x72: /* SMI Triggered By IRQ/GPIO Control */ + case 0x73: /* SMI Triggered By IRQ/GPIO Control */ + dev->pci_conf[addr] = val; + break; + + case 0x74: /* System Standby Timer Reload, + System Standby State Exit And Throttling State Exit Control */ + case 0x75: /* System Standby Timer Reload, + System Standby State Exit And Throttling State Exit Control */ + case 0x76: /* Monitor Standby Timer Reload And Monitor Standby State ExitControl */ + case 0x77: /* Monitor Standby Timer Reload And Monitor Standby State ExitControl */ + dev->pci_conf[addr] = val; + break; + + default: + break; + } +} + +static void +sis_5513_11_pci_to_isa_write(int addr, uint8_t val, sis_5513_pci_to_isa_t *dev) +{ + uint8_t old; + + switch (addr) { + case 0x61: /* IDEIRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: IDEIRQ -> %02X\n", val); + dev->pci_conf[addr] = val & 0xcf; + dev->sis->ide_bits_1_3_writable = !!(val & 0x40); + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ2, val & 0xf); + break; + + case 0x62: /* USBIRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: USBIRQ -> %02X\n", val); + dev->pci_conf[addr] = val; + dev->sis->usb_enabled = !!(val & 0x40); + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ3, val & 0xf); + break; + + case 0x63: /* GPCS0 Control Register */ + case 0x64: /* GPCS1 Control Register */ + case 0x65: /* GPCS0 Output Mode Control Register */ + case 0x66: /* GPCS0 Output Mode Control Register */ + case 0x67: /* GPCS1 Output Mode Control Register */ + case 0x68: /* GPCS1 Output Mode Control Register */ + case 0x6b: + case 0x6c: + dev->pci_conf[addr] = val; + break; + + case 0x69: /* GPCS0/1 De-Bounce Control Register */ + dev->pci_conf[addr] = val & 0xdf; + if ((dev->apc_regs[0x03] & 0x40) && (val & 0x10)) { + plat_power_off(); + return; + } + break; + + case 0x6a: /* ACPI/SCI IRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: ACPI/SCI IRQ -> %02X\n", val); + dev->pci_conf[addr] = val; + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ5, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ5, val & 0xf); + break; + + case 0x6d: /* I2C Bus Control Register */ + dev->pci_conf[addr] = val; + /* TODO: Keyboard/mouse swapping and keyboard hot key. */ + break; + + case 0x6e: /* Software-Controlled Interrupt Request, Channels 7-0 */ + old = dev->pci_conf[addr]; + picint((val ^ old) & val); + picintc((val ^ old) & ~val); + dev->pci_conf[addr] = val; + break; + + case 0x6f: /* Software-Controlled Interrupt Request, channels 15-8 */ + old = dev->pci_conf[addr]; + picint(((val ^ old) & val) << 8); + picintc(((val ^ old) & ~val) << 8); + dev->pci_conf[addr] = val; + break; + + case 0x70: /* Misc. Controller Register */ + dev->pci_conf[addr] = val; + /* TODO: Keyboard Lock Enable/Disable. */ + break; + + case 0x71: /* Type F DMA Control Register */ + dev->pci_conf[addr] = val & 0xef; + break; + + case 0x72: /* SMI Triggered By IRQ Control */ + dev->pci_conf[addr] = val & 0xfa; + break; + case 0x73: /* SMI Triggered By IRQ Control */ + case 0x75: /* System Standby Timer Reload, System Standby State Exit And Throttling State Exit */ + case 0x77: /* Monoitor Standby Timer Reload And Monoitor Standby State Exit Control */ + dev->pci_conf[addr] = val; + break; + + case 0x74: /* System Standby Timer Reload, System Standby State Exit And Throttling State Exit */ + case 0x76: /* Monoitor Standby Timer Reload And Monoitor Standby State Exit Control */ + dev->pci_conf[addr] = val & 0xfb; + break; + dev->pci_conf[addr] = val; + break; + + case 0x80: /* Distributed DMA Master Configuration Register */ + case 0x81: /* Distributed DMA Master Configuration Register */ + dev->pci_conf[addr] = val; + sis_5595_ddma_recalc(dev); + break; + + case 0x84: /* Individual Distributed DMA Channel Enable */ + dev->pci_conf[addr] = val; + sis_5595_ddma_recalc(dev); + break; + + case 0x88: /* Serial Interrupt Control Register */ + case 0x89: /* Serial Interrupt Enable Register 1 */ + case 0x8a: /* Serial Interrupt Enable Register 2 */ + dev->pci_conf[addr] = val; + break; + + case 0x90: /* ACPI Base Address Register */ + dev->pci_conf[addr] = val & 0xc0; + sis_5595_acpi_recalc(dev); + break; + case 0x91: /* ACPI Base Address Register */ + dev->pci_conf[addr] = val; + sis_5595_acpi_recalc(dev); + break; + + default: + break; + } +} + +static void +sis_5513_b0_pci_to_isa_write(int addr, uint8_t val, sis_5513_pci_to_isa_t *dev) +{ + uint8_t old; + + switch (addr) { + case 0x61: /* IDEIRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: IDEIRQ -> %02X\n", val); + dev->pci_conf[addr] = val & 0xdf; + sff_set_mirq(dev->sis->bm[0], (val & 0x10) ? 7 : 2); + sff_set_mirq(dev->sis->bm[1], (val & 0x10) ? 2 : 7); + pci_set_mirq_routing(PCI_MIRQ7, 14 + (!!(val & 0x10))); + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ2, val & 0xf); + break; + + case 0x62: /* USBIRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: USBIRQ -> %02X\n", val); + dev->pci_conf[addr] = val; + dev->sis->usb_enabled = !!(val & 0x40); + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ3, val & 0xf); + break; + + case 0x63: /* PCI OutputBuffer Current Strength Register */ + dev->pci_conf[addr] = val; + if ((dev->apc_regs[0x03] & 0x40) && (val & 0x04)) { + plat_power_off(); + return; + } + if ((val & 0x18) == 0x18) { + dma_reset(); + dma_set_at(1); + + device_reset_all(DEVICE_ALL); + + cpu_alt_reset = 0; + + pci_reset(); + + mem_a20_alt = 0; + mem_a20_recalc(); + + flushmmucache(); + + resetx86(); + } + break; + + case 0x64: /* INIT Enable Register */ + dev->pci_conf[addr] = val; + cpu_cpurst_on_sr = !(val & 0x20); + break; + + case 0x65: /* PHOLD# Timer */ + case 0x66: /* Priority Timer */ + case 0x67: /* Respond to C/D Segments Register */ + case 0x6b: /* Test Mode Register I */ + case 0x6c: /* Test Mode Register II */ + case 0x71: /* Reserved */ + case 0x72: /* Individual PC/PCI DMA Channel Enable */ + case 0x7c: /* Data Acquisition Module ADC Calibration */ + case 0x7d: /* Data Acquisition Module ADC Calibration */ + case 0x88: /* Serial Interrupt Control Register */ + case 0x89: /* Serial Interrupt Enable Register 1 */ + case 0x8a: /* Serial Interrupt Enable Register 2 */ + case 0x8c: /* Serial Interrupt Enable Register 3 */ + dev->pci_conf[addr] = val; + break; + + case 0x68: /* Data Acquistion Module Base Address */ + dev->pci_conf[addr] = val & 0xf8; + sis_5595_dam_recalc(dev); + break; + + case 0x6a: /* ACPI/SCI IRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: ACPI/SCI IRQ -> %02X\n", val); + dev->pci_conf[addr] = val & 0x8f; + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ5, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ5, val & 0xf); + break; + + case 0x6d: /* I2C Bus Control Register */ + dev->pci_conf[addr] = val; + /* TODO: Keyboard/mouse swapping and keyboard hot key. */ + break; + + case 0x6e: /* Software-Controlled Interrupt Request, Channels 7-0 */ + old = dev->pci_conf[addr]; + picint((val ^ old) & val); + picintc((val ^ old) & ~val); + dev->pci_conf[addr] = val; + break; + + case 0x6f: /* Software-Controlled Interrupt Request, channels 15-8 */ + old = dev->pci_conf[addr]; + picint(((val ^ old) & val) << 8); + picintc(((val ^ old) & ~val) << 8); + dev->pci_conf[addr] = val; + break; + + case 0x70: /* Misc. Controller Register */ + dev->pci_conf[addr] = val; + /* TODO: Keyboard Lock Enable/Disable. */ + break; + + case 0x73: + case 0x75 ... 0x79: + if (dev->rev == 0x81) + dev->pci_conf[addr] = val; + break; + + case 0x7a: /* Data Acquisition Module Function Selection Register */ + if (dev->rev == 0x81) + dev->pci_conf[addr] = val; + else + dev->pci_conf[addr] = val & 0x90; + break; + + case 0x7b: /* Data Acquisition Module Control Register */ + dev->pci_conf[addr] = val; + sis_5595_dam_recalc(dev); + break; + + case 0x7e: /* Data Acquisition Module and SMBUS IRQ Remapping Control Register */ + sis_5513_pci_to_isa_log("Set MIRQ routing: DAM/SMBUS IRQ -> %02X\n", val); + if (dev->rev == 0x81) + dev->pci_conf[addr] = val & 0x8f; + else { + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x10) | (val & 0xef); + + dev->dam_irq_enable = ((val & 0xc0) == 0x40); + smbus_sis5595_irq_enable(dev->smbus, (val & 0xa0) == 0x20); + } + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ6, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ6, val & 0xf); + break; + + case 0x80: /* Distributed DMA Master Configuration Register */ + case 0x81: /* Distributed DMA Master Configuration Register */ + dev->pci_conf[addr] = val; + sis_5595_ddma_recalc(dev); + break; + + case 0x84: /* Individual Distributed DMA Channel Enable */ + dev->pci_conf[addr] = val; + sis_5595_ddma_recalc(dev); + break; + + case 0x90: /* ACPI Base Address Register */ + dev->pci_conf[addr] = val & 0xc0; + sis_5595_acpi_recalc(dev); + break; + case 0x91: /* ACPI Base Address Register */ + dev->pci_conf[addr] = val; + sis_5595_acpi_recalc(dev); + break; + + default: + break; + } +} + +void +sis_5513_pci_to_isa_write(int addr, uint8_t val, void *priv) +{ + sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; + + sis_5513_pci_to_isa_log("SiS 5513 P2I: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (addr) { + case 0x04: /* Command */ + dev->pci_conf[addr] = val & 0x0f; + break; + + case 0x07: /* Status */ + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x06) & ~(val & 0x30); + break; + + case 0x0d: /* Master Latency Timer */ + if (dev->rev >= 0x11) + dev->pci_conf[addr] = val; + break; + + case 0x40: /* BIOS Control Register */ + if (dev->rev >= 0x11) { + dev->pci_conf[addr] = val; + sis_5595_acpi_recalc(dev); + } else + dev->pci_conf[addr] = val & 0x3f; + break; + + case 0x41: /* INTA# Remapping Control Register */ + case 0x42: /* INTB# Remapping Control Register */ + case 0x43: /* INTC# Remapping Control Register */ + dev->pci_conf[addr] = val & 0x8f; + pci_set_irq_routing(addr & 0x07, (val & 0x80) ? PCI_IRQ_DISABLED : (val & 0x0f)); + break; + case 0x44: /* INTD# Remapping Control Register */ + if (dev->rev == 0x11) { + dev->pci_conf[addr] = val & 0xcf; + sis_5513_apc_recalc(dev, val & 0x10); + } else + dev->pci_conf[addr] = val & 0x8f; + pci_set_irq_routing(addr & 0x07, (val & 0x80) ? PCI_IRQ_DISABLED : (val & 0x0f)); + break; + + case 0x45: /* ISA Bus Control Register I */ + if (dev->rev >= 0x01) { + if (dev->rev == 0x01) + dev->pci_conf[addr] = val & 0xec; + else + dev->pci_conf[addr] = val; + switch (val >> 6) { + case 0: + cpu_set_isa_speed(7159091); + break; + case 1: + cpu_set_isa_pci_div(4); + break; + case 2: + cpu_set_isa_pci_div(3); + break; + + default: + break; + } + nvr_bank_set(0, !!(val & 0x08), dev->nvr); + if (dev->rev == 0xb0) + sis_5513_apc_recalc(dev, val & 0x02); + } + break; + case 0x46: /* ISA Bus Control Register II */ + if (dev->rev >= 0x11) + dev->pci_conf[addr] = val; + else if (dev->rev == 0x00) + dev->pci_conf[addr] = val & 0xec; + break; + case 0x47: /* DMA Clock and Wait State Control Register */ + switch (dev->rev) { + case 0x01: + dev->pci_conf[addr] = val & 0x3e; + break; + case 0x11: + dev->pci_conf[addr] = val & 0x7f; + break; + case 0xb0: + dev->pci_conf[addr] = val & 0xfd; + break; + } + break; + + case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */ + case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */ + case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */ + case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */ + dev->pci_conf[addr] = val; + break; + + default: + switch (dev->rev) { + case 0x00: + sis_5513_00_pci_to_isa_write(addr, val, priv); + break; + case 0x01: + sis_5513_01_pci_to_isa_write(addr, val, priv); + break; + case 0x11: + sis_5513_11_pci_to_isa_write(addr, val, priv); + break; + case 0x81: + case 0xb0: + sis_5513_b0_pci_to_isa_write(addr, val, priv); + break; + } + break; + } +} + +uint8_t +sis_5513_pci_to_isa_read(int addr, void *priv) +{ + const sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; + uint8_t ret = 0xff; + + switch (addr) { + default: + ret = dev->pci_conf[addr]; + break; + case 0x4c ... 0x4f: + ret = pic_read_icw(0, addr & 0x03); + break; + case 0x50 ... 0x53: + ret = pic_read_icw(1, addr & 0x03); + break; + case 0x54 ... 0x55: + ret = pic_read_ocw(0, addr & 0x01); + break; + case 0x56 ... 0x57: + ret = pic_read_ocw(1, addr & 0x01); + break; + case 0x58 ... 0x5f: + ret = dev->pit_read_reg(dev->pit, addr & 0x07); + break; + case 0x60: + if (dev->rev >= 0x01) + ret = inb(0x0070); + else + ret = dev->pci_conf[addr]; + break; + } + + sis_5513_pci_to_isa_log("SiS 5513 P2I: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5513_isa_write(uint16_t addr, uint8_t val, void *priv) +{ + sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; + + switch (addr) { + case 0x22: + dev->index = val - 0x50; + break; + case 0x23: + sis_5513_pci_to_isa_log("SiS 5513 ISA: [W] dev->regs[%02X] = %02X\n", dev->index + 0x50, val); + + switch (dev->index) { + case 0x00: + dev->regs[dev->index] = val & 0xed; + switch (val >> 6) { + case 0: + cpu_set_isa_speed(7159091); + break; + case 1: + cpu_set_isa_pci_div(4); + break; + case 2: + cpu_set_isa_pci_div(3); + break; + + default: + break; + } + nvr_bank_set(0, !!(val & 0x08), dev->nvr); + break; + case 0x01: + dev->regs[dev->index] = val & 0xf4; + break; + case 0x03: + dev->regs[dev->index] = val & 3; + break; + case 0x04: /* BIOS Register */ + dev->regs[dev->index] = val; + break; + case 0x05: + dev->regs[dev->index] = val; + outb(0x70, val); + break; + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + dev->regs[dev->index] = val; + break; + + default: + break; + } + break; + + default: + break; + } +} + +static uint8_t +sis_5513_isa_read(uint16_t addr, void *priv) +{ + const sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; + uint8_t ret = 0xff; + + if (addr == 0x23) { + if (dev->index == 0x05) + ret = inb(0x70); + else + ret = dev->regs[dev->index]; + + sis_5513_pci_to_isa_log("SiS 5513 ISA: [R] dev->regs[%02X] = %02X\n", dev->index + 0x50, ret); + } + + return ret; +} + +static void +sis_5513_00_pci_to_isa_reset(sis_5513_pci_to_isa_t *dev) +{ + dev->pci_conf[0x60] = dev->pci_conf[0x61] = 0x80; + dev->pci_conf[0x62] = 0x00; + dev->pci_conf[0x63] = 0x80; + dev->pci_conf[0x64] = 0x00; + dev->pci_conf[0x65] = 0x00; + dev->pci_conf[0x66] = dev->pci_conf[0x67] = 0x00; + dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00; + dev->pci_conf[0x6a] = 0x04; + + pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); + + dev->regs[0x00] = dev->regs[0x01] = 0x00; + dev->regs[0x03] = dev->regs[0x04] = 0x00; + dev->regs[0x05] = 0x00; + dev->regs[0x08] = dev->regs[0x09] = 0x00; + dev->regs[0x0a] = dev->regs[0x0b] = 0x00; +} + +static void +sis_5513_01_pci_to_isa_reset(sis_5513_pci_to_isa_t *dev) +{ + dev->pci_conf[0x45] = dev->pci_conf[0x46] = 0x00; + dev->pci_conf[0x47] = 0x00; + + dev->pci_conf[0x61] = 0x80; + dev->pci_conf[0x62] = 0x00; + dev->pci_conf[0x63] = 0x80; + dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00; + dev->pci_conf[0x66] = dev->pci_conf[0x67] = 0x00; + dev->pci_conf[0x68] = 0x80; + dev->pci_conf[0x69] = dev->pci_conf[0x6a] = 0x00; + dev->pci_conf[0x6b] = 0x00; + dev->pci_conf[0x6c] = 0x02; + dev->pci_conf[0x6d] = 0x00; + dev->pci_conf[0x6e] = dev->pci_conf[0x6f] = 0x00; + dev->pci_conf[0x70] = dev->pci_conf[0x71] = 0x00; + dev->pci_conf[0x72] = dev->pci_conf[0x73] = 0x00; + dev->pci_conf[0x74] = dev->pci_conf[0x75] = 0x00; + dev->pci_conf[0x76] = dev->pci_conf[0x77] = 0x00; + + pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED); +} + +static void +sis_5513_11_pci_to_isa_reset(sis_5513_pci_to_isa_t *dev) +{ + dev->pci_conf[0x45] = dev->pci_conf[0x46] = 0x00; + dev->pci_conf[0x47] = 0x00; + + dev->pci_conf[0x61] = dev->pci_conf[0x62] = 0x80; + dev->pci_conf[0x63] = dev->pci_conf[0x64] = 0x00; + dev->pci_conf[0x65] = dev->pci_conf[0x66] = 0x00; + dev->pci_conf[0x67] = dev->pci_conf[0x68] = 0x00; + dev->pci_conf[0x69] = 0x01; + dev->pci_conf[0x6a] = 0x80; + dev->pci_conf[0x6b] = 0x00; + dev->pci_conf[0x6c] = 0x20; + dev->pci_conf[0x6d] = 0x19; + dev->pci_conf[0x6e] = dev->pci_conf[0x6f] = 0x00; + dev->pci_conf[0x70] = 0x12; + dev->pci_conf[0x71] = dev->pci_conf[0x72] = 0x00; + dev->pci_conf[0x73] = dev->pci_conf[0x74] = 0x00; + dev->pci_conf[0x75] = dev->pci_conf[0x76] = 0x00; + dev->pci_conf[0x77] = 0x00; + dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00; + dev->pci_conf[0x84] = dev->pci_conf[0x88] = 0x00; + dev->pci_conf[0x89] = dev->pci_conf[0x8a] = 0x00; + dev->pci_conf[0x90] = dev->pci_conf[0x91] = 0x00; + + pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ5, PCI_IRQ_DISABLED); + + picint_common(0xffff, 0, 0, NULL); + + sis_5595_ddma_recalc(dev); + sis_5595_acpi_recalc(dev); + + dev->sis->ide_bits_1_3_writable = 0; + dev->sis->usb_enabled = 0; + + sis_5513_apc_reset(dev); + sis_5513_apc_recalc(dev, 0); +} + +static void +sis_5513_b0_pci_to_isa_reset(sis_5513_pci_to_isa_t *dev) +{ + dev->pci_conf[0x45] = dev->pci_conf[0x46] = 0x00; + dev->pci_conf[0x47] = 0x00; + + dev->pci_conf[0x61] = dev->pci_conf[0x62] = 0x80; + dev->pci_conf[0x63] = dev->pci_conf[0x64] = 0x00; + dev->pci_conf[0x65] = 0x01; + dev->pci_conf[0x66] = dev->pci_conf[0x67] = 0x00; + dev->pci_conf[0x68] = 0x90; + dev->pci_conf[0x69] = 0x02; + dev->pci_conf[0x6a] = 0x80; + dev->pci_conf[0x6b] = 0x00; + dev->pci_conf[0x6c] = 0x20; + dev->pci_conf[0x6d] = 0x19; + dev->pci_conf[0x6e] = dev->pci_conf[0x6f] = 0x00; + dev->pci_conf[0x70] = 0x12; + dev->pci_conf[0x71] = dev->pci_conf[0x72] = 0x00; + dev->pci_conf[0x7a] = dev->pci_conf[0x7b] = 0x00; + dev->pci_conf[0x7c] = dev->pci_conf[0x7d] = 0x00; + dev->pci_conf[0x7e] = 0x80; + dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00; + dev->pci_conf[0x84] = dev->pci_conf[0x88] = 0x00; + dev->pci_conf[0x89] = dev->pci_conf[0x8a] = 0x00; + dev->pci_conf[0x8b] = dev->pci_conf[0x8c] = 0x00; + dev->pci_conf[0x90] = dev->pci_conf[0x91] = 0x00; + + pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ5, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ6, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ7, 15); + + sff_set_mirq(dev->sis->bm[0], 2); + sff_set_mirq(dev->sis->bm[1], 7); + + picint_common(0xffff, 0, 0, NULL); + + sis_5595_ddma_recalc(dev); + sis_5595_acpi_recalc(dev); + + /* SiS 5595 Data Acquisition Module */ + sis_5595_dam_recalc(dev); + sis_5595_dam_reset(dev); + + dev->dam_irq_enable = 0; + + cpu_cpurst_on_sr = 1; + + dev->sis->usb_enabled = 0; + + sis_5513_apc_reset(dev); + sis_5513_apc_recalc(dev, 0); + + if (dev->rev == 0x81) + dev->dam_irq_enable = 1; +} + +static void +sis_5513_pci_to_isa_reset(void *priv) +{ + sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; + + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x08; + dev->pci_conf[0x03] = 0x00; + dev->pci_conf[0x04] = 0x07; + dev->pci_conf[0x05] = dev->pci_conf[0x06] = 0x00; + dev->pci_conf[0x07] = 0x02; + if ((dev->rev == 0x11) || (dev->rev == 0x81)) + dev->pci_conf[0x08] = 0x01; + else + dev->pci_conf[0x08] = dev->rev; + dev->pci_conf[0x09] = 0x00; + dev->pci_conf[0x0a] = 0x01; + dev->pci_conf[0x0b] = 0x06; + dev->pci_conf[0x0e] = 0x80; + dev->pci_conf[0x40] = 0x00; + dev->pci_conf[0x41] = dev->pci_conf[0x42] = 0x80; + dev->pci_conf[0x43] = dev->pci_conf[0x44] = 0x80; + dev->pci_conf[0x48] = dev->pci_conf[0x49] = 0x00; + dev->pci_conf[0x4a] = dev->pci_conf[0x4b] = 0x00; + + switch (dev->rev) { + case 0x00: + sis_5513_00_pci_to_isa_reset(dev); + break; + case 0x01: + sis_5513_01_pci_to_isa_reset(dev); + break; + case 0x11: + sis_5513_11_pci_to_isa_reset(dev); + break; + case 0x81: + case 0xb0: + sis_5513_b0_pci_to_isa_reset(dev); + break; + } + + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + + pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); + + cpu_set_isa_speed(7159091); + nvr_bank_set(0, 0, dev->nvr); +} + +static void +sis_5513_pci_to_isa_close(void *priv) +{ + sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv; + + free(dev); +} + +static void * +sis_5513_pci_to_isa_init(UNUSED(const device_t *info)) +{ + sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) calloc(1, sizeof(sis_5513_pci_to_isa_t)); + uint8_t pit_is_fast = (((pit_mode == -1) && is486) || (pit_mode == 1)); + + dev->rev = info->local; + + dev->sis = device_get_common_priv(); + + /* IDEIRQ */ + pci_enable_mirq(2); + + /* Port 92h */ + dev->port_92 = device_add(&port_92_device); + + /* PIT */ + dev->pit = device_find_first_priv(DEVICE_PIT); + dev->pit_read_reg = pit_is_fast ? pitf_read_reg : pit_read_reg; + + /* NVR */ + dev->nvr = device_add(&at_mb_nvr_device); + + switch (dev->rev) { + case 0x00: + /* MIRQ */ + pci_enable_mirq(0); + pci_enable_mirq(1); + + /* Ports 22h-23h: SiS 5513 ISA */ + io_sethandler(0x0022, 0x0002, + sis_5513_isa_read, NULL, NULL, sis_5513_isa_write, NULL, NULL, dev); + break; + case 0x01: + /* MIRQ */ + pci_enable_mirq(1); + break; + case 0x11: + case 0x81: + case 0xb0: + /* USBIRQ */ + pci_enable_mirq(3); + + /* ACPI/SCI IRQ */ + pci_enable_mirq(5); + + if (dev->rev == 0xb0) { + /* Data Acquisition Module and SMBUS IRQ */ + pci_enable_mirq(6); + + /* Non-remapped native IDE IRQ */ + pci_enable_mirq(7); + } + + dev->ddma = device_add(&ddma_device); + + switch (dev->rev) { + case 0x11: + dev->sis->acpi = device_add(&acpi_sis_5582_device); + break; + case 0x81: + dev->sis->acpi = device_add(&acpi_sis_5595_1997_device); + break; + case 0xb0: + dev->sis->acpi = device_add(&acpi_sis_5595_device); + dev->smbus = acpi_get_smbus(dev->sis->acpi); + break; + } + + dev->sis->acpi->priv = dev->sis; + acpi_set_slot(dev->sis->acpi, dev->sis->sb_pci_slot); + acpi_set_nvr(dev->sis->acpi, dev->nvr); + acpi_set_irq_mode(dev->sis->acpi, 2); + break; + } + + sis_5513_pci_to_isa_reset(dev); + + return dev; +} + +const device_t sis_5513_p2i_device = { + .name = "SiS 5513 PCI to ISA bridge", + .internal_name = "sis_5513_pci_to_isa", + .flags = DEVICE_PCI, + .local = 0x00, + .init = sis_5513_pci_to_isa_init, + .close = sis_5513_pci_to_isa_close, + .reset = sis_5513_pci_to_isa_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5572_p2i_device = { + .name = "SiS 5572 PCI to ISA bridge", + .internal_name = "sis_5572_pci_to_isa", + .flags = DEVICE_PCI, + .local = 0x01, + .init = sis_5513_pci_to_isa_init, + .close = sis_5513_pci_to_isa_close, + .reset = sis_5513_pci_to_isa_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5582_p2i_device = { + .name = "SiS 5582 PCI to ISA bridge", + .internal_name = "sis_5582_pci_to_isa", + .flags = DEVICE_PCI, + .local = 0x11, /* Actually, 0x01, but we need to somehow distinguish it + from SiS 5572 and SiS 5595 1997, which are also revision 0x01. */ + .init = sis_5513_pci_to_isa_init, + .close = sis_5513_pci_to_isa_close, + .reset = sis_5513_pci_to_isa_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5595_1997_p2i_device = { + .name = "SiS 5595 (1997) PCI to ISA bridge", + .internal_name = "sis_5595_1997_pci_to_isa", + .flags = DEVICE_PCI, + .local = 0x81, /* Actually, 0x01, but we need to somehow distinguish it + from SiS 5572 and SiS 5582, which are also revision 0x01. */ + .init = sis_5513_pci_to_isa_init, + .close = sis_5513_pci_to_isa_close, + .reset = sis_5513_pci_to_isa_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5595_p2i_device = { + .name = "SiS 5595 PCI to ISA bridge", + .internal_name = "sis_5595_pci_to_isa", + .flags = DEVICE_PCI, + .local = 0xb0, + .init = sis_5513_pci_to_isa_init, + .close = sis_5513_pci_to_isa_close, + .reset = sis_5513_pci_to_isa_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5571.c b/src/chipset/sis_5571.c index 007a96178..3fb111978 100644 --- a/src/chipset/sis_5571.c +++ b/src/chipset/sis_5571.c @@ -6,11 +6,11 @@ * * This file is part of the 86Box distribution. * - * Implementation of the SiS 5571 Pentium PCI/ISA Chipset. + * Implementation of the SiS 5571/5572 Pentium PCI/ISA Chipset. * * Authors: Miran Grca, * - * Copyright 2023-2024 Miran Grca. + * Copyright 2021-2023 Miran Grca. */ #include #include @@ -23,10 +23,10 @@ #include <86box/device.h> #include <86box/io.h> #include <86box/timer.h> - -// #include <86box/dma.h> #include <86box/mem.h> #include <86box/nvr.h> +#include <86box/apm.h> +#include <86box/acpi.h> #include <86box/hdd.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> @@ -40,8 +40,7 @@ #include <86box/port_92.h> #include <86box/smram.h> #include <86box/spd.h> -#include <86box/usb.h> - +#include <86box/sis_55xx.h> #include <86box/chipset.h> #ifdef ENABLE_SIS_5571_LOG @@ -63,1128 +62,90 @@ sis_5571_log(const char *fmt, ...) #endif typedef struct sis_5571_t { - uint8_t index; - uint8_t nb_slot; - uint8_t sb_slot; - uint8_t pad; + uint8_t nb_slot; + uint8_t sb_slot; - uint8_t regs[16]; - uint8_t states[7]; - uint8_t pad0; + void *h2p; + void *p2i; + void *ide; + void *usb; - uint8_t usb_unk_regs[8]; - - uint8_t pci_conf[256]; - uint8_t pci_conf_sb[3][256]; - - uint16_t usb_unk_base; - - sff8038i_t *bm[2]; - smram_t *smram; - port_92_t *port_92; - void *pit; - nvr_t *nvr; - usb_t *usb; - - uint8_t (*pit_read_reg)(void *priv, uint8_t reg); + sis_55xx_common_t *sis; } sis_5571_t; static void -sis_5571_shadow_recalc(sis_5571_t *dev) +sis_5571_write(int func, int addr, uint8_t val, void *priv) { - int state; - uint32_t base; + const sis_5571_t *dev = (sis_5571_t *) priv; - for (uint8_t i = 0x70; i <= 0x76; i++) { - if (i == 0x76) { - if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) { - state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - mem_set_mem_state_both(0xf0000, 0x10000, state); - sis_5571_log("000F0000-000FFFFF\n"); - } - } else { - base = ((i & 0x07) << 15) + 0xc0000; + sis_5571_log("SiS 5571: [W] dev->pci_conf[%02X] = %02X\n", addr, val); - if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) { - state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - mem_set_mem_state_both(base, 0x4000, state); - sis_5571_log("%08X-%08X\n", base, base + 0x3fff); - } - - if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0x0a) { - state = (dev->pci_conf[i] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - state |= (dev->pci_conf[i] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; - mem_set_mem_state_both(base + 0x4000, 0x4000, state); - sis_5571_log("%08X-%08X\n", base + 0x4000, base + 0x7fff); - } - } - - dev->states[i & 0x0f] = dev->pci_conf[i]; - } - - flushmmucache_nopc(); -} - -static void -sis_5571_smram_recalc(sis_5571_t *dev) -{ - smram_disable_all(); - - switch (dev->pci_conf[0xa3] >> 6) { - case 0: - smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1); - break; - case 1: - smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1); - break; - case 2: - smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1); - break; - case 3: - smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x10000, dev->pci_conf[0xa3] & 0x10, 1); - break; - - default: - break; - } - - flushmmucache(); -} - -static void -sis_5571_mem_to_pci_reset(sis_5571_t *dev) -{ - dev->pci_conf[0x00] = 0x39; - dev->pci_conf[0x01] = 0x10; - dev->pci_conf[0x02] = 0x71; - dev->pci_conf[0x03] = 0x55; - dev->pci_conf[0x04] = 0x05; - dev->pci_conf[0x05] = 0x00; - dev->pci_conf[0x06] = 0x00; - dev->pci_conf[0x07] = 0x02; - dev->pci_conf[0x08] = 0x00; - dev->pci_conf[0x09] = 0x00; - dev->pci_conf[0x0a] = 0x00; - dev->pci_conf[0x0b] = 0x06; - dev->pci_conf[0x0c] = 0x00; - dev->pci_conf[0x0d] = 0x00; - dev->pci_conf[0x0e] = 0x00; - dev->pci_conf[0x0f] = 0x00; - - dev->pci_conf[0x50] = 0x00; - dev->pci_conf[0x51] = 0x00; - dev->pci_conf[0x52] = 0x00; - dev->pci_conf[0x53] = 0x00; - dev->pci_conf[0x54] = 0x54; - dev->pci_conf[0x55] = 0x54; - dev->pci_conf[0x56] = 0x03; - dev->pci_conf[0x57] = 0x00; - dev->pci_conf[0x58] = 0x00; - dev->pci_conf[0x59] = 0x00; - dev->pci_conf[0x5a] = 0x00; - - /* Undocumented DRAM bank registers. */ - dev->pci_conf[0x60] = dev->pci_conf[0x62] = 0x04; - dev->pci_conf[0x64] = dev->pci_conf[0x66] = 0x04; - dev->pci_conf[0x68] = dev->pci_conf[0x6a] = 0x04; - dev->pci_conf[0x61] = dev->pci_conf[0x65] = 0x00; - dev->pci_conf[0x63] = dev->pci_conf[0x67] = 0x80; - dev->pci_conf[0x69] = 0x00; - dev->pci_conf[0x6b] = 0x80; - - dev->pci_conf[0x70] = 0x00; - dev->pci_conf[0x71] = 0x00; - dev->pci_conf[0x72] = 0x00; - dev->pci_conf[0x73] = 0x00; - dev->pci_conf[0x74] = 0x00; - dev->pci_conf[0x75] = 0x00; - dev->pci_conf[0x76] = 0x00; - - dev->pci_conf[0x77] = 0x00; - dev->pci_conf[0x78] = 0x00; - dev->pci_conf[0x79] = 0x00; - dev->pci_conf[0x7a] = 0x00; - dev->pci_conf[0x7b] = 0x00; - - dev->pci_conf[0x80] = 0x00; - dev->pci_conf[0x81] = 0x00; - dev->pci_conf[0x82] = 0x00; - dev->pci_conf[0x83] = 0x00; - dev->pci_conf[0x84] = 0x00; - dev->pci_conf[0x85] = 0x00; - dev->pci_conf[0x86] = 0x00; - dev->pci_conf[0x87] = 0x00; - - dev->pci_conf[0x8c] = 0x00; - dev->pci_conf[0x8d] = 0x00; - dev->pci_conf[0x8e] = 0x00; - dev->pci_conf[0x8f] = 0x00; - - dev->pci_conf[0x90] = 0x00; - dev->pci_conf[0x91] = 0x00; - dev->pci_conf[0x92] = 0x00; - dev->pci_conf[0x93] = 0x00; - dev->pci_conf[0x93] = 0x00; - dev->pci_conf[0x94] = 0x00; - dev->pci_conf[0x95] = 0x00; - dev->pci_conf[0x96] = 0x00; - dev->pci_conf[0x97] = 0x00; - dev->pci_conf[0x98] = 0x00; - dev->pci_conf[0x99] = 0x00; - dev->pci_conf[0x9a] = 0x00; - dev->pci_conf[0x9b] = 0x00; - dev->pci_conf[0x9c] = 0x00; - dev->pci_conf[0x9d] = 0x00; - dev->pci_conf[0x9e] = 0xff; - dev->pci_conf[0x9f] = 0xff; - - dev->pci_conf[0xa0] = 0xff; - dev->pci_conf[0xa1] = 0x00; - dev->pci_conf[0xa2] = 0xff; - dev->pci_conf[0xa3] = 0x00; - - cpu_cache_ext_enabled = 0; - cpu_update_waitstates(); - - sis_5571_smram_recalc(dev); - sis_5571_shadow_recalc(dev); - - flushmmucache(); -} - -static void -sis_5571_mem_to_pci_write(int func, int addr, uint8_t val, void *priv) -{ - sis_5571_t *dev = (sis_5571_t *) priv; - - if (func == 0) { - sis_5571_log("SiS 5571 M2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val); - - switch (addr) { - case 0x04: /* Command - low byte */ - case 0x05: /* Command - high byte */ - dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xfd) | (val & 0x02); - break; - - case 0x07: /* Status - High Byte */ - dev->pci_conf[addr] &= ~(val & 0xb8); - break; - - case 0x0d: /* Master latency timer */ - dev->pci_conf[addr] = val; - break; - - case 0x50: /* Host Interface and DRAM arbiter */ - dev->pci_conf[addr] = val & 0xec; - break; - - case 0x51: /* CACHE */ - dev->pci_conf[addr] = val; - cpu_cache_ext_enabled = !!(val & 0x40); - cpu_update_waitstates(); - break; - - case 0x52: - dev->pci_conf[addr] = val & 0xd0; - break; - - case 0x53: /* DRAM */ - dev->pci_conf[addr] = val & 0xfe; - break; - - case 0x54: /* FP/EDO */ - dev->pci_conf[addr] = val; - break; - - case 0x55: - dev->pci_conf[addr] = val & 0xe0; - break; - - case 0x56: /* MDLE delay */ - dev->pci_conf[addr] = val & 0x07; - break; - - case 0x57: /* SDRAM */ - dev->pci_conf[addr] = val & 0xf8; - break; - - case 0x59: /* Buffer strength and current rating */ - dev->pci_conf[addr] = val; - break; - - case 0x5a: - dev->pci_conf[addr] = val & 0x03; - break; - - /* Undocumented - DRAM bank registers, the exact layout is currently unknown. */ - case 0x60 ... 0x6b: - dev->pci_conf[addr] = val; - break; - - case 0x70 ... 0x75: - dev->pci_conf[addr] = val & 0xee; - sis_5571_shadow_recalc(dev); - break; - case 0x76: - dev->pci_conf[addr] = val & 0xe8; - sis_5571_shadow_recalc(dev); - break; - - case 0x77: /* Characteristics of non-cacheable area */ - dev->pci_conf[addr] = val & 0x0f; - break; - - case 0x78: /* Allocation of Non-Cacheable area #1 */ - case 0x79: /* NCA1REG2 */ - case 0x7a: /* Allocation of Non-Cacheable area #2 */ - case 0x7b: /* NCA2REG2 */ - dev->pci_conf[addr] = val; - break; - - case 0x80: /* PCI master characteristics */ - dev->pci_conf[addr] = val & 0xfe; - break; - - case 0x81: - dev->pci_conf[addr] = val & 0xcc; - break; - - case 0x82: - dev->pci_conf[addr] = val; - break; - - case 0x83: /* CPU to PCI characteristics */ - dev->pci_conf[addr] = val; - /* TODO: Implement Fast A20 and Fast reset stuff on the KBC already! */ - break; - - case 0x84 ... 0x86: - dev->pci_conf[addr] = val; - break; - - case 0x87: /* Miscellanea */ - dev->pci_conf[addr] = val & 0xf8; - break; - - case 0x90: /* PMU control register */ - case 0x91: /* Address trap for green function */ - case 0x92: - dev->pci_conf[addr] = val; - break; - - case 0x93: /* STPCLK# and APM SMI control */ - dev->pci_conf[addr] = val; - - if ((dev->pci_conf[0x9b] & 0x01) && (val & 0x02)) { - smi_raise(); - dev->pci_conf[0x9d] |= 0x01; - } - break; - - case 0x94: /* 6x86 and Green function control */ - dev->pci_conf[addr] = val & 0xf8; - break; - - case 0x95: /* Test mode control */ - case 0x96: /* Time slot and Programmable 10-bit I/O port definition */ - dev->pci_conf[addr] = val & 0xfb; - break; - - case 0x97: /* programmable 10-bit I/O port address */ - case 0x98: /* Programmable 16-bit I/O port */ - case 0x99 ... 0x9c: - dev->pci_conf[addr] = val; - break; - - case 0x9d: - dev->pci_conf[addr] &= val; - break; - - case 0x9e: /* STPCLK# Assertion Timer */ - case 0x9f: /* STPCLK# De-assertion Timer */ - case 0xa0 ... 0xa2: - dev->pci_conf[addr] = val; - break; - - case 0xa3: /* SMRAM access control and Power supply control */ - dev->pci_conf[addr] = val & 0xd0; - sis_5571_smram_recalc(dev); - break; - - default: - break; - } - } + if (func == 0x00) + sis_5571_host_to_pci_write(addr, val, dev->h2p); } static uint8_t -sis_5571_mem_to_pci_read(int func, int addr, void *priv) +sis_5571_read(int func, int addr, void *priv) { const sis_5571_t *dev = (sis_5571_t *) priv; uint8_t ret = 0xff; - if (func == 0x00) { - ret = dev->pci_conf[addr]; + if (func == 0x00) + ret = sis_5571_host_to_pci_read(addr, dev->h2p); - sis_5571_log("SiS 5571 M2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); - } + sis_5571_log("SiS 5571: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); return ret; } static void -sis_5571_pci_to_isa_reset(sis_5571_t *dev) -{ - /* PCI to ISA Bridge */ - dev->pci_conf_sb[0][0x00] = 0x39; - dev->pci_conf_sb[0][0x01] = 0x10; - dev->pci_conf_sb[0][0x02] = 0x08; - dev->pci_conf_sb[0][0x03] = 0x00; - dev->pci_conf_sb[0][0x04] = 0x07; - dev->pci_conf_sb[0][0x05] = 0x00; - dev->pci_conf_sb[0][0x06] = 0x00; - dev->pci_conf_sb[0][0x07] = 0x02; - dev->pci_conf_sb[0][0x08] = 0x01; - dev->pci_conf_sb[0][0x09] = 0x00; - dev->pci_conf_sb[0][0x0a] = 0x01; - dev->pci_conf_sb[0][0x0b] = 0x06; - dev->pci_conf_sb[0][0x0e] = 0x80; - - dev->pci_conf_sb[0][0x40] = 0x00; - dev->pci_conf_sb[0][0x41] = dev->pci_conf_sb[0][0x42] = 0x80; - dev->pci_conf_sb[0][0x43] = dev->pci_conf_sb[0][0x44] = 0x80; - dev->pci_conf_sb[0][0x45] = 0x00; - dev->pci_conf_sb[0][0x46] = 0x00; - dev->pci_conf_sb[0][0x47] = 0x00; - dev->pci_conf_sb[0][0x48] = dev->pci_conf_sb[0][0x49] = 0x00; - dev->pci_conf_sb[0][0x4a] = dev->pci_conf_sb[0][0x4b] = 0x00; - dev->pci_conf_sb[0][0x61] = 0x80; - dev->pci_conf_sb[0][0x62] = 0x00; - dev->pci_conf_sb[0][0x63] = 0x80; - dev->pci_conf_sb[0][0x64] = 0x00; - dev->pci_conf_sb[0][0x65] = 0x00; - dev->pci_conf_sb[0][0x66] = dev->pci_conf_sb[0][0x67] = 0x00; - dev->pci_conf_sb[0][0x68] = 0x80; - dev->pci_conf_sb[0][0x69] = dev->pci_conf_sb[0][0x6a] = 0x00; - dev->pci_conf_sb[0][0x6b] = 0x00; - dev->pci_conf_sb[0][0x6c] = 0x02; - dev->pci_conf_sb[0][0x6d] = 0x00; - dev->pci_conf_sb[0][0x6e] = dev->pci_conf_sb[0][0x6f] = 0x00; - dev->pci_conf_sb[0][0x70] = dev->pci_conf_sb[0][0x71] = 0x00; - dev->pci_conf_sb[0][0x72] = dev->pci_conf_sb[0][0x73] = 0x00; - dev->pci_conf_sb[0][0x74] = dev->pci_conf_sb[0][0x75] = 0x00; - dev->pci_conf_sb[0][0x76] = dev->pci_conf_sb[0][0x77] = 0x00; - - pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); - pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); - - pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); - pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); - pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED); - - cpu_set_isa_speed(7159091); - nvr_bank_set(0, 0, dev->nvr); -} - -static void -sis_5571_pci_to_isa_write(int addr, uint8_t val, void *priv) -{ - sis_5571_t *dev = (sis_5571_t *) priv; - uint8_t old; - - sis_5571_log("SiS 5571 P2I: [W] dev->pci_conf_sb[0][%02X] = %02X\n", addr, val); - - switch (addr) { - default: - break; - - case 0x04: /* Command */ - // dev->pci_conf_sb[0][addr] = val & 0x0f; - break; - - case 0x07: /* Status */ - dev->pci_conf_sb[0][addr] &= ~(val & 0x30); - break; - - case 0x40: /* BIOS Control Register */ - dev->pci_conf_sb[0][addr] = val & 0x3f; - break; - - case 0x41: /* INTA# Remapping Control Register */ - case 0x42: /* INTB# Remapping Control Register */ - case 0x43: /* INTC# Remapping Control Register */ - case 0x44: /* INTD# Remapping Control Register */ - dev->pci_conf_sb[0][addr] = val & 0x8f; - pci_set_irq_routing(addr & 0x07, (val & 0x80) ? PCI_IRQ_DISABLED : (val & 0x0f)); - break; - - case 0x45: - dev->pci_conf_sb[0][addr] = val & 0xec; - switch (val >> 6) { - case 0: - cpu_set_isa_speed(7159091); - break; - case 1: - cpu_set_isa_pci_div(4); - break; - case 2: - cpu_set_isa_pci_div(3); - break; - - default: - break; - } - nvr_bank_set(0, !!(val & 0x08), dev->nvr); - break; - - case 0x46: - dev->pci_conf_sb[0][addr] = val & 0xec; - break; - - case 0x47: /* DMA Clock and Wait State Control Register */ - dev->pci_conf_sb[0][addr] = val & 0x3e; - break; - - case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */ - case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */ - case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */ - case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */ - dev->pci_conf_sb[0][addr] = val; - break; - - case 0x60: - outb(0x0070, val); - break; - - /* Simply skip MIRQ0, so we can reuse the SiS 551x IDEIRQ infrastructure. */ - case 0x61: /* MIRQ Remapping Control Register */ - sis_5571_log("Set MIRQ routing: MIRQ%i -> %02X\n", addr & 0x01, val); - dev->pci_conf_sb[0][addr] = val & 0xcf; - if (val & 0x80) - pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), PCI_IRQ_DISABLED); - else - pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), val & 0xf); - break; - - case 0x62: /* On-board Device DMA Control Register */ - dev->pci_conf_sb[0][addr] = val; - break; - - case 0x63: /* IDEIRQ Remapping Control Register */ - sis_5571_log("Set MIRQ routing: IDEIRQ -> %02X\n", val); - dev->pci_conf_sb[0][addr] = val & 0x8f; - if (val & 0x80) - pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); - else - pci_set_mirq_routing(PCI_MIRQ2, val & 0xf); - break; - - case 0x64: /* GPIO Control Register */ - dev->pci_conf_sb[0][addr] = val & 0xef; - break; - - case 0x65: - dev->pci_conf_sb[0][addr] = val & 0x1b; - break; - - case 0x66: /* GPIO Output Mode Control Register */ - case 0x67: /* GPIO Output Mode Control Register */ - dev->pci_conf_sb[0][addr] = val; - break; - - case 0x68: /* USBIRQ Remapping Control Register */ - sis_5571_log("Set MIRQ routing: USBIRQ -> %02X\n", val); - dev->pci_conf_sb[0][addr] = val & 0xcf; - if (val & 0x80) - pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED); - else - pci_set_mirq_routing(PCI_MIRQ3, val & 0xf); - break; - - case 0x69: - dev->pci_conf_sb[0][addr] = val; - break; - - case 0x6a: - dev->pci_conf_sb[0][addr] = val & 0xfc; - break; - - case 0x6b: - dev->pci_conf_sb[0][addr] = val; - break; - - case 0x6c: - dev->pci_conf_sb[0][addr] = val & 0x02; - break; - - case 0x6e: /* Software-Controlled Interrupt Request, Channels 7-0 */ - old = dev->pci_conf_sb[0][addr]; - picint((val ^ old) & val); - picintc((val ^ old) & ~val); - dev->pci_conf_sb[0][addr] = val; - break; - - case 0x6f: /* Software-Controlled Interrupt Request, channels 15-8 */ - old = dev->pci_conf_sb[0][addr]; - picint(((val ^ old) & val) << 8); - picintc(((val ^ old) & ~val) << 8); - dev->pci_conf_sb[0][addr] = val; - break; - - case 0x70: - dev->pci_conf_sb[0][addr] = (dev->pci_conf_sb[0][addr] & 0x02) | (val & 0xdc); - break; - - case 0x71: /* Type-F DMA Control Register */ - dev->pci_conf_sb[0][addr] = val & 0xef; - break; - - case 0x72: /* SMI Triggered By IRQ/GPIO Control */ - case 0x73: /* SMI Triggered By IRQ/GPIO Control */ - dev->pci_conf_sb[0][addr] = val; - break; - - case 0x74: /* System Standby Timer Reload, - System Standby State Exit And Throttling State Exit Control */ - case 0x75: /* System Standby Timer Reload, - System Standby State Exit And Throttling State Exit Control */ - case 0x76: /* Monitor Standby Timer Reload And Monitor Standby State ExitControl */ - case 0x77: /* Monitor Standby Timer Reload And Monitor Standby State ExitControl */ - dev->pci_conf_sb[0][addr] = val; - break; - } -} - -static uint8_t -sis_5571_pci_to_isa_read(int addr, void *priv) +sis_5572_write(int func, int addr, uint8_t val, void *priv) { const sis_5571_t *dev = (sis_5571_t *) priv; - uint8_t ret = 0xff; - switch (addr) { - default: - ret = dev->pci_conf_sb[0][addr]; - break; - case 0x4c ... 0x4f: - ret = pic_read_icw(0, addr & 0x03); - break; - case 0x50 ... 0x53: - ret = pic_read_icw(1, addr & 0x03); - break; - case 0x54 ... 0x55: - ret = pic_read_ocw(0, addr & 0x01); - break; - case 0x56 ... 0x57: - ret = pic_read_ocw(1, addr & 0x01); - break; - case 0x58 ... 0x5f: - ret = dev->pit_read_reg(dev->pit, addr & 0x07); - break; - case 0x60: - ret = inb(0x0070); - break; - } + sis_5571_log("SiS 5572: [W] dev->pci_conf[%02X] = %02X\n", addr, val); - sis_5571_log("SiS 5571 P2I: [R] dev->pci_conf_sb[0][%02X] = %02X\n", addr, ret); - - return ret; -} - -static void -sis_5571_ide_irq_handler(sis_5571_t *dev) -{ - if (dev->pci_conf_sb[1][0x09] & 0x01) { - /* Primary IDE is native. */ - sis_5571_log("Primary IDE IRQ mode: Native, Native\n"); - sff_set_irq_mode(dev->bm[0], IRQ_MODE_SIS_551X); - } else { - /* Primary IDE is legacy. */ - sis_5571_log("Primary IDE IRQ mode: IRQ14, IRQ15\n"); - sff_set_irq_mode(dev->bm[0], IRQ_MODE_LEGACY); - } - - if (dev->pci_conf_sb[1][0x09] & 0x04) { - /* Secondary IDE is native. */ - sis_5571_log("Secondary IDE IRQ mode: Native, Native\n"); - sff_set_irq_mode(dev->bm[1], IRQ_MODE_SIS_551X); - } else { - /* Secondary IDE is legacy. */ - sis_5571_log("Secondary IDE IRQ mode: IRQ14, IRQ15\n"); - sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY); - } -} - -static void -sis_5571_ide_handler(sis_5571_t *dev) -{ - uint8_t ide_io_on = dev->pci_conf_sb[1][0x04] & 0x01; - - uint16_t native_base_pri_addr = (dev->pci_conf_sb[1][0x11] | dev->pci_conf_sb[1][0x10] << 8) & 0xfffe; - uint16_t native_side_pri_addr = (dev->pci_conf_sb[1][0x15] | dev->pci_conf_sb[1][0x14] << 8) & 0xfffe; - uint16_t native_base_sec_addr = (dev->pci_conf_sb[1][0x19] | dev->pci_conf_sb[1][0x18] << 8) & 0xfffe; - uint16_t native_side_sec_addr = (dev->pci_conf_sb[1][0x1c] | dev->pci_conf_sb[1][0x1b] << 8) & 0xfffe; - - uint16_t current_pri_base; - uint16_t current_pri_side; - uint16_t current_sec_base; - uint16_t current_sec_side; - - /* Primary Channel Programming */ - current_pri_base = (!(dev->pci_conf_sb[1][0x09] & 1)) ? 0x01f0 : native_base_pri_addr; - current_pri_side = (!(dev->pci_conf_sb[1][0x09] & 1)) ? 0x03f6 : native_side_pri_addr; - - /* Secondary Channel Programming */ - current_sec_base = (!(dev->pci_conf_sb[1][0x09] & 4)) ? 0x0170 : native_base_sec_addr; - current_sec_side = (!(dev->pci_conf_sb[1][0x09] & 4)) ? 0x0376 : native_side_sec_addr; - - sis_5571_log("sis_5571_ide_handler(): Disabling primary IDE...\n"); - ide_pri_disable(); - sis_5571_log("sis_5571_ide_handler(): Disabling secondary IDE...\n"); - ide_sec_disable(); - - if (ide_io_on) { - /* Primary Channel Setup */ - if (dev->pci_conf_sb[1][0x4a] & 0x02) { - sis_5571_log("sis_5571_ide_handler(): Primary IDE base now %04X...\n", current_pri_base); - ide_set_base(0, current_pri_base); - sis_5571_log("sis_5571_ide_handler(): Primary IDE side now %04X...\n", current_pri_side); - ide_set_side(0, current_pri_side); - - sis_5571_log("sis_5571_ide_handler(): Enabling primary IDE...\n"); - ide_pri_enable(); - - sis_5571_log("SiS 5571 PRI: BASE %04x SIDE %04x\n", current_pri_base, current_pri_side); - } - - /* Secondary Channel Setup */ - if (dev->pci_conf_sb[1][0x4a] & 0x04) { - sis_5571_log("sis_5571_ide_handler(): Secondary IDE base now %04X...\n", current_sec_base); - ide_set_base(1, current_sec_base); - sis_5571_log("sis_5571_ide_handler(): Secondary IDE side now %04X...\n", current_sec_side); - ide_set_side(1, current_sec_side); - - sis_5571_log("sis_5571_ide_handler(): Enabling secondary IDE...\n"); - ide_sec_enable(); - - sis_5571_log("SiS 5571: BASE %04x SIDE %04x\n", current_sec_base, current_sec_side); - } - } - - sff_bus_master_handler(dev->bm[0], ide_io_on, - ((dev->pci_conf_sb[1][0x20] & 0xf0) | (dev->pci_conf_sb[1][0x21] << 8)) + 0); - sff_bus_master_handler(dev->bm[1], ide_io_on, - ((dev->pci_conf_sb[1][0x20] & 0xf0) | (dev->pci_conf_sb[1][0x21] << 8)) + 8); -} - -static void -sis_5571_ide_reset(sis_5571_t *dev) -{ - /* PCI IDE */ - dev->pci_conf_sb[1][0x00] = 0x39; - dev->pci_conf_sb[1][0x01] = 0x10; - dev->pci_conf_sb[1][0x02] = 0x13; - dev->pci_conf_sb[1][0x03] = 0x55; - dev->pci_conf_sb[1][0x04] = dev->pci_conf_sb[1][0x05] = 0x00; - dev->pci_conf_sb[1][0x06] = dev->pci_conf_sb[1][0x07] = 0x00; - dev->pci_conf_sb[1][0x08] = 0xc0; - dev->pci_conf_sb[1][0x09] = 0x8a; - dev->pci_conf_sb[1][0x0a] = dev->pci_conf_sb[1][0x0b] = 0x01; - dev->pci_conf_sb[1][0x0c] = dev->pci_conf_sb[1][0x0d] = 0x00; - dev->pci_conf_sb[1][0x0e] = 0x80; - dev->pci_conf_sb[1][0x0f] = 0x00; - dev->pci_conf_sb[1][0x10] = 0xf1; - dev->pci_conf_sb[1][0x11] = 0x01; - dev->pci_conf_sb[1][0x14] = 0xf5; - dev->pci_conf_sb[1][0x15] = 0x03; - dev->pci_conf_sb[1][0x18] = 0x71; - dev->pci_conf_sb[1][0x19] = 0x01; - dev->pci_conf_sb[1][0x1c] = 0x75; - dev->pci_conf_sb[1][0x1d] = 0x03; - dev->pci_conf_sb[1][0x20] = 0x01; - dev->pci_conf_sb[1][0x21] = 0xf0; - dev->pci_conf_sb[1][0x22] = dev->pci_conf_sb[1][0x23] = 0x00; - dev->pci_conf_sb[1][0x24] = dev->pci_conf_sb[1][0x25] = 0x00; - dev->pci_conf_sb[1][0x26] = dev->pci_conf_sb[1][0x27] = 0x00; - dev->pci_conf_sb[1][0x28] = dev->pci_conf_sb[1][0x29] = 0x00; - dev->pci_conf_sb[1][0x2a] = dev->pci_conf_sb[1][0x2b] = 0x00; -#ifdef DATASHEET - dev->pci_conf_sb[1][0x2c] = dev->pci_conf_sb[1][0x2d] = 0x00; -#else - /* The only Linux lspci listing I could find of this chipset, - shows a subsystem of 0058:0000. */ - dev->pci_conf_sb[1][0x2c] = 0x58; - dev->pci_conf_sb[1][0x2d] = 0x00; -#endif - dev->pci_conf_sb[1][0x2e] = dev->pci_conf_sb[1][0x2f] = 0x00; - dev->pci_conf_sb[1][0x30] = dev->pci_conf_sb[1][0x31] = 0x00; - dev->pci_conf_sb[1][0x32] = dev->pci_conf_sb[1][0x33] = 0x00; - dev->pci_conf_sb[1][0x40] = dev->pci_conf_sb[1][0x41] = 0x00; - dev->pci_conf_sb[1][0x42] = dev->pci_conf_sb[1][0x43] = 0x00; - dev->pci_conf_sb[1][0x44] = dev->pci_conf_sb[1][0x45] = 0x00; - dev->pci_conf_sb[1][0x46] = dev->pci_conf_sb[1][0x47] = 0x00; - dev->pci_conf_sb[1][0x48] = dev->pci_conf_sb[1][0x49] = 0x00; - dev->pci_conf_sb[1][0x4a] = 0x06; - dev->pci_conf_sb[1][0x4b] = 0x00; - dev->pci_conf_sb[1][0x4c] = dev->pci_conf_sb[1][0x4d] = 0x00; - dev->pci_conf_sb[1][0x4e] = dev->pci_conf_sb[1][0x4f] = 0x00; - - sis_5571_ide_irq_handler(dev); - sis_5571_ide_handler(dev); - - sff_bus_master_reset(dev->bm[0]); - sff_bus_master_reset(dev->bm[1]); -} - -static void -sis_5571_ide_write(int addr, uint8_t val, void *priv) -{ - sis_5571_t *dev = (sis_5571_t *) priv; - - sis_5571_log("SiS 5571 IDE: [W] dev->pci_conf_sb[1][%02X] = %02X\n", addr, val); - - switch (addr) { - default: - break; - - case 0x04: /* Command low byte */ - dev->pci_conf_sb[1][addr] = val & 0x05; - sis_5571_ide_handler(dev); - break; - case 0x06: /* Status low byte */ - dev->pci_conf_sb[1][addr] = val & 0x20; - break; - case 0x07: /* Status high byte */ - dev->pci_conf_sb[1][addr] = (dev->pci_conf_sb[1][addr] & 0x06) & ~(val & 0x38); - break; - case 0x09: /* Programming Interface Byte */ - dev->pci_conf_sb[1][addr] = (dev->pci_conf_sb[1][addr] & 0x8a) | (val & 0x45); - sis_5571_ide_irq_handler(dev); - sis_5571_ide_handler(dev); - break; - case 0x0d: /* Latency Timer */ - dev->pci_conf_sb[1][addr] = val; - break; - - /* Primary Base Address */ - case 0x10: - case 0x11: - case 0x14: - case 0x15: - fallthrough; - - /* Secondary Base Address */ - case 0x18: - case 0x19: - case 0x1c: - case 0x1d: - fallthrough; - - /* Bus Mastering Base Address */ - case 0x20: - case 0x21: - if (addr == 0x20) - dev->pci_conf_sb[1][addr] = (val & 0xe0) | 0x01; - else - dev->pci_conf_sb[1][addr] = val; - sis_5571_ide_handler(dev); - break; - - /* The only Linux lspci listing I could find of this chipset, - does not show any BIOS bar, therefore writes to that are disabled. */ -#ifdef DATASHEET - case 0x30: /* Expansion ROM Base Address */ - case 0x31: /* Expansion ROM Base Address */ - case 0x32: /* Expansion ROM Base Address */ - case 0x33: /* Expansion ROM Base Address */ - dev->pci_conf_sb[1][addr] = val; - break; -#endif - - case 0x40: /* IDE Primary Channel/Master Drive Data Recovery Time Control */ - case 0x42: /* IDE Primary Channel/Slave Drive Data Recovery Time Control */ - case 0x44: /* IDE Secondary Channel/Master Drive Data Recovery Time Control */ - case 0x46: /* IDE Secondary Channel/Slave Drive Data Recovery Time Control */ - case 0x48: /* IDE Command Recovery Time Control */ - dev->pci_conf_sb[1][addr] = val & 0x0f; - break; - - case 0x41: /* IDE Primary Channel/Master Drive DataActive Time Control */ - case 0x43: /* IDE Primary Channel/Slave Drive Data Active Time Control */ - case 0x45: /* IDE Secondary Channel/Master Drive Data Active Time Control */ - case 0x47: /* IDE Secondary Channel/Slave Drive Data Active Time Control */ - case 0x49: /* IDE Command Active Time Control */ - dev->pci_conf_sb[1][addr] = val & 0x07; - break; - - case 0x4a: /* IDE General Control Register 0 */ - dev->pci_conf_sb[1][addr] = val & 0xaf; - sis_5571_ide_handler(dev); - break; - - case 0x4b: /* IDE General Control register 1 */ - dev->pci_conf_sb[1][addr] = val; - break; - - case 0x4c: /* Prefetch Count of Primary Channel (Low Byte) */ - case 0x4d: /* Prefetch Count of Primary Channel (High Byte) */ - case 0x4e: /* Prefetch Count of Secondary Channel (Low Byte) */ - case 0x4f: /* Prefetch Count of Secondary Channel (High Byte) */ - dev->pci_conf_sb[1][addr] = val; - break; - } -} - -static uint8_t -sis_5571_ide_read(int addr, void *priv) -{ - const sis_5571_t *dev = (sis_5571_t *) priv; - uint8_t ret = 0xff; - - switch (addr) { - default: - ret = dev->pci_conf_sb[1][addr]; - break; - - case 0x09: - ret = dev->pci_conf_sb[1][addr]; - if (dev->pci_conf_sb[1][0x09] & 0x40) - ret |= ((dev->pci_conf_sb[1][0x4a] & 0x06) << 3); - break; - - case 0x3d: - ret = (dev->pci_conf_sb[1][0x09] & 0x05) ? PCI_INTA : 0x00; - break; - } - - sis_5571_log("SiS 5571 IDE: [R] dev->pci_conf_sb[1][%02X] = %02X\n", addr, ret); - - return ret; -} - -/* SiS 5571 unknown I/O port (second USB PCI BAR). */ -static void -sis_5571_usb_unk_write(uint16_t addr, uint8_t val, void *priv) -{ - sis_5571_t *dev = (sis_5571_t *) priv; - - addr = (addr - dev->usb_unk_base) & 0x07; - - sis_5571_log("SiS 5571 USB UNK: [W] dev->usb_unk_regs[%02X] = %02X\n", addr, val); - - dev->usb_unk_regs[addr] = val; -} - -static uint8_t -sis_5571_usb_unk_read(uint16_t addr, void *priv) -{ - const sis_5571_t *dev = (sis_5571_t *) priv; - uint8_t ret = 0xff; - - addr = (addr - dev->usb_unk_base) & 0x07; - - ret = dev->usb_unk_regs[addr & 0x07]; - - sis_5571_log("SiS 5571 USB UNK: [R] dev->usb_unk_regs[%02X] = %02X\n", addr, ret); - - return ret; -} - -static void -sis_5571_usb_reset(sis_5571_t *dev) -{ - /* USB */ - dev->pci_conf_sb[2][0x00] = 0x39; - dev->pci_conf_sb[2][0x01] = 0x10; - dev->pci_conf_sb[2][0x02] = 0x01; - dev->pci_conf_sb[2][0x03] = 0x70; - dev->pci_conf_sb[2][0x04] = dev->pci_conf_sb[1][0x05] = 0x00; - dev->pci_conf_sb[2][0x06] = 0x00; - dev->pci_conf_sb[2][0x07] = 0x02; - dev->pci_conf_sb[2][0x08] = 0xb0; - dev->pci_conf_sb[2][0x09] = 0x10; - dev->pci_conf_sb[2][0x0a] = 0x03; - dev->pci_conf_sb[2][0x0b] = 0x0c; - dev->pci_conf_sb[2][0x0c] = dev->pci_conf_sb[1][0x0d] = 0x00; - dev->pci_conf_sb[2][0x0e] = 0x80 /* 0x10 - Datasheet erratum - header type 0x10 is invalid! */; - dev->pci_conf_sb[2][0x0f] = 0x00; - dev->pci_conf_sb[2][0x10] = 0x00; - dev->pci_conf_sb[2][0x11] = 0x00; - dev->pci_conf_sb[2][0x12] = 0x00; - dev->pci_conf_sb[2][0x13] = 0x00; - dev->pci_conf_sb[2][0x14] = 0x01; - dev->pci_conf_sb[2][0x15] = 0x00; - dev->pci_conf_sb[2][0x16] = 0x00; - dev->pci_conf_sb[2][0x17] = 0x00; - dev->pci_conf_sb[2][0x3c] = 0x00; - dev->pci_conf_sb[2][0x3d] = PCI_INTA; - dev->pci_conf_sb[2][0x3e] = 0x00; - dev->pci_conf_sb[2][0x3f] = 0x00; - - ohci_update_mem_mapping(dev->usb, - dev->pci_conf_sb[2][0x11], dev->pci_conf_sb[2][0x12], - dev->pci_conf_sb[2][0x13], dev->pci_conf_sb[2][0x04] & 0x02); - - if (dev->usb_unk_base != 0x0000) { - io_removehandler(dev->usb_unk_base, 0x0002, - sis_5571_usb_unk_read, NULL, NULL, - sis_5571_usb_unk_write, NULL, NULL, dev); - } - - dev->usb_unk_base = 0x0000; - - memset(dev->usb_unk_regs, 0x00, sizeof(dev->usb_unk_regs)); -} - -static void -sis_5571_usb_write(int addr, uint8_t val, void *priv) -{ - sis_5571_t *dev = (sis_5571_t *) priv; - - sis_5571_log("SiS 5571 USB: [W] dev->pci_conf_sb[2][%02X] = %02X\n", addr, val); - - if (dev->pci_conf_sb[0][0x68] & 0x40) switch (addr) { - default: - break; - - case 0x04: /* Command - Low Byte */ - dev->pci_conf_sb[2][addr] = val & 0x47; - if (dev->usb_unk_base != 0x0000) { - io_removehandler(dev->usb_unk_base, 0x0002, - sis_5571_usb_unk_read, NULL, NULL, - sis_5571_usb_unk_write, NULL, NULL, dev); - if (dev->pci_conf_sb[2][0x04] & 0x01) - io_sethandler(dev->usb_unk_base, 0x0002, - sis_5571_usb_unk_read, NULL, NULL, - sis_5571_usb_unk_write, NULL, NULL, dev); - } - ohci_update_mem_mapping(dev->usb, - dev->pci_conf_sb[2][0x11], dev->pci_conf_sb[2][0x12], - dev->pci_conf_sb[2][0x13], dev->pci_conf_sb[2][0x04] & 0x02); - break; - - case 0x05: /* Command - High Byte */ - dev->pci_conf_sb[2][addr] = val & 0x01; - break; - - case 0x07: /* Status - High Byte */ - dev->pci_conf_sb[2][addr] &= ~(val & 0xf9); - break; - - case 0x0d: /* Latency Timer */ - dev->pci_conf_sb[2][addr] = val; - break; - - case 0x11: /* Memory Space Base Address Register */ - case 0x12: /* Memory Space Base Address Register */ - case 0x13: /* Memory Space Base Address Register */ - dev->pci_conf_sb[2][addr] = val & ((addr == 0x11) ? 0xf0 : 0xff); - ohci_update_mem_mapping(dev->usb, - dev->pci_conf_sb[2][0x11], dev->pci_conf_sb[2][0x12], - dev->pci_conf_sb[2][0x13], dev->pci_conf_sb[2][4] & 0x02); - break; - - case 0x14: /* IO Space Base Address Register */ - case 0x15: /* IO Space Base Address Register */ - if (dev->usb_unk_base != 0x0000) { - io_removehandler(dev->usb_unk_base, 0x0002, - sis_5571_usb_unk_read, NULL, NULL, - sis_5571_usb_unk_write, NULL, NULL, dev); - } - dev->pci_conf_sb[2][addr] = val; - dev->usb_unk_base = (dev->pci_conf_sb[2][0x14] & 0xf8) | - (dev->pci_conf_sb[2][0x15] << 8); - if (dev->usb_unk_base != 0x0000) { - io_sethandler(dev->usb_unk_base, 0x0002, - sis_5571_usb_unk_read, NULL, NULL, - sis_5571_usb_unk_write, NULL, NULL, dev); - } - break; - - case 0x3c: /* Interrupt Line */ - dev->pci_conf_sb[2][addr] = val; - break; - } -} - -static uint8_t -sis_5571_usb_read(int addr, void *priv) -{ - const sis_5571_t *dev = (sis_5571_t *) priv; - uint8_t ret = 0xff; - - if (dev->pci_conf_sb[0][0x68] & 0x40) { - ret = dev->pci_conf_sb[2][addr]; - - sis_5571_log("SiS 5571 USB: [R] dev->pci_conf_sb[2][%02X] = %02X\n", addr, ret); - } - - return ret; -} - -static void -sis_5571_sb_write(int func, int addr, uint8_t val, void *priv) -{ switch (func) { case 0x00: - sis_5571_pci_to_isa_write(addr, val, priv); + sis_5513_pci_to_isa_write(addr, val, dev->p2i); break; case 0x01: - sis_5571_ide_write(addr, val, priv); + sis_5513_ide_write(addr, val, dev->ide); break; case 0x02: - sis_5571_usb_write(addr, val, priv); + sis_5572_usb_write(addr, val, dev->usb); break; } } static uint8_t -sis_5571_sb_read(int func, int addr, void *priv) +sis_5572_read(int func, int addr, void *priv) { + const sis_5571_t *dev = (sis_5571_t *) priv; uint8_t ret = 0xff; switch (func) { case 0x00: - ret = sis_5571_pci_to_isa_read(addr, priv); + ret = sis_5513_pci_to_isa_read(addr, dev->p2i); break; case 0x01: - ret = sis_5571_ide_read(addr, priv); + ret = sis_5513_ide_read(addr, dev->ide); break; case 0x02: - ret = sis_5571_usb_read(addr, priv); + ret = sis_5572_usb_read(addr, dev->usb); break; } + sis_5571_log("SiS 5572: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + return ret; } -static void -sis_5571_reset(void *priv) -{ - sis_5571_t *dev = (sis_5571_t *) priv; - - /* Memory/PCI Bridge */ - sis_5571_mem_to_pci_reset(dev); - - /* PCI to ISA bridge */ - sis_5571_pci_to_isa_reset(dev); - - /* IDE Controller */ - sis_5571_ide_reset(dev); - - /* USB Controller */ - sis_5571_usb_reset(dev); -} - static void sis_5571_close(void *priv) { sis_5571_t *dev = (sis_5571_t *) priv; - smram_del(dev->smram); free(dev); } @@ -1192,44 +153,18 @@ static void * sis_5571_init(UNUSED(const device_t *info)) { sis_5571_t *dev = (sis_5571_t *) calloc(1, sizeof(sis_5571_t)); - uint8_t pit_is_fast = (((pit_mode == -1) && is486) || (pit_mode == 1)); - /* Device 0: Memory/PCI Bridge */ - pci_add_card(PCI_ADD_NORTHBRIDGE, - sis_5571_mem_to_pci_read, sis_5571_mem_to_pci_write, dev, &dev->nb_slot); - /* Device 1: Southbridge */ - pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5571_sb_read, sis_5571_sb_write, dev, &dev->sb_slot); + /* Device 0: SiS 5571 */ + pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5571_read, sis_5571_write, dev, &dev->nb_slot); + /* Device 1: SiS 5572 */ + pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5572_read, sis_5572_write, dev, &dev->sb_slot); - /* MIRQ */ - pci_enable_mirq(1); + dev->sis = device_add(&sis_55xx_common_device); - /* IDEIRQ */ - pci_enable_mirq(2); - - /* USBIRQ */ - pci_enable_mirq(3); - - /* Port 92h */ - dev->port_92 = device_add(&port_92_device); - - /* SFF IDE */ - dev->bm[0] = device_add_inst(&sff8038i_device, 1); - dev->bm[1] = device_add_inst(&sff8038i_device, 2); - - /* SMRAM */ - dev->smram = smram_add(); - - /* PIT */ - dev->pit = device_find_first_priv(DEVICE_PIT); - dev->pit_read_reg = pit_is_fast ? pitf_read_reg : pit_read_reg; - - /* NVR */ - dev->nvr = device_add(&at_mb_nvr_device); - - /* USB */ - dev->usb = device_add(&usb_device); - - sis_5571_reset(dev); + dev->h2p = device_add_linked(&sis_5571_h2p_device, dev->sis); + dev->p2i = device_add_linked(&sis_5572_p2i_device, dev->sis); + dev->ide = device_add_linked(&sis_5572_ide_device, dev->sis); + dev->usb = device_add_linked(&sis_5572_usb_device, dev->sis); return dev; } @@ -1241,7 +176,7 @@ const device_t sis_5571_device = { .local = 0, .init = sis_5571_init, .close = sis_5571_close, - .reset = sis_5571_reset, + .reset = NULL, { .available = NULL }, .speed_changed = NULL, .force_redraw = NULL, diff --git a/src/chipset/sis_5571_h2p.c b/src/chipset/sis_5571_h2p.c new file mode 100644 index 000000000..26c74a3c0 --- /dev/null +++ b/src/chipset/sis_5571_h2p.c @@ -0,0 +1,458 @@ +/* + * 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 SiS 5571 Host to PCI bridge. + * + * Authors: Miran Grca, + * + * Copyright 2024 Miran Grca. + */ +#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/dma.h> +#include <86box/mem.h> +#include <86box/nvr.h> +#include <86box/hdd.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/pci.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/pit_fast.h> +#include <86box/plat.h> +#include <86box/plat_unused.h> +#include <86box/port_92.h> +#include <86box/smram.h> +#include <86box/spd.h> +#include <86box/apm.h> +#include <86box/ddma.h> +#include <86box/acpi.h> +#include <86box/smbus.h> +#include <86box/spd.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> +#include <86box/usb.h> +#include <86box/agpgart.h> + +#ifdef ENABLE_SIS_5571_HOST_TO_PCI_LOG +int sis_5571_host_to_pci_do_log = ENABLE_SIS_5571_HOST_TO_PCI_LOG; + +static void +sis_5571_host_to_pci_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5571_host_to_pci_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5571_host_to_pci_log(fmt, ...) +#endif + +typedef struct sis_5571_host_to_pci_t { + uint8_t pci_conf[256]; + uint8_t states[7]; + + sis_55xx_common_t *sis; + + smram_t *smram; +} sis_5571_host_to_pci_t; + +static void +sis_5571_shadow_recalc(sis_5571_host_to_pci_t *dev) +{ + int state; + uint32_t base; + + for (uint8_t i = 0x70; i <= 0x76; i++) { + if (i == 0x76) { + if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) { + state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_both(0xf0000, 0x10000, state); + sis_5571_host_to_pci_log("000F0000-000FFFFF\n"); + } + } else { + base = ((i & 0x07) << 15) + 0xc0000; + + if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) { + state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_both(base, 0x4000, state); + sis_5571_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff); + } + + if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0x0a) { + state = (dev->pci_conf[i] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[i] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_both(base + 0x4000, 0x4000, state); + sis_5571_host_to_pci_log("%08X-%08X\n", base + 0x4000, base + 0x7fff); + } + } + + dev->states[i & 0x0f] = dev->pci_conf[i]; + } + + flushmmucache_nopc(); +} + +static void +sis_5571_smram_recalc(sis_5571_host_to_pci_t *dev) +{ + smram_disable_all(); + + switch (dev->pci_conf[0x68] >> 6) { + case 0: + smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x68] & 0x10, 1); + break; + case 1: + smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x68] & 0x10, 1); + break; + case 2: + smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x68] & 0x10, 1); + break; + case 3: + smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x10000, dev->pci_conf[0x68] & 0x10, 1); + break; + + default: + break; + } + + flushmmucache(); +} + +void +sis_5571_host_to_pci_write(int addr, uint8_t val, void *priv) +{ + sis_5571_host_to_pci_t *dev = (sis_5571_host_to_pci_t *) priv; + + sis_5571_host_to_pci_log("SiS 5571 H2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (addr) { + default: + break; + + case 0x04: /* Command - low byte */ + case 0x05: /* Command - high byte */ + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xfd) | (val & 0x02); + break; + + case 0x07: /* Status - High Byte */ + dev->pci_conf[addr] &= ~(val & 0xb8); + break; + + case 0x0d: /* Master latency timer */ + dev->pci_conf[addr] = val; + break; + + case 0x50: /* Host Interface and DRAM arbiter */ + dev->pci_conf[addr] = val & 0xec; + break; + + case 0x51: /* CACHE */ + dev->pci_conf[addr] = val; + cpu_cache_ext_enabled = !!(val & 0x40); + cpu_update_waitstates(); + break; + + case 0x52: + dev->pci_conf[addr] = val & 0xd0; + break; + + case 0x53: /* DRAM */ + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x54: /* FP/EDO */ + dev->pci_conf[addr] = val; + break; + + case 0x55: + dev->pci_conf[addr] = val & 0xe0; + break; + + case 0x56: /* MDLE delay */ + dev->pci_conf[addr] = val & 0x07; + break; + + case 0x57: /* SDRAM */ + dev->pci_conf[addr] = val & 0xf8; + break; + + case 0x59: /* Buffer strength and current rating */ + dev->pci_conf[addr] = val; + break; + + case 0x5a: + dev->pci_conf[addr] = val & 0x03; + break; + + /* Undocumented - DRAM bank registers, the exact layout is currently unknown. */ + case 0x60 ... 0x6b: + dev->pci_conf[addr] = val; + break; + + case 0x70 ... 0x75: + dev->pci_conf[addr] = val & 0xee; + sis_5571_shadow_recalc(dev); + break; + case 0x76: + dev->pci_conf[addr] = val & 0xe8; + sis_5571_shadow_recalc(dev); + break; + + case 0x77: /* Characteristics of non-cacheable area */ + dev->pci_conf[addr] = val & 0x0f; + break; + + case 0x78: /* Allocation of Non-Cacheable area #1 */ + case 0x79: /* NCA1REG2 */ + case 0x7a: /* Allocation of Non-Cacheable area #2 */ + case 0x7b: /* NCA2REG2 */ + dev->pci_conf[addr] = val; + break; + + case 0x80: /* PCI master characteristics */ + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x81: + dev->pci_conf[addr] = val & 0xcc; + break; + + case 0x82: + dev->pci_conf[addr] = val; + break; + + case 0x83: /* CPU to PCI characteristics */ + dev->pci_conf[addr] = val; + /* TODO: Implement Fast A20 and Fast reset stuff on the KBC already! */ + break; + + case 0x84 ... 0x86: + dev->pci_conf[addr] = val; + break; + + case 0x87: /* Miscellanea */ + dev->pci_conf[addr] = val & 0xf8; + break; + + case 0x90: /* PMU control register */ + case 0x91: /* Address trap for green function */ + case 0x92: + dev->pci_conf[addr] = val; + break; + + case 0x93: /* STPCLK# and APM SMI control */ + dev->pci_conf[addr] = val; + + if ((dev->pci_conf[0x9b] & 0x01) && (val & 0x02)) { + smi_raise(); + dev->pci_conf[0x9d] |= 0x01; + } + break; + + case 0x94: /* 6x86 and Green function control */ + dev->pci_conf[addr] = val & 0xf8; + break; + + case 0x95: /* Test mode control */ + case 0x96: /* Time slot and Programmable 10-bit I/O port definition */ + dev->pci_conf[addr] = val & 0xfb; + break; + + case 0x97: /* programmable 10-bit I/O port address */ + case 0x98: /* Programmable 16-bit I/O port */ + case 0x99 ... 0x9c: + dev->pci_conf[addr] = val; + break; + + case 0x9d: + dev->pci_conf[addr] &= val; + break; + + case 0x9e: /* STPCLK# Assertion Timer */ + case 0x9f: /* STPCLK# De-assertion Timer */ + case 0xa0 ... 0xa2: + dev->pci_conf[addr] = val; + break; + + case 0xa3: /* SMRAM access control and Power supply control */ + dev->pci_conf[addr] = val & 0xd0; + sis_5571_smram_recalc(dev); + break; + } +} + +uint8_t +sis_5571_host_to_pci_read(int addr, void *priv) +{ + const sis_5571_host_to_pci_t *dev = (sis_5571_host_to_pci_t *) priv; + uint8_t ret = 0xff; + + ret = dev->pci_conf[addr]; + + sis_5571_host_to_pci_log("SiS 5571 H2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5571_host_to_pci_reset(void *priv) +{ + sis_5571_host_to_pci_t *dev = (sis_5571_host_to_pci_t *) priv; + + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x71; + dev->pci_conf[0x03] = 0x55; + dev->pci_conf[0x04] = 0x05; + dev->pci_conf[0x05] = 0x00; + dev->pci_conf[0x06] = 0x00; + dev->pci_conf[0x07] = 0x02; + dev->pci_conf[0x08] = 0x00; + dev->pci_conf[0x09] = 0x00; + dev->pci_conf[0x0a] = 0x00; + dev->pci_conf[0x0b] = 0x06; + dev->pci_conf[0x0c] = 0x00; + dev->pci_conf[0x0d] = 0x00; + dev->pci_conf[0x0e] = 0x00; + dev->pci_conf[0x0f] = 0x00; + + dev->pci_conf[0x50] = 0x00; + dev->pci_conf[0x51] = 0x00; + dev->pci_conf[0x52] = 0x00; + dev->pci_conf[0x53] = 0x00; + dev->pci_conf[0x54] = 0x54; + dev->pci_conf[0x55] = 0x54; + dev->pci_conf[0x56] = 0x03; + dev->pci_conf[0x57] = 0x00; + dev->pci_conf[0x58] = 0x00; + dev->pci_conf[0x59] = 0x00; + dev->pci_conf[0x5a] = 0x00; + + /* Undocumented DRAM bank registers. */ + dev->pci_conf[0x60] = dev->pci_conf[0x62] = 0x04; + dev->pci_conf[0x64] = dev->pci_conf[0x66] = 0x04; + dev->pci_conf[0x68] = dev->pci_conf[0x6a] = 0x04; + dev->pci_conf[0x61] = dev->pci_conf[0x65] = 0x00; + dev->pci_conf[0x63] = dev->pci_conf[0x67] = 0x80; + dev->pci_conf[0x69] = 0x00; + dev->pci_conf[0x6b] = 0x80; + + dev->pci_conf[0x70] = 0x00; + dev->pci_conf[0x71] = 0x00; + dev->pci_conf[0x72] = 0x00; + dev->pci_conf[0x73] = 0x00; + dev->pci_conf[0x74] = 0x00; + dev->pci_conf[0x75] = 0x00; + dev->pci_conf[0x76] = 0x00; + + dev->pci_conf[0x77] = 0x00; + dev->pci_conf[0x78] = 0x00; + dev->pci_conf[0x79] = 0x00; + dev->pci_conf[0x7a] = 0x00; + dev->pci_conf[0x7b] = 0x00; + + dev->pci_conf[0x80] = 0x00; + dev->pci_conf[0x81] = 0x00; + dev->pci_conf[0x82] = 0x00; + dev->pci_conf[0x83] = 0x00; + dev->pci_conf[0x84] = 0x00; + dev->pci_conf[0x85] = 0x00; + dev->pci_conf[0x86] = 0x00; + dev->pci_conf[0x87] = 0x00; + + dev->pci_conf[0x8c] = 0x00; + dev->pci_conf[0x8d] = 0x00; + dev->pci_conf[0x8e] = 0x00; + dev->pci_conf[0x8f] = 0x00; + + dev->pci_conf[0x90] = 0x00; + dev->pci_conf[0x91] = 0x00; + dev->pci_conf[0x92] = 0x00; + dev->pci_conf[0x93] = 0x00; + dev->pci_conf[0x93] = 0x00; + dev->pci_conf[0x94] = 0x00; + dev->pci_conf[0x95] = 0x00; + dev->pci_conf[0x96] = 0x00; + dev->pci_conf[0x97] = 0x00; + dev->pci_conf[0x98] = 0x00; + dev->pci_conf[0x99] = 0x00; + dev->pci_conf[0x9a] = 0x00; + dev->pci_conf[0x9b] = 0x00; + dev->pci_conf[0x9c] = 0x00; + dev->pci_conf[0x9d] = 0x00; + dev->pci_conf[0x9e] = 0xff; + dev->pci_conf[0x9f] = 0xff; + + dev->pci_conf[0xa0] = 0xff; + dev->pci_conf[0xa1] = 0x00; + dev->pci_conf[0xa2] = 0xff; + dev->pci_conf[0xa3] = 0x00; + + cpu_cache_ext_enabled = 0; + cpu_update_waitstates(); + + sis_5571_smram_recalc(dev); + sis_5571_shadow_recalc(dev); + + flushmmucache(); +} + +static void +sis_5571_host_to_pci_close(void *priv) +{ + sis_5571_host_to_pci_t *dev = (sis_5571_host_to_pci_t *) priv; + + smram_del(dev->smram); + free(dev); +} + +static void * +sis_5571_host_to_pci_init(UNUSED(const device_t *info)) +{ + sis_5571_host_to_pci_t *dev = (sis_5571_host_to_pci_t *) calloc(1, sizeof(sis_5571_host_to_pci_t)); + + dev->sis = device_get_common_priv(); + + /* SMRAM */ + dev->smram = smram_add(); + + sis_5571_host_to_pci_reset(dev); + + return dev; +} + +const device_t sis_5571_h2p_device = { + .name = "SiS 5571 Host to PCI bridge", + .internal_name = "sis_5571_host_to_pci", + .flags = DEVICE_PCI, + .local = 0x00, + .init = sis_5571_host_to_pci_init, + .close = sis_5571_host_to_pci_close, + .reset = sis_5571_host_to_pci_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5571_old.c b/src/chipset/sis_5571_old.c new file mode 100644 index 000000000..f130ecd8a --- /dev/null +++ b/src/chipset/sis_5571_old.c @@ -0,0 +1,772 @@ +/* + * 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 SiS 5571 Chipset. + * + * + * + * Authors: Tiseno100, + * + * Copyright 2021 Tiseno100. + */ +#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/dma.h> +#include <86box/mem.h> +#include <86box/pci.h> +#include <86box/pic.h> +#include <86box/plat_unused.h> +#include <86box/port_92.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/smram.h> +#include <86box/usb.h> + +#include <86box/chipset.h> + +/* Shadow RAM */ +#define LSB_READ ((dev->pci_conf[0x70 + (cur_reg & 0x07)] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) +#define LSB_WRITE ((dev->pci_conf[0x70 + (cur_reg & 0x07)] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY) +#define MSB_READ ((dev->pci_conf[0x70 + (cur_reg & 0x07)] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) +#define MSB_WRITE ((dev->pci_conf[0x70 + (cur_reg & 0x07)] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY) +#define SYSTEM_READ ((dev->pci_conf[0x76] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) +#define SYSTEM_WRITE ((dev->pci_conf[0x76] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY) + +/* IDE Flags (1 Native / 0 Compatibility)*/ +#define PRIMARY_COMP_NAT_SWITCH (dev->pci_conf_sb[1][9] & 1) +#define SECONDARY_COMP_NAT_SWITCH (dev->pci_conf_sb[1][9] & 4) +#define PRIMARY_NATIVE_BASE (dev->pci_conf_sb[1][0x11] << 8) | (dev->pci_conf_sb[1][0x10] & 0xf8) +#define PRIMARY_NATIVE_SIDE (((dev->pci_conf_sb[1][0x15] << 8) | (dev->pci_conf_sb[1][0x14] & 0xfc)) + 2) +#define SECONDARY_NATIVE_BASE (dev->pci_conf_sb[1][0x19] << 8) | (dev->pci_conf_sb[1][0x18] & 0xf8) +#define SECONDARY_NATIVE_SIDE (((dev->pci_conf_sb[1][0x1d] << 8) | (dev->pci_conf_sb[1][0x1c] & 0xfc)) + 2) +#define BUS_MASTER_BASE ((dev->pci_conf_sb[1][0x20] & 0xf0) | (dev->pci_conf_sb[1][0x21] << 8)) + +#ifdef ENABLE_SIS_5571_LOG +int sis_5571_do_log = ENABLE_SIS_5571_LOG; + +static void +sis_5571_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5571_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5571_log(fmt, ...) +#endif + +typedef struct sis_5571_t { + uint8_t nb_slot; + uint8_t sb_slot; + uint8_t pad; + uint8_t usb_irq_state; + + uint8_t pci_conf[256]; + uint8_t pci_conf_sb[3][256]; + + port_92_t *port_92; + sff8038i_t *ide_drive[2]; + smram_t *smram; + usb_t *usb; +} sis_5571_t; + +static void +sis_5571_shadow_recalc(int cur_reg, sis_5571_t *dev) +{ + if (cur_reg != 0x76) { + mem_set_mem_state_both(0xc0000 + (0x8000 * (cur_reg & 0x07)), 0x4000, LSB_READ | LSB_WRITE); + mem_set_mem_state_both(0xc4000 + (0x8000 * (cur_reg & 0x07)), 0x4000, MSB_READ | MSB_WRITE); + } else + mem_set_mem_state_both(0xf0000, 0x10000, SYSTEM_READ | SYSTEM_WRITE); + + flushmmucache_nopc(); +} + +static void +sis_5571_smm_recalc(sis_5571_t *dev) +{ + smram_disable_all(); + + switch ((dev->pci_conf[0xa3] & 0xc0) >> 6) { + case 0x00: + smram_enable(dev->smram, 0xe0000, 0xe0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1); + break; + case 0x01: + smram_enable(dev->smram, 0xe0000, 0xa0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1); + break; + case 0x02: + smram_enable(dev->smram, 0xe0000, 0xb0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1); + break; + case 0x03: + smram_enable(dev->smram, 0xa0000, 0xa0000, 0x10000, (dev->pci_conf[0xa3] & 0x10), 1); + break; + + default: + break; + } + + flushmmucache(); +} + +void +sis_5571_ide_handler(sis_5571_t *dev) +{ + ide_pri_disable(); + ide_sec_disable(); + if (dev->pci_conf_sb[1][4] & 1) { + if (dev->pci_conf_sb[1][0x4a] & 4) { + ide_set_base(0, PRIMARY_COMP_NAT_SWITCH ? PRIMARY_NATIVE_BASE : 0x1f0); + ide_set_side(0, PRIMARY_COMP_NAT_SWITCH ? PRIMARY_NATIVE_SIDE : 0x3f6); + ide_pri_enable(); + } + if (dev->pci_conf_sb[1][0x4a] & 2) { + ide_set_base(1, SECONDARY_COMP_NAT_SWITCH ? SECONDARY_NATIVE_BASE : 0x170); + ide_set_side(1, SECONDARY_COMP_NAT_SWITCH ? SECONDARY_NATIVE_SIDE : 0x376); + ide_sec_enable(); + } + } +} + +void +sis_5571_bm_handler(sis_5571_t *dev) +{ + sff_bus_master_handler(dev->ide_drive[0], dev->pci_conf_sb[1][4] & 4, BUS_MASTER_BASE); + sff_bus_master_handler(dev->ide_drive[1], dev->pci_conf_sb[1][4] & 4, BUS_MASTER_BASE + 8); +} + +static void +memory_pci_bridge_write(UNUSED(int func), int addr, uint8_t val, void *priv) +{ + sis_5571_t *dev = (sis_5571_t *) priv; + + switch (addr) { + case 0x04: /* Command - low byte */ + case 0x05: /* Command - high byte */ + dev->pci_conf[addr] |= val; + break; + + case 0x06: /* Status - Low Byte */ + dev->pci_conf[addr] &= val; + break; + + case 0x07: /* Status - High Byte */ + dev->pci_conf[addr] &= val & 0xbe; + break; + + case 0x0d: /* Master latency timer */ + dev->pci_conf[addr] = val; + break; + + case 0x50: /* Host Interface and DRAM arbiter */ + dev->pci_conf[addr] = val & 0xec; + break; + + case 0x51: /* CACHE */ + dev->pci_conf[addr] = val; + cpu_cache_ext_enabled = !!(val & 0x40); + cpu_update_waitstates(); + break; + + case 0x52: + dev->pci_conf[addr] = val & 0xd0; + break; + + case 0x53: /* DRAM */ + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x54: /* FP/EDO */ + dev->pci_conf[addr] = val; + break; + + case 0x55: + dev->pci_conf[addr] = val & 0xe0; + break; + + case 0x56: /* MDLE delay */ + case 0x57: /* SDRAM */ + dev->pci_conf[addr] = val & 0xf8; + break; + + case 0x59: /* Buffer strength and current rating */ + dev->pci_conf[addr] = val; + break; + + case 0x5a: + dev->pci_conf[addr] = val & 0x03; + break; + + case 0x60: /* Undocumented */ + case 0x61: /* Undocumented */ + case 0x62: /* Undocumented */ + case 0x63: /* Undocumented */ + case 0x64: /* Undocumented */ + case 0x65: /* Undocumented */ + case 0x66: /* Undocumented */ + case 0x67: /* Undocumented */ + case 0x68: /* Undocumented */ + case 0x69: /* Undocumented */ + case 0x6a: /* Undocumented */ + case 0x6b: /* Undocumented */ + dev->pci_conf[addr] = val; + break; + + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: /* Attribute of shadow RAM for BIOS area */ + dev->pci_conf[addr] = val & ((addr != 0x76) ? 0xee : 0xe8); + sis_5571_shadow_recalc(addr, dev); + sis_5571_smm_recalc(dev); + break; + + case 0x77: /* Characteristics of non-cacheable area */ + dev->pci_conf[addr] = val & 0x0f; + break; + + case 0x78: /* Allocation of Non-Cacheable area #1 */ + case 0x79: /* NCA1REG2 */ + case 0x7a: /* Allocation of Non-Cacheable area #2 */ + case 0x7b: /* NCA2REG2 */ + dev->pci_conf[addr] = val; + break; + + case 0x80: /* PCI master characteristics */ + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x81: + dev->pci_conf[addr] = val & 0xcc; + break; + + case 0x82: + dev->pci_conf[addr] = val; + break; + + case 0x83: /* CPU to PCI characteristics */ + dev->pci_conf[addr] = val; + port_92_set_features(dev->port_92, !!(val & 0x40), !!(val & 0x80)); + break; + + case 0x84: + case 0x85: + case 0x86: + dev->pci_conf[addr] = val; + break; + + case 0x87: /* Miscellanea */ + dev->pci_conf[addr] = val & 0xf8; + break; + + case 0x90: /* PMU control register */ + case 0x91: /* Address trap for green function */ + case 0x92: + dev->pci_conf[addr] = val; + break; + + case 0x93: /* STPCLK# and APM SMI control */ + dev->pci_conf[addr] = val; + + if ((dev->pci_conf[0x9b] & 1) && !!(val & 2)) { + smi_raise(); + dev->pci_conf[0x9d] |= 1; + } + break; + + case 0x94: /* 6x86 and Green function control */ + dev->pci_conf[addr] = val & 0xf8; + break; + + case 0x95: /* Test mode control */ + case 0x96: /* Time slot and Programmable 10-bit I/O port definition */ + dev->pci_conf[addr] = val & 0xfb; + break; + + case 0x97: /* programmable 10-bit I/O port address */ + case 0x98: /* Programmable 16-bit I/O port */ + case 0x99: + case 0x9a: + case 0x9b: + case 0x9c: + dev->pci_conf[addr] = val; + break; + + case 0x9d: + dev->pci_conf[addr] &= val; + break; + + case 0x9e: /* STPCLK# Assertion Timer */ + case 0x9f: /* STPCLK# De-assertion Timer */ + case 0xa0: + case 0xa1: + case 0xa2: + dev->pci_conf[addr] = val; + break; + + case 0xa3: /* SMRAM access control and Power supply control */ + dev->pci_conf[addr] = val & 0xd0; + sis_5571_smm_recalc(dev); + break; + + default: + break; + } + sis_5571_log("SiS5571: dev->pci_conf[%02x] = %02x\n", addr, val); +} + +static uint8_t +memory_pci_bridge_read(UNUSED(int func), int addr, void *priv) +{ + const sis_5571_t *dev = (sis_5571_t *) priv; + + sis_5571_log("SiS5571: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf[addr]); + return dev->pci_conf[addr]; +} + +static void +pci_isa_bridge_write(int func, int addr, uint8_t val, void *priv) +{ + sis_5571_t *dev = (sis_5571_t *) priv; + switch (func) { + case 0: /* Bridge */ + switch (addr) { + case 0x04: /* Command */ + dev->pci_conf_sb[0][addr] |= val & 0x0f; + break; + + case 0x06: /* Status */ + dev->pci_conf_sb[0][addr] &= val; + break; + + case 0x40: /* BIOS Control Register */ + dev->pci_conf_sb[0][addr] = val & 0x3f; + break; + + case 0x41: /* INTA# Remapping Control Register */ + case 0x42: /* INTB# Remapping Control Register */ + case 0x43: /* INTC# Remapping Control Register */ + case 0x44: /* INTD# Remapping Control Register */ + dev->pci_conf_sb[0][addr] = val & 0x8f; + pci_set_irq_routing((addr & 0x07), !(val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED); + break; + + case 0x45: + dev->pci_conf_sb[0][addr] = val & 0xec; + switch ((val & 0xc0) >> 6) { + case 0: + cpu_set_isa_speed(7159091); + break; + case 1: + cpu_set_isa_pci_div(4); + break; + case 2: + cpu_set_isa_pci_div(3); + break; + + default: + break; + } + break; + + case 0x46: + dev->pci_conf_sb[0][addr] = val & 0xec; + break; + + case 0x47: /* DMA Clock and Wait State Control Register */ + dev->pci_conf_sb[0][addr] = val & 0x3e; + break; + + case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */ + case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */ + case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */ + case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */ + dev->pci_conf_sb[0][addr] = val; + break; + + case 0x4c: + case 0x4d: + case 0x4e: + case 0x4f: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5a: + case 0x5b: + case 0x5c: + case 0x5d: + case 0x5e: + dev->pci_conf_sb[0][addr] = val; + break; + + case 0x5f: + dev->pci_conf_sb[0][addr] = val & 0x3f; + break; + + case 0x60: + dev->pci_conf_sb[0][addr] = val; + break; + + case 0x61: /* MIRQ Remapping Control Register */ + dev->pci_conf_sb[0][addr] = val; + pci_set_mirq_routing(PCI_MIRQ0, !(val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED); + break; + + case 0x62: /* On-board Device DMA Control Register */ + dev->pci_conf_sb[0][addr] = val & 0x0f; + dma_set_drq((val & 0x07), 1); + break; + + case 0x63: /* IDEIRQ Remapping Control Register */ + dev->pci_conf_sb[0][addr] = val & 0x8f; + if (val & 0x80) { + sff_set_irq_line(dev->ide_drive[0], val & 0x0f); + sff_set_irq_line(dev->ide_drive[1], val & 0x0f); + } + break; + + case 0x64: /* GPIO Control Register */ + dev->pci_conf_sb[0][addr] = val & 0xef; + break; + + case 0x65: + dev->pci_conf_sb[0][addr] = val & 0x1b; + break; + + case 0x66: /* GPIO Output Mode Control Register */ + case 0x67: /* GPIO Output Mode Control Register */ + dev->pci_conf_sb[0][addr] = val; + break; + + case 0x68: /* USBIRQ Remapping Control Register */ + dev->pci_conf_sb[0][addr] = val & 0x1b; + break; + + case 0x69: + dev->pci_conf_sb[0][addr] = val; + break; + + case 0x6a: + dev->pci_conf_sb[0][addr] = val & 0xfc; + break; + + case 0x6b: + dev->pci_conf_sb[0][addr] = val; + break; + + case 0x6c: + dev->pci_conf_sb[0][addr] = val & 0x03; + break; + + case 0x6e: /* Software-Controlled Interrupt Request, Channels 7-0 */ + case 0x6f: /* Software-Controlled Interrupt Request, channels 15-8 */ + dev->pci_conf_sb[0][addr] = val; + break; + + case 0x70: + dev->pci_conf_sb[0][addr] = val & 0xde; + break; + + case 0x71: /* Type-F DMA Control Register */ + dev->pci_conf_sb[0][addr] = val & 0xfe; + break; + + case 0x72: /* SMI Triggered By IRQ/GPIO Control */ + case 0x73: /* SMI Triggered By IRQ/GPIO Control */ + dev->pci_conf_sb[0][addr] = (addr == 0x72) ? val & 0xfe : val; + break; + + case 0x74: /* System Standby Timer Reload, System Standby State Exit And Throttling State Exit Control */ + case 0x75: /* System Standby Timer Reload, System Standby State Exit And Throttling State Exit Control */ + case 0x76: /* Monitor Standby Timer Reload And Monitor Standby State ExitControl */ + case 0x77: /* Monitor Standby Timer Reload And Monitor Standby State ExitControl */ + dev->pci_conf_sb[0][addr] = val; + break; + + default: + break; + } + sis_5571_log("SiS5571-SB: dev->pci_conf[%02x] = %02x\n", addr, val); + break; + + case 1: /* IDE Controller */ + switch (addr) { + case 0x04: /* Command low byte */ + dev->pci_conf_sb[1][addr] = val & 0x05; + sis_5571_ide_handler(dev); + sis_5571_bm_handler(dev); + break; + + case 0x07: /* Status high byte */ + dev->pci_conf_sb[1][addr] &= val; + break; + + case 0x09: /* Programming Interface Byte */ + dev->pci_conf_sb[1][addr] = val & 0xcf; + sis_5571_ide_handler(dev); + break; + + case 0x0d: /* Latency Time */ + case 0x10: /* Primary Channel Base Address Register */ + case 0x11: /* Primary Channel Base Address Register */ + case 0x12: /* Primary Channel Base Address Register */ + case 0x13: /* Primary Channel Base Address Register */ + case 0x14: /* Primary Channel Base Address Register */ + case 0x15: /* Primary Channel Base Address Register */ + case 0x16: /* Primary Channel Base Address Register */ + case 0x17: /* Primary Channel Base Address Register */ + case 0x18: /* Secondary Channel Base Address Register */ + case 0x19: /* Secondary Channel Base Address Register */ + case 0x1a: /* Secondary Channel Base Address Register */ + case 0x1b: /* Secondary Channel Base Address Register */ + case 0x1c: /* Secondary Channel Base Address Register */ + case 0x1d: /* Secondary Channel Base Address Register */ + case 0x1e: /* Secondary Channel Base Address Register */ + case 0x1f: /* Secondary Channel Base Address Register */ + dev->pci_conf_sb[1][addr] = val; + sis_5571_ide_handler(dev); + break; + + case 0x20: /* Bus Master IDE Control Register Base Address */ + case 0x21: /* Bus Master IDE Control Register Base Address */ + case 0x22: /* Bus Master IDE Control Register Base Address */ + case 0x23: /* Bus Master IDE Control Register Base Address */ + dev->pci_conf_sb[1][addr] = val; + sis_5571_bm_handler(dev); + break; + + case 0x30: /* Expansion ROM Base Address */ + case 0x31: /* Expansion ROM Base Address */ + case 0x32: /* Expansion ROM Base Address */ + case 0x33: /* Expansion ROM Base Address */ + case 0x40: /* IDE Primary Channel/Master Drive Data Recovery Time Control */ + case 0x41: /* IDE Primary Channel/Master Drive DataActive Time Control */ + case 0x42: /* IDE Primary Channel/Slave Drive Data Recovery Time Control */ + case 0x43: /* IDE Primary Channel/Slave Drive Data Active Time Control */ + case 0x44: /* IDE Secondary Channel/Master Drive Data Recovery Time Control */ + case 0x45: /* IDE Secondary Channel/Master Drive Data Active Time Control */ + case 0x46: /* IDE Secondary Channel/Slave Drive Data Recovery Time Control */ + case 0x47: /* IDE Secondary Channel/Slave Drive Data Active Time Control */ + case 0x48: /* IDE Command Recovery Time Control */ + case 0x49: /* IDE Command Active Time Control */ + dev->pci_conf_sb[1][addr] = val; + break; + + case 0x4a: /* IDE General Control Register 0 */ + dev->pci_conf_sb[1][addr] = val & 0xaf; + sis_5571_ide_handler(dev); + break; + + case 0x4b: /* IDE General Control register 1 */ + case 0x4c: /* Prefetch Count of Primary Channel (Low Byte) */ + case 0x4d: /* Prefetch Count of Primary Channel (High Byte) */ + case 0x4e: /* Prefetch Count of Secondary Channel (Low Byte) */ + case 0x4f: /* Prefetch Count of Secondary Channel (High Byte) */ + dev->pci_conf_sb[1][addr] = val; + break; + + default: + break; + } + sis_5571_log("SiS5571-IDE: dev->pci_conf[%02x] = %02x\n", addr, val); + break; + + case 2: /* USB Controller */ + switch (addr) { + case 0x04: /* Command - Low Byte */ + dev->pci_conf_sb[2][addr] = val; + ohci_update_mem_mapping(dev->usb, dev->pci_conf_sb[2][0x11], dev->pci_conf_sb[2][0x12], dev->pci_conf_sb[2][0x13], dev->pci_conf_sb[2][4] & 1); + break; + + case 0x05: /* Command - High Byte */ + dev->pci_conf_sb[2][addr] = val & 0x03; + break; + + case 0x06: /* Status - Low Byte */ + dev->pci_conf_sb[2][addr] &= val & 0xc0; + break; + + case 0x07: /* Status - High Byte */ + dev->pci_conf_sb[2][addr] &= val; + break; + + case 0x10: /* Memory Space Base Address Register */ + case 0x11: /* Memory Space Base Address Register */ + case 0x12: /* Memory Space Base Address Register */ + case 0x13: /* Memory Space Base Address Register */ + dev->pci_conf_sb[2][addr] = val & ((addr == 0x11) ? 0x0f : 0xff); + ohci_update_mem_mapping(dev->usb, dev->pci_conf_sb[2][0x11], dev->pci_conf_sb[2][0x12], dev->pci_conf_sb[2][0x13], dev->pci_conf_sb[2][4] & 1); + break; + + case 0x14: /* IO Space Base Address Register */ + case 0x15: /* IO Space Base Address Register */ + case 0x16: /* IO Space Base Address Register */ + case 0x17: /* IO Space Base Address Register */ + case 0x3c: /* Interrupt Line */ + dev->pci_conf_sb[2][addr] = val; + break; + + default: + break; + } + sis_5571_log("SiS5571-USB: dev->pci_conf[%02x] = %02x\n", addr, val); + break; + + default: + break; + } +} + +static uint8_t +pci_isa_bridge_read(int func, int addr, void *priv) +{ + const sis_5571_t *dev = (sis_5571_t *) priv; + + switch (func) { + case 0: + sis_5571_log("SiS5571-SB: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf_sb[0][addr]); + return dev->pci_conf_sb[0][addr]; + case 1: + sis_5571_log("SiS5571-IDE: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf_sb[1][addr]); + return dev->pci_conf_sb[1][addr]; + case 2: + sis_5571_log("SiS5571-USB: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf_sb[2][addr]); + return dev->pci_conf_sb[2][addr]; + + default: + return 0xff; + } +} + +static void +sis_5571_reset(void *priv) +{ + sis_5571_t *dev = (sis_5571_t *) priv; + + /* Memory/PCI Bridge */ + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x71; + dev->pci_conf[0x03] = 0x55; + dev->pci_conf[0x04] = 0xfd; + dev->pci_conf[0x0b] = 0x06; + dev->pci_conf[0x9e] = 0xff; + dev->pci_conf[0x9f] = 0xff; + dev->pci_conf[0xa2] = 0xff; + + /* PCI to ISA bridge */ + dev->pci_conf_sb[0][0x00] = 0x39; + dev->pci_conf_sb[0][0x01] = 0x10; + dev->pci_conf_sb[0][0x02] = 0x08; + dev->pci_conf_sb[0][0x04] = 0xfd; + dev->pci_conf_sb[0][0x08] = 0x01; + dev->pci_conf_sb[0][0x0a] = 0x01; + dev->pci_conf_sb[0][0x0b] = 0x06; + + /* IDE Controller */ + dev->pci_conf_sb[1][0x00] = 0x39; + dev->pci_conf_sb[1][0x01] = 0x10; + dev->pci_conf_sb[1][0x02] = 0x13; + dev->pci_conf_sb[1][0x03] = 0x55; + dev->pci_conf_sb[1][0x08] = 0xc0; + dev->pci_conf_sb[1][0x0a] = 0x01; + dev->pci_conf_sb[1][0x0b] = 0x01; + dev->pci_conf_sb[1][0x0e] = 0x80; + dev->pci_conf_sb[1][0x4a] = 0x06; + sff_set_slot(dev->ide_drive[0], dev->sb_slot); + sff_set_slot(dev->ide_drive[1], dev->sb_slot); + sff_bus_master_reset(dev->ide_drive[0]); + sff_bus_master_reset(dev->ide_drive[1]); + + /* USB Controller */ + dev->pci_conf_sb[2][0x00] = 0x39; + dev->pci_conf_sb[2][0x01] = 0x10; + dev->pci_conf_sb[2][0x02] = 0x01; + dev->pci_conf_sb[2][0x03] = 0x70; + dev->pci_conf_sb[2][0x08] = 0xb0; + dev->pci_conf_sb[2][0x09] = 0x10; + dev->pci_conf_sb[2][0x0a] = 0x03; + dev->pci_conf_sb[2][0x0b] = 0xc0; + dev->pci_conf_sb[2][0x0e] = 0x80; + dev->pci_conf_sb[2][0x14] = 0x01; + dev->pci_conf_sb[2][0x3d] = 0x01; +} + +static void +sis_5571_close(void *priv) +{ + sis_5571_t *dev = (sis_5571_t *) priv; + + smram_del(dev->smram); + free(dev); +} + +static void * +sis_5571_init(UNUSED(const device_t *info)) +{ + sis_5571_t *dev = (sis_5571_t *) malloc(sizeof(sis_5571_t)); + memset(dev, 0x00, sizeof(sis_5571_t)); + + pci_add_card(PCI_ADD_NORTHBRIDGE, memory_pci_bridge_read, memory_pci_bridge_write, dev, &dev->nb_slot); + pci_add_card(PCI_ADD_SOUTHBRIDGE, pci_isa_bridge_read, pci_isa_bridge_write, dev, &dev->sb_slot); + + /* MIRQ */ + pci_enable_mirq(0); + + /* Port 92 & SMRAM */ + dev->port_92 = device_add(&port_92_pci_device); + dev->smram = smram_add(); + + /* SFF IDE */ + dev->ide_drive[0] = device_add_inst(&sff8038i_device, 1); + dev->ide_drive[1] = device_add_inst(&sff8038i_device, 2); + + /* USB */ + dev->usb = device_add(&usb_device); + + sis_5571_reset(dev); + + return dev; +} + +const device_t sis_5571_device = { + .name = "SiS 5571", + .internal_name = "sis_5571", + .flags = DEVICE_PCI, + .local = 0, + .init = sis_5571_init, + .close = sis_5571_close, + .reset = sis_5571_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5572_usb.c b/src/chipset/sis_5572_usb.c new file mode 100644 index 000000000..250c32587 --- /dev/null +++ b/src/chipset/sis_5572_usb.c @@ -0,0 +1,323 @@ +/* + * 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 SiS 5572 USB controller. + * + * Authors: Miran Grca, + * + * Copyright 2024 Miran Grca. + */ +#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/dma.h> +#include <86box/mem.h> +#include <86box/nvr.h> +#include <86box/hdd.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/pci.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/pit_fast.h> +#include <86box/plat.h> +#include <86box/plat_unused.h> +#include <86box/port_92.h> +#include <86box/smram.h> +#include <86box/spd.h> +#include <86box/apm.h> +#include <86box/ddma.h> +#include <86box/acpi.h> +#include <86box/smbus.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> +#include <86box/usb.h> + +#ifdef ENABLE_SIS_5572_USB_LOG +int sis_5572_usb_do_log = ENABLE_SIS_5572_USB_LOG; + +static void +sis_5572_usb_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5572_usb_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5572_usb_log(fmt, ...) +#endif + +typedef struct sis_5572_usb_t { + uint8_t rev; + + uint8_t usb_unk_regs[256]; + uint8_t pci_conf[256]; + + uint16_t usb_unk_base; + + usb_t *usb; + + sis_55xx_common_t *sis; +} sis_5572_usb_t; + +/* SiS 5572 unknown I/O port (second USB PCI BAR). */ +static void +sis_5572_usb_unk_write(uint16_t addr, uint8_t val, void *priv) +{ + sis_5572_usb_t *dev = (sis_5572_usb_t *) priv; + + addr = (addr - dev->usb_unk_base) & 0x07; + + sis_5572_usb_log("SiS 5572 USB UNK: [W] dev->usb_unk_regs[%02X] = %02X\n", addr, val); + + dev->usb_unk_regs[addr] = val; +} + +static uint8_t +sis_5572_usb_unk_read(uint16_t addr, void *priv) +{ + const sis_5572_usb_t *dev = (sis_5572_usb_t *) priv; + uint8_t ret = 0xff; + + addr = (addr - dev->usb_unk_base) & 0x07; + + ret = dev->usb_unk_regs[addr & 0x07]; + + sis_5572_usb_log("SiS 5572 USB UNK: [R] dev->usb_unk_regs[%02X] = %02X\n", addr, ret); + + return ret; +} + +void +sis_5572_usb_write(int addr, uint8_t val, void *priv) +{ + sis_5572_usb_t *dev = (sis_5572_usb_t *) priv; + + sis_5572_usb_log("SiS 5572 USB: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + if (dev->sis->usb_enabled) switch (addr) { + default: + break; + + case 0x04: /* Command - Low Byte */ + if (dev->rev == 0xb0) + dev->pci_conf[addr] = val & 0x47; + else + dev->pci_conf[addr] = val & 0x57; + if (dev->usb_unk_base != 0x0000) { + io_removehandler(dev->usb_unk_base, 0x0002, + sis_5572_usb_unk_read, NULL, NULL, + sis_5572_usb_unk_write, NULL, NULL, dev); + if (dev->pci_conf[0x04] & 0x01) + io_sethandler(dev->usb_unk_base, 0x0002, + sis_5572_usb_unk_read, NULL, NULL, + sis_5572_usb_unk_write, NULL, NULL, dev); + } + ohci_update_mem_mapping(dev->usb, + dev->pci_conf[0x11], dev->pci_conf[0x12], + dev->pci_conf[0x13], dev->pci_conf[0x04] & 0x02); + break; + + case 0x05: /* Command - High Byte */ + dev->pci_conf[addr] = val & 0x01; + break; + + case 0x07: /* Status - High Byte */ + dev->pci_conf[addr] &= ~(val & 0xf9); + break; + + case 0x0d: /* Latency Timer */ + dev->pci_conf[addr] = val; + break; + + case 0x11 ... 0x13: /* Memory Space Base Address Register */ + dev->pci_conf[addr] = val & ((addr == 0x11) ? 0xf0 : 0xff); + ohci_update_mem_mapping(dev->usb, + dev->pci_conf[0x11], dev->pci_conf[0x12], + dev->pci_conf[0x13], dev->pci_conf[4] & 0x02); + break; + + case 0x14 ... 0x15: /* IO Space Base Address Register */ + if (dev->rev == 0xb0) { + if (dev->usb_unk_base != 0x0000) { + io_removehandler(dev->usb_unk_base, 0x0002, + sis_5572_usb_unk_read, NULL, NULL, + sis_5572_usb_unk_write, NULL, NULL, dev); + } + dev->pci_conf[addr] = val; + dev->usb_unk_base = (dev->pci_conf[0x14] & 0xf8) | + (dev->pci_conf[0x15] << 8); + if (dev->usb_unk_base != 0x0000) { + io_sethandler(dev->usb_unk_base, 0x0002, + sis_5572_usb_unk_read, NULL, NULL, + sis_5572_usb_unk_write, NULL, NULL, dev); + } + } + break; + + case 0x2c ... 0x2f: + if (dev->rev == 0x11) + dev->pci_conf[addr] = val; + break; + + case 0x3c: /* Interrupt Line */ + dev->pci_conf[addr] = val; + break; + } +} + +uint8_t +sis_5572_usb_read(int addr, void *priv) +{ + const sis_5572_usb_t *dev = (sis_5572_usb_t *) priv; + uint8_t ret = 0xff; + + if (dev->sis->usb_enabled) { + ret = dev->pci_conf[addr]; + + sis_5572_usb_log("SiS 5572 USB: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + } + + return ret; +} + +static void +sis_5572_usb_reset(void *priv) +{ + sis_5572_usb_t *dev = (sis_5572_usb_t *) priv; + + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x01; + dev->pci_conf[0x03] = 0x70; + dev->pci_conf[0x04] = dev->pci_conf[0x05] = 0x00; + dev->pci_conf[0x06] = (dev->rev == 0xb0) ? 0x00 : 0x80; + dev->pci_conf[0x07] = 0x02; + dev->pci_conf[0x08] = dev->rev; + dev->pci_conf[0x09] = 0x10; + dev->pci_conf[0x0a] = 0x03; + dev->pci_conf[0x0b] = 0x0c; + dev->pci_conf[0x0c] = dev->pci_conf[0x0d] = 0x00; + dev->pci_conf[0x0e] = 0x80 /* 0x10 - Datasheet erratum - header type 0x10 is invalid! */; + dev->pci_conf[0x0f] = 0x00; + dev->pci_conf[0x10] = 0x00; + dev->pci_conf[0x11] = 0x00; + dev->pci_conf[0x12] = 0x00; + dev->pci_conf[0x13] = 0x00; + if (dev->rev == 0xb0) { + dev->pci_conf[0x14] = 0x01; + dev->pci_conf[0x15] = 0x00; + dev->pci_conf[0x16] = 0x00; + dev->pci_conf[0x17] = 0x00; + } else if (dev->rev == 0x11) { + dev->pci_conf[0x2c] = 0x00; + dev->pci_conf[0x2d] = 0x00; + dev->pci_conf[0x2e] = 0x00; + dev->pci_conf[0x2f] = 0x00; + } + dev->pci_conf[0x3c] = 0x00; + dev->pci_conf[0x3d] = PCI_INTA; + dev->pci_conf[0x3e] = 0x00; + dev->pci_conf[0x3f] = 0x00; + + if (dev->rev == 0xb0) { + ohci_update_mem_mapping(dev->usb, + dev->pci_conf[0x11], dev->pci_conf[0x12], + dev->pci_conf[0x13], dev->pci_conf[0x04] & 0x02); + + if (dev->usb_unk_base != 0x0000) { + io_removehandler(dev->usb_unk_base, 0x0002, + sis_5572_usb_unk_read, NULL, NULL, + sis_5572_usb_unk_write, NULL, NULL, dev); + } + + dev->usb_unk_base = 0x0000; + + memset(dev->usb_unk_regs, 0x00, sizeof(dev->usb_unk_regs)); + } +} + +static void +sis_5572_usb_close(void *priv) +{ + sis_5572_usb_t *dev = (sis_5572_usb_t *) priv; + + free(dev); +} + +static void * +sis_5572_usb_init(UNUSED(const device_t *info)) +{ + sis_5572_usb_t *dev = (sis_5572_usb_t *) calloc(1, sizeof(sis_5572_usb_t)); + + dev->rev = info->local; + + dev->sis = device_get_common_priv(); + + /* USB */ + dev->usb = device_add(&usb_device); + + sis_5572_usb_reset(dev); + + return dev; +} + +const device_t sis_5572_usb_device = { + .name = "SiS 5572 USB controller", + .internal_name = "sis_5572_usb", + .flags = DEVICE_PCI, + .local = 0xb0, + .init = sis_5572_usb_init, + .close = sis_5572_usb_close, + .reset = sis_5572_usb_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5582_usb_device = { + .name = "SiS 5582 USB controller", + .internal_name = "sis_5582_usb", + .flags = DEVICE_PCI, + .local = 0xe0, + .init = sis_5572_usb_init, + .close = sis_5572_usb_close, + .reset = sis_5572_usb_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5595_usb_device = { + .name = "SiS 5595 USB controller", + .internal_name = "sis_5595_usb", + .flags = DEVICE_PCI, + .local = 0x11, + .init = sis_5572_usb_init, + .close = sis_5572_usb_close, + .reset = sis_5572_usb_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5581.c b/src/chipset/sis_5581.c new file mode 100644 index 000000000..98b37897c --- /dev/null +++ b/src/chipset/sis_5581.c @@ -0,0 +1,185 @@ +/* + * 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 SiS 5581/5582 Pentium PCI/ISA Chipset. + * + * Authors: Miran Grca, + * + * Copyright 2024 Miran Grca. + */ +#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/mem.h> +#include <86box/nvr.h> +#include <86box/apm.h> +#include <86box/acpi.h> +#include <86box/hdd.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/pci.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/pit_fast.h> +#include <86box/plat.h> +#include <86box/plat_unused.h> +#include <86box/port_92.h> +#include <86box/smram.h> +#include <86box/spd.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> + +#define ENABLE_SIS_5581_LOG 1 +#ifdef ENABLE_SIS_5581_LOG +int sis_5581_do_log = ENABLE_SIS_5581_LOG; + +static void +sis_5581_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5581_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5581_log(fmt, ...) +#endif + +typedef struct sis_5581_t { + uint8_t nb_slot; + uint8_t sb_slot; + + void *h2p; + void *p2i; + void *ide; + void *usb; + + sis_55xx_common_t *sis; +} sis_5581_t; + +static void +sis_5581_write(int func, int addr, uint8_t val, void *priv) +{ + const sis_5581_t *dev = (sis_5581_t *) priv; + + sis_5581_log("SiS 5581: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + if (func == 0x00) + sis_5581_host_to_pci_write(addr, val, dev->h2p); +} + +static uint8_t +sis_5581_read(int func, int addr, void *priv) +{ + const sis_5581_t *dev = (sis_5581_t *) priv; + uint8_t ret = 0xff; + + if (func == 0x00) + ret = sis_5581_host_to_pci_read(addr, dev->h2p); + + sis_5581_log("SiS 5581: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5582_write(int func, int addr, uint8_t val, void *priv) +{ + const sis_5581_t *dev = (sis_5581_t *) priv; + + sis_5581_log("SiS 5582: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (func) { + case 0x00: + sis_5513_pci_to_isa_write(addr, val, dev->p2i); + break; + case 0x01: + sis_5513_ide_write(addr, val, dev->ide); + break; + case 0x02: + sis_5572_usb_write(addr, val, dev->usb); + break; + } +} + +static uint8_t +sis_5582_read(int func, int addr, void *priv) +{ + const sis_5581_t *dev = (sis_5581_t *) priv; + uint8_t ret = 0xff; + + switch (func) { + case 0x00: + ret = sis_5513_pci_to_isa_read(addr, dev->p2i); + break; + case 0x01: + ret = sis_5513_ide_read(addr, dev->ide); + break; + case 0x02: + ret = sis_5572_usb_read(addr, dev->usb); + break; + } + + sis_5581_log("SiS 5582: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5581_close(void *priv) +{ + sis_5581_t *dev = (sis_5581_t *) priv; + + free(dev); +} + +static void * +sis_5581_init(UNUSED(const device_t *info)) +{ + sis_5581_t *dev = (sis_5581_t *) calloc(1, sizeof(sis_5581_t)); + + /* Device 0: SiS 5581 */ + pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5581_read, sis_5581_write, dev, &dev->nb_slot); + /* Device 1: SiS 5582 */ + pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5582_read, sis_5582_write, dev, &dev->sb_slot); + + dev->sis = device_add(&sis_55xx_common_device); + + dev->p2i = device_add_linked(&sis_5582_p2i_device, dev->sis); + dev->h2p = device_add_linked(&sis_5581_h2p_device, dev->sis); + dev->ide = device_add_linked(&sis_5582_ide_device, dev->sis); + dev->usb = device_add_linked(&sis_5582_usb_device, dev->sis); + + return dev; +} + +const device_t sis_5581_device = { + .name = "SiS 5581", + .internal_name = "sis_5581", + .flags = DEVICE_PCI, + .local = 0, + .init = sis_5581_init, + .close = sis_5581_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5581_h2p.c b/src/chipset/sis_5581_h2p.c new file mode 100644 index 000000000..48d61f25e --- /dev/null +++ b/src/chipset/sis_5581_h2p.c @@ -0,0 +1,553 @@ +/* + * 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 SiS 5581 Host to PCI bridge. + * + * Authors: Miran Grca, + * + * Copyright 2024 Miran Grca. + */ +#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/dma.h> +#include <86box/mem.h> +#include <86box/nvr.h> +#include <86box/hdd.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/pci.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/pit_fast.h> +#include <86box/plat.h> +#include <86box/plat_unused.h> +#include <86box/port_92.h> +#include <86box/smram.h> +#include <86box/spd.h> +#include <86box/apm.h> +#include <86box/ddma.h> +#include <86box/acpi.h> +#include <86box/smbus.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> +#include <86box/usb.h> + +#ifdef ENABLE_SIS_5581_HOST_TO_PCI_LOG +int sis_5581_host_to_pci_do_log = ENABLE_SIS_5581_HOST_TO_PCI_LOG; + +static void +sis_5581_host_to_pci_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5581_host_to_pci_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5581_host_to_pci_log(fmt, ...) +#endif + +typedef struct { + uint8_t installed; + uint8_t code; + uint32_t phys_size; +} ram_bank_t; + +typedef struct sis_5581_io_trap_t { + void *priv; + void *trap; + uint8_t flags, mask; + uint8_t *sts_reg, sts_mask; + uint16_t addr; +} sis_5581_io_trap_t; + +typedef struct sis_5581_host_to_pci_t { + uint8_t pci_conf[256]; + uint8_t states[7]; + + ram_bank_t ram_banks[3]; + + sis_5581_io_trap_t io_traps[10]; + + sis_55xx_common_t *sis; + + smram_t *smram; +} sis_5581_host_to_pci_t; + +static uint8_t bank_codes[7] = { 0x00, 0x20, 0x24, 0x22, 0x26, 0x2a, 0x2b }; + +static uint32_t bank_sizes[7] = { 0x00800000, /* 8 MB */ + 0x01000000, /* 16 MB */ + 0x02000000, /* 32 MB */ + 0x04000000, /* 64 MB */ + 0x08000000, /* 128 MB */ + 0x10000000, /* 256 MB */ + 0x20000000 }; /* 512 MB */ + +static void +sis_5581_shadow_recalc(sis_5581_host_to_pci_t *dev) +{ + int state; + uint32_t base; + + for (uint8_t i = 0x70; i <= 0x76; i++) { + if (i == 0x76) { + if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) { + state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_both(0xf0000, 0x10000, state); + sis_5581_host_to_pci_log("000F0000-000FFFFF\n"); + } + } else { + base = ((i & 0x07) << 15) + 0xc0000; + + if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) { + state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_both(base, 0x4000, state); + sis_5581_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff); + } + + if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0x0a) { + state = (dev->pci_conf[i] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[i] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_both(base + 0x4000, 0x4000, state); + sis_5581_host_to_pci_log("%08X-%08X\n", base + 0x4000, base + 0x7fff); + } + } + + dev->states[i & 0x0f] = dev->pci_conf[i]; + } + + flushmmucache_nopc(); +} + +static void +sis_5581_trap_io(UNUSED(int size), UNUSED(uint16_t addr), UNUSED(uint8_t write), UNUSED(uint8_t val), + void *priv) +{ + sis_5581_io_trap_t *trap = (sis_5581_io_trap_t *) priv; + sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) trap->priv; + + trap->sts_reg[0x04] |= trap->sts_mask; + + if (trap->sts_reg[0x00] & trap->sts_mask) + acpi_sis5582_pmu_event(dev->sis->acpi); +} + +static void +sis_5581_trap_io_mask(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv) +{ + sis_5581_io_trap_t *trap = (sis_5581_io_trap_t *) priv; + + if ((addr & trap->mask) == (trap->addr & trap->mask)) + sis_5581_trap_io(size, addr, write, val, priv); +} + +static void +sis_5581_trap_update_devctl(sis_5581_host_to_pci_t *dev, uint8_t trap_id, uint8_t enable, + uint8_t flags, uint8_t mask, uint8_t *sts_reg, uint8_t sts_mask, + uint16_t addr, uint16_t size) +{ + sis_5581_io_trap_t *trap = &dev->io_traps[trap_id]; + enable = enable; + + /* Set up Device I/O traps dynamically. */ + if (enable && !trap->trap) { + trap->priv = (void *) dev; + trap->flags = flags; + trap->mask = mask; + trap->addr = addr; + if (flags & 0x08) + trap->trap = io_trap_add(sis_5581_trap_io_mask, trap); + else + trap->trap = io_trap_add(sis_5581_trap_io, trap); + trap->sts_reg = sts_reg; + trap->sts_mask = sts_mask; + } + + /* Remap I/O trap. */ + io_trap_remap(trap->trap, enable, addr, size); +} + +static void +sis_5581_trap_update(void *priv) +{ + sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) priv; + uint8_t trap_id = 0; + uint8_t *fregs = dev->pci_conf; + uint16_t temp; + uint8_t mask; + uint8_t on; + + on = fregs[0x9a]; + + temp = ((fregs[0x96] & 0x02) | (fregs[0x97] << 2)) & 0x03ff; + mask = ~((1 << ((fregs[0x96] >> 3) & 0x07)) - 1); + + sis_5581_trap_update_devctl(dev, trap_id++, + on & 0x40, 0x08, mask, &(fregs[0x9c]), 0x40, temp, 0x80); + + temp = fregs[0x98] | (fregs[0x99] << 8); + mask = 0xff; + + sis_5581_trap_update_devctl(dev, trap_id++, + on & 0x20, 0x08, mask, &(fregs[0x9c]), 0x20, temp, 0x80); + + sis_5581_trap_update_devctl(dev, trap_id++, + on & 0x10, 0x00, 0xff, &(fregs[0x9c]), 0x10, 0x378, 0x08); + sis_5581_trap_update_devctl(dev, trap_id++, + on & 0x10, 0x00, 0xff, &(fregs[0x9c]), 0x10, 0x278, 0x08); + + sis_5581_trap_update_devctl(dev, trap_id++, + on & 0x08, 0x00, 0xff, &(fregs[0x9c]), 0x08, 0x3f8, 0x08); + + sis_5581_trap_update_devctl(dev, trap_id++, + on & 0x04, 0x00, 0xff, &(fregs[0x9c]), 0x04, 0x2f8, 0x08); + + sis_5581_trap_update_devctl(dev, trap_id++, + on & 0x02, 0x00, 0xff, &(fregs[0x9c]), 0x02, 0x1f0, 0x08); + + sis_5581_trap_update_devctl(dev, trap_id++, + on & 0x01, 0x00, 0xff, &(fregs[0x9c]), 0x01, 0x170, 0x08); + + on = fregs[0x9b]; + sis_5581_trap_update_devctl(dev, trap_id++, + on & 0x08, 0x00, 0xff, &(fregs[0x9d]), 0x08, 0x064, 0x01); + sis_5581_trap_update_devctl(dev, trap_id++, + on & 0x08, 0x00, 0xff, &(fregs[0x9d]), 0x08, 0x060, 0x01); +} + +static void +sis_5581_smram_recalc(sis_5581_host_to_pci_t *dev) +{ + smram_disable_all(); + + switch (dev->pci_conf[0xa3] >> 6) { + case 0: + smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1); + break; + case 1: + smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1); + break; + case 2: + smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1); + break; + case 3: + smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x10000, dev->pci_conf[0xa3] & 0x10, 1); + break; + + default: + break; + } + + flushmmucache(); +} + +void +sis_5581_host_to_pci_write(int addr, uint8_t val, void *priv) +{ + sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) priv; + + sis_5581_host_to_pci_log("SiS 5581 H2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (addr) { + default: + break; + + case 0x04: /* Command - Low Byte */ + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xfc) | (val & 0x03); + break; + case 0x05: /* Command - High Byte */ + dev->pci_conf[addr] = val & 0x02; + break; + + case 0x07: /* Status - High Byte */ + dev->pci_conf[addr] &= ~(val & 0xb8); + break; + + case 0x0d: /* Master latency timer */ + case 0x50: + case 0x54: + case 0x56 ... 0x57: + case 0x59: + dev->pci_conf[addr] = val; + break; + + case 0x51: + dev->pci_conf[addr] = val; + cpu_cache_ext_enabled = !!(val & 0x40); + cpu_update_waitstates(); + break; + + case 0x52: + dev->pci_conf[addr] = val & 0xeb; + break; + + case 0x53: + case 0x55: + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x58: + dev->pci_conf[addr] = val & 0xfc; + break; + + case 0x5a: + dev->pci_conf[addr] = val & 0x03; + break; + + case 0x60 ... 0x62: + dev->pci_conf[addr] = dev->ram_banks[addr & 0x0f].code | 0xc0; + break; + + case 0x63: + dev->pci_conf[addr] = dev->ram_banks[0].installed | + (dev->ram_banks[1].installed << 1) | + (dev->ram_banks[2].installed << 2); + break; + + case 0x70 ... 0x75: + dev->pci_conf[addr] = val & 0xee; + sis_5581_shadow_recalc(dev); + break; + case 0x76: + dev->pci_conf[addr] = val & 0xe8; + sis_5581_shadow_recalc(dev); + break; + + case 0x77: /* Characteristics of non-cacheable area */ + dev->pci_conf[addr] = val & 0x0f; + break; + + case 0x78: /* Allocation of Non-Cacheable area #1 */ + case 0x79: /* NCA1REG2 */ + case 0x7a: /* Allocation of Non-Cacheable area #2 */ + case 0x7b: /* NCA2REG2 */ + dev->pci_conf[addr] = val; + break; + + case 0x80: /* PCI master characteristics */ + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x81: + dev->pci_conf[addr] = val & 0xde; + break; + + case 0x82: + dev->pci_conf[addr] = val; + break; + + case 0x83: /* CPU to PCI characteristics */ + dev->pci_conf[addr] = val; + /* TODO: Implement Fast A20 and Fast reset stuff on the KBC already! */ + break; + + case 0x84 ... 0x86: + case 0x88 ... 0x8b: + dev->pci_conf[addr] = val; + break; + + case 0x87: /* Miscellanea */ + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x8c ... 0x92: + case 0x9e ... 0xa2: + dev->pci_conf[addr] = val; + break; + + case 0x93: + dev->pci_conf[addr] = val; + if (val & 0x02) { + dev->pci_conf[0x9d] |= 0x01; + if (dev->pci_conf[0x9b] & 0x01) + acpi_sis5582_pmu_event(dev->sis->acpi); + } + break; + + case 0x94: + dev->pci_conf[addr] = val & 0xf8; + break; + + case 0x95: + dev->pci_conf[addr] = val & 0xfb; + break; + + case 0x96: + dev->pci_conf[addr] = val & 0xfb; + sis_5581_trap_update(dev); + break; + case 0x97 ... 0x9b: + dev->pci_conf[addr] = val; + sis_5581_trap_update(dev); + break; + + case 0x9c ... 0x9d: + dev->pci_conf[addr] &= ~val; + break; + + case 0xa3: + dev->pci_conf[addr] = val; + sis_5581_smram_recalc(dev); + break; + } +} + +uint8_t +sis_5581_host_to_pci_read(int addr, void *priv) +{ + const sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) priv; + uint8_t ret = 0xff; + + ret = dev->pci_conf[addr]; + + sis_5581_host_to_pci_log("SiS 5581 H2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5581_host_to_pci_reset(void *priv) +{ + sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) priv; + + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x97; + dev->pci_conf[0x03] = 0x55; + dev->pci_conf[0x04] = 0x05; + dev->pci_conf[0x05] = dev->pci_conf[0x06] = 0x00; + dev->pci_conf[0x07] = 0x02; + dev->pci_conf[0x08] = 0x02; + dev->pci_conf[0x09] = dev->pci_conf[0x0a] = 0x00; + dev->pci_conf[0x0b] = 0x06; + dev->pci_conf[0x0c] = 0x00; + dev->pci_conf[0x0d] = 0xff; + dev->pci_conf[0x0e] = dev->pci_conf[0x0f] = 0x00; + dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x00; + dev->pci_conf[0x52] = 0x00; + dev->pci_conf[0x53] = 0x38; + dev->pci_conf[0x54] = 0x54; + dev->pci_conf[0x55] = 0x00; + dev->pci_conf[0x56] = 0x80; + dev->pci_conf[0x57] = dev->pci_conf[0x58] = 0x00; + dev->pci_conf[0x59] = dev->pci_conf[0x5a] = 0x00; + dev->pci_conf[0x60] = dev->pci_conf[0x61] = 0x00; + dev->pci_conf[0x62] = 0x00; + dev->pci_conf[0x63] = 0xff; + dev->pci_conf[0x70] = dev->pci_conf[0x71] = 0x00; + dev->pci_conf[0x72] = dev->pci_conf[0x73] = 0x00; + dev->pci_conf[0x74] = dev->pci_conf[0x75] = 0x00; + dev->pci_conf[0x76] = dev->pci_conf[0x77] = 0x00; + dev->pci_conf[0x78] = dev->pci_conf[0x79] = 0x00; + dev->pci_conf[0x7a] = dev->pci_conf[0x7b] = 0x00; + dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00; + dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00; + dev->pci_conf[0x84] = dev->pci_conf[0x85] = 0x00; + dev->pci_conf[0x86] = dev->pci_conf[0x87] = 0x00; + dev->pci_conf[0x88] = dev->pci_conf[0x89] = 0x00; + dev->pci_conf[0x8a] = dev->pci_conf[0x8b] = 0x00; + dev->pci_conf[0x90] = dev->pci_conf[0x91] = 0x00; + dev->pci_conf[0x92] = dev->pci_conf[0x93] = 0x00; + dev->pci_conf[0x94] = dev->pci_conf[0x95] = 0x00; + dev->pci_conf[0x96] = dev->pci_conf[0x97] = 0x00; + dev->pci_conf[0x98] = dev->pci_conf[0x99] = 0x00; + dev->pci_conf[0x9a] = dev->pci_conf[0x9b] = 0x00; + dev->pci_conf[0x9c] = dev->pci_conf[0x9d] = 0x00; + dev->pci_conf[0x9e] = dev->pci_conf[0x9f] = 0xff; + dev->pci_conf[0xa0] = 0xff; + dev->pci_conf[0xa1] = 0x00; + dev->pci_conf[0xa2] = 0xff; + dev->pci_conf[0xa3] = 0x00; + + cpu_cache_ext_enabled = 0; + cpu_update_waitstates(); + + sis_5581_shadow_recalc(dev); + + sis_5581_trap_update(dev); + + sis_5581_smram_recalc(dev); +} + +static void +sis_5581_host_to_pci_close(void *priv) +{ + sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) priv; + + smram_del(dev->smram); + free(dev); +} + +static void * +sis_5581_host_to_pci_init(UNUSED(const device_t *info)) +{ + sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) calloc(1, sizeof(sis_5581_host_to_pci_t)); + uint32_t total_mem = mem_size << 10; + ram_bank_t *rb; + + dev->sis = device_get_common_priv(); + + /* Calculate the physical RAM banks. */ + for (uint8_t i = 0; i < 3; i++) { + rb = &(dev->ram_banks[i]); + uint32_t size = 0x00000000; + uint8_t index = 0; + for (int8_t j = 6; j >= 0; j--) { + uint32_t *bs = &(bank_sizes[j]); + if (*bs <= total_mem) { + size = *bs; + index = j; + break; + } + } + if (size != 0x00000000) { + rb->installed = 1; + rb->code = bank_codes[index]; + rb->phys_size = size; + total_mem -= size; + } else + rb->installed = 0; + } + + /* SMRAM */ + dev->smram = smram_add(); + + sis_5581_host_to_pci_reset(dev); + + return dev; +} + +const device_t sis_5581_h2p_device = { + .name = "SiS 5581 Host to PCI bridge", + .internal_name = "sis_5581_host_to_pci", + .flags = DEVICE_PCI, + .local = 0x00, + .init = sis_5581_host_to_pci_init, + .close = sis_5581_host_to_pci_close, + .reset = sis_5581_host_to_pci_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5591.c b/src/chipset/sis_5591.c new file mode 100644 index 000000000..969fcb8dd --- /dev/null +++ b/src/chipset/sis_5591.c @@ -0,0 +1,210 @@ +/* + * 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 SiS 5591/5592 Pentium PCI/ISA Chipset. + * + * Authors: Miran Grca, + * + * Copyright 2024 Miran Grca. + */ +#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/mem.h> +#include <86box/nvr.h> +#include <86box/apm.h> +#include <86box/acpi.h> +#include <86box/hdd.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/pci.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/pit_fast.h> +#include <86box/plat.h> +#include <86box/plat_unused.h> +#include <86box/port_92.h> +#include <86box/smram.h> +#include <86box/spd.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> + +#ifdef ENABLE_SIS_5591_LOG +int sis_5591_do_log = ENABLE_SIS_5591_LOG; + +static void +sis_5591_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5591_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5591_log(fmt, ...) +#endif + +typedef struct sis_5591_t { + uint8_t nb_slot; + uint8_t sb_slot; + + void *h2p; + void *p2i; + void *ide; + void *usb; + void *pmu; + + sis_55xx_common_t *sis; +} sis_5591_t; + +static void +sis_5591_write(int func, int addr, uint8_t val, void *priv) +{ + const sis_5591_t *dev = (sis_5591_t *) priv; + + sis_5591_log("SiS 5591: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + if (func == 0x00) + sis_5591_host_to_pci_write(addr, val, dev->h2p); + else if (func == 0x01) + sis_5513_ide_write(addr, val, dev->ide); +} + +static uint8_t +sis_5591_read(int func, int addr, void *priv) +{ + const sis_5591_t *dev = (sis_5591_t *) priv; + uint8_t ret = 0xff; + + if (func == 0x00) + ret = sis_5591_host_to_pci_read(addr, dev->h2p); + else if (func == 0x01) + ret = sis_5513_ide_read(addr, dev->ide); + + sis_5591_log("SiS 5591: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5595_write(int func, int addr, uint8_t val, void *priv) +{ + const sis_5591_t *dev = (sis_5591_t *) priv; + + sis_5591_log("SiS 5595: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (func) { + case 0x00: + sis_5513_pci_to_isa_write(addr, val, dev->p2i); + break; + case 0x01: + sis_5595_pmu_write(addr, val, dev->pmu); + break; + case 0x02: + sis_5572_usb_write(addr, val, dev->usb); + break; + } +} + +static uint8_t +sis_5595_read(int func, int addr, void *priv) +{ + const sis_5591_t *dev = (sis_5591_t *) priv; + uint8_t ret = 0xff; + + switch (func) { + case 0x00: + ret = sis_5513_pci_to_isa_read(addr, dev->p2i); + break; + case 0x01: + ret = sis_5595_pmu_read(addr, dev->pmu); + break; + case 0x02: + ret = sis_5572_usb_read(addr, dev->usb); + break; + } + + sis_5591_log("SiS 5592: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5591_close(void *priv) +{ + sis_5591_t *dev = (sis_5591_t *) priv; + + free(dev); +} + +static void * +sis_5591_init(UNUSED(const device_t *info)) +{ + sis_5591_t *dev = (sis_5591_t *) calloc(1, sizeof(sis_5591_t)); + + /* Device 0: SiS 5591 */ + pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5591_read, sis_5591_write, dev, &dev->nb_slot); + /* Device 1: SiS 5595 */ + pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5595_read, sis_5595_write, dev, &dev->sb_slot); + + dev->sis = device_add(&sis_55xx_common_device); + + dev->ide = device_add_linked(&sis_5591_5600_ide_device, dev->sis); + if (info->local) + dev->p2i = device_add_linked(&sis_5595_1997_p2i_device, dev->sis); + else + dev->p2i = device_add_linked(&sis_5595_p2i_device, dev->sis); + dev->h2p = device_add_linked(&sis_5591_h2p_device, dev->sis); + dev->usb = device_add_linked(&sis_5595_usb_device, dev->sis); + if (info->local) + dev->pmu = device_add_linked(&sis_5595_1997_pmu_device, dev->sis); + else + dev->pmu = device_add_linked(&sis_5595_pmu_device, dev->sis); + + return dev; +} + +const device_t sis_5591_1997_device = { + .name = "SiS 5591 (1997)", + .internal_name = "sis_5591_1997", + .flags = DEVICE_PCI, + .local = 1, + .init = sis_5591_init, + .close = sis_5591_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5591_device = { + .name = "SiS 5591", + .internal_name = "sis_5591", + .flags = DEVICE_PCI, + .local = 0, + .init = sis_5591_init, + .close = sis_5591_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5591_h2p.c b/src/chipset/sis_5591_h2p.c new file mode 100644 index 000000000..8fcbeeb6f --- /dev/null +++ b/src/chipset/sis_5591_h2p.c @@ -0,0 +1,493 @@ +/* + * 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 SiS 5591 Host to PCI bridge. + * + * Authors: Miran Grca, + * + * Copyright 2024 Miran Grca. + */ +#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/dma.h> +#include <86box/mem.h> +#include <86box/nvr.h> +#include <86box/hdd.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/pci.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/pit_fast.h> +#include <86box/plat.h> +#include <86box/plat_unused.h> +#include <86box/port_92.h> +#include <86box/smram.h> +#include <86box/spd.h> +#include <86box/apm.h> +#include <86box/ddma.h> +#include <86box/acpi.h> +#include <86box/smbus.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> +#include <86box/usb.h> +#include <86box/agpgart.h> + +#ifdef ENABLE_SIS_5591_HOST_TO_PCI_LOG +int sis_5591_host_to_pci_do_log = ENABLE_SIS_5591_HOST_TO_PCI_LOG; + +static void +sis_5591_host_to_pci_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5591_host_to_pci_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5591_host_to_pci_log(fmt, ...) +#endif + +typedef struct { + uint8_t installed; + uint8_t code; + uint32_t phys_size; +} ram_bank_t; + +typedef struct sis_5591_host_to_pci_t { + uint8_t pci_conf[256]; + + uint8_t states[7]; + uint8_t states_bus[7]; + + ram_bank_t ram_banks[3]; + + sis_55xx_common_t *sis; + + smram_t *smram; + + agpgart_t *agpgart; +} sis_5591_host_to_pci_t; + +static uint8_t bank_codes[6] = { 0x00, 0x20, 0x24, 0x22, 0x26, 0x2a }; + +static uint32_t bank_sizes[6] = { 0x00800000, /* 8 MB */ + 0x01000000, /* 16 MB */ + 0x02000000, /* 32 MB */ + 0x04000000, /* 64 MB */ + 0x08000000, /* 128 MB */ + 0x10000000 }; /* 256 MB */ + +static void +sis_5591_shadow_recalc(sis_5591_host_to_pci_t *dev) +{ + uint32_t base; + uint32_t state; + uint8_t val; + + for (uint8_t i = 0x70; i <= 0x76; i++) { + if (i == 0x76) { + val = dev->pci_conf[i]; + if ((dev->states[i & 0x0f] ^ val) & 0xa0) { + state = (val & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (val & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_cpu_both(0xf0000, 0x10000, state); + sis_5591_host_to_pci_log("000F0000-000FFFFF\n"); + + dev->states[i & 0x0f] = val; + } + + if (!(dev->pci_conf[0x76] & 0x08)) + val &= 0x5f; + if ((dev->states_bus[i & 0x0f] ^ val) & 0xa0) { + state = (val & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (val & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_bus_both(0xf0000, 0x10000, state); + sis_5591_host_to_pci_log("000F0000-000FFFFF\n"); + + dev->states_bus[i & 0x0f] = val; + } + } else { + base = ((i & 0x07) << 15) + 0xc0000; + + val = dev->pci_conf[i]; + if ((dev->states[i & 0x0f] ^ val) & 0xa0) { + state = (val & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (val & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_cpu_both(base, 0x4000, state); + sis_5591_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff); + + dev->states[i & 0x0f] = (dev->states[i & 0x0f] & 0x0f) | (val & 0xf0); + } + if ((dev->states[i & 0x0f] ^ val) & 0x0a) { + state = (val & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (val & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_cpu_both(base + 0x4000, 0x4000, state); + sis_5591_host_to_pci_log("%08X-%08X\n", base + 0x4000, base + 0x7fff); + + dev->states[i & 0x0f] = (dev->states[i & 0x0f] & 0xf0) | (val & 0x0f); + } + + if (!(dev->pci_conf[0x76] & 0x08)) + val &= 0x55; + if ((dev->states_bus[i & 0x0f] ^ val) & 0xa0) { + state = (val & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (val & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_bus_both(base, 0x4000, state); + sis_5591_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff); + + dev->states_bus[i & 0x0f] = (dev->states_bus[i & 0x0f] & 0x0f) | (val & 0xf0); + } + if ((dev->states_bus[i & 0x0f] ^ val) & 0x0a) { + state = (val & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (val & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_bus_both(base + 0x4000, 0x4000, state); + sis_5591_host_to_pci_log("%08X-%08X\n", base + 0x4000, base + 0x7fff); + + dev->states_bus[i & 0x0f] = (dev->states_bus[i & 0x0f] & 0xf0) | (val & 0x0f); + } + } + } + + flushmmucache_nopc(); +} + +static void +sis_5591_smram_recalc(sis_5591_host_to_pci_t *dev) +{ + smram_disable_all(); + + switch (dev->pci_conf[0x68] >> 6) { + case 0: + smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x68] & 0x10, 1); + break; + case 1: + smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x68] & 0x10, 1); + break; + case 2: + smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x68] & 0x10, 1); + break; + case 3: + smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x10000, dev->pci_conf[0x68] & 0x10, 1); + break; + + default: + break; + } + + flushmmucache(); +} + +static void +sis_5591_mask_bar(uint8_t *regs, void *agpgart) +{ + uint32_t bar; + uint32_t sizes[8] = { 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x00000000 } ; + + /* Make sure the aperture's base is aligned to its size. */ + bar = (regs[0x13] << 24) | (regs[0x12] << 16); + bar &= (sizes[(regs[0x94] >> 4) & 0x07] | 0xf0000000); + regs[0x12] = (bar >> 16) & 0xff; + regs[0x13] = (bar >> 24) & 0xff; + + if (!agpgart) + return; + + /* Map aperture and GART. */ + agpgart_set_aperture(agpgart, + bar, + sizes[(regs[0x94] >> 4) & 0x07], + !!(regs[0x94] & 0x02)); + if (regs[0x94] & 0x01) + agpgart_set_gart(agpgart, (regs[0x91] << 8) | (regs[0x92] << 16) | (regs[0x93] << 24)); + else + agpgart_set_gart(agpgart, 0x00000000); +} + +void +sis_5591_host_to_pci_write(int addr, uint8_t val, void *priv) +{ + sis_5591_host_to_pci_t *dev = (sis_5591_host_to_pci_t *) priv; + + sis_5591_host_to_pci_log("SiS 5591 H2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (addr) { + default: + break; + + case 0x04: /* Command - Low Byte */ + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xfd) | (val & 0x02); + break; + case 0x05: /* Command - High Byte */ + dev->pci_conf[addr] = val & 0x03; + break; + + case 0x07: /* Status - High Byte */ + dev->pci_conf[addr] &= ~(val & 0xf0); + break; + + case 0x12: + dev->pci_conf[addr] = val & 0xc0; + sis_5591_mask_bar(dev->pci_conf, dev->agpgart); + break; + case 0x13: + dev->pci_conf[addr] = val; + sis_5591_mask_bar(dev->pci_conf, dev->agpgart); + break; + + case 0x51: + dev->pci_conf[addr] = val; + cpu_cache_ext_enabled = !!(val & 0x80); + cpu_update_waitstates(); + break; + + case 0x60 ... 0x62: + dev->pci_conf[addr] = dev->ram_banks[addr & 0x0f].code | 0xc0; + break; + + case 0x63: + dev->pci_conf[addr] = dev->ram_banks[0].installed | + (dev->ram_banks[1].installed << 1) | + (dev->ram_banks[2].installed << 2); + break; + + case 0x68: + dev->pci_conf[addr] = val; + sis_5591_smram_recalc(dev); + break; + + case 0x70 ... 0x75: + dev->pci_conf[addr] = val & 0xee; + sis_5591_shadow_recalc(dev); + break; + case 0x76: + dev->pci_conf[addr] = val & 0xe8; + sis_5591_shadow_recalc(dev); + break; + + case 0x0d: /* Master latency timer */ + case 0x50: + case 0x52: + case 0x54 ... 0x5a: + case 0x5c ... 0x5f: + case 0x64 ... 0x65: + case 0x69 ... 0x6c: + case 0x77 ... 0x7b: + case 0x80 ... 0x8d: + case 0x90: + case 0x97 ... 0xab: + case 0xb0: + case 0xc8 ... 0xcb: + case 0xd4 ... 0xda: + case 0xe0 ... 0xe3: + case 0xef: + dev->pci_conf[addr] = val; + break; + + case 0x91 ... 0x93: + dev->pci_conf[addr] = val; + sis_5591_mask_bar(dev->pci_conf, dev->agpgart); + break; + case 0x94: + dev->pci_conf[addr] = val & 0x7f; + sis_5591_mask_bar(dev->pci_conf, dev->agpgart); + break; + + case 0xb2: + dev->pci_conf[addr] &= ~(val & 0x01); + break; + } +} + +uint8_t +sis_5591_host_to_pci_read(int addr, void *priv) +{ + const sis_5591_host_to_pci_t *dev = (sis_5591_host_to_pci_t *) priv; + uint8_t ret = 0xff; + + ret = dev->pci_conf[addr]; + + sis_5591_host_to_pci_log("SiS 5591 H2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5591_host_to_pci_reset(void *priv) +{ + sis_5591_host_to_pci_t *dev = (sis_5591_host_to_pci_t *) priv; + + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x91; + dev->pci_conf[0x03] = 0x55; + dev->pci_conf[0x04] = 0x05; + dev->pci_conf[0x05] = 0x00; + dev->pci_conf[0x06] = 0x10; + dev->pci_conf[0x07] = 0x02; + dev->pci_conf[0x08] = 0x02; + dev->pci_conf[0x09] = dev->pci_conf[0x0a] = 0x00; + dev->pci_conf[0x0b] = 0x06; + dev->pci_conf[0x0c] = 0x00; + dev->pci_conf[0x0d] = 0xff; + dev->pci_conf[0x0e] = 0x80; + dev->pci_conf[0x0f] = 0x00; + dev->pci_conf[0x10] = dev->pci_conf[0x11] = 0x00; + dev->pci_conf[0x12] = dev->pci_conf[0x13] = 0x00; + dev->pci_conf[0x34] = 0xc0; + dev->pci_conf[0x50] = 0x00; + dev->pci_conf[0x51] = 0x18; + dev->pci_conf[0x52] = dev->pci_conf[0x54] = 0x00; + dev->pci_conf[0x55] = 0x0e; + dev->pci_conf[0x56] = 0x40; + dev->pci_conf[0x57] = 0x00; + dev->pci_conf[0x58] = 0x50; + dev->pci_conf[0x59] = dev->pci_conf[0x5a] = 0x00; + dev->pci_conf[0x5c] = dev->pci_conf[0x5d] = 0x00; + dev->pci_conf[0x5e] = dev->pci_conf[0x5f] = 0x00; + dev->pci_conf[0x60] = dev->pci_conf[0x61] = 0x00; + dev->pci_conf[0x62] = 0x00; + dev->pci_conf[0x63] = 0xff; + dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00; + dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00; + dev->pci_conf[0x6a] = dev->pci_conf[0x6b] = 0x00; + dev->pci_conf[0x6c] = 0x00; + dev->pci_conf[0x70] = dev->pci_conf[0x71] = 0x00; + dev->pci_conf[0x72] = dev->pci_conf[0x73] = 0x00; + dev->pci_conf[0x74] = dev->pci_conf[0x75] = 0x00; + dev->pci_conf[0x76] = dev->pci_conf[0x77] = 0x00; + dev->pci_conf[0x78] = dev->pci_conf[0x79] = 0x00; + dev->pci_conf[0x7a] = dev->pci_conf[0x7b] = 0x00; + dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00; + dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00; + dev->pci_conf[0x84] = dev->pci_conf[0x85] = 0xff; + dev->pci_conf[0x86] = 0xff; + dev->pci_conf[0x87] = 0x00; + dev->pci_conf[0x88] = dev->pci_conf[0x89] = 0x00; + dev->pci_conf[0x8a] = dev->pci_conf[0x8b] = 0x00; + dev->pci_conf[0x8c] = dev->pci_conf[0x8d] = 0x00; + dev->pci_conf[0x90] = dev->pci_conf[0x91] = 0x00; + dev->pci_conf[0x92] = dev->pci_conf[0x93] = 0x00; + dev->pci_conf[0x94] = dev->pci_conf[0x97] = 0x00; + dev->pci_conf[0x98] = dev->pci_conf[0x99] = 0x00; + dev->pci_conf[0x9a] = dev->pci_conf[0x9b] = 0x00; + dev->pci_conf[0x9c] = dev->pci_conf[0x9d] = 0x00; + dev->pci_conf[0x9e] = dev->pci_conf[0x9f] = 0x00; + dev->pci_conf[0xa0] = dev->pci_conf[0xa1] = 0x00; + dev->pci_conf[0xa2] = dev->pci_conf[0xa3] = 0x00; + dev->pci_conf[0xa4] = dev->pci_conf[0xa5] = 0x00; + dev->pci_conf[0xa6] = dev->pci_conf[0xa7] = 0x00; + dev->pci_conf[0xa8] = dev->pci_conf[0xa9] = 0x00; + dev->pci_conf[0xaa] = dev->pci_conf[0xab] = 0x00; + dev->pci_conf[0xb0] = dev->pci_conf[0xb2] = 0x00; + dev->pci_conf[0xc0] = 0x02; + dev->pci_conf[0xc1] = 0x00; + dev->pci_conf[0xc2] = 0x10; + dev->pci_conf[0xc3] = 0x00; + dev->pci_conf[0xc4] = 0x03; + dev->pci_conf[0xc5] = 0x02; + dev->pci_conf[0xc6] = 0x00; + dev->pci_conf[0xc7] = 0x1f; + dev->pci_conf[0xc8] = dev->pci_conf[0xc9] = 0x00; + dev->pci_conf[0xca] = dev->pci_conf[0xcb] = 0x00; + dev->pci_conf[0xd4] = dev->pci_conf[0xd5] = 0x00; + dev->pci_conf[0xd6] = dev->pci_conf[0xd7] = 0x00; + dev->pci_conf[0xd8] = dev->pci_conf[0xd9] = 0x00; + dev->pci_conf[0xda] = 0x00; + dev->pci_conf[0xe0] = dev->pci_conf[0xe1] = 0x00; + dev->pci_conf[0xe2] = dev->pci_conf[0xe3] = 0x00; + dev->pci_conf[0xef] = 0x00; + + sis_5591_mask_bar(dev->pci_conf, dev->agpgart); + + cpu_cache_ext_enabled = 0; + cpu_update_waitstates(); + + sis_5591_shadow_recalc(dev); + + sis_5591_smram_recalc(dev); +} + +static void +sis_5591_host_to_pci_close(void *priv) +{ + sis_5591_host_to_pci_t *dev = (sis_5591_host_to_pci_t *) priv; + + smram_del(dev->smram); + free(dev); +} + +static void * +sis_5591_host_to_pci_init(UNUSED(const device_t *info)) +{ + sis_5591_host_to_pci_t *dev = (sis_5591_host_to_pci_t *) calloc(1, sizeof(sis_5591_host_to_pci_t)); + uint32_t total_mem = mem_size << 10; + ram_bank_t *rb; + + dev->sis = device_get_common_priv(); + + /* Calculate the physical RAM banks. */ + for (uint8_t i = 0; i < 3; i++) { + rb = &(dev->ram_banks[i]); + uint32_t size = 0x00000000; + uint8_t index = 0; + for (int8_t j = 5; j >= 0; j--) { + uint32_t *bs = &(bank_sizes[j]); + if (*bs <= total_mem) { + size = *bs; + index = j; + break; + } + } + if (size != 0x00000000) { + rb->installed = 1; + rb->code = bank_codes[index]; + rb->phys_size = size; + total_mem -= size; + } else + rb->installed = 0; + } + + /* SMRAM */ + dev->smram = smram_add(); + + device_add(&sis_5xxx_agp_device); + dev->agpgart = device_add(&agpgart_device); + + sis_5591_host_to_pci_reset(dev); + + return dev; +} + +const device_t sis_5591_h2p_device = { + .name = "SiS 5591 Host to PCI bridge", + .internal_name = "sis_5591_host_to_pci", + .flags = DEVICE_PCI, + .local = 0x00, + .init = sis_5591_host_to_pci_init, + .close = sis_5591_host_to_pci_close, + .reset = sis_5591_host_to_pci_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5595_pmu.c b/src/chipset/sis_5595_pmu.c new file mode 100644 index 000000000..4c6dbf7c9 --- /dev/null +++ b/src/chipset/sis_5595_pmu.c @@ -0,0 +1,455 @@ +/* + * 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 SiS 5572 USB controller. + * + * Authors: Miran Grca, + * + * Copyright 2024 Miran Grca. + */ +#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/dma.h> +#include <86box/mem.h> +#include <86box/nvr.h> +#include <86box/hdd.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/pci.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/pit_fast.h> +#include <86box/plat.h> +#include <86box/plat_unused.h> +#include <86box/port_92.h> +#include <86box/smram.h> +#include <86box/spd.h> +#include <86box/apm.h> +#include <86box/ddma.h> +#include <86box/acpi.h> +#include <86box/smbus.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> +#include <86box/usb.h> + +#ifdef ENABLE_SIS_5595_PMU_LOG +int sis_5595_pmu_do_log = ENABLE_SIS_5595_PMU_LOG; + +static void +sis_5595_pmu_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5595_pmu_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5595_pmu_log(fmt, ...) +#endif + +typedef struct sis_5595_pmu_io_trap_t { + void *priv; + void *trap; + uint8_t flags, mask; + uint8_t *sts_reg, sts_mask; + uint16_t addr; +} sis_5595_pmu_io_trap_t; + +typedef struct sis_5595_pmu_t { + uint8_t is_1997; + + uint8_t pci_conf[256]; + + sis_5595_pmu_io_trap_t io_traps[22]; + + sis_55xx_common_t *sis; +} sis_5595_pmu_t; + +static void +sis_5595_pmu_trap_io(UNUSED(int size), UNUSED(uint16_t addr), UNUSED(uint8_t write), UNUSED(uint8_t val), + void *priv) +{ + sis_5595_pmu_io_trap_t *trap = (sis_5595_pmu_io_trap_t *) priv; + sis_5595_pmu_t *dev = (sis_5595_pmu_t *) trap->priv; + + trap->sts_reg[0x04] |= trap->sts_mask; + + if (trap->sts_reg[0x00] & trap->sts_mask) + acpi_sis5595_pmu_event(dev->sis->acpi); + + if (trap->sts_reg[0x20] & trap->sts_mask) + acpi_update_irq(dev->sis->acpi); +} + +static void +sis_5595_pmu_trap_io_ide(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv) +{ + sis_5595_pmu_io_trap_t *trap = (sis_5595_pmu_io_trap_t *) priv; + + /* IDE traps are per drive, not per channel. */ + if (ide_drives[trap->flags & 0x03]->selected) + sis_5595_pmu_trap_io(size, addr, write, val, priv); +} + +static void +sis_5595_pmu_trap_io_mask(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv) +{ + sis_5595_pmu_io_trap_t *trap = (sis_5595_pmu_io_trap_t *) priv; + + if ((addr & trap->mask) == (trap->addr & trap->mask)) + sis_5595_pmu_trap_io(size, addr, write, val, priv); +} + +static void +sis_5595_pmu_trap_io_ide_bm(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv) +{ + sis_5595_pmu_io_trap_t *trap = (sis_5595_pmu_io_trap_t *) priv; + sis_5595_pmu_t *dev = (sis_5595_pmu_t *) trap->priv; + + if (trap->flags & 0x01) { + dev->pci_conf[0x67] |= 0x01; + dev->pci_conf[0x64] |= 0x08; + } else { + dev->pci_conf[0x67] |= 0x02; + dev->pci_conf[0x64] |= 0x10; + } + acpi_sis5595_pmu_event(dev->sis->acpi); +} + +static void +sis_5595_pmu_trap_update_devctl(sis_5595_pmu_t *dev, uint8_t trap_id, uint8_t enable, + uint8_t flags, uint8_t mask, uint8_t *sts_reg, uint8_t sts_mask, + uint16_t addr, uint16_t size) +{ + sis_5595_pmu_io_trap_t *trap = &dev->io_traps[trap_id]; + enable = enable; + + /* Set up Device I/O traps dynamically. */ + if (enable && !trap->trap) { + trap->priv = (void *) dev; + trap->flags = flags; + trap->mask = mask; + trap->addr = addr; + if (flags & 0x10) + trap->trap = io_trap_add(sis_5595_pmu_trap_io_ide_bm, trap); + else if (flags & 0x08) + trap->trap = io_trap_add(sis_5595_pmu_trap_io_mask, trap); + else if (flags & 0x04) + trap->trap = io_trap_add(sis_5595_pmu_trap_io_ide, trap); + else + trap->trap = io_trap_add(sis_5595_pmu_trap_io, trap); + trap->sts_reg = sts_reg; + trap->sts_mask = sts_mask; + } + + /* Remap I/O trap. */ + io_trap_remap(trap->trap, enable, addr, size); +} + +static void +sis_5595_pmu_trap_update(void *priv) +{ + sis_5595_pmu_t *dev = (sis_5595_pmu_t *) priv; + uint8_t trap_id = 0; + uint8_t *fregs = dev->pci_conf; + uint16_t temp; + uint8_t mask; + uint8_t on; + + temp = (fregs[0x7e] | (fregs[0x7f] << 8)) & 0xffe0; + + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + fregs[0x7e] & 0x08, 0x10, 0xff, NULL, 0xff, temp, 0x08); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + fregs[0x7e] & 0x04, 0x10, 0xff, NULL, 0xff, temp + 8, 0x08); + + on = fregs[0x63] | fregs[0x83]; + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x02, 0x04, 0xff, &(fregs[0x63]), 0x02, 0x1f0, 0x08); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x01, 0x06, 0xff, &(fregs[0x63]), 0x01, 0x170, 0x08); + + on = fregs[0x62] | fregs[0x82]; + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x80, 0x00, 0xff, &(fregs[0x62]), 0x80, 0x064, 0x01); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x80, 0x00, 0xff, &(fregs[0x62]), 0x80, 0x060, 0x01); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x40, 0x00, 0xff, &(fregs[0x62]), 0x40, 0x3f8, 0x08); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x20, 0x00, 0xff, &(fregs[0x62]), 0x20, 0x2f8, 0x08); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x10, 0x00, 0xff, &(fregs[0x62]), 0x10, 0x378, 0x08); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x10, 0x00, 0xff, &(fregs[0x62]), 0x10, 0x278, 0x08); + + temp = (fregs[0x5c] | (fregs[0x5d] << 8)) & 0x03ff; + mask = fregs[0x5d] >> 2; + + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x04, 0x08, mask, &(fregs[0x62]), 0x04, temp, 0x40); + + temp = fregs[0x5e] | (fregs[0x5f] << 8); + + if (dev->is_1997) { + mask = fregs[0x4d] & 0x1f; + + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x02, 0x08, mask, &(fregs[0x62]), 0x02, temp, 0x20); + } else { + mask = fregs[0x4d]; + + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x02, 0x08, mask, &(fregs[0x62]), 0x02, temp, 0x100); + } + + on = fregs[0x61] | fregs[0x81]; + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x40, 0x00, 0xff, &(fregs[0x61]), 0x40, 0x3b0, 0x30); + + switch ((fregs[0x4c] >> 6) & 0x03) { + case 0x00: + temp = 0xf40; + break; + case 0x01: + temp = 0xe80; + break; + case 0x02: + temp = 0x604; + break; + default: + temp = 0x530; + break; + } + + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x10, 0x00, 0xff, &(fregs[0x61]), 0x10, temp, 0x08); + + switch ((fregs[0x4c] >> 4) & 0x03) { + case 0x00: + temp = 0x280; + break; + case 0x01: + temp = 0x260; + break; + case 0x02: + temp = 0x240; + break; + default: + temp = 0x220; + break; + } + + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x08, 0x00, 0xff, &(fregs[0x61]), 0x08, temp, 0x14); + + switch ((fregs[0x4c] >> 2) & 0x03) { + case 0x00: + temp = 0x330; + break; + case 0x01: + temp = 0x320; + break; + case 0x02: + temp = 0x310; + break; + default: + temp = 0x300; + break; + } + + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x04, 0x00, 0xff, &(fregs[0x61]), 0x04, temp, 0x04); + + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x02, 0x00, 0xff, &(fregs[0x61]), 0x02, 0x200, 0x08); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x02, 0x00, 0xff, &(fregs[0x61]), 0x02, 0x388, 0x04); + + on = fregs[0x60] | fregs[0x80]; + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x20, 0x00, 0xff, &(fregs[0x60]), 0x20, 0x3f0, 0x08); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x20, 0x00, 0xff, &(fregs[0x60]), 0x20, 0x370, 0x08); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x10, 0x05, 0xff, &(fregs[0x60]), 0x10, 0x1f0, 0x08); + sis_5595_pmu_trap_update_devctl(dev, trap_id++, + on & 0x08, 0x07, 0xff, &(fregs[0x60]), 0x08, 0x170, 0x08); +} + +void +sis_5595_pmu_write(int addr, uint8_t val, void *priv) +{ + sis_5595_pmu_t *dev = (sis_5595_pmu_t *) priv; + + sis_5595_pmu_log("SiS 5595 PMU: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + if (dev->sis->usb_enabled) switch (addr) { + default: + break; + + case 0x40 ... 0x4b: + case 0x50 ... 0x5b: + case 0x68 ... 0x7b: + case 0x7d: + dev->pci_conf[addr] = val; + break; + case 0x4c ... 0x4d: + case 0x5c ... 0x63: + case 0x7e ... 0x7f: + case 0x80 ... 0x83: + dev->pci_conf[addr] = val; + sis_5595_pmu_trap_update(dev); + break; + case 0x64 ... 0x67: + dev->pci_conf[addr] &= ~val; + break; + case 0x7c: + dev->pci_conf[addr] = val; + if (val & 0x02) { + dev->pci_conf[0x64] |= 0x04; + if (dev->pci_conf[0x60] & 0x04) + acpi_sis5595_pmu_event(dev->sis->acpi); + } + break; + } +} + +uint8_t +sis_5595_pmu_read(int addr, void *priv) +{ + const sis_5595_pmu_t *dev = (sis_5595_pmu_t *) priv; + uint8_t ret = 0xff; + + ret = dev->pci_conf[addr]; + + sis_5595_pmu_log("SiS 5595 PMU: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5595_pmu_reset(void *priv) +{ + sis_5595_pmu_t *dev = (sis_5595_pmu_t *) priv; + + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x09; + dev->pci_conf[0x03] = 0x00; + dev->pci_conf[0x04] = dev->pci_conf[0x05] = 0x00; + dev->pci_conf[0x06] = 0x00; + dev->pci_conf[0x07] = 0x02; + dev->pci_conf[0x08] = dev->pci_conf[0x09] = 0x00; + dev->pci_conf[0x0a] = 0x00; + dev->pci_conf[0x0b] = 0xff; + dev->pci_conf[0x0c] = dev->pci_conf[0x0d] = 0x00; + dev->pci_conf[0x0e] = 0x80; + dev->pci_conf[0x0f] = 0x00; + dev->pci_conf[0x40] = dev->pci_conf[0x41] = 0x00; + dev->pci_conf[0x42] = dev->pci_conf[0x43] = 0x00; + dev->pci_conf[0x44] = dev->pci_conf[0x45] = 0x00; + dev->pci_conf[0x46] = dev->pci_conf[0x47] = 0x00; + dev->pci_conf[0x48] = dev->pci_conf[0x49] = 0x00; + dev->pci_conf[0x4a] = dev->pci_conf[0x4b] = 0x00; + dev->pci_conf[0x4c] = dev->pci_conf[0x4d] = 0x00; + dev->pci_conf[0x4e] = dev->pci_conf[0x4f] = 0x00; + dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x00; + dev->pci_conf[0x52] = dev->pci_conf[0x53] = 0x00; + dev->pci_conf[0x54] = dev->pci_conf[0x55] = 0x00; + dev->pci_conf[0x56] = dev->pci_conf[0x57] = 0x00; + dev->pci_conf[0x58] = dev->pci_conf[0x59] = 0x00; + dev->pci_conf[0x5a] = dev->pci_conf[0x5b] = 0x00; + dev->pci_conf[0x5c] = dev->pci_conf[0x5d] = 0x00; + dev->pci_conf[0x5e] = dev->pci_conf[0x5f] = 0x00; + dev->pci_conf[0x60] = dev->pci_conf[0x61] = 0x00; + dev->pci_conf[0x62] = dev->pci_conf[0x63] = 0x00; + dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00; + dev->pci_conf[0x66] = dev->pci_conf[0x67] = 0x00; + dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00; + dev->pci_conf[0x6a] = dev->pci_conf[0x6b] = 0x00; + dev->pci_conf[0x6c] = dev->pci_conf[0x6d] = 0x00; + dev->pci_conf[0x6e] = dev->pci_conf[0x6f] = 0x00; + dev->pci_conf[0x70] = dev->pci_conf[0x71] = 0x00; + dev->pci_conf[0x72] = dev->pci_conf[0x73] = 0x00; + dev->pci_conf[0x74] = dev->pci_conf[0x75] = 0x00; + dev->pci_conf[0x76] = dev->pci_conf[0x77] = 0x00; + dev->pci_conf[0x78] = dev->pci_conf[0x79] = 0x00; + dev->pci_conf[0x7a] = dev->pci_conf[0x7b] = 0x00; + dev->pci_conf[0x7c] = dev->pci_conf[0x7d] = 0x00; + dev->pci_conf[0x7e] = dev->pci_conf[0x7f] = 0x00; + dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00; + dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00; + + sis_5595_pmu_trap_update(dev); + acpi_update_irq(dev->sis->acpi); +} + +static void +sis_5595_pmu_close(void *priv) +{ + sis_5595_pmu_t *dev = (sis_5595_pmu_t *) priv; + + free(dev); +} + +static void * +sis_5595_pmu_init(UNUSED(const device_t *info)) +{ + sis_5595_pmu_t *dev = (sis_5595_pmu_t *) calloc(1, sizeof(sis_5595_pmu_t)); + + dev->sis = device_get_common_priv(); + dev->sis->pmu_regs = dev->pci_conf; + + dev->is_1997 = info->local; + + sis_5595_pmu_reset(dev); + + return dev; +} + +const device_t sis_5595_1997_pmu_device = { + .name = "SiS 5595 (1997) PMU", + .internal_name = "sis_5595_1997_pmu", + .flags = DEVICE_PCI, + .local = 0x01, + .init = sis_5595_pmu_init, + .close = sis_5595_pmu_close, + .reset = sis_5595_pmu_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5595_pmu_device = { + .name = "SiS 5595 PMU", + .internal_name = "sis_5595_pmu", + .flags = DEVICE_PCI, + .local = 0x00, + .init = sis_5595_pmu_init, + .close = sis_5595_pmu_close, + .reset = sis_5595_pmu_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_55xx.c b/src/chipset/sis_55xx.c new file mode 100644 index 000000000..2cad21f22 --- /dev/null +++ b/src/chipset/sis_55xx.c @@ -0,0 +1,96 @@ +/* + * 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 SiS 55xx common structure. + * + * Authors: Miran Grca, + * + * Copyright 2024 Miran Grca. + */ +#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/dma.h> +#include <86box/mem.h> +#include <86box/nvr.h> +#include <86box/hdd.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/pci.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/pit_fast.h> +#include <86box/plat.h> +#include <86box/plat_unused.h> +#include <86box/port_92.h> +#include <86box/smram.h> +#include <86box/spd.h> +#include <86box/apm.h> +#include <86box/ddma.h> +#include <86box/acpi.h> +#include <86box/smbus.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> +#include <86box/usb.h> + +#ifdef ENABLE_SIS_55XX_COMMON_LOG +int sis_55xx_common_do_log = ENABLE_SIS_55XX_COMMON_LOG; + +static void +sis_55xx_common_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_55xx_common_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_55xx_common_log(fmt, ...) +#endif + +static void +sis_55xx_common_close(void *priv) +{ + sis_55xx_common_t *dev = (sis_55xx_common_t *) priv; + + free(dev); +} + +static void * +sis_55xx_common_init(UNUSED(const device_t *info)) +{ + sis_55xx_common_t *dev = (sis_55xx_common_t *) calloc(1, sizeof(sis_55xx_common_t)); + + return dev; +} + +const device_t sis_55xx_common_device = { + .name = "SiS 55xx Common Structure", + .internal_name = "sis_55xx_common", + .flags = DEVICE_PCI, + .local = 0x00, + .init = sis_55xx_common_init, + .close = sis_55xx_common_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5600.c b/src/chipset/sis_5600.c new file mode 100644 index 000000000..ed7384740 --- /dev/null +++ b/src/chipset/sis_5600.c @@ -0,0 +1,210 @@ +/* + * 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 SiS (5)600 Pentium PCI/ISA Chipset. + * + * Authors: Miran Grca, + * + * Copyright 2024 Miran Grca. + */ +#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/mem.h> +#include <86box/nvr.h> +#include <86box/apm.h> +#include <86box/acpi.h> +#include <86box/hdd.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/pci.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/pit_fast.h> +#include <86box/plat.h> +#include <86box/plat_unused.h> +#include <86box/port_92.h> +#include <86box/smram.h> +#include <86box/spd.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> + +#ifdef ENABLE_SIS_5600_LOG +int sis_5600_do_log = ENABLE_SIS_5600_LOG; + +static void +sis_5600_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5600_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5600_log(fmt, ...) +#endif + +typedef struct sis_5600_t { + uint8_t nb_slot; + uint8_t sb_slot; + + void *h2p; + void *p2i; + void *ide; + void *usb; + void *pmu; + + sis_55xx_common_t *sis; +} sis_5600_t; + +static void +sis_5600_write(int func, int addr, uint8_t val, void *priv) +{ + const sis_5600_t *dev = (sis_5600_t *) priv; + + sis_5600_log("SiS 5600: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + if (func == 0x00) + sis_5600_host_to_pci_write(addr, val, dev->h2p); + else if (func == 0x01) + sis_5513_ide_write(addr, val, dev->ide); +} + +static uint8_t +sis_5600_read(int func, int addr, void *priv) +{ + const sis_5600_t *dev = (sis_5600_t *) priv; + uint8_t ret = 0xff; + + if (func == 0x00) + ret = sis_5600_host_to_pci_read(addr, dev->h2p); + else if (func == 0x01) + ret = sis_5513_ide_read(addr, dev->ide); + + sis_5600_log("SiS 5600: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5595_write(int func, int addr, uint8_t val, void *priv) +{ + const sis_5600_t *dev = (sis_5600_t *) priv; + + sis_5600_log("SiS 5595: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (func) { + case 0x00: + sis_5513_pci_to_isa_write(addr, val, dev->p2i); + break; + case 0x01: + sis_5595_pmu_write(addr, val, dev->pmu); + break; + case 0x02: + sis_5572_usb_write(addr, val, dev->usb); + break; + } +} + +static uint8_t +sis_5595_read(int func, int addr, void *priv) +{ + const sis_5600_t *dev = (sis_5600_t *) priv; + uint8_t ret = 0xff; + + switch (func) { + case 0x00: + ret = sis_5513_pci_to_isa_read(addr, dev->p2i); + break; + case 0x01: + ret = sis_5595_pmu_read(addr, dev->pmu); + break; + case 0x02: + ret = sis_5572_usb_read(addr, dev->usb); + break; + } + + sis_5600_log("SiS 5602: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5600_close(void *priv) +{ + sis_5600_t *dev = (sis_5600_t *) priv; + + free(dev); +} + +static void * +sis_5600_init(UNUSED(const device_t *info)) +{ + sis_5600_t *dev = (sis_5600_t *) calloc(1, sizeof(sis_5600_t)); + + /* Device 0: SiS 5600 */ + pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5600_read, sis_5600_write, dev, &dev->nb_slot); + /* Device 1: SiS 5595 */ + pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5595_read, sis_5595_write, dev, &dev->sb_slot); + + dev->sis = device_add(&sis_55xx_common_device); + + dev->ide = device_add_linked(&sis_5591_5600_ide_device, dev->sis); + if (info->local) + dev->p2i = device_add_linked(&sis_5595_1997_p2i_device, dev->sis); + else + dev->p2i = device_add_linked(&sis_5595_p2i_device, dev->sis); + dev->h2p = device_add_linked(&sis_5600_h2p_device, dev->sis); + dev->usb = device_add_linked(&sis_5595_usb_device, dev->sis); + if (info->local) + dev->pmu = device_add_linked(&sis_5595_1997_pmu_device, dev->sis); + else + dev->pmu = device_add_linked(&sis_5595_pmu_device, dev->sis); + + return dev; +} + +const device_t sis_5600_1997_device = { + .name = "SiS (5)600 (1997)", + .internal_name = "sis_5600_1997", + .flags = DEVICE_PCI, + .local = 1, + .init = sis_5600_init, + .close = sis_5600_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_5600_device = { + .name = "SiS (5)600", + .internal_name = "sis_5600", + .flags = DEVICE_PCI, + .local = 0, + .init = sis_5600_init, + .close = sis_5600_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_5600_h2p.c b/src/chipset/sis_5600_h2p.c new file mode 100644 index 000000000..f6ee926da --- /dev/null +++ b/src/chipset/sis_5600_h2p.c @@ -0,0 +1,434 @@ +/* + * 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 SiS (5)600 Host to PCI bridge. + * + * Authors: Miran Grca, + * + * Copyright 2024 Miran Grca. + */ +#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/dma.h> +#include <86box/mem.h> +#include <86box/nvr.h> +#include <86box/hdd.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/pci.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/pit_fast.h> +#include <86box/plat.h> +#include <86box/plat_unused.h> +#include <86box/port_92.h> +#include <86box/smram.h> +#include <86box/spd.h> +#include <86box/apm.h> +#include <86box/ddma.h> +#include <86box/acpi.h> +#include <86box/smbus.h> +#include <86box/sis_55xx.h> +#include <86box/chipset.h> +#include <86box/usb.h> +#include <86box/agpgart.h> + +#ifdef ENABLE_SIS_5600_HOST_TO_PCI_LOG +int sis_5600_host_to_pci_do_log = ENABLE_SIS_5600_HOST_TO_PCI_LOG; + +static void +sis_5600_host_to_pci_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5600_host_to_pci_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define sis_5600_host_to_pci_log(fmt, ...) +#endif + +typedef struct { + uint8_t installed; + uint8_t code; + uint32_t phys_size; +} ram_bank_t; + +typedef struct sis_5600_host_to_pci_t { + uint8_t pci_conf[256]; + uint8_t states[7]; + + ram_bank_t ram_banks[3]; + + sis_55xx_common_t *sis; + + smram_t *smram; + + agpgart_t *agpgart; +} sis_5600_host_to_pci_t; + +static uint8_t bank_codes[7] = { 0x00, 0x20, 0x24, 0x22, 0x26, 0x2a, 0x2b }; + +static uint32_t bank_sizes[7] = { 0x00800000, /* 8 MB */ + 0x01000000, /* 16 MB */ + 0x02000000, /* 32 MB */ + 0x04000000, /* 64 MB */ + 0x08000000, /* 128 MB */ + 0x10000000, /* 256 MB */ + 0x20000000 }; /* 512 MB */ + +static void +sis_5600_shadow_recalc(sis_5600_host_to_pci_t *dev) +{ + int state; + uint32_t base; + + for (uint8_t i = 0; i < 8; i++) { + base = 0x000c0000 + (i << 14); + state = (dev->pci_conf[0x70] & (1 << i)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[0x72] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + if (((dev->pci_conf[0x70] ^ dev->states[0]) & (1 << i)) || + ((dev->pci_conf[0x72] ^ dev->states[2]) & (1 << i))) { + mem_set_mem_state_both(base, 0x4000, state); + sis_5600_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff); + } + } + + for (uint8_t i = 0; i < 4; i++) { + base = 0x000e0000 + (i << 14); + state = (dev->pci_conf[0x71] & (1 << i)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[0x73] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + if (((dev->pci_conf[0x71] ^ dev->states[1]) & (1 << i)) || + ((dev->pci_conf[0x73] ^ dev->states[3]) & (1 << i))) { + mem_set_mem_state_both(base, 0x4000, state); + sis_5600_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff); + } + } + + base = 0x000f0000; + state = (dev->pci_conf[0x71] & (1 << 4)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[0x73] & (1 << 4)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + if (((dev->pci_conf[0x71] ^ dev->states[1]) & (1 << 4)) || + ((dev->pci_conf[0x73] ^ dev->states[3]) & (1 << 4))) { + mem_set_mem_state_both(base, 0x10000, state); + sis_5600_host_to_pci_log("%08X-%08X\n", base, base + 0xffff); + } + + for (uint8_t i = 0; i < 4; i++) + dev->states[i] = dev->pci_conf[0x70 + i]; + + flushmmucache_nopc(); +} + +static void +sis_5600_smram_recalc(sis_5600_host_to_pci_t *dev) +{ + smram_disable_all(); + + switch (dev->pci_conf[0x6a] >> 6) { + case 0: + smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x6a] & 0x10, 1); + break; + case 1: + smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x6a] & 0x10, 1); + break; + case 2: + smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x6a] & 0x10, 1); + break; + case 3: + smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x10000, dev->pci_conf[0x6a] & 0x10, 1); + break; + + default: + break; + } + + flushmmucache(); +} + +static void +sis_5600_mask_bar(uint8_t *regs, void *agpgart) +{ + uint32_t bar; + uint32_t sizes[8] = { 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x00000000 } ; + + /* Make sure the aperture's base is aligned to its size. */ + bar = (regs[0x13] << 24) | (regs[0x12] << 16); + bar &= (sizes[(regs[0x94] >> 4) & 0x07] | 0xf0000000); + regs[0x12] = (bar >> 16) & 0xff; + regs[0x13] = (bar >> 24) & 0xff; + + if (!agpgart) + return; + + /* Map aperture and GART. */ + agpgart_set_aperture(agpgart, + bar, + sizes[(regs[0x94] >> 4) & 0x07], + !!(regs[0x94] & 0x02)); + if (regs[0x94] & 0x01) + agpgart_set_gart(agpgart, (regs[0x91] << 8) | (regs[0x92] << 16) | (regs[0x93] << 24)); + else + agpgart_set_gart(agpgart, 0x00000000); +} + +void +sis_5600_host_to_pci_write(int addr, uint8_t val, void *priv) +{ + sis_5600_host_to_pci_t *dev = (sis_5600_host_to_pci_t *) priv; + + sis_5600_host_to_pci_log("SiS 5600 H2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val); + + switch (addr) { + default: + break; + + case 0x04: /* Command - Low Byte */ + dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xfd) | (val & 0x02); + break; + case 0x05: /* Command - High Byte */ + dev->pci_conf[addr] = val & 0x03; + break; + + case 0x07: /* Status - High Byte */ + dev->pci_conf[addr] = (dev->pci_conf[addr] & ~(val & 0x70)) | (val & 0x01); + break; + + case 0x0d: /* Master latency timer */ + case 0x50 ... 0x5a: + case 0x64 ... 0x69: + case 0x6b ... 0x6c: + case 0x74 ... 0x75: + case 0x77 ... 0x80: + case 0x82 ... 0x8f: + case 0x97 ... 0x9b: + case 0xc8 ... 0xcb: + case 0xd4 ... 0xd8: + case 0xda: + case 0xe0: + case 0xe2 ... 0xe3: + dev->pci_conf[addr] = val; + break; + + case 0x12: + dev->pci_conf[addr] = val & 0xc0; + sis_5600_mask_bar(dev->pci_conf, dev->agpgart); + break; + case 0x13: + dev->pci_conf[addr] = val; + sis_5600_mask_bar(dev->pci_conf, dev->agpgart); + break; + + case 0x60 ... 0x62: + dev->pci_conf[addr] = dev->ram_banks[addr & 0x0f].code | 0xc0; + break; + + case 0x63: + dev->pci_conf[addr] = dev->ram_banks[0].installed | + (dev->ram_banks[1].installed << 1) | + (dev->ram_banks[2].installed << 2); + break; + + case 0x6a: + dev->pci_conf[addr] = val; + sis_5600_smram_recalc(dev); + break; + + case 0x70 ... 0x73: + dev->pci_conf[addr] = val; + sis_5600_shadow_recalc(dev); + break; + + case 0x91 ... 0x93: + dev->pci_conf[addr] = val; + sis_5600_mask_bar(dev->pci_conf, dev->agpgart); + break; + case 0x94: + dev->pci_conf[addr] = val & 0x7f; + sis_5600_mask_bar(dev->pci_conf, dev->agpgart); + break; + } +} + +uint8_t +sis_5600_host_to_pci_read(int addr, void *priv) +{ + const sis_5600_host_to_pci_t *dev = (sis_5600_host_to_pci_t *) priv; + uint8_t ret = 0xff; + + ret = dev->pci_conf[addr]; + + sis_5600_host_to_pci_log("SiS 5600 H2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret); + + return ret; +} + +static void +sis_5600_host_to_pci_reset(void *priv) +{ + sis_5600_host_to_pci_t *dev = (sis_5600_host_to_pci_t *) priv; + + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x00; + dev->pci_conf[0x03] = 0x56; + dev->pci_conf[0x04] = 0x05; + dev->pci_conf[0x05] = 0x00; + dev->pci_conf[0x06] = 0x10; + dev->pci_conf[0x07] = 0x02; + dev->pci_conf[0x08] = 0x10; + dev->pci_conf[0x09] = dev->pci_conf[0x0a] = 0x00; + dev->pci_conf[0x0b] = 0x06; + dev->pci_conf[0x0c] = 0x00; + dev->pci_conf[0x0d] = 0xff; + dev->pci_conf[0x0e] = 0x80; + dev->pci_conf[0x0f] = 0x00; + dev->pci_conf[0x10] = dev->pci_conf[0x11] = 0x00; + dev->pci_conf[0x12] = dev->pci_conf[0x13] = 0x00; + dev->pci_conf[0x34] = 0xc0; + dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x02; + dev->pci_conf[0x52] = dev->pci_conf[0x53] = 0x00; + dev->pci_conf[0x54] = dev->pci_conf[0x55] = 0x00; + dev->pci_conf[0x56] = dev->pci_conf[0x57] = 0x00; + dev->pci_conf[0x58] = dev->pci_conf[0x59] = 0x00; + dev->pci_conf[0x5a] = 0x00; + dev->pci_conf[0x60] = dev->pci_conf[0x61] = 0x00; + dev->pci_conf[0x62] = 0x00; + dev->pci_conf[0x63] = 0xff; + dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00; + dev->pci_conf[0x66] = dev->pci_conf[0x67] = 0x00; + dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00; + dev->pci_conf[0x6a] = dev->pci_conf[0x6b] = 0x00; + dev->pci_conf[0x6c] = 0x00; + dev->pci_conf[0x70] = dev->pci_conf[0x71] = 0x00; + dev->pci_conf[0x72] = dev->pci_conf[0x73] = 0x00; + dev->pci_conf[0x74] = dev->pci_conf[0x75] = 0x00; + dev->pci_conf[0x77] = 0x00; + dev->pci_conf[0x78] = dev->pci_conf[0x79] = 0x00; + dev->pci_conf[0x7a] = dev->pci_conf[0x7b] = 0x00; + dev->pci_conf[0x7c] = dev->pci_conf[0x7d] = 0x00; + dev->pci_conf[0x7e] = dev->pci_conf[0x7f] = 0x00; + dev->pci_conf[0x80] = 0x00; + dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00; + dev->pci_conf[0x84] = dev->pci_conf[0x85] = 0xff; + dev->pci_conf[0x86] = 0xff; + dev->pci_conf[0x87] = 0x00; + dev->pci_conf[0x88] = dev->pci_conf[0x89] = 0x00; + dev->pci_conf[0x8a] = dev->pci_conf[0x8b] = 0x00; + dev->pci_conf[0x8c] = 0x00; + dev->pci_conf[0x8d] = 0x62; + dev->pci_conf[0x8e] = dev->pci_conf[0x8f] = 0x00; + dev->pci_conf[0x90] = dev->pci_conf[0x91] = 0x00; + dev->pci_conf[0x92] = dev->pci_conf[0x93] = 0x00; + dev->pci_conf[0x94] = dev->pci_conf[0x97] = 0x00; + dev->pci_conf[0x98] = dev->pci_conf[0x99] = 0x00; + dev->pci_conf[0x9a] = dev->pci_conf[0x9b] = 0x00; + dev->pci_conf[0xc0] = 0x02; + dev->pci_conf[0xc1] = 0x00; + dev->pci_conf[0xc2] = 0x10; + dev->pci_conf[0xc3] = 0x00; + dev->pci_conf[0xc4] = 0x03; + dev->pci_conf[0xc5] = 0x02; + dev->pci_conf[0xc6] = 0x00; + dev->pci_conf[0xc7] = 0x1f; + dev->pci_conf[0xc8] = dev->pci_conf[0xc9] = 0x00; + dev->pci_conf[0xca] = dev->pci_conf[0xcb] = 0x00; + dev->pci_conf[0xd4] = dev->pci_conf[0xd5] = 0x00; + dev->pci_conf[0xd6] = dev->pci_conf[0xd7] = 0x00; + dev->pci_conf[0xd8] = dev->pci_conf[0xda] = 0x00; + dev->pci_conf[0xe0] = 0x00; + dev->pci_conf[0xe2] = dev->pci_conf[0xe3] = 0x00; + + sis_5600_mask_bar(dev->pci_conf, dev->agpgart); + + cpu_cache_ext_enabled = 1; + cpu_update_waitstates(); + + sis_5600_shadow_recalc(dev); + + sis_5600_smram_recalc(dev); +} + +static void +sis_5600_host_to_pci_close(void *priv) +{ + sis_5600_host_to_pci_t *dev = (sis_5600_host_to_pci_t *) priv; + + smram_del(dev->smram); + free(dev); +} + +static void * +sis_5600_host_to_pci_init(UNUSED(const device_t *info)) +{ + sis_5600_host_to_pci_t *dev = (sis_5600_host_to_pci_t *) calloc(1, sizeof(sis_5600_host_to_pci_t)); + uint32_t total_mem = mem_size << 10; + ram_bank_t *rb; + + dev->sis = device_get_common_priv(); + + /* Calculate the physical RAM banks. */ + for (uint8_t i = 0; i < 3; i++) { + rb = &(dev->ram_banks[i]); + uint32_t size = 0x00000000; + uint8_t index = 0; + for (int8_t j = 6; j >= 0; j--) { + uint32_t *bs = &(bank_sizes[j]); + if (*bs <= total_mem) { + size = *bs; + index = j; + break; + } + } + if (size != 0x00000000) { + rb->installed = 1; + rb->code = bank_codes[index]; + rb->phys_size = size; + total_mem -= size; + } else + rb->installed = 0; + } + + /* SMRAM */ + dev->smram = smram_add(); + + device_add(&sis_5xxx_agp_device); + dev->agpgart = device_add(&agpgart_device); + + sis_5600_host_to_pci_reset(dev); + + return dev; +} + +const device_t sis_5600_h2p_device = { + .name = "SiS (5)600 Host to PCI bridge", + .internal_name = "sis_5600_host_to_pci", + .flags = DEVICE_PCI, + .local = 0x00, + .init = sis_5600_host_to_pci_init, + .close = sis_5600_host_to_pci_close, + .reset = sis_5600_host_to_pci_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/sis_85c496.c b/src/chipset/sis_85c496.c index 4d1db2d9e..b9b2544c8 100644 --- a/src/chipset/sis_85c496.c +++ b/src/chipset/sis_85c496.c @@ -123,7 +123,7 @@ sis_85c497_isa_read(uint16_t port, void *priv) const sis_85c496_t *dev = (sis_85c496_t *) priv; uint8_t ret = 0xff; - if (port == 0x23) + if ((port == 0x23) && (dev->cur_reg < 0xc0)) ret = dev->regs[dev->cur_reg]; else if (port == 0x33) ret = 0x3c /*random_generate()*/; diff --git a/src/chipset/sis_85c50x.c b/src/chipset/sis_85c50x.c index 7f4aebb7c..8ec0498ff 100644 --- a/src/chipset/sis_85c50x.c +++ b/src/chipset/sis_85c50x.c @@ -6,15 +6,13 @@ * * This file is part of the 86Box distribution. * - * Implementation of the SiS 85C50x Chipset. + * Implementation of the SiS 85C50x and 550x Chipsets. * + * Authors: Miran Grca, + * Tiseno100, * - * - * Authors: Tiseno100, - * Miran Grca, - * - * Copyright 2020-2021 Tiseno100. - * Copyright 2020-2021 Miran Grca. + * Copyright 2020-2024 Miran Grca. + * Copyright 2020-2024 Tiseno100. */ #include #include @@ -27,16 +25,20 @@ #include <86box/device.h> #include <86box/io.h> #include <86box/timer.h> - #include <86box/apm.h> #include <86box/machine.h> #include <86box/pic.h> +#include <86box/pit.h> +#include <86box/pit_fast.h> #include <86box/plat_unused.h> #include <86box/mem.h> +#include <86box/nvr.h> #include <86box/smram.h> #include <86box/pci.h> #include <86box/port_92.h> - +#include <86box/spd.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> #include <86box/chipset.h> #ifdef ENABLE_SIS_85C50X_LOG @@ -58,17 +60,23 @@ sis_85c50x_log(const char *fmt, ...) #endif typedef struct sis_85c50x_t { - uint8_t index; - uint8_t nb_slot; - uint8_t sb_slot; - uint8_t pad; + uint8_t index; + uint8_t nb_slot; + uint8_t sb_slot; + uint8_t type; - uint8_t pci_conf[256]; - uint8_t pci_conf_sb[256]; - uint8_t regs[256]; + uint8_t pci_conf[256]; + uint8_t pci_conf_sb[256]; + uint8_t pci_conf_ide[256]; + uint8_t regs[256]; + uint32_t states[13]; smram_t *smram[2]; port_92_t *port_92; + void *pit; + nvr_t *nvr; + + uint8_t (*pit_read_reg)(void *priv, uint8_t reg); } sis_85c50x_t; static void @@ -77,23 +85,59 @@ sis_85c50x_shadow_recalc(sis_85c50x_t *dev) uint32_t base; uint32_t can_read; uint32_t can_write; + uint32_t state; can_read = (dev->pci_conf[0x53] & 0x40) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; can_write = (dev->pci_conf[0x53] & 0x20) ? MEM_WRITE_EXTANY : MEM_WRITE_INTERNAL; - if (!can_read) - can_write = MEM_WRITE_EXTANY; - mem_set_mem_state_both(0xf0000, 0x10000, can_read | can_write); - shadowbios = 1; - shadowbios_write = 1; + state = can_read | can_write; + if (dev->states[12] != state) { + mem_set_mem_state_both(0x000f0000, 0x00010000, state); + sis_85c50x_log("F0000-FFFFF: R%c, W%c\n", + (dev->pci_conf[0x53] & 0x40) ? 'I' : 'E', + (dev->pci_conf[0x53] & 0x20) ? 'P' : 'I'); + dev->states[12] = state; + } for (uint8_t i = 0; i < 4; i++) { - base = 0xe0000 + (i << 14); - mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x54] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); - base = 0xd0000 + (i << 14); - mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x55] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); - base = 0xc0000 + (i << 14); - mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x56] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + base = 0x000e0000 + (i << 14); + state = (dev->pci_conf[0x54] & (0x80 >> i)) ? + (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY); + if (dev->states[8 + i] != state) { + mem_set_mem_state_both(base, 0x00004000, state); + sis_85c50x_log("%05X-%05X: R%c, W%c\n", base, base + 0x3fff, + (dev->pci_conf[0x543 & (0x80 >> i)) ? + ((dev->pci_conf[0x54] & 0x40) ? 'I' : 'D') : 'E', + (dev->pci_conf[0x54] & (0x80 >> i)) ? + ((dev->pci_conf[0x53] & 0x20) ? 'P' : 'I') : 'E'); + dev->states[8 + i] = state; + } + + base = 0x000d0000 + (i << 14); + state = (dev->pci_conf[0x55] & (0x80 >> i)) ? + (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY); + if (dev->states[4 + i] != state) { + mem_set_mem_state_both(base, 0x00004000, state); + sis_85c50x_log("%05X-%05X: R%c, W%c\n", base, base + 0x3fff, + (dev->pci_conf[0x55] & (0x80 >> i)) ? + ((dev->pci_conf[0x53] & 0x40) ? 'I' : 'D') : 'E', + (dev->pci_conf[0x55] & (0x80 >> i)) ? + ((dev->pci_conf[0x53] & 0x20) ? 'P' : 'I') : 'E'); + dev->states[4 + i] = state; + } + + base = 0x000c0000 + (i << 14); + state = (dev->pci_conf[0x56] & (0x80 >> i)) ? + (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY); + if (dev->states[i] != state) { + mem_set_mem_state_both(base, 0x00004000, state); + sis_85c50x_log("%05X-%05X: R%c, W%c\n", base, base + 0x3fff, + (dev->pci_conf[0x56] & (0x80 >> i)) ? + ((dev->pci_conf[0x53] & 0x40) ? 'I' : 'D') : 'E', + (dev->pci_conf[0x56] & (0x80 >> i)) ? + ((dev->pci_conf[0x53] & 0x20) ? 'P' : 'I') : 'E'); + dev->states[i] = state; + } } flushmmucache_nopc(); @@ -117,27 +161,35 @@ sis_85c50x_smm_recalc(sis_85c50x_t *dev) break; case 0x01: host_base |= 0x000b0000; - sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000B0000-000BFFFF\n", host_base, host_base + 0x10000 - 1); + sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000B0000-000BFFFF\n", + host_base, host_base + 0x10000 - 1); smram_enable(dev->smram[0], host_base, 0xb0000, 0x10000, (dev->pci_conf[0x65] & 0x10), 1); - smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xb0000, 0x10000, (dev->pci_conf[0x65] & 0x10), 1); + smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xb0000, + 0x10000, (dev->pci_conf[0x65] & 0x10), 1); break; case 0x02: host_base |= 0x000a0000; - sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000A0000-000AFFFF\n", host_base, host_base + 0x10000 - 1); + sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000A0000-000AFFFF\n", + host_base, host_base + 0x10000 - 1); smram_enable(dev->smram[0], host_base, 0xa0000, 0x10000, (dev->pci_conf[0x65] & 0x10), 1); - smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000, 0x10000, (dev->pci_conf[0x65] & 0x10), 1); + smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000, + 0x10000, (dev->pci_conf[0x65] & 0x10), 1); break; case 0x04: host_base |= 0x000a0000; - sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000A0000-000AFFFF\n", host_base, host_base + 0x8000 - 1); + sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000A0000-000AFFFF\n", + host_base, host_base + 0x8000 - 1); smram_enable(dev->smram[0], host_base, 0xa0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1); - smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1); + smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000, + 0x8000, (dev->pci_conf[0x65] & 0x10), 1); break; case 0x06: host_base |= 0x000b0000; - sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000B0000-000BFFFF\n", host_base, host_base + 0x8000 - 1); + sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000B0000-000BFFFF\n", + host_base, host_base + 0x8000 - 1); smram_enable(dev->smram[0], host_base, 0xb0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1); - smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1); + smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000, + 0x8000, (dev->pci_conf[0x65] & 0x10), 1); break; default: break; @@ -160,7 +212,10 @@ sis_85c50x_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf[addr] = ((dev->pci_conf[addr] & 0xf9) & ~(val & 0xf8)) | (val & 0x06); break; case 0x50: - dev->pci_conf[addr] = val; + if (dev->type & 1) + dev->pci_conf[addr] = val & 0xf7; + else + dev->pci_conf[addr] = val; break; case 0x51: /* Cache */ dev->pci_conf[addr] = val; @@ -176,8 +231,6 @@ sis_85c50x_write(int func, int addr, uint8_t val, void *priv) case 0x56: dev->pci_conf[addr] = val; sis_85c50x_shadow_recalc(dev); - if (addr == 0x54) - sis_85c50x_smm_recalc(dev); break; case 0x57: case 0x58: @@ -223,6 +276,31 @@ sis_85c50x_write(int func, int addr, uint8_t val, void *priv) case 0x69: dev->pci_conf[addr] &= ~val; break; + case 0x70 ... 0x77: + if (dev->type & 1) + spd_write_drbs(dev->pci_conf, 0x70, 0x77, 2); + break; + case 0x78: + case 0x7c ... 0x7e: + if (dev->type & 1) + dev->pci_conf[addr] = val; + break; + case 0x79: + if (dev->type & 1) { + spd_write_drbs(dev->pci_conf, 0xf8, 0xff, 4); + dev->pci_conf[addr] = 0x00; + for (uint8_t i = 0; i < 8; i++) + if (dev->pci_conf[0xf8 + i] & 0x80) dev->pci_conf[addr] |= (1 << i); + } + break; + case 0x7a: + if (dev->type & 1) + dev->pci_conf[addr] = val & 0xfe; + break; + case 0x7b: + if (dev->type & 1) + dev->pci_conf[addr] = val & 0xe0; + break; default: break; @@ -235,14 +313,33 @@ sis_85c50x_read(int func, int addr, void *priv) const sis_85c50x_t *dev = (sis_85c50x_t *) priv; uint8_t ret = 0xff; - if (func == 0x00) - ret = dev->pci_conf[addr]; + if (func == 0x00) { + if (addr >= 0xf8) + ret = 0x00; + else + ret = dev->pci_conf[addr]; + } sis_85c50x_log("85C501: [R] (%02X, %02X) = %02X\n", func, addr, ret); return ret; } +static void +sis_85c50x_ide_recalc(sis_85c50x_t *dev) +{ + ide_pri_disable(); + ide_set_base(0, (dev->pci_conf_ide[0x40] & 0x80) ? 0x0170 : 0x01f0); + ide_set_side(0, (dev->pci_conf_ide[0x40] & 0x80) ? 0x0376 : 0x03f6); + ide_pri_enable(); + + ide_sec_disable(); + ide_set_base(1, (dev->pci_conf_ide[0x40] & 0x80) ? 0x01f0 : 0x0170); + ide_set_side(1, (dev->pci_conf_ide[0x40] & 0x80) ? 0x03f6 : 0x0376); + if (dev->pci_conf_ide[0x41] & 0x01) + ide_sec_enable(); +} + static void sis_85c50x_sb_write(int func, int addr, uint8_t val, void *priv) { @@ -250,38 +347,46 @@ sis_85c50x_sb_write(int func, int addr, uint8_t val, void *priv) sis_85c50x_log("85C503: [W] (%02X, %02X) = %02X\n", func, addr, val); - if (func == 0x00) - switch (addr) { - case 0x04: /* Command */ - dev->pci_conf_sb[addr] = val & 0x0f; - break; - case 0x07: /* Status */ - dev->pci_conf_sb[addr] &= ~(val & 0x30); - break; - case 0x40: /* BIOS Control Register */ - dev->pci_conf_sb[addr] = val & 0x3f; - break; - case 0x41: - case 0x42: - case 0x43: - case 0x44: - /* INTA/B/C/D# Remapping Control Register */ - dev->pci_conf_sb[addr] = val & 0x8f; - if (val & 0x80) - pci_set_irq_routing(PCI_INTA + (addr - 0x41), PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTA + (addr - 0x41), val & 0xf); - break; - case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */ - case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */ - case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */ - case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */ - dev->pci_conf_sb[addr] = val; - break; + if (func == 0x00) switch (addr) { + case 0x04: /* Command */ + dev->pci_conf_sb[addr] = val & 0x0f; + break; + case 0x07: /* Status */ + dev->pci_conf_sb[addr] &= ~(val & 0x30); + break; + case 0x40: /* BIOS Control Register */ + dev->pci_conf_sb[addr] = val & 0x3f; + break; + case 0x41: + case 0x42: + case 0x43: + case 0x44: + /* INTA/B/C/D# Remapping Control Register */ + dev->pci_conf_sb[addr] = val & 0x8f; + if (val & 0x80) + pci_set_irq_routing(PCI_INTA + (addr - 0x41), PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTA + (addr - 0x41), val & 0xf); + break; + case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */ + case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */ + case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */ + case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */ + dev->pci_conf_sb[addr] = val; + break; - default: - break; - } + default: + break; + } else if ((dev->type & 2) && !(dev->regs[0x81] & 0x02) && (func == 0x01)) switch (addr) { + case 0x40: + case 0x41: + dev->pci_conf_ide[addr] = val; + sis_85c50x_ide_recalc(dev); + break; + + default: + break; + } } static uint8_t @@ -290,8 +395,42 @@ sis_85c50x_sb_read(int func, int addr, void *priv) const sis_85c50x_t *dev = (sis_85c50x_t *) priv; uint8_t ret = 0xff; - if (func == 0x00) - ret = dev->pci_conf_sb[addr]; + if (func == 0x00) switch (addr) { + default: + ret = dev->pci_conf_sb[addr]; + break; + case 0x4c ... 0x4f: + if (dev->type & 2) + ret = pic_read_icw(0, addr & 0x03); + else + ret = dev->pci_conf_sb[addr]; + break; + case 0x50 ... 0x53: + if (dev->type & 2) + ret = pic_read_icw(1, addr & 0x03); + else + ret = dev->pci_conf_sb[addr]; + break; + case 0x54 ... 0x55: + if (dev->type & 2) + ret = pic_read_ocw(0, addr & 0x01); + else + ret = dev->pci_conf_sb[addr]; + break; + case 0x56 ... 0x57: + if (dev->type & 2) + ret = pic_read_ocw(1, addr & 0x01); + else + ret = dev->pci_conf_sb[addr]; + break; + case 0x58 ... 0x5f: + if (dev->type & 2) + ret = dev->pit_read_reg(dev->pit, addr & 0x07); + else + ret = dev->pci_conf_sb[addr]; + break; + } else if ((dev->type & 2) && !(dev->regs[0x81] & 0x02) && (func == 0x01)) + ret = dev->pci_conf_ide[addr]; sis_85c50x_log("85C503: [W] (%02X, %02X) = %02X\n", func, addr, ret); @@ -313,10 +452,39 @@ sis_85c50x_isa_write(uint16_t addr, uint8_t val, void *priv) case 0x23: switch (dev->index) { case 0x80: - dev->regs[dev->index] = val & 0xe7; + if (dev->type & 2) { + dev->regs[dev->index] = val; + nvr_bank_set(0, !!(val & 0x08), dev->nvr); + } else + dev->regs[dev->index] = val & 0xe7; + switch (val >> 6) { + case 0: + cpu_set_isa_speed(7159091); + break; + case 1: + cpu_set_isa_pci_div(4); + break; + case 2: + cpu_set_isa_pci_div(3); + break; + + default: + break; + } break; case 0x81: - dev->regs[dev->index] = val & 0xf4; + if (dev->type & 2) + dev->regs[dev->index] = val & 0xf6; + else + dev->regs[dev->index] = val & 0xf4; + break; + case 0x82: + if (dev->type & 2) + dev->regs[dev->index] = val; + break; + case 0x83: + if (dev->type & 2) + dev->regs[dev->index] = val & 0x03; break; case 0x84: case 0x88: @@ -394,6 +562,12 @@ sis_85c50x_reset(void *priv) sis_85c50x_write(0, 0x68, 0x00, dev); sis_85c50x_write(0, 0x69, 0xff, dev); + if (dev->type & 1) { + for (uint8_t i = 0; i < 8; i++) + dev->pci_conf[0x70 + i] = 0x00; + dev->pci_conf[0x79] = 0x00; + } + /* South Bridge (SiS 85C503) */ dev->pci_conf_sb[0x00] = 0x39; dev->pci_conf_sb[0x01] = 0x10; @@ -407,10 +581,51 @@ sis_85c50x_reset(void *priv) dev->pci_conf_sb[0x09] = 0x00; dev->pci_conf_sb[0x0a] = 0x01; dev->pci_conf_sb[0x0b] = 0x06; + if (dev->type & 2) + dev->pci_conf_sb[0x0e] = 0x80; sis_85c50x_sb_write(0, 0x41, 0x80, dev); sis_85c50x_sb_write(0, 0x42, 0x80, dev); sis_85c50x_sb_write(0, 0x43, 0x80, dev); sis_85c50x_sb_write(0, 0x44, 0x80, dev); + + if (dev->type & 2) { + /* IDE (SiS 5503) */ + dev->pci_conf_ide[0x00] = 0x39; + dev->pci_conf_ide[0x01] = 0x10; + dev->pci_conf_ide[0x02] = 0x01; + dev->pci_conf_ide[0x03] = 0x06; + dev->pci_conf_ide[0x04] = 0x89; + dev->pci_conf_ide[0x05] = 0x00; + dev->pci_conf_ide[0x06] = 0x00; + dev->pci_conf_ide[0x07] = 0x00; + dev->pci_conf_ide[0x08] = 0x00; + dev->pci_conf_ide[0x09] = 0x00; + dev->pci_conf_ide[0x0a] = 0x01; + dev->pci_conf_ide[0x0b] = 0x01; + dev->pci_conf_ide[0x0c] = 0x00; + dev->pci_conf_ide[0x0d] = 0x00; + dev->pci_conf_ide[0x0e] = 0x80; + dev->pci_conf_ide[0x0f] = 0x00; + dev->pci_conf_ide[0x10] = 0x71; + dev->pci_conf_ide[0x11] = 0x01; + dev->pci_conf_ide[0x14] = 0xf1; + dev->pci_conf_ide[0x15] = 0x01; + dev->pci_conf_ide[0x18] = 0x71; + dev->pci_conf_ide[0x19] = 0x03; + dev->pci_conf_ide[0x1c] = 0xf1; + dev->pci_conf_ide[0x1d] = 0x03; + dev->pci_conf_ide[0x20] = 0x01; + dev->pci_conf_ide[0x24] = 0x01; + dev->pci_conf_ide[0x40] = 0x00; + dev->pci_conf_ide[0x41] = 0x40; + + sis_85c50x_ide_recalc(dev); + } + + cpu_set_isa_speed(7159091); + + if (dev->type & 2) + nvr_bank_set(0, 0, dev->nvr); } static void @@ -426,8 +641,10 @@ sis_85c50x_close(void *priv) static void * sis_85c50x_init(UNUSED(const device_t *info)) { - sis_85c50x_t *dev = (sis_85c50x_t *) malloc(sizeof(sis_85c50x_t)); - memset(dev, 0x00, sizeof(sis_85c50x_t)); + sis_85c50x_t *dev = (sis_85c50x_t *) calloc(1, sizeof(sis_85c50x_t)); + uint8_t pit_is_fast = (((pit_mode == -1) && is486) || (pit_mode == 1)); + + dev->type = info->local; /* 501/502 (Northbridge) */ pci_add_card(PCI_ADD_NORTHBRIDGE, sis_85c50x_read, sis_85c50x_write, dev, &dev->nb_slot); @@ -441,6 +658,17 @@ sis_85c50x_init(UNUSED(const device_t *info)) dev->port_92 = device_add(&port_92_device); + if (dev->type & 2) { + /* PIT */ + dev->pit = device_find_first_priv(DEVICE_PIT); + dev->pit_read_reg = pit_is_fast ? pitf_read_reg : pit_read_reg; + + /* NVR */ + dev->nvr = device_add(&at_mb_nvr_device); + + device_add(&ide_pci_2ch_device); + } + sis_85c50x_reset(dev); return dev; @@ -459,3 +687,45 @@ const device_t sis_85c50x_device = { .force_redraw = NULL, .config = NULL }; + +const device_t sis_550x_85c503_device = { + .name = "SiS 550x", + .internal_name = "sis_550x", + .flags = DEVICE_PCI, + .local = 1, + .init = sis_85c50x_init, + .close = sis_85c50x_close, + .reset = sis_85c50x_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_85c50x_5503_device = { + .name = "SiS 85C50x", + .internal_name = "sis_85c50x", + .flags = DEVICE_PCI, + .local = 2, + .init = sis_85c50x_init, + .close = sis_85c50x_close, + .reset = sis_85c50x_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t sis_550x_device = { + .name = "SiS 550x", + .internal_name = "sis_550x", + .flags = DEVICE_PCI, + .local = 3, + .init = sis_85c50x_init, + .close = sis_85c50x_close, + .reset = sis_85c50x_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/umc_8886.c b/src/chipset/umc_8886.c index f6a923346..7a049b1cb 100644 --- a/src/chipset/umc_8886.c +++ b/src/chipset/umc_8886.c @@ -79,17 +79,14 @@ #include <86box/timer.h> #include <86box/io.h> #include <86box/device.h> - #include <86box/hdd.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> #include <86box/pic.h> #include <86box/pci.h> - +#include <86box/port_92.h> #include <86box/chipset.h> -#define IDE_BIT 0x01 - #ifdef ENABLE_UMC_8886_LOG int umc_8886_do_log = ENABLE_UMC_8886_LOG; @@ -108,18 +105,6 @@ umc_8886_log(const char *fmt, ...) # define umc_8886_log(fmt, ...) #endif -/* PCI IRQ Flags */ -#define INTA (PCI_INTA + (2 * !(addr & 1))) -#define INTB (PCI_INTB + (2 * !(addr & 1))) -#define IRQRECALCA (((val & 0xf0) != 0) ? ((val & 0xf0) >> 4) : PCI_IRQ_DISABLED) -#define IRQRECALCB (((val & 0x0f) != 0) ? (val & 0x0f) : PCI_IRQ_DISABLED) - -/* Disable Internal IDE Flag needed for the AF or BF Southbridge variant */ -#define HAS_IDE dev->has_ide - -/* Southbridge Revision */ -#define SB_ID dev->sb_id - typedef struct umc_8886_t { uint8_t max_func; /* Last function number */ uint8_t pci_slot; @@ -128,19 +113,24 @@ typedef struct umc_8886_t { uint8_t pci_conf_sb[2][256]; /* PCI Registers */ - uint16_t sb_id; /* Southbridge Revision */ - int has_ide; /* Check if Southbridge Revision is AF or F */ + uint16_t sb_id; /* Southbridge Revision */ + uint16_t ide_id; /* IDE Revision */ + + int has_ide; /* Check if Southbridge Revision is F, AF, or BF */ } umc_8886_t; static void -umc_8886_ide_handler(int status) +umc_8886_ide_handler(umc_8886_t *dev) { ide_pri_disable(); ide_sec_disable(); - if (status) { - ide_pri_enable(); - ide_sec_enable(); + if (dev->pci_conf_sb[1][0x04] & 0x01) { + if (dev->pci_conf_sb[1][0x40] & 0x80) + ide_pri_enable(); + + if (dev->pci_conf_sb[1][0x40] & 0x40) + ide_sec_enable(); } } @@ -148,6 +138,7 @@ static void umc_8886_write(int func, int addr, uint8_t val, void *priv) { umc_8886_t *dev = (umc_8886_t *) priv; + int irq_routing; if (func <= dev->max_func) switch (func) { @@ -155,8 +146,17 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) umc_8886_log("UM8886: dev->regs[%02x] = %02x POST %02x\n", addr, val, inb(0x80)); switch (addr) { - case 0x04: - case 0x05: + case 0x04 ... 0x05: + case 0x0c ... 0x0d: + case 0x40 ... 0x42: + case 0x45: + case 0x50 ... 0x55: + case 0x57: + case 0x70 ... 0x76: + case 0x80 ... 0x82: + case 0x90 ... 0x92: + case 0xa0 ... 0xa1: + case 0xa5 ... 0xa8: dev->pci_conf_sb[func][addr] = val; break; @@ -164,46 +164,31 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf_sb[func][addr] &= ~(val & 0xf9); break; - case 0x0c: - case 0x0d: - dev->pci_conf_sb[func][addr] = val; - break; - - case 0x40: - case 0x41: - case 0x42: - dev->pci_conf_sb[func][addr] = val; - break; - case 0x43: + dev->pci_conf_sb[func][addr] = val; + irq_routing = (dev->pci_conf_sb[func][0x46] & 0x01) ? (val >> 8) : + PCI_IRQ_DISABLED; + pci_set_irq_routing(PCI_INTA, irq_routing); + irq_routing = (dev->pci_conf_sb[func][0x46] & 0x02) ? (val & 0x0f) : + PCI_IRQ_DISABLED; + pci_set_irq_routing(PCI_INTB, irq_routing); + break; case 0x44: dev->pci_conf_sb[func][addr] = val; - pci_set_irq_routing(INTA, IRQRECALCA); - pci_set_irq_routing(INTB, IRQRECALCB); + irq_routing = (dev->pci_conf_sb[func][0x46] & 0x04) ? (val >> 8) : + PCI_IRQ_DISABLED; + pci_set_irq_routing(PCI_INTC, irq_routing); + irq_routing = (dev->pci_conf_sb[func][0x46] & 0x08) ? (val & 0x0f) : + PCI_IRQ_DISABLED; + pci_set_irq_routing(PCI_INTD, irq_routing); break; - case 0x45: - dev->pci_conf_sb[func][addr] = val; - break; - - case 0x46: + case 0x46: /* Bits 3-0 = 0 = IRQ disabled, 1 = IRQ enabled. */ + case 0x47: /* Bits 3-0 = 0 = IRQ edge-triggered, 1 = IRQ level-triggered. */ /* Bit 6 seems to be the IRQ/SMI# toggle, 1 = IRQ, 0 = SMI#. */ dev->pci_conf_sb[func][addr] = val; break; - case 0x47: - dev->pci_conf_sb[func][addr] = val; - break; - - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - dev->pci_conf_sb[func][addr] = val; - break; - case 0x56: dev->pci_conf_sb[func][addr] = val; @@ -220,16 +205,6 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) default: break; } - - break; - - case 0x57: - case 0x70 ... 0x76: - case 0x80: - case 0x81: - case 0x90 ... 0x92: - case 0xa0 ... 0xa1: - dev->pci_conf_sb[func][addr] = val; break; case 0xa2: @@ -243,7 +218,6 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) picint(1 << ((dev->pci_conf_sb[0][0x46] & 0x80) ? 15 : 10)); else smi_raise(); - dev->pci_conf_sb[0][0xa3] |= 0x04; } dev->pci_conf_sb[func][addr] = val; @@ -254,10 +228,6 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) cpu_set_pci_speed(cpu_busspeed / ((val & 1) ? 1 : 2)); break; - case 0xa5 ... 0xa8: - dev->pci_conf_sb[func][addr] = val; - break; - default: break; } @@ -269,7 +239,8 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) switch (addr) { case 0x04: dev->pci_conf_sb[func][addr] = val; - umc_8886_ide_handler(val & 1); + if (dev->ide_id == 0x673a) + umc_8886_ide_handler(dev); break; case 0x07: @@ -277,9 +248,17 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) break; case 0x3c: + case 0x41 ... 0x4b: + case 0x54 ... 0x59: + if (dev->ide_id == 0x673a) + dev->pci_conf_sb[func][addr] = val; + break; + case 0x40: - case 0x41: - dev->pci_conf_sb[func][addr] = val; + if (dev->ide_id == 0x673a) { + dev->pci_conf_sb[func][addr] = val; + umc_8886_ide_handler(dev); + } break; default: @@ -311,47 +290,73 @@ umc_8886_reset(void *priv) memset(dev->pci_conf_sb[0], 0x00, sizeof(dev->pci_conf_sb[0])); memset(dev->pci_conf_sb[1], 0x00, sizeof(dev->pci_conf_sb[1])); - dev->pci_conf_sb[0][0] = 0x60; /* UMC */ - dev->pci_conf_sb[0][1] = 0x10; - - dev->pci_conf_sb[0][2] = (SB_ID & 0xff); /* 8886xx */ - dev->pci_conf_sb[0][3] = ((SB_ID >> 8) & 0xff); - - dev->pci_conf_sb[0][4] = 0x0f; - dev->pci_conf_sb[0][7] = 2; - - dev->pci_conf_sb[0][8] = 0x0e; - + dev->pci_conf_sb[0][0x00] = 0x60; /* UMC */ + dev->pci_conf_sb[0][0x01] = 0x10; + dev->pci_conf_sb[0][0x02] = (dev->sb_id & 0xff); /* 8886xx */ + dev->pci_conf_sb[0][0x03] = ((dev->sb_id >> 8) & 0xff); + dev->pci_conf_sb[0][0x04] = 0x0f; + dev->pci_conf_sb[0][0x07] = 0x02; + dev->pci_conf_sb[0][0x08] = 0x0e; dev->pci_conf_sb[0][0x09] = 0x00; dev->pci_conf_sb[0][0x0a] = 0x01; dev->pci_conf_sb[0][0x0b] = 0x06; - - dev->pci_conf_sb[0][0x40] = 1; - dev->pci_conf_sb[0][0x41] = 6; - dev->pci_conf_sb[0][0x42] = 8; - dev->pci_conf_sb[0][0x43] = 0x9a; - dev->pci_conf_sb[0][0x44] = 0xbc; - dev->pci_conf_sb[0][0x45] = 4; + dev->pci_conf_sb[0][0x40] = 0x01; + dev->pci_conf_sb[0][0x41] = 0x06; + dev->pci_conf_sb[0][0x42] = 0x08; + dev->pci_conf_sb[0][0x43] = 0x00; + dev->pci_conf_sb[0][0x44] = 0x00; + dev->pci_conf_sb[0][0x45] = 0x04; + dev->pci_conf_sb[0][0x46] = 0x00; dev->pci_conf_sb[0][0x47] = 0x40; - dev->pci_conf_sb[0][0x50] = 1; - dev->pci_conf_sb[0][0x51] = 3; + dev->pci_conf_sb[0][0x50] = 0x01; + dev->pci_conf_sb[0][0x51] = 0x03; + dev->pci_conf_sb[0][0x56] = dev->pci_conf_sb[0][0x57] = 0x00; + dev->pci_conf_sb[0][0x70] = dev->pci_conf_sb[0][0x71] = 0x00; + dev->pci_conf_sb[0][0x72] = dev->pci_conf_sb[0][0x73] = 0x00; + dev->pci_conf_sb[0][0x74] = dev->pci_conf_sb[0][0x76] = 0x00; + dev->pci_conf_sb[0][0x82] = 0x00; + dev->pci_conf_sb[0][0x90] = dev->pci_conf_sb[0][0x91] = 0x00; + dev->pci_conf_sb[0][0xa0] = dev->pci_conf_sb[0][0xa2] = 0x00; + dev->pci_conf_sb[0][0xa4] = 0x00; dev->pci_conf_sb[0][0xa8] = 0x20; - if (HAS_IDE) { - dev->pci_conf_sb[1][0] = 0x60; /* UMC */ - dev->pci_conf_sb[1][1] = 0x10; + if (dev->has_ide) { + dev->pci_conf_sb[1][0x00] = 0x60; /* UMC */ + dev->pci_conf_sb[1][0x01] = 0x10; + dev->pci_conf_sb[1][0x02] = (dev->ide_id & 0xff); /* 8886xx IDE */ + dev->pci_conf_sb[1][0x03] = ((dev->ide_id >> 8) & 0xff); + dev->pci_conf_sb[1][0x04] = 0x05; /* Start with Internal IDE Enabled */ + dev->pci_conf_sb[1][0x08] = 0x10; + dev->pci_conf_sb[1][0x09] = 0x8f; + dev->pci_conf_sb[1][0x0a] = dev->pci_conf_sb[1][0x0b] = 0x01; + dev->pci_conf_sb[1][0x10] = 0xf1; + dev->pci_conf_sb[1][0x11] = 0x01; + dev->pci_conf_sb[1][0x14] = 0xf5; + dev->pci_conf_sb[1][0x15] = 0x03; + dev->pci_conf_sb[1][0x18] = 0x71; + dev->pci_conf_sb[1][0x19] = 0x01; + dev->pci_conf_sb[1][0x1c] = 0x75; + dev->pci_conf_sb[1][0x1d] = 0x03; + dev->pci_conf_sb[1][0x20] = 0x01; + dev->pci_conf_sb[1][0x21] = 0x10; - dev->pci_conf_sb[1][2] = 0x3a; /* 8886BF IDE */ - dev->pci_conf_sb[1][3] = 0x67; + if (dev->ide_id == 0x673a) { + dev->pci_conf_sb[1][0x40] = 0xc0; + dev->pci_conf_sb[1][0x41] = 0x00; + dev->pci_conf_sb[1][0x42] = dev->pci_conf_sb[1][0x43] = 0x00; + dev->pci_conf_sb[1][0x44] = dev->pci_conf_sb[1][0x45] = 0x00; + dev->pci_conf_sb[1][0x46] = dev->pci_conf_sb[1][0x47] = 0x00; + dev->pci_conf_sb[1][0x48] = dev->pci_conf_sb[1][0x49] = 0x00; + dev->pci_conf_sb[1][0x4a] = dev->pci_conf_sb[1][0x4b] = 0x00; + dev->pci_conf_sb[1][0x54] = dev->pci_conf_sb[1][0x55] = 0x00; + dev->pci_conf_sb[1][0x56] = dev->pci_conf_sb[1][0x57] = 0x00; + dev->pci_conf_sb[1][0x58] = dev->pci_conf_sb[1][0x59] = 0x00; - dev->pci_conf_sb[1][4] = 1; /* Start with Internal IDE Enabled */ + umc_8886_ide_handler(dev); - dev->pci_conf_sb[1][8] = 0x10; - - dev->pci_conf_sb[1][0x09] = 0x0f; - dev->pci_conf_sb[1][0x0a] = dev->pci_conf_sb[1][0x0b] = 1; - - umc_8886_ide_handler(1); + picintc(1 << 14); + picintc(1 << 15); + } } for (uint8_t i = 1; i < 5; i++) /* Disable all IRQ interrupts */ @@ -375,17 +380,28 @@ umc_8886_init(const device_t *info) umc_8886_t *dev = (umc_8886_t *) malloc(sizeof(umc_8886_t)); memset(dev, 0, sizeof(umc_8886_t)); - dev->has_ide = !!(info->local == 0x886a); - pci_add_card(PCI_ADD_SOUTHBRIDGE, umc_8886_read, umc_8886_write, dev, &dev->pci_slot); /* Device 12: UMC 8886xx */ - - /* Add IDE if UM8886AF variant */ - if (HAS_IDE) - device_add(&ide_pci_2ch_device); - - dev->max_func = (HAS_IDE) ? 1 : 0; + /* Device 12: UMC 8886xx */ + pci_add_card(PCI_ADD_SOUTHBRIDGE, umc_8886_read, umc_8886_write, dev, &dev->pci_slot); /* Get the Southbridge Revision */ - SB_ID = info->local; + dev->sb_id = info->local & 0xffff; + + /* IDE Revision */ + dev->ide_id = info->local >> 16; + + dev->has_ide = (dev->ide_id != 0x0000); + + dev->max_func = 0; + + /* Add IDE if this is the UM8886AF or UM8886BF. */ + if (dev->ide_id == 0x673a) { + /* UM8886BF */ + device_add(&ide_pci_2ch_device); + dev->max_func = 1; + } else if (dev->ide_id == 0x1001) { + /* UM8886AF */ + device_add(&ide_um8673f_device); + } umc_8886_reset(dev); @@ -396,7 +412,7 @@ const device_t umc_8886f_device = { .name = "UMC 8886F", .internal_name = "umc_8886f", .flags = DEVICE_PCI, - .local = 0x8886, + .local = 0x00008886, .init = umc_8886_init, .close = umc_8886_close, .reset = umc_8886_reset, @@ -407,10 +423,24 @@ const device_t umc_8886f_device = { }; const device_t umc_8886af_device = { - .name = "UMC 8886AF/8886BF", + .name = "UMC 8886AF", .internal_name = "umc_8886af", .flags = DEVICE_PCI, - .local = 0x886a, + .local = 0x1001886a, + .init = umc_8886_init, + .close = umc_8886_close, + .reset = umc_8886_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t umc_8886bf_device = { + .name = "UMC 8886BF", + .internal_name = "umc_8886bf", + .flags = DEVICE_PCI, + .local = 0x673a888a, .init = umc_8886_init, .close = umc_8886_close, .reset = umc_8886_reset, diff --git a/src/chipset/umc_8890.c b/src/chipset/umc_8890.c new file mode 100644 index 000000000..7de2ca1d0 --- /dev/null +++ b/src/chipset/umc_8890.c @@ -0,0 +1,241 @@ +/* + * 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 8890 Chipset. + * + * Note: This chipset has no datasheet, everything were done via + * reverse engineering the BIOS of various machines using it. + * + * Authors: Tiseno100, + * Miran Grca, + * + * Copyright 2021 Tiseno100. + * Copyright 2021-2024 Miran Grca. + */ + +#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/apm.h> +#include <86box/mem.h> +#include <86box/pci.h> +#include <86box/port_92.h> +#include <86box/smram.h> + +#include <86box/chipset.h> + +#ifdef ENABLE_UMC_8890_LOG +int umc_8890_do_log = ENABLE_UMC_8890_LOG; + +static void +umc_8890_log(const char *fmt, ...) +{ + va_list ap; + + if (umc_8890_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define umc_8890_log(fmt, ...) +#endif + +typedef struct umc_8890_t { + uint8_t pci_slot; + + uint8_t pci_conf[256]; /* PCI Registers */ + + int mem_state[2]; + + uint32_t smram_base; + + smram_t *smram; /* SMRAM Handler */ +} umc_8890_t; + +static void +um8890_shadow(umc_8890_t *dev) +{ + uint8_t flag; + uint16_t state; + + flag = (dev->pci_conf[0x5f] & 0x0c) >> 2; + state = (flag & 1) ? (MEM_READ_INTERNAL | ((flag & 2) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) : + (MEM_READ_EXTANY | MEM_WRITE_EXTANY); + + if ((dev->mem_state[1] ^ dev->pci_conf[0x5f]) & 0x0c) { + mem_set_mem_state_both(0xe0000, 0x10000, state); + dev->mem_state[1] = (dev->mem_state[1] & 0xf0) | (dev->pci_conf[0x5f] & 0x0f); + } + + flag = (dev->pci_conf[0x5f] & 0xc0) >> 6; + state = (flag & 1) ? (MEM_READ_INTERNAL | ((flag & 2) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) : + (MEM_READ_EXTANY | MEM_WRITE_EXTANY); + + if ((dev->mem_state[1] ^ dev->pci_conf[0x5f]) & 0xc0) { + mem_set_mem_state_both(0xf0000, 0x10000, state); + dev->mem_state[1] = (dev->mem_state[1] & 0x0f) | (dev->pci_conf[0x5f] & 0xf0); + } + + for (uint8_t i = 0; i < 8; i++) { + state = (dev->pci_conf[0x5d] & (1 << i)) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : + (MEM_READ_EXTANY | MEM_WRITE_EXTANY); + + if ((dev->mem_state[0] ^ dev->pci_conf[0x5d]) & (1 << i)) { + mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, state); + dev->mem_state[0] = (dev->mem_state[0] & ~(1 << i)) | (dev->pci_conf[0x5d] & (1 << i)); + } + } + + flushmmucache_nopc(); +} + + +static void +um8890_smram(umc_8890_t *dev) +{ + smram_disable_all(); + + /* Bit 4, if set, enables SMRAM access outside SMM. SMRAM appears to be always enabled + in SMM, and is always set to A0000-BFFFF. */ + smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x20000, dev->pci_conf[0x65] & 0x10, 1); +} + +static void +um8890_write(int func, int addr, uint8_t val, void *priv) +{ + umc_8890_t *dev = (umc_8890_t *)priv; + + if (func == 0) switch (addr) { + case 0x04 ... 0x05: + case 0x0c ... 0x0d: + case 0x40 ... 0x5b: + case 0x60 ... 0x63: + case 0x66 ... 0xff: + dev->pci_conf[addr] = val; + break; + + case 0x07: + dev->pci_conf[addr] &= ~(val & 0xf9); + break; + + case 0x5c ... 0x5f: + dev->pci_conf[addr] = val; + um8890_shadow(dev); + break; + + /* Register 64h, 16-bit: + Bit 12: SMRAM enabled outside SMM (1 = yes, 0 = no); + Bit 10: ???? (set by Award BIOS); + Bits 7- 0: SMM handler offset to SMBASE, shifted to the right by 14. + */ + case 0x64: case 0x65: + dev->pci_conf[addr] = val; + if (addr == 0x65) + um8890_smram(dev); + break; + } + + umc_8890_log("UM8890: dev->regs[%02x] = %02x POST: %02x\n", addr, dev->pci_conf[addr], inb(0x80)); +} + + +static uint8_t +um8890_read(int func, int addr, void *priv) +{ + umc_8890_t *dev = (umc_8890_t *)priv; + uint8_t ret = 0xff; + + if (func == 0) + ret = dev->pci_conf[addr]; + + return ret; +} + +static void +umc_8890_reset(void *priv) +{ + umc_8890_t *dev = (umc_8890_t *)priv; + + memset(dev->pci_conf, 0x00, sizeof(dev->pci_conf)); + + /* Defaults */ + dev->pci_conf[0x00] = 0x60; /* UMC */ + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x91; /* 8891F */ + dev->pci_conf[0x03] = 0x88; + dev->pci_conf[0x07] = 0x02; + dev->pci_conf[0x08] = 0x01; + dev->pci_conf[0x09] = 0x00; + dev->pci_conf[0x0a] = 0x00; + dev->pci_conf[0x0b] = 0x06; + dev->pci_conf[0x5c] = 0x00; + dev->pci_conf[0x5d] = 0x00; + dev->pci_conf[0x5e] = 0x00; + dev->pci_conf[0x5f] = 0x00; + dev->pci_conf[0x64] = 0x00; + dev->pci_conf[0x65] = 0x00; + + um8890_shadow(dev); + + um8890_smram(dev); +} + + +static void +umc_8890_close(void *priv) +{ + umc_8890_t *dev = (umc_8890_t *)priv; + + smram_del(dev->smram); + free(dev); +} + + +static void * +umc_8890_init(const device_t *info) +{ + umc_8890_t *dev = (umc_8890_t *) calloc(1, sizeof(umc_8890_t)); + + /* Device 0: UMC 8890 */ + pci_add_card(PCI_ADD_NORTHBRIDGE, um8890_read, um8890_write, dev, &dev->pci_slot); + + /* Port 92 */ + device_add(&port_92_pci_device); + + dev->smram = smram_add(); + + umc_8890_reset(dev); + + return dev; +} + +const device_t umc_8890_device = { + .name = "UMC 8890(8891BF/8892BF)", + .internal_name = "umc_8890", + .flags = DEVICE_PCI, + .local = 0x886a, + .init = umc_8890_init, + .close = umc_8890_close, + .reset = umc_8890_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/chipset/umc_hb4.c b/src/chipset/umc_hb4.c index d5cce0fca..a7ed0b880 100644 --- a/src/chipset/umc_hb4.c +++ b/src/chipset/umc_hb4.c @@ -14,13 +14,11 @@ * Note 2: Additional information were also used from all * around the web. * - * - * * Authors: Tiseno100, * Miran Grca, * * Copyright 2021 Tiseno100. - * Copyright 2021 Miran Grca. + * Copyright 2021-2024 Miran Grca. */ /* @@ -75,15 +73,24 @@ Bit 3: CC000-CFFFF Read Enable Bit 2: C8000-CBFFF Read Enable Bit 1: C0000-C7FFF Read Enable - Bit 0: Enable C0000-DFFFF Shadow Segment Bits + Bit 0: E0000-EFFFF Read Enable Register 55: - Bit 7: E0000-FFFF Read Enable + Bit 7: F0000-FFFF Read Enable Bit 6: Shadow Write Status (1: Write Protect/0: Write) Register 56h & 57h: DRAM Bank 0 Configuration Register 58h & 59h: DRAM Bank 1 Configuration + Register 5A: + Bit 2: Detrubo + + Register 5C: + Bits 7-0: SMRAM base A27-A20 + + Register 5D: + Bits 3-0: SMRAM base A31-A28 + Register 60: Bit 5: If set and SMRAM is enabled, data cycles go to PCI and code cycles go to DRAM Bit 0: SMRAM Local Access Enable - if set, SMRAM is also enabled outside SMM @@ -129,14 +136,15 @@ hb4_log(const char *fmt, ...) #endif typedef struct hb4_t { - uint8_t shadow; - uint8_t shadow_read; - uint8_t shadow_write; uint8_t pci_slot; uint8_t pci_conf[256]; /* PCI Registers */ + int mem_state[9]; - smram_t *smram[3]; /* SMRAM Handlers */ + + uint32_t smram_base; + + smram_t *smram; /* SMRAM Handler */ } hb4_t; static int shadow_bios[4] = { (MEM_READ_EXTANY | MEM_WRITE_INTERNAL), (MEM_READ_EXTANY | MEM_WRITE_EXTANY), @@ -167,7 +175,8 @@ hb4_shadow_bios_low(hb4_t *dev) { int state; - state = shadow_bios[(dev->pci_conf[0x55] >> 6) & (dev->shadow | 0x01)]; + /* Erratum in Vogons' datasheet: Register 55h bit 7 in fact controls E0000-FFFFF. */ + state = shadow_bios[dev->pci_conf[0x55] >> 6]; if (state != dev->mem_state[7]) { mem_set_mem_state_both(0xe0000, 0x10000, state); @@ -185,7 +194,8 @@ hb4_shadow_main(hb4_t *dev) int n = 0; for (uint8_t i = 0; i < 6; i++) { - state = shadow_read[dev->shadow && ((dev->pci_conf[0x54] >> (i + 2)) & 0x01)] | shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01]; + state = shadow_read[(dev->pci_conf[0x54] >> (i + 2)) & 0x01] | + shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01]; if (state != dev->mem_state[i + 1]) { n++; @@ -202,7 +212,8 @@ hb4_shadow_video(hb4_t *dev) { int state; - state = shadow_read[dev->shadow && ((dev->pci_conf[0x54] >> 1) & 0x01)] | shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01]; + state = shadow_read[(dev->pci_conf[0x54] >> 1) & 0x01] | + shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01]; if (state != dev->mem_state[0]) { mem_set_mem_state_both(0xc0000, 0x8000, state); @@ -232,22 +243,26 @@ static void hb4_smram(hb4_t *dev) { smram_disable_all(); + if (dev->smram_base != 0x00000000) + umc_smram_recalc(dev->smram_base >> 12, 0); + + dev->smram_base = ((uint32_t) dev->pci_conf[0x5c]) << 20; + dev->smram_base |= ((uint32_t) (dev->pci_conf[0x5d] & 0x0f)) << 28; + dev->smram_base |= 0x000a0000; /* Bit 0, if set, enables SMRAM access outside SMM. SMRAM appears to be always enabled in SMM, and is always set to A0000-BFFFF. */ - smram_enable(dev->smram[0], 0x000a0000, 0x000a0000, 0x20000, dev->pci_conf[0x60] & 0x01, 1); - /* There's a mirror of the SMRAM at 0E0A0000, mapped to A0000. */ - smram_enable(dev->smram[1], 0x0e0a0000, 0x000a0000, 0x20000, dev->pci_conf[0x60] & 0x01, 1); - /* There's another mirror of the SMRAM at 4E0A0000, mapped to A0000. */ - smram_enable(dev->smram[2], 0x4e0a0000, 0x000a0000, 0x20000, dev->pci_conf[0x60] & 0x01, 1); + smram_enable(dev->smram, dev->smram_base, 0x000a0000, 0x20000, dev->pci_conf[0x60] & 0x01, 1); /* Bit 5 seems to set data to go to PCI and code to DRAM. The Samsung SPC7700P-LW uses this. */ if (dev->pci_conf[0x60] & 0x20) { if (dev->pci_conf[0x60] & 0x01) - mem_set_mem_state_smram_ex(0, 0x000a0000, 0x20000, 0x02); - mem_set_mem_state_smram_ex(1, 0x000a0000, 0x20000, 0x02); + mem_set_mem_state_smram_ex(0, dev->smram_base, 0x20000, 0x02); + mem_set_mem_state_smram_ex(1, dev->smram_base, 0x20000, 0x02); } + + umc_smram_recalc(dev->smram_base >> 12, 1); } static void @@ -278,38 +293,27 @@ hb4_write(UNUSED(int func), int addr, uint8_t val, void *priv) cpu_update_waitstates(); break; - case 0x51: - case 0x52: + case 0x51 ... 0x53: dev->pci_conf[addr] = val; break; - case 0x53: - dev->pci_conf[addr] = val; - hb4_log("HB53: %02X\n", val); - break; - - case 0x55: - dev->shadow_read = (val & 0x80); - dev->shadow_write = (val & 0x40); - dev->pci_conf[addr] = val; - hb4_shadow(dev); - break; - case 0x54: - dev->shadow = (val & 0x01) << 1; + case 0x54 ... 0x55: dev->pci_conf[addr] = val; hb4_shadow(dev); break; - case 0x56 ... 0x5f: + case 0x56 ... 0x5b: + case 0x5e ... 0x5f: dev->pci_conf[addr] = val; break; + case 0x5c ... 0x5d: case 0x60: dev->pci_conf[addr] = val; hb4_smram(dev); break; - case 0x61: + case 0x61 ... 0x62: dev->pci_conf[addr] = val; break; @@ -336,30 +340,35 @@ hb4_reset(void *priv) hb4_t *dev = (hb4_t *) priv; memset(dev->pci_conf, 0x00, sizeof(dev->pci_conf)); - dev->pci_conf[0] = 0x60; /* UMC */ - dev->pci_conf[1] = 0x10; - - dev->pci_conf[2] = 0x81; /* 8881x */ - dev->pci_conf[3] = 0x88; - - dev->pci_conf[7] = 2; - - dev->pci_conf[8] = 4; - + dev->pci_conf[0x00] = 0x60; /* UMC */ + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x81; /* 8881x */ + dev->pci_conf[0x03] = 0x88; + dev->pci_conf[0x07] = 0x02; + dev->pci_conf[0x08] = 0x04; dev->pci_conf[0x09] = 0x00; dev->pci_conf[0x0a] = 0x00; dev->pci_conf[0x0b] = 0x06; - - dev->pci_conf[0x51] = 1; - dev->pci_conf[0x52] = 1; - dev->pci_conf[0x5a] = 4; - dev->pci_conf[0x5c] = 0xc0; + dev->pci_conf[0x50] = 0x00; + dev->pci_conf[0x51] = 0x00; + dev->pci_conf[0x52] = 0x01; + dev->pci_conf[0x53] = 0x00; + dev->pci_conf[0x54] = 0x00; + dev->pci_conf[0x55] = 0x00; + dev->pci_conf[0x56] = 0x00; + dev->pci_conf[0x57] = 0x00; + dev->pci_conf[0x58] = 0x00; + dev->pci_conf[0x59] = 0x00; + dev->pci_conf[0x5a] = 0x04; + dev->pci_conf[0x5c] = 0x00; dev->pci_conf[0x5d] = 0x20; dev->pci_conf[0x5f] = 0xff; + dev->pci_conf[0x60] = 0x00; + dev->pci_conf[0x61] = 0x00; + dev->pci_conf[0x62] = 0x00; - hb4_write(0, 0x54, 0x00, dev); - hb4_write(0, 0x55, 0x00, dev); - hb4_write(0, 0x60, 0x80, dev); + hb4_shadow(dev); + hb4_smram(dev); cpu_cache_ext_enabled = 0; cpu_update_waitstates(); @@ -372,6 +381,7 @@ hb4_close(void *priv) { hb4_t *dev = (hb4_t *) priv; + smram_del(dev->smram); free(dev); } @@ -387,10 +397,9 @@ hb4_init(UNUSED(const device_t *info)) device_add(&port_92_pci_device); /* SMRAM */ - dev->smram[0] = smram_add(); - dev->smram[1] = smram_add(); - dev->smram[2] = smram_add(); + dev->smram = smram_add(); + dev->smram_base = 0x000a0000; hb4_reset(dev); return dev; diff --git a/src/chipset/wd76c10.c b/src/chipset/wd76c10.c index ae4b30228..ef076b606 100644 --- a/src/chipset/wd76c10.c +++ b/src/chipset/wd76c10.c @@ -8,14 +8,10 @@ * * 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: Miran Grca, * + * Copyright 2024 Miran Grca. * - * - * Authors: Tiseno100 - * - * Copyright 2021 Tiseno100 */ #include #include @@ -37,112 +33,452 @@ #include <86box/hdc_ide.h> #include <86box/lpt.h> #include <86box/mem.h> -#include <86box/plat_unused.h> +#include <86box/nvr.h> #include <86box/port_92.h> #include <86box/serial.h> +#include <86box/plat_fallthrough.h> #include <86box/chipset.h> /* Lock/Unlock Procedures */ -#define LOCK dev->lock -#define UNLOCKED !dev->lock +#define LOCK dev->locked +#define UNLOCKED !dev->locked + +#define WD76C10_ADDR_INVALID 0x80000000 #ifdef ENABLE_WD76C10_LOG int wd76c10_do_log = ENABLE_WD76C10_LOG; - static void wd76c10_log(const char *fmt, ...) { va_list ap; - if (wd76c10_do_log) { + if (wd76c10_do_log) + { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -# define wd76c10_log(fmt, ...) +#define wd76c10_log(fmt, ...) #endif -typedef struct wd76c10_t { - uint16_t lock_reg; - uint16_t oscillator_40mhz; - uint16_t cache_flush; - uint16_t ems_page_reg; - uint16_t ems_page_reg_pointer; - uint16_t port_shadow; - uint16_t pmc_interrupt; - uint16_t high_mem_protect_boundry; - uint16_t delay_line; - uint16_t diagnostic; - uint16_t nmi_status; - uint16_t pmc_input; - uint16_t pmc_timer; - uint16_t pmc_output; - uint16_t ems_control_low_address_boundry; - uint16_t shadow_ram; - uint16_t split_addr; - uint16_t bank32staddr; - uint16_t bank10staddr; - uint16_t non_page_mode_dram_timing; - uint16_t mem_control; - uint16_t refresh_control; - uint16_t disk_chip_select; - uint16_t prog_chip_sel_addr; - uint16_t bus_timing_power_down_ctl; - uint16_t clk_control; +typedef struct { + uint32_t enable; + uint32_t virt_addr, phys_addr; + uint32_t virt_size, phys_size; +} ram_bank_t; - int lock; +typedef struct { + uint8_t enabled; - fdc_t *fdc_controller; - mem_mapping_t *mem_mapping; - serial_t *uart[2]; + uint32_t virt, phys; + uint32_t size; +} ems_page_t; + +typedef struct +{ + uint8_t ep, p92; + + uint8_t vbios_states[4]; + uint8_t bios_states[8]; + uint8_t high_bios_states[8]; + uint8_t mem_pages[1024]; + + uint16_t toggle, cpuclk, fpu_ctl, mem_ctl, + split_sa, sh_wp, hmwpb, npmdmt, + ems_ctl, ems_pp, ser_par_cs, rtc_disk_cs, + prog_cs, pmc_in; + + union + { + uint16_t bank_base_regs[2]; + uint8_t bank_bases[4]; + }; + + uint16_t ems_page_regs[40]; + + int locked; + + uint32_t mem_top, hmwp_base; + + ram_bank_t ram_banks[5]; + + ems_page_t ems_pages[40]; + + mem_mapping_t ram_mapping; + + nvr_t *nvr; + + fdc_t *fdc; + serial_t *uart[2]; } wd76c10_t; -static void -wd76c10_refresh_control(wd76c10_t *dev) +static uint32_t bank_sizes[4] = { 0x00020000, /* 64 Kbit X 16 = 1024 Kbit = 128 kB, 8x 8 */ + 0x00080000, /* 256 Kbit X 16 = 4096 Kbit = 512 kB, 9x 9 */ + 0x00200000, /* 1 Mbit X 16 = 16 Mbit = 2 MB, 10x10 */ + 0x00800000 }; /* 4 Mbit X 16 = 64 Mbit = 8 MB, 11x11 */ + +static uint32_t +wd76c10_calc_addr(wd76c10_t *dev, uint32_t addr) +{ + uint32_t ret; + uint8_t ems_page; + uint8_t ems_en = (uint8_t) ((dev->ems_ctl >> 10) & 0x03); + ems_page_t *ep; + uint8_t en_res = (uint8_t) ((dev->ems_ctl >> 7) & 0x01); + uint32_t low_boundary = (((uint32_t) (dev->ems_ctl & 0x007f)) << 17) + 131072; + ram_bank_t *rb = &(dev->ram_banks[4]); + + addr &= 0x00ffffff; + ems_page = dev->mem_pages[addr >> 14]; + + ep = &dev->ems_pages[ems_page]; + + ret = addr; + + /* First, do any address translation (EMS, low boundary filtering). */ + if ((ems_page < 0x20) && (ems_en == 0x03)) + /* Low EMS pages. */ + ret = addr - ep->virt + ep->phys; + else if ((ems_page >= 0x20) && (ems_page < 0x2a) && (ems_en >= 0x02) && ep->enabled) + /* High EMS pages. */ + ret = addr - ep->virt + ep->phys; + else if (en_res && (addr >= low_boundary)) + /* EMS low boundary. */ + ret = WD76C10_ADDR_INVALID; + + /* Then, do the split. */ + if (rb->enable && (ret >= rb->virt_addr) && (ret < (rb->virt_addr + rb->virt_size))) + ret = ret - rb->virt_addr + rb->phys_addr; + + /* Then, disable the required amount of on-board memory between 128k and 640k if so requested. */ + if ((ret >= dev->mem_top) && (ret < 0x000a0000)) + ret = WD76C10_ADDR_INVALID; + + /* Then, handle the physical memory banks. */ + if (ret >= (mem_size << 10)) + /* The physical memory address is too high or disabled, which is invalid. */ + ret = WD76C10_ADDR_INVALID; + /* Otherwise, map it to the correct bank so the BIOS can auto-size it correctly. */ + else for (uint8_t i = 0; i < 4; i++) { + rb = &(dev->ram_banks[i]); + if (rb->enable && (ret >= rb->virt_addr) && (ret < (rb->virt_addr + rb->virt_size))) { + if (rb->phys_size == 0x00000000) + ret = WD76C10_ADDR_INVALID; + else + ret = ((ret - rb->virt_addr) % rb->phys_size) + rb->phys_addr; + break; + } + } + + return ret; +} + +static uint8_t +wd76c10_read_ram(uint32_t addr, void *priv) +{ + wd76c10_t *dev = (wd76c10_t *) priv; + uint8_t ret = 0xff; + + addr = wd76c10_calc_addr(dev, addr); + + if (addr != WD76C10_ADDR_INVALID) + ret = mem_read_ram(addr, priv); + + return ret; +} + +static uint16_t +wd76c10_read_ramw(uint32_t addr, void *priv) +{ + wd76c10_t *dev = (wd76c10_t *) priv; + uint16_t ret = 0xffff; + + addr = wd76c10_calc_addr(dev, addr); + + if (addr != WD76C10_ADDR_INVALID) + ret = mem_read_ramw(addr, priv); + + return ret; +} + +static void +wd76c10_write_ram(uint32_t addr, uint8_t val, void *priv) +{ + wd76c10_t *dev = (wd76c10_t *) priv; + + addr = wd76c10_calc_addr(dev, addr); + + if (addr != WD76C10_ADDR_INVALID) + mem_write_ram(addr, val, priv); +} + +static void +wd76c10_write_ramw(uint32_t addr, uint16_t val, void *priv) +{ + wd76c10_t *dev = (wd76c10_t *) priv; + + addr = wd76c10_calc_addr(dev, addr); + + if (addr != WD76C10_ADDR_INVALID) + mem_write_ramw(addr, val, priv); +} + +static void +wd76c10_banks_recalc(wd76c10_t *dev) +{ + for (uint8_t i = 0; i < 4; i++) { + ram_bank_t *rb = &(dev->ram_banks[i]); + uint8_t bit = i << 1; + rb->virt_size = bank_sizes[(dev->mem_ctl >> bit) & 0x03]; + bit = i + 12; + rb->enable = (dev->split_sa >> bit) & 0x01; + rb->virt_addr = ((uint32_t) dev->bank_bases[i]) << 17; + } +} + +static void +wd76c10_split_recalc(wd76c10_t *dev) +{ + uint32_t sp_size = (dev->split_sa >> 8) & 0x03; + uint32_t split_size = ((sp_size - 1) * 65536); + ram_bank_t *rb = &(dev->ram_banks[4]); + + if (rb->enable && (rb->virt_size != 0x00000000)) + mem_set_mem_state(rb->virt_addr, rb->virt_size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + rb->virt_addr = ((uint32_t) ((dev->split_sa >> 2) & 0x3f)) << 19; + switch (sp_size) { + case 0x00: + rb->virt_size = 0x00000000; + break; + default: + rb->virt_size = 256 * 1024 + split_size; + break; + } + rb->enable = !!sp_size; + if (rb->enable && (rb->virt_size != 0x00000000)) + mem_set_mem_state(rb->virt_addr, rb->virt_size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); +} + +static void +wd76c10_dis_mem_recalc(wd76c10_t *dev) +{ + uint8_t dis_mem = (uint8_t) ((dev->sh_wp >> 14) & 0x03); + uint32_t mem_top; + + switch (dis_mem) { + case 0x00: + default: + mem_top = 640 * 1024; + break; + case 0x01: + mem_top = 512 * 1024; + break; + case 0x02: + mem_top = 256 * 1024; + break; + case 0x03: + mem_top = 128 * 1024; + break; + } + + dev->mem_top = mem_top; +} + +static void +wd76c10_shadow_ram_do_recalc(uint8_t *new_st, uint8_t *old_st, uint8_t min, uint8_t max, uint32_t addr) +{ + uint32_t base = 0x00000000; + int flags = 0; + + for (uint8_t i = min; i < max; i++) { + if (new_st[i] != old_st[i]) { + old_st[i] = new_st[i]; + base = addr + ((uint32_t) i) * 0x00004000; + flags = (new_st[i] & 0x01) ? MEM_READ_INTERNAL : + ((new_st[i] & 0x04) ? MEM_READ_ROMCS : MEM_READ_EXTERNAL); + flags |= (new_st[i] & 0x02) ? MEM_WRITE_INTERNAL : + ((new_st[i] & 0x04) ? MEM_WRITE_ROMCS : MEM_WRITE_EXTERNAL); + mem_set_mem_state_both(base, 0x00004000, flags); + } + } +} + + +static void +wd76c10_shadow_ram_recalc(wd76c10_t *dev) +{ + uint8_t vbios_states[4] = { 0 }; + uint8_t bios_states[8] = { 0 }; + uint8_t high_bios_states[8] = { 0 }; + uint8_t wp = (uint8_t) ((dev->sh_wp >> 12) & 0x01); + uint8_t shd = (uint8_t) ((dev->sh_wp >> 8) & 0x03); + uint8_t x_mem = (uint8_t) ((dev->sh_wp >> 7) & 0x01); + uint8_t vb_siz = (uint8_t) ((dev->sh_wp >> 4) & 0x03); + uint8_t vb_top = vb_siz + 1; + uint8_t rom_typ = (uint8_t) ((dev->sh_wp >> 2) & 0x03); + + switch (shd) { + case 0x03: + for (uint8_t i = 0; i < vb_top; i++) { + vbios_states[i] |= 0x01; /* Read. */ + if (!wp) + vbios_states[i] |= 0x02; /* Write. */ + } + if (x_mem) { + for (uint8_t i = 2; i < 4; i++) + bios_states[i] |= 0x03; /* Read/write. */ + } + fallthrough; + case 0x01: + for (uint8_t i = 4; i < 8; i++) { + bios_states[i] |= 0x01; /* Read. */ + if (!wp) + bios_states[i] |= 0x02; /* Write. */ + } + break; + case 0x02: + for (uint8_t i = 0; i < 8; i++) { + bios_states[i] |= 0x01; /* Read. */ + if (!wp) + bios_states[i] |= 0x02; /* Write. */ + } + break; + } + + switch (rom_typ) { + case 0x00: + for (uint8_t i = 0; i < 8; i++) { + bios_states[i] |= 0x04; /* CSPROM#. */ + high_bios_states[i] |= 0x04; /* CSPROM#. */ + } + break; + case 0x02: + for (uint8_t i = 0; i < vb_top; i++) + vbios_states[i] |= 0x04; /* CSPROM#. */ + fallthrough; + case 0x01: + for (uint8_t i = 4; i < 8; i++) { + bios_states[i] |= 0x04; /* CSPROM#. */ + high_bios_states[i] |= 0x04; /* CSPROM#. */ + } + break; + } + + wd76c10_shadow_ram_do_recalc(vbios_states, dev->vbios_states, 0, 4, 0x000c0000); + wd76c10_shadow_ram_do_recalc(bios_states, dev->bios_states, 0, 8, 0x000e0000); + + /* This is not shadowed, but there is a CSPROM# (= ROMCS#) toggle. */ + wd76c10_shadow_ram_do_recalc(high_bios_states, dev->high_bios_states, 0, 8, 0x00fe0000); + + flushmmucache_nopc(); +} + +static void +wd76c10_high_mem_wp_recalc(wd76c10_t *dev) +{ + uint8_t hm_wp = (uint8_t) ((dev->sh_wp >> 13) & 0x01); + uint32_t base = ((uint32_t) (dev->hmwpb & 0x00f0)) << 17; + uint32_t size = 0x01000000 - dev->hmwp_base; + + /* ACCESS_NORMAL means both ACCESS_BUS and ACCESS_CPU are set. */ + mem_set_wp(dev->hmwp_base, size, ACCESS_NORMAL, 0); + + size = 0x01000000 - base; + mem_set_wp(base, size, ACCESS_NORMAL, hm_wp); + + dev->hmwp_base = base; +} + +static void +wd76c10_pf_loc_reset(wd76c10_t *dev) +{ + uint32_t base; + + for (uint8_t i = 0x031; i <= 0x03b; i++) { + dev->mem_pages[i] = 0xff; + base = ((uint32_t) i) << 14; + mem_set_mem_state(base, 0x00004000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + } + + /* Re-apply any ROMCS#, etc. flags. */ + wd76c10_shadow_ram_recalc(dev); +} + +static void +wd76c10_pf_loc_recalc(wd76c10_t *dev) +{ + uint8_t pf_loc = (uint8_t) ((dev->ems_ctl >> 13) & 0x03); + uint8_t ems_en = (uint8_t) ((dev->ems_ctl >> 10) & 0x03); + uint8_t ems_page; + uint32_t base; + + for (uint8_t i = (0x031 + pf_loc); i <= (0x037 + pf_loc); i++) { + ems_page = (i - 0x10) & 0xf7; + dev->mem_pages[i] = ems_page; + base = ((uint32_t) i) << 14; + dev->ems_pages[ems_page].virt = base; + if ((ems_en >= 0x02) && dev->ems_pages[ems_page].enabled) + mem_set_mem_state(dev->ems_pages[ems_page].virt, 0x00004000, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } +} + +static void +wd76c10_low_pages_recalc(wd76c10_t *dev) +{ + uint8_t ems_page; + uint32_t base; + + for (uint8_t i = 0x008; i <= 0x027; i++) { + ems_page = i & 0x1f; + dev->mem_pages[i] = ems_page; + base = ((uint32_t) i) << 14; + dev->ems_pages[ems_page].virt = base; + } +} + +static void +wd76c10_ser_par_cs_recalc(wd76c10_t *dev) { - serial_remove(dev->uart[1]); /* Serial B */ - switch ((dev->refresh_control >> 1) & 7) { - case 1: + serial_remove(dev->uart[1]); + switch ((dev->ser_par_cs >> 1) & 0x07) { + case 0x01: serial_setup(dev->uart[1], 0x3f8, 3); break; - case 2: + case 0x02: serial_setup(dev->uart[1], 0x2f8, 3); break; - case 3: + case 0x03: serial_setup(dev->uart[1], 0x3e8, 3); break; - case 4: + case 0x04: serial_setup(dev->uart[1], 0x2e8, 3); break; - default: - break; } - serial_remove(dev->uart[0]); /* Serial A */ - switch ((dev->refresh_control >> 5) & 7) { - case 1: + serial_remove(dev->uart[0]); + switch ((dev->ser_par_cs >> 5) & 0x07) { + case 0x01: serial_setup(dev->uart[0], 0x3f8, 4); break; - case 2: + case 0x02: serial_setup(dev->uart[0], 0x2f8, 4); break; - case 3: + case 0x03: serial_setup(dev->uart[0], 0x3e8, 4); break; - case 4: + case 0x04: serial_setup(dev->uart[0], 0x2e8, 4); break; - default: - break; } - lpt1_remove(); /* LPT */ - switch ((dev->refresh_control >> 9) & 3) { + lpt1_remove(); + switch ((dev->ser_par_cs >> 9) & 0x03) { case 1: lpt1_init(0x3bc); lpt1_irq(7); @@ -155,413 +491,463 @@ wd76c10_refresh_control(wd76c10_t *dev) lpt1_init(0x278); lpt1_irq(7); break; - - default: - 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; - default: - break; - } -} - -static void -wd76c10_disk_chip_select(wd76c10_t *dev) +wd76c10_disk_cs_recalc(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(); + ide_set_base(0, (dev->rtc_disk_cs & 0x0010) ? 0x0170 : 0x01f0); + ide_set_side(0, (dev->rtc_disk_cs & 0x0010) ? 0x0376 : 0x03f6); + if (!(dev->rtc_disk_cs & 0x0002)) + 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) ? FDC_PRIMARY_ADDR : FDC_SECONDARY_ADDR); + fdc_remove(dev->fdc); + if (!(dev->rtc_disk_cs & 0x0001)) + fdc_set_base(dev->fdc, (dev->rtc_disk_cs & 0x0010) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); } static void -wd76c10_shadow_recalc(wd76c10_t *dev) +wd76c10_outb(uint16_t port, uint8_t val, void *priv) { - 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; - default: - break; - } + wd76c10_t *dev = (wd76c10_t *)priv; + uint8_t lk_psw = (uint8_t) ((dev->rtc_disk_cs >> 2) & 0x01); + uint8_t valxor; - 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; - default: + switch (port) { + case 0x0092: + if ((lk_psw && (val & 0x08)) || ((dev->p92 & 0x08) && !(val & 0x08))) + val = (val & 0xf7) | (dev->p92 & 0x08); + + valxor = (dev->p92 ^ val) & 0x08; + dev->p92 = (val & 0x08) | 0xf7; + + if (valxor) + nvr_lock_set(0x38, 0x08, (val & 0x08) ? 0x03 : 0x00, dev->nvr); break; } } static void -wd76c10_write(uint16_t addr, uint16_t val, void *priv) +wd76c10_outw(uint16_t port, uint16_t val, void *priv) { - wd76c10_t *dev = (wd76c10_t *) priv; + wd76c10_t *dev = (wd76c10_t *)priv; + uint8_t inc = (uint8_t) ((dev->ems_ctl >> 15) & 0x01); + uint8_t ems_en; - if (UNLOCKED) { - switch (addr) { - case 0x1072: - dev->clk_control = val; - break; + if (!dev->locked || (port < 0x1072) || (port > 0xf872) || + (port == 0xe072) || (port == 0xe872) || (port == 0xf073)) switch (port) { + case 0x1072: + dev->cpuclk = val; + break; - case 0x1872: - dev->bus_timing_power_down_ctl = val; - break; + case 0x1872: + dev->fpu_ctl = val; + break; - case 0x2072: - dev->refresh_control = val; - wd76c10_refresh_control(dev); - break; + case 0x2072: + dev->ser_par_cs = val; + wd76c10_ser_par_cs_recalc(dev); + break; - case 0x2872: - dev->disk_chip_select = val; - wd76c10_disk_chip_select(dev); - break; + case 0x2872: + dev->rtc_disk_cs = val; + wd76c10_disk_cs_recalc(dev); + break; - case 0x3072: - dev->prog_chip_sel_addr = val; - break; + case 0x3072: + dev->prog_cs = val; + break; - case 0x3872: - dev->non_page_mode_dram_timing = val; - break; + /* TODO: Log this to determine how the BIOS does bank sizing. */ + case 0x3872: + dev->mem_ctl = val; + wd76c10_banks_recalc(dev); + break; - case 0x4072: - dev->mem_control = val; - break; + case 0x4072: + dev->npmdmt = val; + break; - case 0x4872: - dev->bank10staddr = val; - break; + /* A17-A24 */ + case 0x4872: + dev->bank_base_regs[0] = val; + wd76c10_banks_recalc(dev); + break; - case 0x5072: - dev->bank32staddr = val; - break; + /* A17-A24 */ + case 0x5072: + dev->bank_base_regs[1] = val; + wd76c10_banks_recalc(dev); + break; - case 0x5872: - dev->split_addr = val; - wd76c10_split_addr(dev); - break; + case 0x5872: + dev->split_sa = val; + wd76c10_banks_recalc(dev); + wd76c10_split_recalc(dev); + break; - case 0x6072: - dev->shadow_ram = val & 0xffbf; - wd76c10_shadow_recalc(dev); - break; + case 0x6072: + dev->sh_wp = val; + wd76c10_dis_mem_recalc(dev); + wd76c10_pf_loc_reset(dev); + wd76c10_pf_loc_recalc(dev); + wd76c10_low_pages_recalc(dev); + wd76c10_high_mem_wp_recalc(dev); + break; - case 0x6872: - dev->ems_control_low_address_boundry = val & 0xecff; - break; + case 0x6872: + dev->ems_ctl = val; + wd76c10_pf_loc_reset(dev); + wd76c10_pf_loc_recalc(dev); + wd76c10_low_pages_recalc(dev); + break; - case 0x7072: - dev->pmc_output = (val >> 8) & 0x00ff; - break; + case 0x8872: + dev->pmc_in = val; + break; - case 0x7872: - dev->pmc_output = val & 0xff00; - break; + case 0xc072: + dev->hmwpb = val; + wd76c10_high_mem_wp_recalc(dev); + 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; - - default: - break; - } - wd76c10_log("WD76C10: dev->regs[%04x] = %04x\n", addr, val); - } - - switch (addr) { case 0xe072: - dev->ems_page_reg_pointer = val & 0x003f; + dev->ems_pp = val; + dev->ep = (val & 0x3f) % 40; break; case 0xe872: - dev->ems_page_reg = val & 0x8fff; + ems_en = (uint8_t) ((dev->ems_ctl >> 10) & 0x03); + if (ems_en) { + dev->ems_page_regs[dev->ep] = val; + dev->ems_pages[dev->ep].phys = ((uint32_t) (val & 0x0fff)) << 14; + if (dev->ep >= 32) { + dev->ems_pages[dev->ep].enabled = !!(val & 0x8000); + if (ems_en >= 0x02) { + wd76c10_pf_loc_reset(dev); + wd76c10_pf_loc_recalc(dev); + } + } else { + dev->ems_pages[dev->ep].enabled = (ems_en == 0x03); + if (ems_en == 0x03) + wd76c10_low_pages_recalc(dev); + } + } + if (inc) + dev->ep = (dev->ep + 1) % 40; break; case 0xf073: - dev->lock_reg = val & 0x00ff; - LOCK = !(val & 0x00da); + dev->locked = ((val & 0x00ff) != 0x00da); break; - default: + case 0xf872: + flushmmucache(); break; } } -static uint16_t -wd76c10_read(uint16_t addr, void *priv) +static uint8_t +wd76c10_inb(uint16_t port, void *priv) { - const wd76c10_t *dev = (wd76c10_t *) priv; + wd76c10_t *dev = (wd76c10_t *)priv; + uint8_t ret = 0xff; - wd76c10_log("WD76C10: R dev->regs[%04x]\n", addr); - switch (addr) { + switch (port) { + case 0x0092: + ret = (dev->p92 & 0x08) | 0xf7; + break; + } + + return ret; +} + +static uint16_t +wd76c10_inw(uint16_t port, void *priv) +{ + wd76c10_t *dev = (wd76c10_t *)priv; + uint8_t inc = (uint8_t) ((dev->ems_ctl >> 15) & 0x01); + uint16_t ret = 0xffff; + + wd76c10_log("WD76C10: R dev->regs[%04x]\n", port); + + if (!dev->locked || (port < 0x1072) || (port > 0xf872) || + (port == 0xe072) || (port == 0xe872) || (port == 0xf073)) switch (port) { case 0x1072: - return dev->clk_control; + ret = dev->cpuclk; + break; case 0x1872: - return dev->bus_timing_power_down_ctl; + ret = dev->fpu_ctl; + break; case 0x2072: - return dev->refresh_control; + ret = dev->ser_par_cs; + break; case 0x2872: - return dev->disk_chip_select; + ret = dev->rtc_disk_cs; + break; case 0x3072: - return dev->prog_chip_sel_addr; + ret = dev->prog_cs; + break; case 0x3872: - return dev->non_page_mode_dram_timing; + ret = dev->mem_ctl; + break; case 0x4072: - return dev->mem_control; + ret = dev->npmdmt; + break; case 0x4872: - return dev->bank10staddr; + ret = dev->bank_base_regs[0]; + break; case 0x5072: - return dev->bank32staddr; + ret = dev->bank_base_regs[1]; + break; case 0x5872: - return dev->split_addr; + ret = dev->split_sa; + break; case 0x6072: - return dev->shadow_ram; + ret = dev->sh_wp; + break; case 0x6872: - return dev->ems_control_low_address_boundry; - - case 0x7072: - return (dev->pmc_output << 8) & 0xff00; - - case 0x7872: - return (dev->pmc_output) & 0xff00; - - case 0x8072: - return dev->pmc_timer; + ret = dev->ems_ctl; + break; case 0x8872: - return dev->pmc_input; - - case 0x9072: - return dev->nmi_status; - - case 0x9872: - return dev->diagnostic; - - case 0xa072: - return dev->delay_line; + ret = dev->pmc_in; + break; case 0xb872: - return (inb(0x040b) << 8) | inb(0x04d6); + ret = dma[0].mode; + ret |= (((uint16_t) dma[1].mode) << 8); + break; - case 0xc872: - return dev->pmc_interrupt; + case 0xc072: + ret = dev->hmwpb; + break; case 0xd072: - return dev->port_shadow; + ret = (serial_read(0x0002, dev->uart[0]) & 0xc0) << 8; + ret |= (serial_read(0x0002, dev->uart[1]) & 0xc0) << 6; + ret |= (lpt_read_port(0, 0x0002) & 0x0f) << 8; + ret |= lpt_read_port(0, 0x0000); + break; case 0xe072: - return dev->ems_page_reg_pointer; + ret = (dev->ems_pp & 0xffc0) | dev->ep; + break; case 0xe872: - return dev->ems_page_reg; + ret = dev->ems_page_regs[dev->ep]; + if (inc) + dev->ep = (dev->ep + 1) % 40; + break; case 0xfc72: - return 0x0ff0; - - default: - return 0xffff; + ret = ((lpt_read_status(0) & 0x20) >> 2); + ret |= (((uint16_t) dma_m) << 4); + ret |= dev->toggle; + dev->toggle ^= 0x8000; + break; } + + return ret; } static void wd76c10_close(void *priv) { - wd76c10_t *dev = (wd76c10_t *) priv; + wd76c10_t *dev = (wd76c10_t *)priv; free(dev); } -static void * -wd76c10_init(UNUSED(const device_t *info)) + +static void +wd76c10_reset(void *priv) { - wd76c10_t *dev = (wd76c10_t *) malloc(sizeof(wd76c10_t)); - memset(dev, 0, sizeof(wd76c10_t)); + wd76c10_t *dev = (wd76c10_t *)priv; + + dev->locked = 1; + dev->toggle = 0; + + dev->p92 = 0xf7; + + dev->cpuclk = 0x1000; + dev->fpu_ctl = 0x00ca; + dev->mem_ctl = 0x0000; + dev->bank_base_regs[0] = 0x0000; + dev->bank_base_regs[1] = 0x0000; + dev->split_sa = 0x0000; + dev->sh_wp = 0x0000; + dev->hmwpb = 0x0000; + dev->npmdmt = 0x0000; + dev->ems_ctl = 0x0000; + dev->ems_pp = 0x0000; + dev->ser_par_cs = 0x0000; + dev->rtc_disk_cs = 0x0000; + + for (uint8_t i = 0; i < 40; i++) { + dev->ems_page_regs[i] = 0x0000; + dev->ems_pages[i].enabled = 0; + dev->ems_pages[i].phys = 0x00000000; + } + + nvr_lock_set(0x38, 0x08, 0x00, dev->nvr); + + wd76c10_banks_recalc(dev); + wd76c10_split_recalc(dev); + wd76c10_dis_mem_recalc(dev); + wd76c10_high_mem_wp_recalc(dev); + wd76c10_pf_loc_reset(dev); + wd76c10_pf_loc_recalc(dev); + wd76c10_low_pages_recalc(dev); + wd76c10_ser_par_cs_recalc(dev); + wd76c10_disk_cs_recalc(dev); +} + + +static void * +wd76c10_init(const device_t *info) +{ + wd76c10_t *dev = (wd76c10_t *) calloc(1, sizeof(wd76c10_t)); + uint32_t total_mem = mem_size << 10; + uint32_t accum_mem = 0x00000000; + ram_bank_t *rb; + + /* Calculate the physical RAM banks. */ + for (uint8_t i = 0; i < 4; i++) { + rb = &(dev->ram_banks[i]); + uint32_t size = 0x00000000; + for (int8_t j = 3; j >= 0; j--) { + uint32_t *bs = &(bank_sizes[j]); + if (*bs <= total_mem) { + size = *bs; + break; + } + } + if (size != 0x00000000) { + rb->phys_addr = accum_mem; + rb->phys_size = size; + total_mem -= size; + accum_mem += size; + } + } + + rb = &(dev->ram_banks[4]); + rb->phys_addr = 0x000a0000; + rb->phys_size = 0x00060000; + + memset(dev->mem_pages, 0xff, sizeof(dev->mem_pages)); + for (uint8_t i = 0x008; i < 0x01f; i++) + dev->mem_pages[i] = i; + for (uint8_t i = 0x020; i < 0x027; i++) + dev->mem_pages[i] = i - 0x20; 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); + dev->nvr = device_add(&amstrad_megapc_nvr_device); + dev->uart[0] = device_add_inst(&ns16450_device, 1); + dev->uart[1] = device_add_inst(&ns16450_device, 2); + dev->fdc = device_add(&fdc_at_device); device_add(&ide_isa_device); - /* Lock Configuration */ - LOCK = 1; + wd76c10_reset(dev); + + /* Password Lock */ + io_sethandler(0x0092, 1, wd76c10_inb, NULL, NULL, wd76c10_outb, NULL, NULL, dev); /* Clock Control */ - io_sethandler(0x1072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + io_sethandler(0x1072, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); - /* Bus Timing & Power Down Control */ - io_sethandler(0x1872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + /* FPU Bus Timing & Power Down Control */ + io_sethandler(0x1872, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); - /* Refresh Control(Serial & Parallel) */ - io_sethandler(0x2072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + /* Refresh Control, Serial and Parallel Chip Selects */ + io_sethandler(0x2072, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); - /* Disk Chip Select */ - io_sethandler(0x2872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + /* RTC, PVGA, 80287 Timing, and Disk Chip Selects */ + io_sethandler(0x2872, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); - /* Programmable Chip Select Address(Needs more further examination!) */ - io_sethandler(0x3072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + /* Programmable Chip Select Address */ + io_sethandler(0x3072, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); + + /* Memory Control */ + io_sethandler(0x3872, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); + + /* Non-page Mode DRAM Memory Timing */ + io_sethandler(0x4072, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); /* Bank 1 & 0 Start Address */ - io_sethandler(0x4872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + io_sethandler(0x4872, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); /* Bank 3 & 2 Start Address */ - io_sethandler(0x5072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + io_sethandler(0x5072, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); /* Split Address */ - io_sethandler(0x5872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + io_sethandler(0x5872, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); - /* EMS Control & EMS Low level boundry */ - io_sethandler(0x6072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + /* RAM Shadow And Write Protect */ + io_sethandler(0x6072, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); - /* EMS Control & EMS Low level boundry */ - io_sethandler(0x6872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + /* EMS Control And Lower EMS Boundary */ + io_sethandler(0x6872, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); - /* PMC Output */ - io_sethandler(0x7072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + /* PMC Inputs */ + io_sethandler(0x8872, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); - /* PMC Output */ - io_sethandler(0x7872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + /* DMA Mode Shadow Register */ + io_sethandler(0xb872, 1, NULL, wd76c10_inw, NULL, NULL, NULL, NULL, dev); - /* PMC Status */ - io_sethandler(0x8072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + /* High Memory Write Protect Boundry */ + io_sethandler(0xc072, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, 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); + /* Shadow Register */ + io_sethandler(0xd072, 1, NULL, wd76c10_inw, NULL, NULL, NULL, NULL, dev); /* EMS Page Register Pointer */ - io_sethandler(0xe072, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + io_sethandler(0xe072, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, NULL, dev); /* EMS Page Register */ - io_sethandler(0xe872, 1, NULL, wd76c10_read, NULL, NULL, wd76c10_write, NULL, dev); + io_sethandler(0xe872, 1, NULL, wd76c10_inw, NULL, NULL, wd76c10_outw, 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); + io_sethandler(0xf073, 1, NULL, NULL, NULL, NULL, wd76c10_outw, NULL, dev); /* Cache Flush */ - io_sethandler(0xf872, 1, NULL, wd76c10_read, NULL, NULL, NULL, NULL, dev); + io_sethandler(0xf872, 1, NULL, NULL, NULL, NULL, wd76c10_outw, NULL, dev); + + /* Lock Status */ + io_sethandler(0xfc72, 1, NULL, wd76c10_inw, NULL, NULL, NULL, NULL, dev); dma_ext_mode_init(); - wd76c10_shadow_recalc(dev); - wd76c10_refresh_control(dev); - wd76c10_disk_chip_select(dev); + mem_mapping_add(&dev->ram_mapping, + 0x00000000, + (mem_size + 384) << 10, + wd76c10_read_ram, + wd76c10_read_ramw, + NULL, + wd76c10_write_ram, + wd76c10_write_ramw, + NULL, + ram, + MEM_MAPPING_INTERNAL, + dev); + mem_mapping_disable(&ram_low_mapping); + mem_mapping_disable(&ram_mid_mapping); + mem_mapping_disable(&ram_high_mapping); + mem_mapping_enable(&dev->ram_mapping); + return dev; } diff --git a/src/config.c b/src/config.c index c973abf23..3e4fd7222 100644 --- a/src/config.c +++ b/src/config.c @@ -139,8 +139,6 @@ load_general(void) rctrl_is_lalt = ini_section_get_int(cat, "rctrl_is_lalt", 0); update_icons = ini_section_get_int(cat, "update_icons", 1); - status_icons_fullscreen = !!ini_section_get_int(cat, "status_icons_fullscreen", 0); - window_remember = ini_section_get_int(cat, "window_remember", 0); if (!window_remember && !(vid_resize & 2)) @@ -244,25 +242,81 @@ load_machine(void) { ini_section_t cat = ini_find_section(config, "Machine"); const char *p; + const char *migrate_from = NULL; int c; int i; + int j; int speed; double multi; p = ini_section_get_string(cat, "machine", NULL); - if (p != NULL) - machine = machine_get_machine_from_internal_name(p); - else + if (p != NULL) { + migrate_from = p; + /* Migrate renamed machines. */ + if (!strcmp(p, "430nx")) + machine = machine_get_machine_from_internal_name("586ip"); + else if (!strcmp(p, "586mc1")) + machine = machine_get_machine_from_internal_name("586is"); + else { + machine = machine_get_machine_from_internal_name(p); + migrate_from = NULL; + } + } else machine = 0; if (machine >= machine_count()) machine = machine_count() - 1; + /* Copy NVR files when migrating a machine to a new internal name. */ + if (migrate_from) { + char old_fn[256]; + strcpy(old_fn, migrate_from); + strcat(old_fn, "."); + c = strlen(old_fn); + char new_fn[256]; + strcpy(new_fn, machines[machine].internal_name); + strcat(new_fn, "."); + i = strlen(new_fn); + + /* Iterate through NVR files. */ + DIR *dirp = opendir(nvr_path(".")); + if (dirp) { + struct dirent *entry; + while ((entry = readdir(dirp))) { + /* Check if this file corresponds to the old name. */ + if (strncmp(entry->d_name, old_fn, c)) + continue; + + /* Add extension to the new name. */ + strcpy(&new_fn[i], &entry->d_name[c]); + + /* Only copy if a file with the new name doesn't already exist. */ + FILE *g = nvr_fopen(new_fn, "rb"); + if (!g) { + FILE *f = nvr_fopen(entry->d_name, "rb"); + g = nvr_fopen(new_fn, "wb"); + + uint8_t buf[4096]; + while ((j = fread(buf, 1, sizeof(buf), f))) + fwrite(buf, 1, j, g); + + fclose(f); + } + fclose(g); + } + } + } + cpu_override = ini_section_get_int(cat, "cpu_override", 0); cpu_f = NULL; p = ini_section_get_string(cat, "cpu_family", NULL); if (p) { - cpu_f = cpu_get_family(p); + /* Migrate CPU family changes. */ + if ((!strcmp(machines[machine].internal_name, "deskpro386") || + !strcmp(machines[machine].internal_name, "deskpro386_05_1988"))) + cpu_f = cpu_get_family("i386dx_deskpro386"); + else + cpu_f = cpu_get_family(p); if (cpu_f && !cpu_family_is_eligible(cpu_f, machine)) /* only honor eligible families */ cpu_f = NULL; @@ -721,6 +775,7 @@ static void load_storage_controllers(void) { ini_section_t cat = ini_find_section(config, "Storage controllers"); + ini_section_t migration_cat; char *p; char temp[512]; int c; @@ -754,17 +809,16 @@ load_storage_controllers(void) } free_p = 1; } - if (!strcmp(p, "mfm_xt")) - hdc_current = hdc_get_from_internal_name("st506_xt"); - else if (!strcmp(p, "mfm_xt_dtc5150x")) - hdc_current = hdc_get_from_internal_name("st506_xt_dtc5150x"); - else if (!strcmp(p, "mfm_at")) - hdc_current = hdc_get_from_internal_name("st506_at"); - else if (!strcmp(p, "vlb_isa")) - hdc_current = hdc_get_from_internal_name("ide_vlb"); - else if (!strcmp(p, "vlb_isa_2ch")) - hdc_current = hdc_get_from_internal_name("ide_vlb_2ch"); - else + /* Migrate renamed and merged cards. */ + if (!strcmp(p, "xtide_plus")) { + hdc_current = hdc_get_from_internal_name("xtide"); + migration_cat = ini_find_or_create_section(config, "PC/XT XTIDE"); + ini_section_set_string(migration_cat, "bios", "xt_plus"); + } else if (!strcmp(p, "xtide_at_386")) { + hdc_current = hdc_get_from_internal_name("xtide_at"); + migration_cat = ini_find_or_create_section(config, "PC/AT XTIDE"); + ini_section_set_string(migration_cat, "bios", "at_386"); + } else hdc_current = hdc_get_from_internal_name(p); if (free_p) { @@ -1533,7 +1587,8 @@ load_other_peripherals(void) void config_load(void) { - int i; + int i; + ini_section_t c; config_log("Loading config file '%s'..\n", cfg_path); @@ -1623,6 +1678,23 @@ config_load(void) load_other_removable_devices(); /* Other removable devices */ load_other_peripherals(); /* Other peripherals */ + /* Migrate renamed device configurations. */ + c = ini_find_section(config, "MDA"); + if (c != NULL) + ini_rename_section(c, "IBM MDA"); + c = ini_find_section(config, "CGA"); + if (c != NULL) + ini_rename_section(c, "IBM CGA"); + c = ini_find_section(config, "EGA"); + if (c != NULL) + ini_rename_section(c, "IBM EGA"); + c = ini_find_section(config, "3DFX Voodoo Graphics"); + if (c != NULL) + ini_rename_section(c, "3Dfx Voodoo Graphics"); + c = ini_find_section(config, "3dfx Voodoo Banshee"); + if (c != NULL) + ini_rename_section(c, "3Dfx Voodoo Banshee"); + /* Mark the configuration as changed. */ config_changed = 1; @@ -1785,11 +1857,6 @@ save_general(void) else ini_section_delete_var(cat, "open_dir_usr_path"); - if (status_icons_fullscreen) - ini_section_set_int(cat, "status_icons_fullscreen", status_icons_fullscreen); - else - ini_section_delete_var(cat, "status_icons_fullscreen"); - if (video_framerate != -1) ini_section_set_int(cat, "video_gl_framerate", video_framerate); else @@ -1846,11 +1913,6 @@ save_machine(void) { ini_section_t cat = ini_find_or_create_section(config, "Machine"); const char *p; - int c; - int i = 0; - int legacy_mfg; - int legacy_cpu = -1; - int closest_legacy_cpu = -1; p = machine_get_internal_name(); ini_section_set_string(cat, "machine", p); @@ -1867,57 +1929,6 @@ save_machine(void) ini_section_delete_var(cat, "cpu_manufacturer"); ini_section_delete_var(cat, "cpu"); - /* Look for a machine entry on the legacy table. */ - c = 0; - while (cpu_legacy_table[c].machine) { - if (!strcmp(p, cpu_legacy_table[c].machine)) - break; - c++; - } - if (cpu_legacy_table[c].machine) { - /* Look for a corresponding CPU entry. */ - const cpu_legacy_table_t *legacy_table_entry; - for (legacy_mfg = 0; legacy_mfg < 4; legacy_mfg++) { - if (!cpu_legacy_table[c].tables[legacy_mfg]) - continue; - - i = 0; - while (cpu_legacy_table[c].tables[legacy_mfg][i].family) { - legacy_table_entry = &cpu_legacy_table[c].tables[legacy_mfg][i]; - - /* Match the family name, speed and multiplier. */ - if (!strcmp(cpu_f->internal_name, legacy_table_entry->family)) { - if ((legacy_table_entry->rspeed == cpu_f->cpus[cpu].rspeed) && - (legacy_table_entry->multi == cpu_f->cpus[cpu].multi)) { - /* Exact speed/multiplier match. */ - legacy_cpu = i; - break; - } else if ((legacy_table_entry->rspeed >= cpu_f->cpus[cpu].rspeed) && - (closest_legacy_cpu == -1)) - /* Closest speed match. */ - closest_legacy_cpu = i; - } - - i++; - } - - /* Use the closest speed match if no exact match was found. */ - if ((legacy_cpu == -1) && (closest_legacy_cpu > -1)) { - legacy_cpu = closest_legacy_cpu; - break; - } else if (legacy_cpu > -1) /* exact match found */ - break; - } - - /* Set legacy values if a match was found. */ - if (legacy_cpu > -1) { - if (legacy_mfg) - ini_section_set_int(cat, "cpu_manufacturer", legacy_mfg); - if (legacy_cpu) - ini_section_set_int(cat, "cpu", legacy_cpu); - } - } - if (cpu_waitstates == 0) ini_section_delete_var(cat, "cpu_waitstates"); else diff --git a/src/cpu/386.c b/src/cpu/386.c index 295f94056..ad310d31e 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -25,6 +25,7 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/machine.h> +#include <86box/plat_fallthrough.h> #include <86box/gdbstub.h> #ifndef OPS_286_386 # define OPS_286_386 @@ -240,6 +241,7 @@ exec386_2386(int32_t cycs) cycdiff = 0; oldcyc = cycles; while (cycdiff < cycle_period) { + int ins_fetch_fault = 0; ins_cycles = cycles; #ifndef USE_NEW_DYNAREC @@ -259,6 +261,13 @@ exec386_2386(int32_t cycs) fetchdat = fastreadl_fetch(cs + cpu_state.pc); ol = opcode_length[fetchdat & 0xff]; CHECK_READ_CS(MIN(ol, 4)); + ins_fetch_fault = cpu_386_check_instruction_fault(); + + /* Breakpoint fault has priority over other faults. */ + if (ins_fetch_fault) { + ins_fetch_fault = 0; + cpu_state.abrt = 1; + } if (!cpu_state.abrt) { #ifdef ENABLE_386_LOG @@ -267,10 +276,11 @@ exec386_2386(int32_t cycs) #endif opcode = fetchdat & 0xFF; fetchdat >>= 8; - trap = cpu_state.flags & T_FLAG; + trap |= !!(cpu_state.flags & T_FLAG); cpu_state.pc++; - x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); + cpu_state.eflags &= ~(RF_FLAG); + x86_2386_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); if (x86_was_reset) break; } @@ -311,7 +321,8 @@ exec386_2386(int32_t cycs) } } else if (trap) { flags_rebuild(); - dr[6] |= (trap == 2) ? 0x8000 : 0x4000; + if (trap & 2) dr[6] |= 0x8000; + if (trap & 1) dr[6] |= 0x4000; trap = 0; #ifndef USE_NEW_DYNAREC oldcs = CS; diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index 60ecd8954..0abf8e936 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -80,6 +80,7 @@ int smm_in_hlt = 0; int smi_block = 0; int prefetch_prefixes = 0; +int rf_flag_no_clear = 0; int tempc; int oldcpl; @@ -119,6 +120,53 @@ int opcode_length[256] = { 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 3, /* 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2, 1, 1, 1, 1, /* 0xex */ 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 3, 3 }; /* 0xfx */ +/* 0 = no, 1 = always, 2 = depends on second opcode, 3 = depends on mod/rm */ +int lock_legal[256] = { 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 2, /* 0x0x */ + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, /* 0x1x */ + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, /* 0x2x */ + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x3x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x4x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x5x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x6x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x7x */ + 3, 3, 3, 3, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x8x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xax */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xbx */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xcx */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xdx */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xex */ + 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 3, 3 }; /* 0xfx */ + +int lock_legal_0f[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x0x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x1x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x2x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x3x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x4x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x5x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x6x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x7x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x8x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9x */ + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, /* 0xax */ + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, /* 0xbx */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xcx */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xdx */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xex */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* 0xfx */ + +/* (modrm >> 3) & 0x07 */ +int lock_legal_ba[8] = { 0, 0, 0, 0, 1, 1, 1, 1 }; + +/* Also applies to 81, 82, and 83 */ +int lock_legal_80[8] = { 1, 1, 1, 1, 1, 1, 1, 0 }; + +/* Also applies to F7 */ +int lock_legal_f6[8] = { 0, 0, 1, 1, 0, 0, 0, 0 }; + +/* Also applies to FF */ +int lock_legal_fe[8] = { 1, 1, 0, 0, 0, 0, 0, 0 }; + uint32_t addr64; uint32_t addr64_2; uint32_t addr64a[8]; @@ -127,9 +175,9 @@ uint32_t addr64a_2[8]; static pc_timer_t *cpu_fast_off_timer = NULL; static double cpu_fast_off_period = 0.0; -#define AMD_SYSCALL_EIP (msr.star & 0xFFFFFFFF) -#define AMD_SYSCALL_SB ((msr.star >> 32) & 0xFFFF) -#define AMD_SYSRET_SB ((msr.star >> 48) & 0xFFFF) +#define AMD_SYSCALL_EIP (msr.amd_star & 0xFFFFFFFF) +#define AMD_SYSCALL_SB ((msr.amd_star >> 32) & 0xFFFF) +#define AMD_SYSRET_SB ((msr.amd_star >> 48) & 0xFFFF) /* These #define's and enum have been borrowed from Bochs. */ /* SMM feature masks */ @@ -1411,7 +1459,7 @@ x86_int(int num) cpu_state.pc = cpu_state.oldpc; if (msw & 1) - is486 ? pmodeint(num, 0) : pmodeint_2386(num, 0); + cpu_use_exec ? pmodeint(num, 0) : pmodeint_2386(num, 0); else { addr = (num << 2) + idt.base; @@ -1444,7 +1492,7 @@ x86_int(int num) oxpc = cpu_state.pc; #endif cpu_state.pc = readmemw(0, addr); - is486 ? loadcs(readmemw(0, addr + 2)) : loadcs_2386(readmemw(0, addr + 2)); + cpu_use_exec ? loadcs(readmemw(0, addr + 2)) : loadcs_2386(readmemw(0, addr + 2)); } } @@ -1461,7 +1509,7 @@ x86_int_sw(int num) cycles -= timing_int; if (msw & 1) - is486 ? pmodeint(num, 1) : pmodeint_2386(num, 1); + cpu_use_exec ? pmodeint(num, 1) : pmodeint_2386(num, 1); else { addr = (num << 2) + idt.base; @@ -1486,12 +1534,15 @@ x86_int_sw(int num) oxpc = cpu_state.pc; #endif cpu_state.pc = readmemw(0, addr); - is486 ? loadcs(readmemw(0, addr + 2)) : loadcs_2386(readmemw(0, addr + 2)); + cpu_use_exec ? loadcs(readmemw(0, addr + 2)) : loadcs_2386(readmemw(0, addr + 2)); cycles -= timing_int_rm; } } - trap = 0; + if (cpu_use_exec) + trap = 0; + else + trap &= ~1; CPU_BLOCK_END(); } @@ -1528,13 +1579,16 @@ x86_int_sw_rm(int num) cpu_state.eflags &= ~VIF_FLAG; cpu_state.flags &= ~T_FLAG; cpu_state.pc = new_pc; - is486 ? loadcs(new_cs) : loadcs_2386(new_cs); + cpu_use_exec ? loadcs(new_cs) : loadcs_2386(new_cs); #ifndef USE_NEW_DYNAREC oxpc = cpu_state.pc; #endif cycles -= timing_int_rm; - trap = 0; + if (cpu_use_exec) + trap = 0; + else + trap &= ~1; CPU_BLOCK_END(); return 0; @@ -1551,6 +1605,13 @@ checkio(uint32_t port, int mask) { uint32_t t; + if (!(tr.access & 0x08)) { + if ((CPL) > (IOPL)) + return 1; + + return 0; + } + cpl_override = 1; t = readmemw(tr.base, 0x66); @@ -1655,6 +1716,37 @@ cpu_386_flags_rebuild(void) flags_rebuild(); } +extern uint64_t mmutranslate_noabrt_2386(uint32_t addr, int rw); +int +cpu_386_check_instruction_fault(void) +{ + int i = 0; + int fault = 0; + /* Report no fault if RF is set. */ + if (cpu_state.eflags & RF_FLAG) + return 0; + + /* Make sure breakpoints are enabled. */ + if (!(dr[7] & 0xFF)) + return 0; + + for (i = 0; i < 4; i++) { + int breakpoint_enabled = !!(dr[7] & (0x3 << (2 * i))) && !(dr[7] & (0x30000 << (4 * i))); + uint32_t translated_addr = 0xffffffff; + if (!breakpoint_enabled) + continue; + + translated_addr = dr[i]; + + if ((cs + cpu_state.pc) == (uint32_t)translated_addr) { + dr[6] |= (1 << i); + fault = 1; + } + } + + return fault; +} + int sysenter(uint32_t fetchdat) { diff --git a/src/cpu/386_common.h b/src/cpu/386_common.h index 22fbd4bff..a98a3e930 100644 --- a/src/cpu/386_common.h +++ b/src/cpu/386_common.h @@ -225,19 +225,37 @@ int checkio(uint32_t port, int mask); static __inline uint8_t fastreadb(uint32_t a) { - return readmembl_2386(a); + uint8_t ret; + read_type = 1; + ret = readmembl_2386(a); + read_type = 4; + if (cpu_state.abrt) + return 0; + return ret; } static __inline uint16_t fastreadw(uint32_t a) { - return readmemwl_2386(a); + uint16_t ret; + read_type = 1; + ret = readmemwl_2386(a); + read_type = 4; + if (cpu_state.abrt) + return 0; + return ret; } static __inline uint32_t fastreadl(uint32_t a) { - return readmemll_2386(a); + uint32_t ret; + read_type = 1; + ret = readmemll_2386(a); + read_type = 4; + if (cpu_state.abrt) + return 0; + return ret; } #else static __inline uint8_t @@ -342,31 +360,41 @@ extern int opcode_length[256]; static __inline uint16_t fastreadw_fetch(uint32_t a) { - uint16_t val; + uint16_t ret; if ((a & 0xFFF) > 0xFFE) { - val = fastreadb(a); - if (opcode_length[val & 0xff] > 1) - val |= ((uint16_t) fastreadb(a + 1) << 8); - return val; + ret = fastreadb(a); + if (!cpu_state.abrt && (opcode_length[ret & 0xff] > 1)) + ret |= ((uint16_t) fastreadb(a + 1) << 8); + } else if (cpu_state.abrt) + ret = 0; + else { + read_type = 1; + ret = readmemwl_2386(a); + read_type = 4; } - return readmemwl_2386(a); + return ret; } static __inline uint32_t fastreadl_fetch(uint32_t a) { - uint32_t val; + uint32_t ret; if (cpu_16bitbus || ((a & 0xFFF) > 0xFFC)) { - val = fastreadw_fetch(a); - if (opcode_length[val & 0xff] > 2) - val |= ((uint32_t) fastreadw(a + 2) << 16); - return val; + ret = fastreadw_fetch(a); + if (!cpu_state.abrt && (opcode_length[ret & 0xff] > 2)) + ret |= ((uint32_t) fastreadw(a + 2) << 16); + } else if (cpu_state.abrt) + ret = 0; + else { + read_type = 1; + ret = readmemll_2386(a); + read_type = 4; } - return readmemll_2386(a); + return ret; } #else static __inline uint16_t @@ -674,3 +702,8 @@ seteaq(uint64_t v) cpu_state.pc += 2 #endif + +/* Resume Flag handling. */ +extern int rf_flag_no_clear; + +int cpu_386_check_instruction_fault(void); \ No newline at end of file diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index e132c0300..c96e3420d 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -48,6 +48,7 @@ #define CPU_BLOCK_END() cpu_block_end = 1 +int cpu_override_dynarec = 0; int inrecomp = 0; int cpu_block_end = 0; int cpu_end_block_after_ins = 0; @@ -718,7 +719,7 @@ exec386_dynarec(int32_t cycs) cycles_old = cycles; oldtsc = tsc; tsc_old = tsc; - if (!CACHE_ON()) /*Interpret block*/ + if ((!CACHE_ON()) || cpu_override_dynarec) /*Interpret block*/ { exec386_dynarec_int(); } else { diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index 8a0f4cd5a..3e0d191f2 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -181,8 +181,16 @@ extern void x386_dynarec_log(const char *fmt, ...); #ifndef OPS_286_386 # include "x86_ops_cyrix.h" #endif -#include "x86_ops_flag.h" -#include "x86_ops_fpu.h" +#ifdef OPS_286_386 +# include "x86_ops_flag_2386.h" +#else +# include "x86_ops_flag.h" +#endif +#ifdef OPS_286_386 +# include "x86_ops_fpu_2386.h" +#else +# include "x86_ops_fpu.h" +#endif #include "x86_ops_inc_dec.h" #include "x86_ops_int.h" #include "x86_ops_io.h" @@ -200,7 +208,11 @@ extern void x386_dynarec_log(const char *fmt, ...); # include "x86_ops_mmx_shift.h" #endif #include "x86_ops_mov.h" -#include "x86_ops_mov_ctrl.h" +#ifdef OPS_286_386 +# include "x86_ops_mov_ctrl_2386.h" +#else +# include "x86_ops_mov_ctrl.h" +#endif #include "x86_ops_mov_seg.h" #include "x86_ops_movx.h" #ifndef OPS_286_386 @@ -208,7 +220,11 @@ extern void x386_dynarec_log(const char *fmt, ...); #endif #include "x86_ops_mul.h" #include "x86_ops_pmode.h" -#include "x86_ops_prefix.h" +#ifdef OPS_286_386 +# include "x86_ops_prefix_2386.h" +#else +# include "x86_ops_prefix.h" +#endif #ifdef IS_DYNAREC # include "x86_ops_rep_dyn.h" #else @@ -218,7 +234,11 @@ extern void x386_dynarec_log(const char *fmt, ...); # include "x86_ops_rep.h" # endif #endif -#include "x86_ops_ret.h" +#ifdef OPS_286_386 +# include "x86_ops_ret_2386.h" +#else +# include "x86_ops_ret.h" +#endif #include "x86_ops_set.h" #include "x86_ops_stack.h" #ifdef OPS_286_386 @@ -629,7 +649,7 @@ const OpFn OP_TABLE(386_0f)[1024] = { // clang-format off /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -644,14 +664,14 @@ const OpFn OP_TABLE(386_0f)[1024] = { /*a0*/ opPUSH_FS_w, opPOP_FS_w, ILLEGAL, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, /*b0*/ ILLEGAL, ILLEGAL, opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, -/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*32-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ opMOV_b_r_a16, opMOV_l_r_a16, opMOV_r_b_a16, opMOV_r_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -666,14 +686,14 @@ const OpFn OP_TABLE(386_0f)[1024] = { /*a0*/ opPUSH_FS_l, opPOP_FS_l, ILLEGAL, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, /*b0*/ ILLEGAL, ILLEGAL, opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, -/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*16-bit data, 32-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ opMOV_b_r_a32, opMOV_w_r_a32, opMOV_r_b_a32, opMOV_r_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -688,14 +708,14 @@ const OpFn OP_TABLE(386_0f)[1024] = { /*a0*/ opPUSH_FS_w, opPOP_FS_w, ILLEGAL, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, /*b0*/ ILLEGAL, ILLEGAL, opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, -/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*32-bit data, 32-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ opMOV_b_r_a32, opMOV_l_r_a32, opMOV_r_b_a32, opMOV_r_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -710,7 +730,7 @@ const OpFn OP_TABLE(386_0f)[1024] = { /*a0*/ opPUSH_FS_l, opPOP_FS_l, ILLEGAL, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, /*b0*/ ILLEGAL, ILLEGAL, opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, -/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 3572f2c9f..90563d9ab 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -563,9 +563,10 @@ reset_808x(int hard) _opseg[3] = &cpu_state.seg_ds; pfq_size = (is8086) ? 6 : 4; - pfq_clear(); } + pfq_clear(); + load_cs(0xFFFF); cpu_state.pc = 0; if (is_nec) @@ -1222,34 +1223,48 @@ static void add(int bits) { int size_mask = (1 << bits) - 1; + int special_case = 0; + uint32_t temp_src = cpu_src; + + if ((cpu_alu_op == 2) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG)) + special_case = 1; cpu_data = cpu_dest + cpu_src; + if ((cpu_alu_op == 2) && (cpu_state.flags & C_FLAG)) + cpu_src--; set_apzs(bits); set_of_add(bits); /* Anything - FF with carry on is basically anything + 0x100: value stays unchanged but carry goes on. */ - if ((cpu_alu_op == 2) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG)) + if (special_case) cpu_state.flags |= C_FLAG; else - set_cf((cpu_src & size_mask) > (cpu_data & size_mask)); + set_cf((temp_src & size_mask) > (cpu_data & size_mask)); } static void sub(int bits) { int size_mask = (1 << bits) - 1; + int special_case = 0; + uint32_t temp_src = cpu_src; + + if ((cpu_alu_op == 3) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG)) + special_case = 1; cpu_data = cpu_dest - cpu_src; + if ((cpu_alu_op == 3) && (cpu_state.flags & C_FLAG)) + cpu_src--; set_apzs(bits); set_of_sub(bits); /* Anything - FF with carry on is basically anything - 0x100: value stays unchanged but carry goes on. */ - if ((cpu_alu_op == 3) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG)) + if (special_case) cpu_state.flags |= C_FLAG; else - set_cf((cpu_src & size_mask) > (cpu_dest & size_mask)); + set_cf((temp_src & size_mask) > (cpu_dest & size_mask)); } static void diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 5d3bbea34..6b0dc4cb9 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -55,27 +55,31 @@ #define CCR3_NMI_EN (1 << 1) enum { - CPUID_FPU = (1 << 0), - CPUID_VME = (1 << 1), - CPUID_PSE = (1 << 3), - CPUID_TSC = (1 << 4), - CPUID_MSR = (1 << 5), - CPUID_PAE = (1 << 6), - CPUID_MCE = (1 << 7), - CPUID_CMPXCHG8B = (1 << 8), - CPUID_AMDSEP = (1 << 10), - CPUID_SEP = (1 << 11), - CPUID_MTRR = (1 << 12), - CPUID_PGE = (1 << 13), - CPUID_MCA = (1 << 14), - CPUID_CMOV = (1 << 15), - CPUID_MMX = (1 << 23), - CPUID_FXSR = (1 << 24) + CPUID_FPU = (1 << 0), /* On-chip Floating Point Unit */ + CPUID_VME = (1 << 1), /* Virtual 8086 mode extensions */ + CPUID_DE = (1 << 2), /* Debugging extensions */ + CPUID_PSE = (1 << 3), /* Page Size Extension */ + CPUID_TSC = (1 << 4), /* Time Stamp Counter */ + CPUID_MSR = (1 << 5), /* Model-specific registers */ + CPUID_PAE = (1 << 6), /* Physical Address Extension */ + CPUID_MCE = (1 << 7), /* Machine Check Exception */ + CPUID_CMPXCHG8B = (1 << 8), /* CMPXCHG8B instruction */ + CPUID_APIC = (1 << 9), /* On-chip APIC */ + CPUID_AMDPGE = (1 << 9), /* Global Page Enable (AMD K5 Model 0 only) */ + CPUID_AMDSEP = (1 << 10), /* SYSCALL and SYSRET instructions (AMD K6 only) */ + CPUID_SEP = (1 << 11), /* SYSENTER and SYSEXIT instructions (SYSCALL and SYSRET if EAX=80000001h) */ + CPUID_MTRR = (1 << 12), /* Memory type range registers */ + CPUID_PGE = (1 << 13), /* Page Global Enable */ + CPUID_MCA = (1 << 14), /* Machine Check Architecture */ + CPUID_CMOV = (1 << 15), /* Conditional move instructions */ + CPUID_PAT = (1 << 16), /* Page Attribute Table */ + CPUID_MMX = (1 << 23), /* MMX technology */ + CPUID_FXSR = (1 << 24) /* FXSAVE and FXRSTOR instructions */ }; -/*Addition flags returned by CPUID function 0x80000001*/ -#define CPUID_3DNOW (1UL << 31UL) -#define CPUID_3DNOWE (1UL << 30UL) +/* Additional flags returned by CPUID function 0x80000001 */ +#define CPUID_3DNOWE (1UL << 30UL) /* Extended 3DNow! instructions */ +#define CPUID_3DNOW (1UL << 31UL) /* 3DNow! instructions */ /* Make sure this is as low as possible. */ cpu_state_t cpu_state; @@ -182,6 +186,7 @@ int cpu_16bitbus; int cpu_64bitbus; int cpu_cyrix_alignment; int cpu_cpurst_on_sr; +int cpu_use_exec = 0; int CPUID; int is186; @@ -243,8 +248,7 @@ uint32_t cache_index = 0; uint8_t _cache[2048]; uint64_t cpu_CR4_mask; -uint64_t tsc = 0; -uint64_t pmc[2] = { 0, 0 }; +uint64_t tsc = 0; double cpu_dmulti; double cpu_busspeed; @@ -1604,11 +1608,16 @@ cpu_set(void) cpu_CR4_mask |= (CR4_VME | CR4_PVI | CR4_PSE); if (cpu_s->cpu_type <= CPU_K6) cpu_CR4_mask |= CR4_PCE; - } + else if (cpu_s->cpu_type >= CPU_K6_2C) + cpu_CR4_mask |= CR4_PGE; + } else + cpu_CR4_mask |= CR4_PGE; #else cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE; if (cpu_s->cpu_type == CPU_K6) cpu_CR4_mask |= CR4_PCE; + else if (cpu_s->cpu_type >= CPU_K6_2C) + cpu_CR4_mask |= CR4_PGE; #endif #ifdef USE_DYNAREC @@ -1784,16 +1793,20 @@ cpu_set(void) x87_concurrency = x87_concurrency_486; } + cpu_use_exec = 0; + if (is386) { #if defined(USE_DYNAREC) && !defined(USE_GDBSTUB) - if (cpu_use_dynarec) + if (cpu_use_dynarec) { cpu_exec = exec386_dynarec; - else + cpu_use_exec = 1; + } else #endif /* Use exec386 for CPU_IBM486SLC because it can reach 100 MHz. */ - if ((cpu_s->cpu_type == CPU_IBM486SLC) || (cpu_s->cpu_type > CPU_486DLC)) + if ((cpu_s->cpu_type == CPU_IBM486SLC) || (cpu_s->cpu_type > CPU_486DLC)) { cpu_exec = exec386; - else + cpu_use_exec = 1; + } else cpu_exec = exec386_2386; } else if (cpu_s->cpu_type >= CPU_286) cpu_exec = exec386_2386; @@ -1901,7 +1914,7 @@ cpu_CPUID(void) case CPU_i486SX_SLENH: if (!EAX) { EAX = 0x00000001; - EBX = 0x756e6547; + EBX = 0x756e6547; /* GenuineIntel */ EDX = 0x49656e69; ECX = 0x6c65746e; } else if (EAX == 1) { @@ -1915,7 +1928,7 @@ cpu_CPUID(void) case CPU_i486DX_SLENH: if (!EAX) { EAX = 0x00000001; - EBX = 0x756e6547; + EBX = 0x756e6547; /* GenuineIntel */ EDX = 0x49656e69; ECX = 0x6c65746e; } else if (EAX == 1) { @@ -1931,21 +1944,21 @@ cpu_CPUID(void) case CPU_ENH_Am486DX: if (!EAX) { - EAX = 1; - EBX = 0x68747541; + EAX = 0x00000001; + EBX = 0x68747541;/* AuthenticAMD */ ECX = 0x444D4163; EDX = 0x69746E65; } else if (EAX == 1) { EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU; /*FPU*/ + EDX = CPUID_FPU; } else EAX = EBX = ECX = EDX = 0; break; case CPU_WINCHIP: if (!EAX) { - EAX = 1; + EAX = 0x00000001; if (msr.fcr2 & (1 << 14)) { EBX = msr.fcr3 >> 32; ECX = msr.fcr3 & 0xffffffff; @@ -1956,7 +1969,7 @@ cpu_CPUID(void) EDX = 0x48727561; } } else if (EAX == 1) { - EAX = 0x540; + EAX = ((msr.fcr2 & 0x0ff0) ? ((msr.fcr2 & 0x0ff0) | (CPUID & 0xf00f)) : CPUID); EBX = ECX = 0; EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; if (cpu_has_feature(CPU_FEATURE_CX8)) @@ -1970,7 +1983,7 @@ cpu_CPUID(void) case CPU_WINCHIP2: switch (EAX) { case 0: - EAX = 1; + EAX = 0x00000001; if (msr.fcr2 & (1 << 14)) { EBX = msr.fcr3 >> 32; ECX = msr.fcr3 & 0xffffffff; @@ -1982,7 +1995,7 @@ cpu_CPUID(void) } break; case 1: - EAX = CPUID; + EAX = ((msr.fcr2 & 0x0ff0) ? ((msr.fcr2 & 0x0ff0) | (CPUID & 0xf00f)) : CPUID); EBX = ECX = 0; EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; if (cpu_has_feature(CPU_FEATURE_CX8)) @@ -2027,13 +2040,15 @@ cpu_CPUID(void) case CPU_PENTIUM: if (!EAX) { EAX = 0x00000001; - EBX = 0x756e6547; + EBX = 0x756e6547; /* GenuineIntel */ EDX = 0x49656e69; ECX = 0x6c65746e; } else if (EAX == 1) { EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B; + if (cpu_s->cpu_type != CPU_P24T) + EDX |= CPUID_MCE; } else EAX = EBX = ECX = EDX = 0; break; @@ -2042,106 +2057,69 @@ cpu_CPUID(void) case CPU_K5: if (!EAX) { EAX = 0x00000001; - EBX = 0x68747541; + EBX = 0x68747541; /* AuthenticAMD */ EDX = 0x69746E65; ECX = 0x444D4163; } else if (EAX == 1) { EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDPGE; } else EAX = EBX = ECX = EDX = 0; break; case CPU_5K86: - if (!EAX) { - EAX = 0x00000001; - EBX = 0x68747541; - EDX = 0x69746E65; - ECX = 0x444D4163; - } else if (EAX == 1) { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B; - } else if (EAX == 0x80000000) { - EAX = 0x80000005; - EBX = ECX = EDX = 0; - } else if (EAX == 0x80000001) { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B; - } else if (EAX == 0x80000002) { - EAX = 0x2D444D41; - EBX = 0x7428354B; - ECX = 0x5020296D; - EDX = 0x65636F72; - } else if (EAX == 0x80000003) { - EAX = 0x726F7373; - EBX = ECX = EDX = 0; - } else if (EAX == 0x80000004) - EAX = EBX = ECX = EDX = 0; - else if (EAX == 0x80000005) { - EAX = 0; - EBX = 0x04800000; - ECX = 0x08040120; - EDX = 0x10040120; - } else - EAX = EBX = ECX = EDX = 0; + switch (EAX) { + case 0: + EAX = 0x00000001; + EBX = 0x68747541; /* AuthenticAMD */ + EDX = 0x69746E65; + ECX = 0x444D4163; + break; + case 1: + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE; + break; + case 0x80000000: + EAX = 0x80000005; + EBX = ECX = EDX = 0; + break; + case 0x80000001: + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE; + break; + case 0x80000002: /* Processor name string */ + EAX = 0x2D444D41; /* AMD-K5(tm) Proce */ + EBX = 0x7428354B; + ECX = 0x5020296D; + EDX = 0x65636F72; + break; + case 0x80000003: /* Processor name string */ + EAX = 0x726F7373; /* ssor */ + EBX = ECX = EDX = 0; + break; + case 0x80000005: /* Cache information */ + EAX = 0; + EBX = 0x04800000; /* TLBs */ + ECX = 0x08040120; /* L1 data cache */ + EDX = 0x10040120; /* L1 instruction cache */ + break; + default: + EAX = EBX = ECX = EDX = 0; + break; + } break; #endif case CPU_K6: - if (!EAX) { - EAX = 0x00000001; - EBX = 0x68747541; - EDX = 0x69746E65; - ECX = 0x444D4163; - } else if (EAX == 1) { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; - } else if (EAX == 0x80000000) { - EAX = 0x80000005; - EBX = ECX = EDX = 0; - } else if (EAX == 0x80000001) { - EAX = CPUID + 0x100; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX; - } else if (EAX == 0x80000002) { - EAX = 0x2D444D41; - EBX = 0x6D74364B; - ECX = 0x202F7720; - EDX = 0x746C756D; - } else if (EAX == 0x80000003) { - EAX = 0x64656D69; - EBX = 0x65206169; - ECX = 0x6E657478; - EDX = 0x6E6F6973; - } else if (EAX == 0x80000004) { - EAX = 0x73; - EBX = ECX = EDX = 0; - } else if (EAX == 0x80000005) { - EAX = 0; - EBX = 0x02800140; - ECX = 0x20020220; - EDX = 0x20020220; - } else if (EAX == 0x8FFFFFFF) { - EAX = 0x4778654E; - EBX = 0x72656E65; - ECX = 0x6F697461; - EDX = 0x444D416E; - } else - EAX = EBX = ECX = EDX = 0; - break; - - case CPU_K6_2: - case CPU_K6_2C: switch (EAX) { case 0: - EAX = 1; + EAX = 0x00000001; EBX = 0x68747541; /* AuthenticAMD */ - ECX = 0x444d4163; - EDX = 0x69746e65; + EDX = 0x69746E65; + ECX = 0x444D4163; break; case 1: EAX = CPUID; @@ -2155,7 +2133,68 @@ cpu_CPUID(void) case 0x80000001: EAX = CPUID + 0x100; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX | CPUID_3DNOW; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX; + break; + case 0x80000002: /* Processor name string */ + EAX = 0x2D444D41; /* AMD-K6tm w/ mult */ + EBX = 0x6D74364B; + ECX = 0x202F7720; + EDX = 0x746C756D; + break; + case 0x80000003: /* Processor name string */ + EAX = 0x64656D69; /* imedia extension */ + EBX = 0x65206169; + ECX = 0x6E657478; + EDX = 0x6E6F6973; + break; + case 0x80000004: /* Processor name string */ + EAX = 0x73; /* s */ + EBX = ECX = EDX = 0; + break; + case 0x80000005: /* Cache information */ + EAX = 0; + EBX = 0x02800140; /* TLBs */ + ECX = 0x20020220; /* L1 data cache */ + EDX = 0x20020220; /* L1 instruction cache */ + break; + case 0x8FFFFFFF: /* Easter egg */ + EAX = 0x4778654E; /* NexGenerationAMD */ + EBX = 0x72656E65; + ECX = 0x6F697461; + EDX = 0x444D416E; + break; + default: + EAX = EBX = ECX = EDX = 0; + break; + } + break; + + case CPU_K6_2: + case CPU_K6_2C: + switch (EAX) { + case 0: + EAX = 0x00000001; + EBX = 0x68747541; /* AuthenticAMD */ + ECX = 0x444d4163; + EDX = 0x69746e65; + break; + case 1: + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; + if (cpu_s->cpu_type == CPU_K6_2C) + EDX |= CPUID_PGE; + break; + case 0x80000000: + EAX = 0x80000005; + EBX = ECX = EDX = 0; + break; + case 0x80000001: + EAX = CPUID + 0x100; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_SEP | CPUID_MMX | CPUID_3DNOW; + if (cpu_s->cpu_type == CPU_K6_2C) + EDX |= CPUID_PGE; break; case 0x80000002: /* Processor name string */ EAX = 0x2d444d41; /* AMD-K6(tm) 3D pr */ @@ -2169,11 +2208,11 @@ cpu_CPUID(void) ECX = 0x00000000; EDX = 0x00000000; break; - case 0x80000005: /*Cache information*/ + case 0x80000005: /* Cache information */ EAX = 0; - EBX = 0x02800140; /*TLBs*/ - ECX = 0x20020220; /*L1 data cache*/ - EDX = 0x20020220; /*L1 instruction cache*/ + EBX = 0x02800140; /* TLBs */ + ECX = 0x20020220; /* L1 data cache */ + EDX = 0x20020220; /* L1 instruction cache */ break; default: EAX = EBX = ECX = EDX = 0; @@ -2184,7 +2223,7 @@ cpu_CPUID(void) case CPU_K6_3: switch (EAX) { case 0: - EAX = 1; + EAX = 0x00000001; EBX = 0x68747541; /* AuthenticAMD */ ECX = 0x444d4163; EDX = 0x69746e65; @@ -2192,7 +2231,7 @@ cpu_CPUID(void) case 1: EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE | CPUID_MMX; break; case 0x80000000: EAX = 0x80000006; @@ -2201,7 +2240,7 @@ cpu_CPUID(void) case 0x80000001: EAX = CPUID + 0x100; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX | CPUID_3DNOW; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_SEP | CPUID_PGE | CPUID_MMX | CPUID_3DNOW; break; case 0x80000002: /* Processor name string */ EAX = 0x2d444d41; /* AMD-K6(tm) 3D+ P */ @@ -2218,8 +2257,8 @@ cpu_CPUID(void) case 0x80000005: /* Cache information */ EAX = 0; EBX = 0x02800140; /* TLBs */ - ECX = 0x20020220; /*L1 data cache*/ - EDX = 0x20020220; /*L1 instruction cache*/ + ECX = 0x20020220; /* L1 data cache */ + EDX = 0x20020220; /* L1 instruction cache */ break; case 0x80000006: /* L2 Cache information */ EAX = EBX = EDX = 0; @@ -2235,7 +2274,7 @@ cpu_CPUID(void) case CPU_K6_3P: switch (EAX) { case 0: - EAX = 1; + EAX = 0x00000001; EBX = 0x68747541; /* AuthenticAMD */ ECX = 0x444d4163; EDX = 0x69746e65; @@ -2243,7 +2282,7 @@ cpu_CPUID(void) case 1: EAX = CPUID; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE | CPUID_MMX; break; case 0x80000000: EAX = 0x80000007; @@ -2252,7 +2291,7 @@ cpu_CPUID(void) case 0x80000001: EAX = CPUID + 0x100; EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX | CPUID_3DNOW | CPUID_3DNOWE; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_SEP | CPUID_MMX | CPUID_PGE | CPUID_3DNOW | CPUID_3DNOWE; break; case 0x80000002: /* Processor name string */ EAX = 0x2d444d41; /* AMD-K6(tm)-III P */ @@ -2292,7 +2331,7 @@ cpu_CPUID(void) case CPU_PENTIUMMMX: if (!EAX) { EAX = 0x00000001; - EBX = 0x756e6547; + EBX = 0x756e6547; /* GenuineIntel */ EDX = 0x49656e69; ECX = 0x6c65746e; } else if (EAX == 1) { @@ -2307,7 +2346,7 @@ cpu_CPUID(void) case CPU_Cx6x86: if (!EAX) { EAX = 0x00000001; - EBX = 0x69727943; + EBX = 0x69727943; /* CyrixInstead */ EDX = 0x736e4978; ECX = 0x64616574; } else if (EAX == 1) { @@ -2321,7 +2360,7 @@ cpu_CPUID(void) case CPU_Cx6x86L: if (!EAX) { EAX = 0x00000001; - EBX = 0x69727943; + EBX = 0x69727943; /* CyrixInstead */ EDX = 0x736e4978; ECX = 0x64616574; } else if (EAX == 1) { @@ -2335,7 +2374,7 @@ cpu_CPUID(void) case CPU_CxGX1: if (!EAX) { EAX = 0x00000001; - EBX = 0x69727943; + EBX = 0x69727943; /* CyrixInstead */ EDX = 0x736e4978; ECX = 0x64616574; } else if (EAX == 1) { @@ -2349,7 +2388,7 @@ cpu_CPUID(void) case CPU_Cx6x86MX: if (!EAX) { EAX = 0x00000001; - EBX = 0x69727943; + EBX = 0x69727943; /* CyrixInstead */ EDX = 0x736e4978; ECX = 0x64616574; } else if (EAX == 1) { @@ -2364,7 +2403,7 @@ cpu_CPUID(void) case CPU_PENTIUMPRO: if (!EAX) { EAX = 0x00000002; - EBX = 0x756e6547; + EBX = 0x756e6547; /* GenuineIntel */ EDX = 0x49656e69; ECX = 0x6c65746e; } else if (EAX == 1) { @@ -2379,7 +2418,7 @@ cpu_CPUID(void) EDX = 0x06040a42; /* 2nd-level cache: 256 KB, 4-way set associative, 32-byte line size 1st-level data cache: 8 KB, 2-way set associative, 32-byte line size Data TLB: 4 MB pages, 4-way set associative, 8 entries - 1st-level instruction cache:8 KB, 4-way set associative, 32-byte line size */ + 1st-level instruction cache: 8 KB, 4-way set associative, 32-byte line size */ } else EAX = EBX = ECX = EDX = 0; break; @@ -2387,7 +2426,7 @@ cpu_CPUID(void) case CPU_PENTIUM2: if (!EAX) { EAX = 0x00000002; - EBX = 0x756e6547; + EBX = 0x756e6547; /* GenuineIntel */ EDX = 0x49656e69; ECX = 0x6c65746e; } else if (EAX == 1) { @@ -2410,7 +2449,7 @@ cpu_CPUID(void) case CPU_PENTIUM2D: if (!EAX) { EAX = 0x00000002; - EBX = 0x756e6547; + EBX = 0x756e6547; /* GenuineIntel */ EDX = 0x49656e69; ECX = 0x6c65746e; } else if (EAX == 1) { @@ -2441,7 +2480,7 @@ cpu_CPUID(void) case CPU_CYRIX3S: switch (EAX) { case 0: - EAX = 1; + EAX = 0x00000001; if (msr.fcr2 & (1 << 14)) { EBX = msr.fcr3 >> 32; ECX = msr.fcr3 & 0xffffffff; @@ -2453,7 +2492,7 @@ cpu_CPUID(void) } break; case 1: - EAX = CPUID; + EAX = ((msr.fcr2 & 0x0ff0) ? ((msr.fcr2 & 0x0ff0) | (CPUID & 0xf00f)) : CPUID); EBX = ECX = 0; EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_MMX | CPUID_MTRR; if (cpu_has_feature(CPU_FEATURE_CX8)) @@ -2499,9 +2538,12 @@ cpu_ven_reset(void) switch (cpu_s->cpu_type) { case CPU_WINCHIP: case CPU_WINCHIP2: - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - if (cpu_s->cpu_type == CPU_WINCHIP2) - msr.fcr |= (1 << 18) | (1 << 20); + msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); + msr.mcr_ctrl = 0xf8000000; + if (cpu_s->cpu_type == CPU_WINCHIP2) { + msr.fcr |= (1 << 18) | (1 << 20); + msr.mcr_ctrl |= (1 << 17); + } break; case CPU_K6_2P: @@ -2541,18 +2583,28 @@ cpu_RDMSR(void) case CPU_IBM486BL: EAX = EDX = 0; switch (ECX) { + /* Processor Operation Register */ case 0x1000: EAX = msr.ibm_por & ((cpu_s->cpu_type > CPU_IBM386SLC) ? 0xffeff : 0xfeff); break; + /* Cache Region Control Register */ case 0x1001: - EAX = msr.ibm_crcr & 0xffffffffff; + EAX = msr.ibm_crcr & 0xffffffff; + EDX = (msr.ibm_crcr >> 32) & 0x0000ffff; break; + /* Processor Operation Register */ case 0x1002: if ((cpu_s->cpu_type > CPU_IBM386SLC) && cpu_s->multi) EAX = msr.ibm_por2 & 0x3f000000; break; + + /* Processor Control Register */ + case 0x1004: + if (cpu_s->cpu_type > CPU_IBM486SLC) + EAX = msr.ibm_pcr & 0x00d6001a; + break; } break; @@ -2560,42 +2612,74 @@ cpu_RDMSR(void) case CPU_WINCHIP2: EAX = EDX = 0; switch (ECX) { + /* Pentium Processor Parity Reversal Register */ case 0x02: EAX = msr.tr1; break; + /* Pentium Processor New Feature Control */ case 0x0e: EAX = msr.tr12; break; + /* Time Stamp Counter */ case 0x10: EAX = tsc & 0xffffffff; EDX = tsc >> 32; break; + /* Performance Monitor - Control and Event Select */ case 0x11: EAX = msr.cesr; break; + /* Performance Monitor - Event Counter 0 */ + case 0x12: + EAX = msr.pmc[0] & 0xffffffff; + EDX = msr.pmc[0] >> 32; + break; + /* Performance Monitor - Event Counter 1 */ + case 0x13: + EAX = msr.pmc[1] & 0xffffffff; + EDX = msr.pmc[1] >> 32; + break; + /* Feature Control Register */ case 0x107: EAX = msr.fcr; break; + /* Feature Control Register 2 */ case 0x108: EAX = msr.fcr2 & 0xffffffff; EDX = msr.fcr2 >> 32; break; + /* Feature Control Register 4 */ case 0x10a: EAX = cpu_multi & 3; break; + /* Memory Configuration Register Control */ + case 0x120: + EAX = msr.mcr_ctrl; + break; + /* Unknown */ + case 0x131: + case 0x142 ... 0x145: + case 0x147: + case 0x150: + case 0x151: + break; } break; case CPU_CYRIX3S: EAX = EDX = 0; switch (ECX) { + /* Machine Check Exception Address */ case 0x00: + /* Machine Check Exception Type */ case 0x01: break; + /* Time Stamp Counter */ case 0x10: EAX = tsc & 0xffffffff; EDX = tsc >> 32; break; + /* EBL_CR_POWERON - Processor Hard Power-On Configuration */ case 0x2a: EAX = 0xc4000000; EDX = 0; @@ -2622,29 +2706,41 @@ cpu_RDMSR(void) if (cpu_busspeed >= 84000000) EAX |= (1 << 19); break; + /* PERFCTR0 - Performance Counter Register 0 - aliased to TSC */ + case 0xc1: + EAX = tsc & 0xffffffff; + EDX = (tsc >> 32) & 0xff; + break; + /* PERFCTR1 - Performance Counter Register 1 */ + case 0xc2: + EAX = msr.perfctr[1] & 0xffffffff; + EDX = msr.perfctr[1] >> 32; + break; + /* BBL_CR_CTL3 - L2 Cache Control Register 3 */ + case 0x11e: + EAX = 0x800000; /* L2 cache disabled */ + break; + /* EVNTSEL0 - Performance Counter Event Select 0 - hardcoded */ + case 0x186: + EAX = 0x470079; + break; + /* EVNTSEL1 - Performance Counter Event Select 1 */ + case 0x187: + EAX = msr.evntsel[1] & 0xffffffff; + EDX = msr.evntsel[1] >> 32; + break; + /* Feature Control Register */ case 0x1107: EAX = msr.fcr; break; + /* Feature Control Register 2 */ case 0x1108: EAX = msr.fcr2 & 0xffffffff; EDX = msr.fcr2 >> 32; break; - case 0x200: - case 0x201: - case 0x202: - case 0x203: - case 0x204: - case 0x205: - case 0x206: - case 0x207: - case 0x208: - case 0x209: - case 0x20a: - case 0x20b: - case 0x20c: - case 0x20d: - case 0x20e: - case 0x20f: + /* ECX & 0: MTRRphysBase0 ... MTRRphysBase7 + ECX & 1: MTRRphysMask0 ... MTRRphysMask7 */ + case 0x200 ... 0x20f: if (ECX & 1) { EAX = msr.mtrr_physmask[(ECX - 0x200) >> 1] & 0xffffffff; EDX = msr.mtrr_physmask[(ECX - 0x200) >> 1] >> 32; @@ -2653,29 +2749,27 @@ cpu_RDMSR(void) EDX = msr.mtrr_physbase[(ECX - 0x200) >> 1] >> 32; } break; + /* MTRRfix64K_00000 */ case 0x250: EAX = msr.mtrr_fix64k_8000 & 0xffffffff; EDX = msr.mtrr_fix64k_8000 >> 32; break; + /* MTRRfix16K_80000 */ case 0x258: EAX = msr.mtrr_fix16k_8000 & 0xffffffff; EDX = msr.mtrr_fix16k_8000 >> 32; break; + /* MTRRfix16K_A0000 */ case 0x259: EAX = msr.mtrr_fix16k_a000 & 0xffffffff; EDX = msr.mtrr_fix16k_a000 >> 32; break; - case 0x268: - case 0x269: - case 0x26a: - case 0x26b: - case 0x26c: - case 0x26d: - case 0x26e: - case 0x26f: + /* MTRRfix4K_C0000 ... MTRRfix4K_F8000 */ + case 0x268 ... 0x26f: EAX = msr.mtrr_fix4k[ECX - 0x268] & 0xffffffff; EDX = msr.mtrr_fix4k[ECX - 0x268] >> 32; break; + /* MTRRdefType */ case 0x2ff: EAX = msr.mtrr_deftype & 0xffffffff; EDX = msr.mtrr_deftype >> 32; @@ -2693,37 +2787,75 @@ cpu_RDMSR(void) case CPU_K6_3: case CPU_K6_2P: case CPU_K6_3P: - EAX = EDX = 0; + EAX = 0; + /* EDX is left unchanged when reading this MSR! */ + if (ECX != 0x82) + EDX = 0; switch (ECX) { + /* Machine Check Address Register */ case 0x00000000: - case 0x00000001: + EAX = msr.mcar & 0xffffffff; + EDX = msr.mcar >> 32; break; + /* Machine Check Type Register */ + case 0x00000001: + EAX = msr.mctr & 0xffffffff; + EDX = msr.mctr >> 32; + break; + /* Test Register 12 */ case 0x0000000e: EAX = msr.tr12; break; + /* Time Stamp Counter */ case 0x00000010: EAX = tsc & 0xffffffff; EDX = tsc >> 32; break; - case 0x00000083: - EAX = msr.ecx83 & 0xffffffff; - EDX = msr.ecx83 >> 32; + /* Array Access Register */ + case 0x00000082: + if (cpu_s->cpu_type > CPU_5K86) + goto amd_k_invalid_rdmsr; + EAX = msr.amd_aar & 0xffffffff; + /* EDX is left unchanged! */ break; + /* Hardware Configuration Register */ + case 0x00000083: + EAX = msr.amd_hwcr & 0xffffffff; + EDX = msr.amd_hwcr >> 32; + break; + /* Write Allocate Top-of-Memory and Control Register */ + case 0x00000085: + if (cpu_s->cpu_type != CPU_5K86) + goto amd_k_invalid_rdmsr; + EAX = msr.amd_watmcr & 0xffffffff; + EDX = msr.amd_watmcr >> 32; + break; + /* Write Allocate Programmable Memory Range Register */ + case 0x00000086: + if (cpu_s->cpu_type != CPU_5K86) + goto amd_k_invalid_rdmsr; + EAX = msr.amd_wapmrr & 0xffffffff; + EDX = msr.amd_wapmrr >> 32; + break; + /* Extended Feature Enable Register */ case 0xc0000080: EAX = msr.amd_efer & 0xffffffff; EDX = msr.amd_efer >> 32; break; + /* SYSCALL Target Address Register */ case 0xc0000081: if (cpu_s->cpu_type < CPU_K6_2) goto amd_k_invalid_rdmsr; - EAX = msr.star & 0xffffffff; - EDX = msr.star >> 32; + EAX = msr.amd_star & 0xffffffff; + EDX = msr.amd_star >> 32; break; + /* Write-Handling Control Register */ case 0xc0000082: EAX = msr.amd_whcr & 0xffffffff; EDX = msr.amd_whcr >> 32; break; + /* UC/WC Cacheability Control Register */ case 0xc0000085: if (cpu_s->cpu_type < CPU_K6_2C) goto amd_k_invalid_rdmsr; @@ -2731,6 +2863,7 @@ cpu_RDMSR(void) EAX = msr.amd_uwccr & 0xffffffff; EDX = msr.amd_uwccr >> 32; break; + /* Enhanced Power Management Register */ case 0xc0000086: if (cpu_s->cpu_type < CPU_K6_2P) goto amd_k_invalid_rdmsr; @@ -2738,6 +2871,7 @@ cpu_RDMSR(void) EAX = msr.amd_epmr & 0xffffffff; EDX = msr.amd_epmr >> 32; break; + /* Processor State Observability Register */ case 0xc0000087: if (cpu_s->cpu_type < CPU_K6_2C) goto amd_k_invalid_rdmsr; @@ -2745,6 +2879,7 @@ cpu_RDMSR(void) EAX = msr.amd_psor & 0xffffffff; EDX = msr.amd_psor >> 32; break; + /* Page Flush/Invalidate Register */ case 0xc0000088: if (cpu_s->cpu_type < CPU_K6_2C) goto amd_k_invalid_rdmsr; @@ -2752,6 +2887,7 @@ cpu_RDMSR(void) EAX = msr.amd_pfir & 0xffffffff; EDX = msr.amd_pfir >> 32; break; + /* Level-2 Cache Array Access Register */ case 0xc0000089: if (cpu_s->cpu_type < CPU_K6_3) goto amd_k_invalid_rdmsr; @@ -2769,52 +2905,253 @@ amd_k_invalid_rdmsr: case CPU_P24T: case CPU_PENTIUM: case CPU_PENTIUMMMX: -#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) - case CPU_Cx6x86: - case CPU_Cx6x86L: - case CPU_CxGX1: - case CPU_Cx6x86MX: - if (cpu_s->cpu_type < CPU_Cx6x86) -#endif - EAX = EDX = 0; - switch (ECX) { - case 0x00: - case 0x01: + EAX = EDX = 0; + /* Filter out the upper 27 bits when ECX value is over 0x80000000, as per: + Ralf Brown, Pentium Model-Specific Registers and What They Reveal. + https://www.cs.cmu.edu/~ralf/papers/highmsr.html + But leave the bit 31 intact to be able to handle both low and high + MSRs in a single switch block. */ + switch (ECX & (ECX > 0x7fffffff ? 0x8000001f : 0x7fffffff)) { + /* Machine Check Exception Address */ + case 0x00000000: + case 0x80000000: + EAX = msr.mcar & 0xffffffff; + EDX = msr.mcar >> 32; break; - case 0x10: + /* Machine Check Exception Type */ + case 0x00000001: + case 0x80000001: + EAX = msr.mctr & 0xffffffff; + EDX = msr.mctr >> 32; + msr.mctr &= ~0x1; /* clear the machine check pending bit */ + break; + /* TR1 - Parity Reversal Test Register */ + case 0x00000002: + case 0x80000002: + EAX = msr.tr1; + break; + /* TR2 - Instruction Cache End Bit */ + case 0x00000004: + case 0x80000004: + if (cpu_s->cpu_type == CPU_PENTIUMMMX) + goto pentium_invalid_rdmsr; + EAX = msr.tr2; + break; + /* TR3 - Cache Test Data */ + case 0x00000005: + case 0x80000005: + EAX = msr.tr3; + break; + /* TR4 - Cache Test Tag */ + case 0x00000006: + case 0x80000006: + EAX = msr.tr4; + break; + /* TR5 - Cache Test Control */ + case 0x00000007: + case 0x80000007: + EAX = msr.tr5; + break; + /* TR6 - TLB Test Command */ + case 0x00000008: + case 0x80000008: + EAX = msr.tr6; + break; + /* TR7 - TLB Test Data */ + case 0x00000009: + case 0x80000009: + EAX = msr.tr7; + break; + /* TR9 - Branch Target Buffer Tag */ + case 0x0000000b: + case 0x8000000b: + EAX = msr.tr9; + break; + /* TR10 - Branch Target Buffer Target */ + case 0x0000000c: + case 0x8000000c: + EAX = msr.tr10; + break; + /* TR11 - Branch Target Buffer Control */ + case 0x0000000d: + case 0x8000000d: + EAX = msr.tr11; + break; + /* TR12 - New Feature Control */ + case 0x0000000e: + case 0x8000000e: + EAX = msr.tr12; + break; + /* Time Stamp Counter */ + case 0x00000010: + case 0x80000010: EAX = tsc & 0xffffffff; EDX = tsc >> 32; break; + /* Performance Monitor - Control and Event Select */ + case 0x00000011: + case 0x80000011: + EAX = msr.cesr; + break; + /* Performance Monitor - Event Counter 0 */ + case 0x00000012: + case 0x80000012: + EAX = msr.pmc[0] & 0xffffffff; + EDX = msr.pmc[0] >> 32; + break; + /* Performance Monitor - Event Counter 1 */ + case 0x00000013: + case 0x80000013: + EAX = msr.pmc[1] & 0xffffffff; + EDX = msr.pmc[1] >> 32; + break; + /* Unknown */ + case 0x00000014: + case 0x80000014: + if ((CPUID & 0xfff) <= 0x520) + goto pentium_invalid_rdmsr; + break; + /* Unknown, possibly paging-related; initial value is 0004h, + becomes 0008h once paging is enabled */ + case 0x80000018: + EAX = ((cr0 & (1 << 31)) ? 0x00000008 : 0x00000004); + break; + /* Floating point - last prefetched opcode + bits 10-8: low three bits of first byte of FP instruction + bits 7-0: second byte of floating-point instruction */ + case 0x80000019: + EAX = 0; + break; + /* Floating point - last executed non-control opcode */ + case 0x8000001a: + EAX = 0; + break; + /* Floating point - last non-control exception opcode - part + of FSTENV/FSAVE'd environment */ + case 0x8000001b: + EAX = msr.fp_last_xcpt; + break; + /* Unknown */ + case 0x8000001c: + EAX = 0x00000004; + break; + /* Probe Mode Control */ + case 0x8000001d: + EAX = msr.probe_ctl; + break; + /* Unknown, possibly scratchpad register */ + case 0x8000001e: + EAX = msr.ecx8000001e; + break; + /* Unknown, possibly scratchpad register */ + case 0x8000001f: + EAX = msr.ecx8000001f; + break; + /* Reserved/Unimplemented */ + case 0x80000003: + case 0x8000000a: + case 0x8000000f: + case 0x80000015 ... 0x80000017: + EAX = (ECX & 0x1f) * 2; + break; + default: +pentium_invalid_rdmsr: + cpu_log("RDMSR: Invalid MSR: %08X\n", ECX); + x86gpf(NULL, 0); + break; } cpu_log("RDMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX); break; - case CPU_PENTIUMPRO: - case CPU_PENTIUM2: - case CPU_PENTIUM2D: - EAX = EDX = 0; +#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) + case CPU_Cx6x86: + case CPU_Cx6x86L: + case CPU_CxGX1: + case CPU_Cx6x86MX: switch (ECX) { - case 0x00: - case 0x01: + /* Test Data */ + case 0x03: + EAX = msr.tr3; break; + /* Test Address */ + case 0x04: + EAX = msr.tr4; + break; + /* Test Command/Status */ + case 0x05: + EAX = msr.tr5; + break; + /* Time Stamp Counter */ case 0x10: EAX = tsc & 0xffffffff; EDX = tsc >> 32; break; + /* Performance Monitor - Control and Event Select */ + case 0x11: + EAX = msr.cesr; + break; + /* Performance Monitor - Event Counter 0 */ + case 0x12: + EAX = msr.pmc[0] & 0xffffffff; + EDX = msr.pmc[0] >> 32; + break; + /* Performance Monitor - Event Counter 1 */ + case 0x13: + EAX = msr.pmc[1] & 0xffffffff; + EDX = msr.pmc[1] >> 32; + break; + } + cpu_log("RDMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX); + break; +#endif + + case CPU_PENTIUMPRO: + case CPU_PENTIUM2: + case CPU_PENTIUM2D: + EAX = EDX = 0; + /* Per RichardG's probing of a real Deschutes using my RDMSR tool, + we have discovered that the top 18 bits are filtered out. */ + switch (ECX & 0x00003fff) { + /* Machine Check Exception Address */ + case 0x00: + /* Machine Check Exception Type */ + case 0x01: + break; + /* Time Stamp Counter */ + case 0x10: + EAX = tsc & 0xffffffff; + EDX = tsc >> 32; + break; + /* IA32_PLATFORM_ID - Platform ID */ case 0x17: - if (cpu_s->cpu_type != CPU_PENTIUM2D) + if (cpu_s->cpu_type < CPU_PENTIUM2D) goto i686_invalid_rdmsr; if (cpu_f->package == CPU_PKG_SLOT2) - EDX |= 0x80000; + EDX |= (1 << 19); else if (cpu_f->package == CPU_PKG_SOCKET370) - EDX |= 0x100000; + EDX |= (1 << 20); break; + /* Unknown */ + case 0x18: + break; + /* IA32_APIC_BASE - APIC Base Address */ case 0x1B: EAX = msr.apic_base & 0xffffffff; EDX = msr.apic_base >> 32; cpu_log("APIC_BASE read : %08X%08X\n", EDX, EAX); break; + /* Unknown (undocumented?) MSR used by the Hyper-V BIOS */ + case 0x20: + EAX = msr.ecx20 & 0xffffffff; + EDX = msr.ecx20 >> 32; + break; + /* Unknown */ + case 0x21: + if (cpu_s->cpu_type == CPU_PENTIUMPRO) + goto i686_invalid_rdmsr; + break; + /* EBL_CR_POWERON - Processor Hard Power-On Configuration */ case 0x2a: EAX = 0xc4000000; EDX = 0; @@ -2849,47 +3186,85 @@ amd_k_invalid_rdmsr: EAX |= (1 << 19); } break; + /* Unknown */ + case 0x32: + if (cpu_s->cpu_type == CPU_PENTIUMPRO) + goto i686_invalid_rdmsr; + break; + /* TEST_CTL - Test Control Register */ + case 0x33: + EAX = msr.test_ctl; + break; + /* Unknown */ + case 0x34: + case 0x3a: + case 0x3b: + case 0x50 ... 0x54: + break; + /* BIOS_UPDT_TRIG - BIOS Update Trigger */ case 0x79: - EAX = msr.ecx79 & 0xffffffff; - EDX = msr.ecx79 >> 32; + EAX = msr.bios_updt & 0xffffffff; + EDX = msr.bios_updt >> 32; break; - case 0x88: - case 0x89: - case 0x8a: - case 0x8b: - EAX = msr.ecx8x[ECX - 0x88] & 0xffffffff; - EDX = msr.ecx8x[ECX - 0x88] >> 32; + /* BBL_CR_D0 ... BBL_CR_D3 - Chunk 0..3 Data Register + 8Bh: BIOS_SIGN - BIOS Update Signature */ + case 0x88 ... 0x8b: + EAX = msr.bbl_cr_dx[ECX - 0x88] & 0xffffffff; + EDX = msr.bbl_cr_dx[ECX - 0x88] >> 32; break; + /* Unknown */ + case 0xae: + break; + /* PERFCTR0 - Performance Counter Register 0 */ case 0xc1: + /* PERFCTR1 - Performance Counter Register 1 */ case 0xc2: - case 0xc3: - case 0xc4: - case 0xc5: - case 0xc6: - case 0xc7: - case 0xc8: - EAX = msr.ia32_pmc[ECX - 0xC1] & 0xffffffff; - EDX = msr.ia32_pmc[ECX - 0xC1] >> 32; + EAX = msr.perfctr[ECX - 0xC1] & 0xffffffff; + EDX = msr.perfctr[ECX - 0xC1] >> 32; break; + /* MTRRcap */ case 0xfe: EAX = msr.mtrr_cap & 0xffffffff; EDX = msr.mtrr_cap >> 32; break; + /* BBL_CR_ADDR - L2 Cache Address Register */ case 0x116: - EAX = msr.ecx116 & 0xffffffff; - EDX = msr.ecx116 >> 32; + EAX = msr.bbl_cr_addr & 0xffffffff; + EDX = msr.bbl_cr_addr >> 32; break; + /* BBL_CR_DECC - L2 Cache Date ECC Register */ case 0x118: + EAX = msr.bbl_cr_decc & 0xffffffff; + EDX = msr.bbl_cr_decc >> 32; + break; + /* BBL_CR_CTL - L2 Cache Control Register */ case 0x119: + EAX = msr.bbl_cr_ctl & 0xffffffff; + EDX = msr.bbl_cr_ctl >> 32; + break; + /* BBL_CR_TRIG - L2 Cache Trigger Register */ case 0x11a: + EAX = msr.bbl_cr_trig & 0xffffffff; + EDX = msr.bbl_cr_trig >> 32; + break; + /* BBL_CR_BUSY - L2 Cache Busy Register */ case 0x11b: - EAX = msr.ecx11x[ECX - 0x118] & 0xffffffff; - EDX = msr.ecx11x[ECX - 0x118] >> 32; + EAX = msr.bbl_cr_busy & 0xffffffff; + EDX = msr.bbl_cr_busy >> 32; break; + /* BBL_CR_CTL3 - L2 Cache Control Register 3 */ case 0x11e: - EAX = msr.ecx11e & 0xffffffff; - EDX = msr.ecx11e >> 32; + EAX = msr.bbl_cr_ctl3 & 0xffffffff; + EDX = msr.bbl_cr_ctl3 >> 32; break; + /* Unknown */ + case 0x131: + case 0x14e ... 0x151: + case 0x154: + case 0x15b: + case 0x15f: + break; + /* SYSENTER_CS - SYSENTER target CS */ case 0x174: if (cpu_s->cpu_type == CPU_PENTIUMPRO) goto i686_invalid_rdmsr; @@ -2898,6 +3273,7 @@ amd_k_invalid_rdmsr: EAX |= msr.sysenter_cs; EDX = 0x00000000; break; + /* SYSENTER_ESP - SYSENTER target ESP */ case 0x175: if (cpu_s->cpu_type == CPU_PENTIUMPRO) goto i686_invalid_rdmsr; @@ -2905,6 +3281,7 @@ amd_k_invalid_rdmsr: EAX = msr.sysenter_esp; EDX = 0x00000000; break; + /* SYSENTER_EIP - SYSENTER target EIP */ case 0x176: if (cpu_s->cpu_type == CPU_PENTIUMPRO) goto i686_invalid_rdmsr; @@ -2912,23 +3289,25 @@ amd_k_invalid_rdmsr: EAX = msr.sysenter_eip; EDX = 0x00000000; break; + /* MCG_CAP - Machine Check Global Capability */ case 0x179: EAX = 0x00000105; EDX = 0x00000000; break; + /* MCG_STATUS - Machine Check Global Status */ case 0x17a: break; + /* MCG_CTL - Machine Check Global Control */ case 0x17b: EAX = msr.mcg_ctl & 0xffffffff; EDX = msr.mcg_ctl >> 32; break; + /* EVNTSEL0 - Performance Counter Event Select 0 */ case 0x186: - EAX = msr.ecx186 & 0xffffffff; - EDX = msr.ecx186 >> 32; - break; + /* EVNTSEL1 - Performance Counter Event Select 1 */ case 0x187: - EAX = msr.ecx187 & 0xffffffff; - EDX = msr.ecx187 >> 32; + EAX = msr.evntsel[ECX - 0x186] & 0xffffffff; + EDX = msr.evntsel[ECX - 0x186] >> 32; break; case 0x198: EAX = msr.ecx198 & 0xffffffff; @@ -2946,30 +3325,29 @@ amd_k_invalid_rdmsr: EAX = msr.ecx1a0 & 0xffffffff; EDX = msr.ecx1a0 >> 32; break; + /* Unknown */ + case 0x1d3: + break; + /* DEBUGCTLMSR - Debugging Control Register */ case 0x1d9: - EAX = msr.debug_ctl & 0xffffffff; - EDX = msr.debug_ctl >> 32; + EAX = msr.debug_ctl; break; + /* LASTBRANCHFROMIP - address from which a branch was last taken */ + case 0x1db: + /* LASTBRANCHTOIP - destination address of the last taken branch instruction */ + case 0x1dc: + /* LASTINTFROMIP - address at which an interrupt last occurred */ + case 0x1dd: + /* LASTINTTOIP - address to which the last interrupt caused a branch */ + case 0x1de: + break; + /* ROB_CR_BKUPTMPDR6 */ case 0x1e0: - EAX = msr.ecx1e0 & 0xffffffff; - EDX = msr.ecx1e0 >> 32; + EAX = msr.rob_cr_bkuptmpdr6; break; - case 0x200: - case 0x201: - case 0x202: - case 0x203: - case 0x204: - case 0x205: - case 0x206: - case 0x207: - case 0x208: - case 0x209: - case 0x20a: - case 0x20b: - case 0x20c: - case 0x20d: - case 0x20e: - case 0x20f: + /* ECX & 0: MTRRphysBase0 ... MTRRphysBase7 + ECX & 1: MTRRphysMask0 ... MTRRphysMask7 */ + case 0x200 ... 0x20f: if (ECX & 1) { EAX = msr.mtrr_physmask[(ECX - 0x200) >> 1] & 0xffffffff; EDX = msr.mtrr_physmask[(ECX - 0x200) >> 1] >> 32; @@ -2978,79 +3356,87 @@ amd_k_invalid_rdmsr: EDX = msr.mtrr_physbase[(ECX - 0x200) >> 1] >> 32; } break; + /* MTRRfix64K_00000 */ case 0x250: EAX = msr.mtrr_fix64k_8000 & 0xffffffff; EDX = msr.mtrr_fix64k_8000 >> 32; break; + /* MTRRfix16K_80000 */ case 0x258: EAX = msr.mtrr_fix16k_8000 & 0xffffffff; EDX = msr.mtrr_fix16k_8000 >> 32; break; + /* MTRRfix16K_A0000 */ case 0x259: EAX = msr.mtrr_fix16k_a000 & 0xffffffff; EDX = msr.mtrr_fix16k_a000 >> 32; break; - case 0x268: - case 0x269: - case 0x26a: - case 0x26b: - case 0x26c: - case 0x26d: - case 0x26e: - case 0x26f: + /* MTRRfix4K_C0000 ... MTRRfix4K_F8000 */ + case 0x268 ... 0x26f: EAX = msr.mtrr_fix4k[ECX - 0x268] & 0xffffffff; EDX = msr.mtrr_fix4k[ECX - 0x268] >> 32; break; + /* Page Attribute Table */ case 0x277: + if (cpu_s->cpu_type < CPU_PENTIUM2D) + goto i686_invalid_rdmsr; EAX = msr.pat & 0xffffffff; EDX = msr.pat >> 32; break; + /* Unknown */ + case 0x280: + if (cpu_s->cpu_type == CPU_PENTIUMPRO) + goto i686_invalid_rdmsr; + break; + /* MTRRdefType */ case 0x2ff: EAX = msr.mtrr_deftype & 0xffffffff; EDX = msr.mtrr_deftype >> 32; break; + /* MC0_CTL - Machine Check 0 Control */ case 0x400: + /* MC1_CTL - Machine Check 1 Control */ case 0x404: + /* MC2_CTL - Machine Check 2 Control */ case 0x408: + /* MC4_CTL - Machine Check 4 Control */ case 0x40c: + /* MC3_CTL - Machine Check 3 Control */ case 0x410: EAX = msr.mca_ctl[(ECX - 0x400) >> 2] & 0xffffffff; EDX = msr.mca_ctl[(ECX - 0x400) >> 2] >> 32; break; + /* MC0_STATUS - Machine Check 0 Status */ case 0x401: + /* MC0_ADDR - Machine Check 0 Address */ case 0x402: + /* MC1_STATUS - Machine Check 1 Status */ case 0x405: + /* MC1_ADDR - Machine Check 1 Address */ case 0x406: - case 0x407: + /* MC2_STATUS - Machine Check 2 Status */ case 0x409: + /* MC2_ADDR - Machine Check 2 Address */ + case 0x40a: + /* MC4_STATUS - Machine Check 4 Status */ case 0x40d: + /* MC4_ADDR - Machine Check 4 Address */ case 0x40e: + /* MC3_STATUS - Machine Check 3 Status */ case 0x411: + /* MC3_ADDR - Machine Check 3 Address */ case 0x412: break; + /* Unknown */ case 0x570: EAX = msr.ecx570 & 0xffffffff; EDX = msr.ecx570 >> 32; break; - case 0x1002ff: - EAX = msr.ecx1002ff & 0xffffffff; - EDX = msr.ecx1002ff >> 32; - break; - case 0x40000020: - EAX = msr.ecx40000020 & 0xffffffff; - EDX = msr.ecx40000020 >> 32; - break; - case 0xf0f00250: - EAX = msr.ecxf0f00250 & 0xffffffff; - EDX = msr.ecxf0f00250 >> 32; - break; - case 0xf0f00258: - EAX = msr.ecxf0f00258 & 0xffffffff; - EDX = msr.ecxf0f00258 >> 32; - break; - case 0xf0f00259: - EAX = msr.ecxf0f00259 & 0xffffffff; - EDX = msr.ecxf0f00259 >> 32; + /* Unknown, possibly debug registers? */ + case 0x1000 ... 0x1007: + /* Unknown, possibly control registers? */ + case 0x2000: + case 0x2002 ... 0x2004: break; default: i686_invalid_rdmsr: @@ -3073,38 +3459,59 @@ cpu_WRMSR(void) switch (cpu_s->cpu_type) { case CPU_IBM386SLC: - case CPU_IBM486BL: case CPU_IBM486SLC: + case CPU_IBM486BL: switch (ECX) { + /* Processor Operation Register */ case 0x1000: msr.ibm_por = EAX & ((cpu_s->cpu_type > CPU_IBM386SLC) ? 0xffeff : 0xfeff); cpu_cache_int_enabled = (EAX & (1 << 7)); break; + /* Cache Region Control Register */ case 0x1001: - msr.ibm_crcr = EAX & 0xffffffffff; + msr.ibm_crcr = EAX | ((uint64_t) (EDX & 0x0000ffff) << 32); break; + /* Processor Operation Register */ case 0x1002: if ((cpu_s->cpu_type > CPU_IBM386SLC) && cpu_s->multi) msr.ibm_por2 = EAX & 0x3f000000; break; + /* Processor Control Register */ + case 0x1004: + if (cpu_s->cpu_type > CPU_IBM486SLC) + msr.ibm_pcr = EAX & 0x00d6001a; + break; } break; case CPU_WINCHIP: case CPU_WINCHIP2: switch (ECX) { + /* Pentium Processor Parity Reversal Register */ case 0x02: msr.tr1 = EAX & 2; break; + /* Pentium Processor New Feature Control */ case 0x0e: - msr.tr12 = EAX & 0x228; + msr.tr12 = EAX & 0x248; break; + /* Time Stamp Counter */ case 0x10: tsc = EAX | ((uint64_t) EDX << 32); break; + /* Performance Monitor - Control and Event Select */ case 0x11: msr.cesr = EAX & 0xff00ff; break; + /* Performance Monitor - Event Counter 0 */ + case 0x12: + msr.pmc[0] = EAX | ((uint64_t) EDX << 32); + break; + /* Performance Monitor - Event Counter 1 */ + case 0x13: + msr.pmc[1] = EAX | ((uint64_t) EDX << 32); + break; + /* Feature Control Register */ case 0x107: msr.fcr = EAX; if (EAX & (1 << 9)) @@ -3124,23 +3531,67 @@ cpu_WRMSR(void) else CPUID = cpu_s->cpuid_model; break; + /* Feature Control Register 2 */ case 0x108: msr.fcr2 = EAX | ((uint64_t) EDX << 32); break; + /* Feature Control Register 3 */ case 0x109: msr.fcr3 = EAX | ((uint64_t) EDX << 32); break; + /* Memory Configuration Register 0..7 */ + case 0x110 ... 0x117: + temp = ECX - 0x110; + if (cpu_s->cpu_type == CPU_WINCHIP2) { + if (EAX & 0x1f) + msr.mcr_ctrl |= (1 << (temp + 9)); + else + msr.mcr_ctrl &= ~(1 << (temp + 9)); + } + msr.mcr[temp] = EAX | ((uint64_t) EDX << 32); + break; + /* Memory Configuration Register Control */ + case 0x120: + msr.mcr_ctrl = EAX & ((cpu_s->cpu_type == CPU_WINCHIP2) ? 0x1df : 0x1f); + break; + /* Unknown */ + case 0x131: + case 0x142 ... 0x145: + case 0x147: + case 0x150: + case 0x151: + break; } break; case CPU_CYRIX3S: switch (ECX) { + /* Machine Check Exception Address */ case 0x00: + /* Machine Check Exception Type */ case 0x01: break; + /* Time Stamp Counter */ case 0x10: tsc = EAX | ((uint64_t) EDX << 32); break; + /* PERFCTR0 - Performance Counter Register 0 - aliased to TSC */ + case 0xc1: + break; + /* PERFCTR0 - Performance Counter Register 1 */ + case 0xc2: + msr.perfctr[1] = EAX | ((uint64_t) EDX << 32); + break; + /* BBL_CR_CTL3 - L2 Cache Control Register 3 */ + case 0x11e: + /* EVNTSEL0 - Performance Counter Event Select 0 - hardcoded */ + case 0x186: + break; + /* EVNTSEL1 - Performance Counter Event Select 1 */ + case 0x187: + msr.evntsel[1] = EAX | ((uint64_t) EDX << 32); + break; + /* Feature Control Register */ case 0x1107: msr.fcr = EAX; if (EAX & (1 << 1)) @@ -3152,52 +3603,39 @@ cpu_WRMSR(void) else cpu_CR4_mask &= ~CR4_PGE; break; + /* Feature Control Register 2 */ case 0x1108: msr.fcr2 = EAX | ((uint64_t) EDX << 32); break; + /* Feature Control Register 3 */ case 0x1109: msr.fcr3 = EAX | ((uint64_t) EDX << 32); break; - case 0x200: - case 0x201: - case 0x202: - case 0x203: - case 0x204: - case 0x205: - case 0x206: - case 0x207: - case 0x208: - case 0x209: - case 0x20a: - case 0x20b: - case 0x20c: - case 0x20d: - case 0x20e: - case 0x20f: + /* ECX & 0: MTRRphysBase0 ... MTRRphysBase7 + ECX & 1: MTRRphysMask0 ... MTRRphysMask7 */ + case 0x200 ... 0x20f: if (ECX & 1) msr.mtrr_physmask[(ECX - 0x200) >> 1] = EAX | ((uint64_t) EDX << 32); else msr.mtrr_physbase[(ECX - 0x200) >> 1] = EAX | ((uint64_t) EDX << 32); break; + /* MTRRfix64K_00000 */ case 0x250: msr.mtrr_fix64k_8000 = EAX | ((uint64_t) EDX << 32); break; + /* MTRRfix16K_80000 */ case 0x258: msr.mtrr_fix16k_8000 = EAX | ((uint64_t) EDX << 32); break; + /* MTRRfix16K_A0000 */ case 0x259: msr.mtrr_fix16k_a000 = EAX | ((uint64_t) EDX << 32); break; - case 0x268: - case 0x269: - case 0x26A: - case 0x26B: - case 0x26C: - case 0x26D: - case 0x26E: - case 0x26F: + /* MTRRfix4K_C0000 ... MTRRfix4K_F8000 */ + case 0x268 ... 0x26f: msr.mtrr_fix4k[ECX - 0x268] = EAX | ((uint64_t) EDX << 32); break; + /* MTRRdefType */ case 0x2ff: msr.mtrr_deftype = EAX | ((uint64_t) EDX << 32); break; @@ -3215,18 +3653,47 @@ cpu_WRMSR(void) case CPU_K6_2P: case CPU_K6_3P: switch (ECX) { - case 0x00: - case 0x01: + /* Machine Check Address Register */ + case 0x00000000: + if (cpu_s->cpu_type > CPU_5K86) + msr.mcar = EAX | ((uint64_t) EDX << 32); break; - case 0x0e: - msr.tr12 = EAX & 0x228; + /* Machine Check Type Register */ + case 0x00000001: + if (cpu_s->cpu_type > CPU_5K86) + msr.mctr = EAX | ((uint64_t) EDX << 32); break; - case 0x10: + /* Test Register 12 */ + case 0x0000000e: + msr.tr12 = EAX & 0x8; + break; + /* Time Stamp Counter */ + case 0x00000010: tsc = EAX | ((uint64_t) EDX << 32); break; - case 0x83: - msr.ecx83 = EAX | ((uint64_t) EDX << 32); + /* Array Access Register */ + case 0x00000082: + if (cpu_s->cpu_type > CPU_5K86) + goto amd_k_invalid_wrmsr; + msr.amd_aar = EAX | ((uint64_t) EDX << 32); break; + /* Hardware Configuration Register */ + case 0x00000083: + msr.amd_hwcr = EAX | ((uint64_t) EDX << 32); + break; + /* Write Allocate Top-of-Memory and Control Register */ + case 0x00000085: + if (cpu_s->cpu_type != CPU_5K86) + goto amd_k_invalid_wrmsr; + msr.amd_watmcr = EAX | ((uint64_t) EDX << 32); + break; + /* Write Allocate Programmable Memory Range Register */ + case 0x00000086: + if (cpu_s->cpu_type != CPU_5K86) + goto amd_k_invalid_wrmsr; + msr.amd_wapmrr = EAX | ((uint64_t) EDX << 32); + break; + /* Extended Feature Enable Register */ case 0xc0000080: temp = EAX | ((uint64_t) EDX << 32); if (temp & ~1ULL) @@ -3234,39 +3701,46 @@ cpu_WRMSR(void) else msr.amd_efer = temp; break; + /* SYSCALL Target Address Register */ case 0xc0000081: if (cpu_s->cpu_type < CPU_K6_2) goto amd_k_invalid_wrmsr; - msr.star = EAX | ((uint64_t) EDX << 32); + msr.amd_star = EAX | ((uint64_t) EDX << 32); break; + /* Write-Handling Control Register */ case 0xc0000082: msr.amd_whcr = EAX | ((uint64_t) EDX << 32); break; + /* UC/WC Cacheability Control Register */ case 0xc0000085: if (cpu_s->cpu_type < CPU_K6_2C) goto amd_k_invalid_wrmsr; msr.amd_uwccr = EAX | ((uint64_t) EDX << 32); break; + /* Enhanced Power Management Register */ case 0xc0000086: if (cpu_s->cpu_type < CPU_K6_2P) goto amd_k_invalid_wrmsr; msr.amd_epmr = EAX | ((uint64_t) EDX << 32); break; + /* Processor State Observability Register */ case 0xc0000087: if (cpu_s->cpu_type < CPU_K6_2C) goto amd_k_invalid_wrmsr; msr.amd_psor = EAX | ((uint64_t) EDX << 32); break; + /* Page Flush/Invalidate Register */ case 0xc0000088: if (cpu_s->cpu_type < CPU_K6_2C) goto amd_k_invalid_wrmsr; msr.amd_pfir = EAX | ((uint64_t) EDX << 32); break; + /* Level-2 Cache Array Access Register */ case 0xc0000089: if (cpu_s->cpu_type < CPU_K6_3) goto amd_k_invalid_wrmsr; @@ -3283,119 +3757,336 @@ amd_k_invalid_wrmsr: case CPU_P24T: case CPU_PENTIUM: case CPU_PENTIUMMMX: + cpu_log("WRMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX); + /* Filter out the upper 27 bits when ECX value is over 0x80000000, as per: + Ralf Brown, Pentium Model-Specific Registers and What They Reveal. + https://www.cs.cmu.edu/~ralf/papers/highmsr.html + But leave the bit 31 intact to be able to handle both low and high + MSRs in a single switch block. */ + switch (ECX & (ECX > 0x7fffffff ? 0x8000001f : 0x7fffffff)) { + /* Machine Check Exception Address */ + case 0x00000000: + case 0x80000000: + /* Machine Check Exception Type */ + case 0x00000001: + case 0x80000001: + break; + /* TR1 - Parity Reversal Test Register */ + case 0x00000002: + case 0x80000002: + msr.tr1 = EAX & 0x3fff; + break; + /* TR2 - Instruction Cache End Bit */ + case 0x00000004: + case 0x80000004: + if (cpu_s->cpu_type == CPU_PENTIUMMMX) + goto pentium_invalid_wrmsr; + msr.tr2 = EAX & 0xf; + break; + /* TR3 - Cache Test Data */ + case 0x00000005: + case 0x80000005: + msr.tr3 = EAX; + break; + /* TR4 - Cache Test Tag */ + case 0x00000006: + case 0x80000006: + msr.tr4 = EAX & ((cpu_s->cpu_type == CPU_PENTIUMMMX) ? 0xffffff1f : 0xffffff07); + break; + /* TR5 - Cache Test Control */ + case 0x00000007: + case 0x80000007: + msr.tr5 = EAX & ((cpu_s->cpu_type == CPU_PENTIUMMMX) ? 0x87fff : 0x7fff); + break; + /* TR6 - TLB Test Command */ + case 0x00000008: + case 0x80000008: + msr.tr6 = EAX & 0xffffff07; + break; + /* TR7 - TLB Test Data */ + case 0x00000009: + case 0x80000009: + msr.tr7 = EAX & ((cpu_s->cpu_type == CPU_PENTIUMMMX) ? 0xfffffc7f : 0xffffff9c); + break; + /* TR9 - Branch Target Buffer Tag */ + case 0x0000000b: + case 0x8000000b: + msr.tr9 = EAX & ((cpu_s->cpu_type == CPU_PENTIUMMMX) ? 0xffffffff : 0xffffffc3); + break; + /* TR10 - Branch Target Buffer Target */ + case 0x0000000c: + case 0x8000000c: + msr.tr10 = EAX; + break; + /* TR11 - Branch Target Buffer Control */ + case 0x0000000d: + case 0x8000000d: + msr.tr11 = EAX & ((cpu_s->cpu_type >= CPU_PENTIUMMMX) ? 0x3001fcf : 0xfcf); + break; + /* TR12 - New Feature Control */ + case 0x0000000e: + case 0x8000000e: + if (cpu_s->cpu_type == CPU_PENTIUMMMX) + temp = EAX & 0x38034f; + else if ((CPUID & 0xfff) >= 0x52b) + temp = EAX & 0x20435f; + else if ((CPUID & 0xfff) >= 0x520) + temp = EAX & 0x20035f; + else + temp = EAX & 0x20030f; + msr.tr12 = temp; + break; + /* Time Stamp Counter */ + case 0x00000010: + case 0x80000010: + tsc = EAX | ((uint64_t) EDX << 32); + break; + /* Performance Monitor - Control and Event Select */ + case 0x00000011: + case 0x80000011: + msr.cesr = EAX & 0x3ff03ff; + break; + /* Performance Monitor - Event Counter 0 */ + case 0x00000012: + case 0x80000012: + msr.pmc[0] = EAX | ((uint64_t) EDX << 32); + break; + /* Performance Monitor - Event Counter 1 */ + case 0x00000013: + case 0x80000013: + msr.pmc[1] = EAX | ((uint64_t) EDX << 32); + break; + /* Unknown */ + case 0x00000014: + case 0x80000014: + if ((CPUID & 0xfff) <= 0x520) + goto pentium_invalid_wrmsr; + break; + /* Unknown, possibly paging-related; initial value is 0004h, + becomes 0008h once paging is enabled */ + case 0x80000018: + /* Floating point - last prefetched opcode + bits 10-8: low three bits of first byte of FP instruction + bits 7-0: second byte of floating-point instruction */ + case 0x80000019: + /* Floating point - last executed non-control opcode */ + case 0x8000001a: + break; + /* Floating point - last non-control exception opcode - part + of FSTENV/FSAVE'd environment */ + case 0x8000001b: + EAX = msr.fp_last_xcpt & 0x7ff; + break; + /* Unknown */ + case 0x8000001c: + break; + /* Probe Mode Control */ + case 0x8000001d: + EAX = msr.probe_ctl & 0x7; + break; + /* Unknown, possibly scratchpad register */ + case 0x8000001e: + msr.ecx8000001e = EAX; + break; + /* Unknown, possibly scratchpad register */ + case 0x8000001f: + msr.ecx8000001f = EAX; + break; + /* Reserved/Unimplemented */ + case 0x80000003: + case 0x8000000a: + case 0x8000000f: + case 0x80000015 ... 0x80000017: + break; + default: +pentium_invalid_wrmsr: + cpu_log("WRMSR: Invalid MSR: %08X\n", ECX); + x86gpf(NULL, 0); + break; + } + break; + #if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) case CPU_Cx6x86: case CPU_Cx6x86L: case CPU_CxGX1: case CPU_Cx6x86MX: -#endif cpu_log("WRMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX); switch (ECX) { - case 0x00: - case 0x01: - break; + /* Test Data */ + case 0x03: + msr.tr3 = EAX; + /* Test Address */ + case 0x04: + msr.tr4 = EAX; + /* Test Command/Status */ + case 0x05: + msr.tr5 = EAX & 0x008f0f3b; + /* Time Stamp Counter */ case 0x10: tsc = EAX | ((uint64_t) EDX << 32); break; - case 0x8b: -#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) - if (cpu_s->cpu_type < CPU_Cx6x86) { -#endif - cpu_log("WRMSR: Invalid MSR: 0x8B\n"); - x86gpf(NULL, 0); /* Needed for Vista to correctly break on Pentium */ -#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) - } -#endif + /* Performance Monitor - Control and Event Select */ + case 0x11: + msr.cesr = EAX & 0x7ff07ff; + break; + /* Performance Monitor - Event Counter 0 */ + case 0x12: + msr.pmc[0] = EAX | ((uint64_t) EDX << 32); + break; + /* Performance Monitor - Event Counter 1 */ + case 0x13: + msr.pmc[1] = EAX | ((uint64_t) EDX << 32); break; } break; +#endif case CPU_PENTIUMPRO: case CPU_PENTIUM2: case CPU_PENTIUM2D: - switch (ECX) { + /* Per RichardG's probing of a real Deschutes using my RDMSR tool, + we have discovered that the top 18 bits are filtered out. */ + switch (ECX & 0x00003fff) { + /* Machine Check Exception Address */ case 0x00: + /* Machine Check Exception Type */ case 0x01: if (EAX || EDX) x86gpf(NULL, 0); break; + /* Time Stamp Counter */ case 0x10: tsc = EAX | ((uint64_t) EDX << 32); break; + /* Unknown */ + case 0x18: + break; + /* IA32_APIC_BASE - APIC Base Address */ case 0x1b: cpu_log("APIC_BASE write: %08X%08X\n", EDX, EAX); #if 0 msr.apic_base = EAX | ((uint64_t) EDX << 32); #endif break; + /* Unknown (undocumented?) MSR used by the Hyper-V BIOS */ + case 0x20: + msr.ecx20 = EAX | ((uint64_t) EDX << 32); + break; + /* Unknown */ + case 0x21: + if (cpu_s->cpu_type == CPU_PENTIUMPRO) + goto i686_invalid_wrmsr; + break; + /* EBL_CR_POWERON - Processor Hard Power-On Configuration */ case 0x2a: break; + /* Unknown */ + case 0x32: + if (cpu_s->cpu_type == CPU_PENTIUMPRO) + goto i686_invalid_wrmsr; + break; + /* TEST_CTL - Test Control Register */ + case 0x33: + msr.test_ctl = EAX; + break; + /* Unknown */ + case 0x34: + case 0x3a: + case 0x3b: + case 0x50 ... 0x54: + break; + /* BIOS_UPDT_TRIG - BIOS Update Trigger */ case 0x79: - msr.ecx79 = EAX | ((uint64_t) EDX << 32); + msr.bios_updt = EAX | ((uint64_t) EDX << 32); break; - case 0x88: - case 0x89: - case 0x8a: - case 0x8b: - msr.ecx8x[ECX - 0x88] = EAX | ((uint64_t) EDX << 32); + /* BBL_CR_D0 ... BBL_CR_D3 - Chunk 0..3 Data Register + 8Bh: BIOS_SIGN - BIOS Update Signature */ + case 0x88 ... 0x8b: + msr.bbl_cr_dx[ECX - 0x88] = EAX | ((uint64_t) EDX << 32); break; + /* Unknown */ + case 0xae: + break; + /* PERFCTR0 - Performance Counter Register 0 */ case 0xc1: + /* PERFCTR1 - Performance Counter Register 1 */ case 0xc2: - case 0xc3: - case 0xc4: - case 0xc5: - case 0xc6: - case 0xc7: - case 0xc8: - msr.ia32_pmc[ECX - 0xC1] = EAX | ((uint64_t) EDX << 32); + msr.perfctr[ECX - 0xC1] = EAX | ((uint64_t) EDX << 32); break; + /* MTRRcap */ case 0xfe: msr.mtrr_cap = EAX | ((uint64_t) EDX << 32); break; + /* BBL_CR_ADDR - L2 Cache Address Register */ case 0x116: - msr.ecx116 = EAX | ((uint64_t) EDX << 32); + msr.bbl_cr_addr = EAX | ((uint64_t) EDX << 32); break; + /* BBL_CR_DECC - L2 Cache Date ECC Register */ case 0x118: + msr.bbl_cr_decc = EAX | ((uint64_t) EDX << 32); + break; + /* BBL_CR_CTL - L2 Cache Control Register */ case 0x119: + msr.bbl_cr_ctl = EAX | ((uint64_t) EDX << 32); + break; + /* BBL_CR_TRIG - L2 Cache Trigger Register */ case 0x11a: + msr.bbl_cr_trig = EAX | ((uint64_t) EDX << 32); + break; + /* BBL_CR_BUSY - L2 Cache Busy Register */ case 0x11b: - msr.ecx11x[ECX - 0x118] = EAX | ((uint64_t) EDX << 32); + msr.bbl_cr_busy = EAX | ((uint64_t) EDX << 32); break; + /* BBL_CR_CTL3 - L2 Cache Control Register 3 */ case 0x11e: - msr.ecx11e = EAX | ((uint64_t) EDX << 32); + msr.bbl_cr_ctl3 = EAX | ((uint64_t) EDX << 32); break; + /* Unknown */ + case 0x131: + case 0x14e ... 0x151: + case 0x154: + case 0x15b: + case 0x15f: + break; + /* SYSENTER_CS - SYSENTER target CS */ case 0x174: if (cpu_s->cpu_type == CPU_PENTIUMPRO) goto i686_invalid_wrmsr; msr.sysenter_cs = EAX & 0xFFFF; break; + /* SYSENTER_ESP - SYSENTER target ESP */ case 0x175: if (cpu_s->cpu_type == CPU_PENTIUMPRO) goto i686_invalid_wrmsr; msr.sysenter_esp = EAX; break; + /* SYSENTER_EIP - SYSENTER target EIP */ case 0x176: if (cpu_s->cpu_type == CPU_PENTIUMPRO) goto i686_invalid_wrmsr; msr.sysenter_eip = EAX; break; + /* MCG_CAP - Machine Check Global Capability */ case 0x179: break; + /* MCG_STATUS - Machine Check Global Status */ case 0x17a: if (EAX || EDX) x86gpf(NULL, 0); break; + /* MCG_CTL - Machine Check Global Control */ case 0x17b: msr.mcg_ctl = EAX | ((uint64_t) EDX << 32); break; + /* EVNTSEL0 - Performance Counter Event Select 0 */ case 0x186: - msr.ecx186 = EAX | ((uint64_t) EDX << 32); - break; + /* EVNTSEL1 - Performance Counter Event Select 1 */ case 0x187: - msr.ecx187 = EAX | ((uint64_t) EDX << 32); + msr.evntsel[ECX - 0x186] = EAX | ((uint64_t) EDX << 32); break; case 0x198: msr.ecx198 = EAX | ((uint64_t) EDX << 32); @@ -3409,95 +4100,99 @@ amd_k_invalid_wrmsr: case 0x1a0: msr.ecx1a0 = EAX | ((uint64_t) EDX << 32); break; + case 0x1d3: + break; + /* DEBUGCTLMSR - Debugging Control Register */ case 0x1d9: - msr.debug_ctl = EAX | ((uint64_t) EDX << 32); + msr.debug_ctl = EAX; break; + /* ROB_CR_BKUPTMPDR6 */ case 0x1e0: - msr.ecx1e0 = EAX | ((uint64_t) EDX << 32); + msr.rob_cr_bkuptmpdr6 = EAX; break; - case 0x200: - case 0x201: - case 0x202: - case 0x203: - case 0x204: - case 0x205: - case 0x206: - case 0x207: - case 0x208: - case 0x209: - case 0x20a: - case 0x20b: - case 0x20c: - case 0x20d: - case 0x20e: - case 0x20f: + /* ECX & 0: MTRRphysBase0 ... MTRRphysBase7 + ECX & 1: MTRRphysMask0 ... MTRRphysMask7 */ + case 0x200 ... 0x20f: if (ECX & 1) msr.mtrr_physmask[(ECX - 0x200) >> 1] = EAX | ((uint64_t) EDX << 32); else msr.mtrr_physbase[(ECX - 0x200) >> 1] = EAX | ((uint64_t) EDX << 32); break; + /* MTRRfix64K_00000 */ case 0x250: msr.mtrr_fix64k_8000 = EAX | ((uint64_t) EDX << 32); break; + /* MTRRfix16K_80000 */ case 0x258: msr.mtrr_fix16k_8000 = EAX | ((uint64_t) EDX << 32); break; + /* MTRRfix16K_A0000 */ case 0x259: msr.mtrr_fix16k_a000 = EAX | ((uint64_t) EDX << 32); break; - case 0x268: - case 0x269: - case 0x26a: - case 0x26b: - case 0x26c: - case 0x26d: - case 0x26e: - case 0x26f: + /* MTRRfix4K_C0000 ... MTRRfix4K_F8000 */ + case 0x268 ... 0x26f: msr.mtrr_fix4k[ECX - 0x268] = EAX | ((uint64_t) EDX << 32); break; + /* Page Attribute Table */ case 0x277: + if (cpu_s->cpu_type < CPU_PENTIUM2D) + goto i686_invalid_wrmsr; msr.pat = EAX | ((uint64_t) EDX << 32); break; + /* Unknown */ + case 0x280: + if (cpu_s->cpu_type == CPU_PENTIUMPRO) + goto i686_invalid_wrmsr; + break; + /* MTRRdefType */ case 0x2ff: msr.mtrr_deftype = EAX | ((uint64_t) EDX << 32); break; + /* MC0_CTL - Machine Check 0 Control */ case 0x400: + /* MC1_CTL - Machine Check 1 Control */ case 0x404: + /* MC2_CTL - Machine Check 2 Control */ case 0x408: + /* MC4_CTL - Machine Check 4 Control */ case 0x40c: + /* MC3_CTL - Machine Check 3 Control */ case 0x410: msr.mca_ctl[(ECX - 0x400) >> 2] = EAX | ((uint64_t) EDX << 32); break; + /* MC0_STATUS - Machine Check 0 Status */ case 0x401: + /* MC0_ADDR - Machine Check 0 Address */ case 0x402: + /* MC1_STATUS - Machine Check 1 Status */ case 0x405: + /* MC1_ADDR - Machine Check 1 Address */ case 0x406: - case 0x407: + /* MC2_STATUS - Machine Check 2 Status */ case 0x409: + /* MC2_ADDR - Machine Check 2 Address */ + case 0x40a: + /* MC4_STATUS - Machine Check 4 Status */ case 0x40d: + /* MC4_ADDR - Machine Check 4 Address */ case 0x40e: + /* MC3_STATUS - Machine Check 3 Status */ case 0x411: + /* MC3_ADDR - Machine Check 3 Address */ case 0x412: if (EAX || EDX) x86gpf(NULL, 0); break; + /* Unknown */ case 0x570: msr.ecx570 = EAX | ((uint64_t) EDX << 32); break; - case 0x1002ff: - msr.ecx1002ff = EAX | ((uint64_t) EDX << 32); - break; - case 0x40000020: - msr.ecx40000020 = EAX | ((uint64_t) EDX << 32); - break; - case 0xf0f00250: - msr.ecxf0f00250 = EAX | ((uint64_t) EDX << 32); - break; - case 0xf0f00258: - msr.ecxf0f00258 = EAX | ((uint64_t) EDX << 32); - break; - case 0xf0f00259: - msr.ecxf0f00259 = EAX | ((uint64_t) EDX << 32); + /* Unknown, possibly debug registers? */ + case 0x1000 ... 0x1007: + /* Unknown, possibly control registers? */ + case 0x2000: + case 0x2002 ... 0x2004: break; default: i686_invalid_wrmsr: diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 03d4b80dc..019b2ebad 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -86,42 +86,33 @@ enum { }; enum { - CPU_PKG_8088 = (1 << 0), - CPU_PKG_8088_EUROPC = (1 << 1), - CPU_PKG_8086 = (1 << 2), - CPU_PKG_188 = (1 << 3), - CPU_PKG_186 = (1 << 4), - CPU_PKG_286 = (1 << 5), - CPU_PKG_386SX = (1 << 6), - CPU_PKG_386DX = (1 << 7), - CPU_PKG_M6117 = (1 << 8), - CPU_PKG_386SLC_IBM = (1 << 9), - CPU_PKG_486SLC = (1 << 10), - CPU_PKG_486SLC_IBM = (1 << 11), - CPU_PKG_486BL = (1 << 12), - CPU_PKG_486DLC = (1 << 13), - CPU_PKG_SOCKET1 = (1 << 14), - CPU_PKG_SOCKET3 = (1 << 15), - CPU_PKG_SOCKET3_PC330 = (1 << 16), - CPU_PKG_STPC = (1 << 17), - CPU_PKG_SOCKET4 = (1 << 18), - CPU_PKG_SOCKET5_7 = (1 << 19), - CPU_PKG_SOCKET8 = (1 << 20), - CPU_PKG_SLOT1 = (1 << 21), - CPU_PKG_SLOT2 = (1 << 22), - CPU_PKG_SLOTA = (1 << 23), - CPU_PKG_SOCKET370 = (1 << 24), - CPU_PKG_SOCKETA = (1 << 25), - CPU_PKG_EBGA368 = (1 << 26) + CPU_PKG_8088 = (1 << 0), + CPU_PKG_8088_EUROPC = (1 << 1), + CPU_PKG_8086 = (1 << 2), + CPU_PKG_188 = (1 << 3), + CPU_PKG_186 = (1 << 4), + CPU_PKG_286 = (1 << 5), + CPU_PKG_386SX = (1 << 6), + CPU_PKG_386DX = (1 << 7), + CPU_PKG_386DX_DESKPRO386 = (1 << 8), + CPU_PKG_M6117 = (1 << 9), + CPU_PKG_386SLC_IBM = (1 << 10), + CPU_PKG_486SLC = (1 << 11), + CPU_PKG_486SLC_IBM = (1 << 12), + CPU_PKG_486BL = (1 << 13), + CPU_PKG_486DLC = (1 << 14), + CPU_PKG_SOCKET1 = (1 << 15), + CPU_PKG_SOCKET3 = (1 << 16), + CPU_PKG_SOCKET3_PC330 = (1 << 17), + CPU_PKG_STPC = (1 << 18), + CPU_PKG_SOCKET4 = (1 << 19), + CPU_PKG_SOCKET5_7 = (1 << 20), + CPU_PKG_SOCKET8 = (1 << 21), + CPU_PKG_SLOT1 = (1 << 22), + CPU_PKG_SLOT2 = (1 << 23), + CPU_PKG_SOCKET370 = (1 << 24) }; -#define MANU_INTEL 0 -#define MANU_AMD 1 -#define MANU_CYRIX 2 -#define MANU_IDT 3 -#define MANU_NEC 4 -#define MANU_IBM 5 - #define CPU_SUPPORTS_DYNAREC 1 #define CPU_REQUIRES_DYNAREC 2 #define CPU_ALTERNATE_XTAL 4 @@ -165,17 +156,6 @@ typedef struct { const CPU *cpus; } cpu_family_t; -typedef struct { - const char *family; - const uint32_t rspeed; - const double multi; -} cpu_legacy_table_t; - -typedef struct { - const char *machine; - const cpu_legacy_table_t **tables; -} cpu_legacy_machine_t; - #define C_FLAG 0x0001 #define P_FLAG 0x0004 #define A_FLAG 0x0010 @@ -194,6 +174,7 @@ typedef struct { #define VIP_FLAG 0x0010 /* in EFLAGS */ #define VID_FLAG 0x0020 /* in EFLAGS */ +#define EM_FLAG 0x00004 /* in CR0 */ #define WP_FLAG 0x10000 /* in CR0 */ #define CR4_VME (1 << 0) /* Virtual 8086 Mode Extensions */ @@ -246,58 +227,92 @@ typedef union { } MMX_REG; typedef struct { - /* IDT WinChip and WinChip 2 MSR's */ - uint32_t tr1; /* 0x00000002, 0x0000000e */ - uint32_t tr12; /* 0x00000002, 0x0000000e */ - uint32_t cesr; /* 0x00000011 */ + /* IBM 386SLC/486SLC/486BL MSRs */ + uint64_t ibm_por; /* 0x00001000 - 386SLC and later */ + uint64_t ibm_crcr; /* 0x00001001 - 386SLC and later */ + uint64_t ibm_por2; /* 0x00001002 - 486SLC and later */ + uint64_t ibm_pcr; /* 0x00001004 - 486BL3 */ - /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ - uint64_t apic_base; /* 0x0000001b - Should the Pentium not also have this? */ - uint64_t ecx79; /* 0x00000079 */ + /* IDT WinChip C6/2/VIA Cyrix III MSRs */ + uint32_t fcr; /* 0x00000107 (IDT), 0x00001107 (VIA) */ + uint64_t fcr2; /* 0x00000108 (IDT), 0x00001108 (VIA) */ + uint64_t fcr3; /* 0x00000108 (IDT), 0x00001108 (VIA) */ + uint64_t mcr[8]; /* 0x00000110 - 0x00000117 (IDT) */ + uint32_t mcr_ctrl; /* 0x00000120 (IDT) */ - /* AMD K5, 5k86, K6, K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */ - uint64_t ecx83; /* 0x00000083 - AMD K5 and K6 MSR's. */ + /* AMD K5/K6 MSRs */ + uint64_t amd_aar; /* 0x00000082 - all K5 */ + uint64_t amd_hwcr; /* 0x00000083 - all K5 and all K6 */ + uint64_t amd_watmcr; /* 0x00000085 - K5 Model 1 and later */ + uint64_t amd_wapmrr; /* 0x00000086 - K5 Model 1 and later */ - /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ - uint64_t ecx8x[4]; /* 0x00000088 - 0x0000008b */ - uint64_t ia32_pmc[8]; /* 0x000000c1 - 0x000000c8 */ - uint64_t mtrr_cap; /* 0x000000fe */ + uint64_t amd_efer; /* 0xc0000080 - all K5 and all K6 */ + uint64_t amd_star; /* 0xc0000081 - K6-2 and later */ + uint64_t amd_whcr; /* 0xc0000082 - all K5 and all K6 */ + uint64_t amd_uwccr; /* 0xc0000085 - K6-2C and later */ + uint64_t amd_epmr; /* 0xc0000086 - K6-III+/2+ only */ + uint64_t amd_psor; /* 0xc0000087 - K6-2C and later */ + uint64_t amd_pfir; /* 0xc0000088 - K6-2C and later */ + uint64_t amd_l2aar; /* 0xc0000089 - K6-III and later */ - /* IDT WinChip and WinChip 2 MSR's that are also on the VIA Cyrix III */ - uint32_t fcr; /* 0x00000107 (IDT), 0x00001107 (VIA) */ - uint64_t fcr2; /* 0x00000108 (IDT), 0x00001108 (VIA) */ - uint64_t fcr3; /* 0x00000108 (IDT), 0x00001108 (VIA) */ + /* Pentium/Pentium MMX MSRs */ + uint64_t mcar; /* 0x00000000 - also on K5 and (R/W) K6 */ + uint64_t mctr; /* 0x00000001 - also on K5 and (R/W) K6 */ + uint32_t tr1; /* 0x00000002 - also on WinChip C6/2 */ + uint32_t tr2; /* 0x00000004 - reserved on PMMX */ + uint32_t tr3; /* 0x00000005 */ + uint32_t tr4; /* 0x00000006 */ + uint32_t tr5; /* 0x00000007 */ + uint32_t tr6; /* 0x00000008 */ + uint32_t tr7; /* 0x00000009 */ + uint32_t tr9; /* 0x0000000b */ + uint32_t tr10; /* 0x0000000c */ + uint32_t tr11; /* 0x0000000d */ + uint32_t tr12; /* 0x0000000e - also on WinChip C6/2 and K6 */ + uint32_t cesr; /* 0x00000011 - also on WinChip C6/2 and Cx6x86MX */ + uint64_t pmc[2]; /* 0x00000012, 0x00000013 - also on WinChip C6/2 and Cx6x86MX */ + uint32_t fp_last_xcpt; /* 0x8000001b - undocumented */ + uint32_t probe_ctl; /* 0x8000001d - undocumented */ + uint32_t ecx8000001e; /* 0x8000001e - undocumented */ + uint32_t ecx8000001f; /* 0x8000001f - undocumented */ - /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ - uint64_t ecx116; /* 0x00000116 */ - uint64_t ecx11x[4]; /* 0x00000118 - 0x0000011b */ - uint64_t ecx11e; /* 0x0000011e */ + /* Pentium Pro/II MSRs */ + uint64_t apic_base; /* 0x0000001b */ + uint32_t test_ctl; /* 0x00000033 */ + uint64_t bios_updt; /* 0x00000079 */ - /* Pentium II Klamath and Pentium II Deschutes MSR's */ - uint16_t sysenter_cs; /* 0x00000174 - SYSENTER/SYSEXIT MSR's */ - uint32_t sysenter_esp; /* 0x00000175 - SYSENTER/SYSEXIT MSR's */ - uint32_t sysenter_eip; /* 0x00000176 - SYSENTER/SYSEXIT MSR's */ + uint64_t bbl_cr_dx[4]; /* 0x00000088 - 0x0000008b */ + uint64_t perfctr[2]; /* 0x000000c1, 0x000000c2 */ + uint64_t mtrr_cap; /* 0x000000fe */ - /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ - uint64_t mcg_ctl; /* 0x0000017b - Machine Check Architecture */ - uint64_t ecx186; /* 0x00000186, 0x00000187 */ - uint64_t ecx187; /* 0x00000186, 0x00000187 */ + uint64_t bbl_cr_addr; /* 0x00000116 */ + uint64_t bbl_cr_decc; /* 0x00000118 */ + uint64_t bbl_cr_ctl; /* 0x00000119 */ + uint64_t bbl_cr_trig; /* 0x0000011a */ + uint64_t bbl_cr_busy; /* 0x0000011b */ + uint64_t bbl_cr_ctl3; /* 0x0000011e */ - /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ - uint64_t debug_ctl; /* 0x000001d9 - Debug Registers Control */ - uint64_t ecx1e0; /* 0x000001e0 */ + uint16_t sysenter_cs; /* 0x00000174 - Pentium II and later */ + uint32_t sysenter_esp; /* 0x00000175 - Pentium II and later */ + uint32_t sysenter_eip; /* 0x00000176 - Pentium II and later */ - /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's that are also - on the VIA Cyrix III */ - uint64_t mtrr_physbase[8]; /* 0x00000200 - 0x0000020f */ + uint64_t mcg_ctl; /* 0x0000017b */ + uint64_t evntsel[2]; /* 0x00000186, 0x00000187 */ + + uint32_t debug_ctl; /* 0x000001d9 */ + uint32_t rob_cr_bkuptmpdr6; /* 0x000001e0 */ + + /* MTTR-related MSRs also present on the VIA Cyrix III */ + uint64_t mtrr_physbase[8]; /* 0x00000200 - 0x0000020f (ECX & 0) */ uint64_t mtrr_physmask[8]; /* 0x00000200 - 0x0000020f (ECX & 1) */ uint64_t mtrr_fix64k_8000; /* 0x00000250 */ uint64_t mtrr_fix16k_8000; /* 0x00000258 */ uint64_t mtrr_fix16k_a000; /* 0x00000259 */ uint64_t mtrr_fix4k[8]; /* 0x00000268 - 0x0000026f */ + uint64_t mtrr_deftype; /* 0x000002ff */ /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ - uint64_t pat; /* 0x00000277 */ + uint64_t pat; /* 0x00000277 - Pentium II Deschutes and later */ /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's that are also on the VIA Cyrix III */ @@ -310,48 +325,12 @@ typedef struct { uint64_t ecx19d; /* 0x0000019d */ /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ - uint64_t mca_ctl[5]; /* 0x00000400, 0x00000404, 0x00000408, 0x0000040c, 0x00000410 - Machine Check Architecture */ + uint64_t mca_ctl[5]; /* 0x00000400, 0x00000404, 0x00000408, 0x0000040c, 0x00000410 */ uint64_t ecx570; /* 0x00000570 */ - /* IBM 386SLC, 486SLC, and 486BL MSR's */ - uint64_t ibm_por; /* 0x00001000 - Processor Operation Register */ - uint64_t ibm_crcr; /* 0x00001001 - Cache Region Control Register */ - - /* IBM 486SLC and 486BL MSR's */ - uint64_t ibm_por2; /* 0x00001002 - Processor Operation Register */ - - /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ - uint64_t ecx1002ff; /* 0x001002ff - MSR used by some Intel AMI boards */ - - /* AMD K5, 5k86, K6, K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */ - uint64_t amd_efer; /* 0xc0000080 */ - - /* AMD K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */ - uint64_t star; /* 0xc0000081 */ - - /* AMD K5, 5k86, K6, K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */ - uint64_t amd_whcr; /* 0xc0000082 */ - - /* AMD K6-2C, K6-3, K6-2P, and K6-3P MSR's */ - uint64_t amd_uwccr; /* 0xc0000085 */ - - /* AMD K6-2P and K6-3P MSR's */ - uint64_t amd_epmr; /* 0xc0000086 */ - - /* AMD K6-2C, K6-3, K6-2P, and K6-3P MSR's */ - uint64_t amd_psor; /* 0xc0000087, 0xc0000088 */ - uint64_t amd_pfir; /* 0xc0000087, 0xc0000088 */ - - /* K6-3, K6-2P, and K6-3P MSR's */ - uint64_t amd_l2aar; /* 0xc0000089 */ - - /* Weird long MSR's used by the Hyper-V BIOS. */ - uint64_t ecx40000020; /* 0x40000020 */ - - /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */ - uint64_t ecxf0f00250; /* 0xf0f00250 - Some weird long MSR's used by i686 AMI & some Phoenix BIOSes */ - uint64_t ecxf0f00258; /* 0xf0f00258 */ - uint64_t ecxf0f00259; /* 0xf0f00259 */ + /* Other/Unclassified MSRs */ + uint64_t ecx20; /* 0x00000020, really 0x40000020, but we filter out the top 18 bits + like a real Deschutes does. */ } msr_t; typedef struct { @@ -539,7 +518,6 @@ extern cpu_state_t cpu_state; extern fpu_state_t fpu_state; extern const cpu_family_t cpu_families[]; -extern const cpu_legacy_machine_t cpu_legacy_table[]; extern cpu_family_t *cpu_f; extern CPU *cpu_s; extern int cpu_override; @@ -618,7 +596,6 @@ extern double bus_timing; extern double isa_timing; extern double pci_timing; extern double agp_timing; -extern uint64_t pmc[2]; extern uint16_t temp_seg_data[4]; extern uint16_t cs_msr; extern uint32_t esp_msr; @@ -799,6 +776,11 @@ void cyrix_write_seg_descriptor(uint32_t addr, x86seg *seg); #define SMHR_VALID (1 << 0) #define SMHR_ADDR_MASK (0xfffffffc) +typedef union { + uint32_t fd; + uint8_t b[4]; +} fetch_dat_t; + typedef struct { struct { uint32_t base; @@ -820,6 +802,7 @@ extern int hlt_reset_pending; extern cyrix_t cyrix; extern int prefetch_prefixes; +extern int cpu_use_exec; extern uint8_t use_custom_nmi_vector; extern uint32_t custom_nmi_vector; @@ -844,9 +827,19 @@ extern void nmi_raise(void); extern MMX_REG *MMP[8]; extern uint16_t *MMEP[8]; +extern int cpu_block_end; +extern int cpu_override_dynarec; + extern void mmx_init(void); extern void prefetch_flush(void); extern void prefetch_run(int instr_cycles, int bytes, int modrm, int reads, int reads_l, int writes, int writes_l, int ea32); +extern int lock_legal[256]; +extern int lock_legal_0f[256]; +extern int lock_legal_ba[8]; +extern int lock_legal_80[8]; +extern int lock_legal_f6[8]; +extern int lock_legal_fe[8]; + #endif /*EMU_CPU_H*/ diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 947804014..502b2c86e 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -1043,6 +1043,17 @@ const cpu_family_t cpu_families[] = { {"", 0} } }, { + .package = CPU_PKG_386DX_DESKPRO386, + .manufacturer = "Intel", + .name = "i386DX", + .internal_name = "i386dx_deskpro386", + .cpus = (const CPU[]) { + {"16", CPU_386DX, fpus_80286, 16000000, 1, 5000, 0x0308, 0, 0, 0, 3,3,3,3, 2}, + {"20", CPU_386DX, fpus_80386, 20000000, 1, 5000, 0x0308, 0, 0, 0, 4,4,3,3, 3}, + {"25", CPU_386DX, fpus_80386, 25000000, 1, 5000, 0x0308, 0, 0, 0, 4,4,3,3, 3}, + {"", 0} + } + }, { .package = CPU_PKG_386DX, .manufacturer = "Intel", .name = "RapidCAD", @@ -1070,8 +1081,8 @@ const cpu_family_t cpu_families[] = { .name = "M6117", .internal_name = "m6117", .cpus = (const CPU[]) { /* All timings and edx_reset values assumed. */ - {"33", CPU_386SX, fpus_none, 33333333, 1, 5000, 0x2308, 0, 0, 0, 6,6,3,3, 4}, - {"40", CPU_386SX, fpus_none, 40000000, 1, 5000, 0x2308, 0, 0, 0, 7,7,3,3, 5}, + {"33", CPU_386SX, fpus_none, 33333333, 1, 5000, 0x2309, 0, 0, 0, 6,6,3,3, 4}, + {"40", CPU_386SX, fpus_none, 40000000, 1, 5000, 0x2309, 0, 0, 0, 7,7,3,3, 5}, {"", 0} } }, { @@ -1387,9 +1398,9 @@ const cpu_family_t cpu_families[] = { .name = "Am5x86", .internal_name = "am5x86", .cpus = (const CPU[]) { - {"P75", CPU_ENH_Am486DX, fpus_internal, 133333333, 4.0, 5000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16}, - {"P75+", CPU_ENH_Am486DX, fpus_internal, 150000000, 3.0, 5000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*The rare P75+ was indeed a triple-clocked 150 MHz according to research*/ - {"P90", CPU_ENH_Am486DX, fpus_internal, 160000000, 4.0, 5000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*160 MHz on a 40 MHz bus was a common overclock and "5x86/P90" was used by a number of BIOSes to refer to that configuration*/ + {"133 (P75)", CPU_ENH_Am486DX, fpus_internal, 133333333, 4.0, 5000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16}, + {"150 (P75+)", CPU_ENH_Am486DX, fpus_internal, 150000000, 3.0, 5000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*The rare P75+ was indeed a triple-clocked 150 MHz according to research*/ + {"160 (P90)", CPU_ENH_Am486DX, fpus_internal, 160000000, 4.0, 5000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*160 MHz on a 40 MHz bus was a common overclock and "5x86/P90" was used by a number of BIOSes to refer to that configuration*/ {"", 0} } }, { @@ -1604,23 +1615,7 @@ const cpu_family_t cpu_families[] = { { .package = CPU_PKG_SOCKET5_7, .manufacturer = "AMD", - .name = "K5 (5k86)", - .internal_name = "k5_5k86", - .cpus = (const CPU[]) { - {"75 (P75)", CPU_K5, fpus_internal, 75000000, 1.5, 3520, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, - {"90 (P90)", CPU_K5, fpus_internal, 90000000, 1.5, 3520, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2}, - {"100 (P100)", CPU_K5, fpus_internal, 100000000, 1.5, 3520, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, - {"90 (PR120)", CPU_5K86, fpus_internal, 120000000, 2.0, 3520, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, - {"100 (PR133)", CPU_5K86, fpus_internal, 133333333, 2.0, 3520, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, - {"105 (PR150)", CPU_5K86, fpus_internal, 150000000, 2.5, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, - {"116.5 (PR166)", CPU_5K86, fpus_internal, 166666666, 2.5, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, - {"133 (PR200)", CPU_5K86, fpus_internal, 200000000, 3.0, 3520, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "AMD", - .name = "K5 (SSA/5)", + .name = "K5 (Model 0)", .internal_name = "k5_ssa5", .cpus = (const CPU[]) { {"75 (PR75)", CPU_K5, fpus_internal, 75000000, 1.5, 3520, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, @@ -1628,6 +1623,19 @@ const cpu_family_t cpu_families[] = { {"100 (PR100)", CPU_K5, fpus_internal, 100000000, 1.5, 3520, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, {"", 0} } + }, { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "AMD", + .name = "K5 (Model 1/2/3)", + .internal_name = "k5_5k86", + .cpus = (const CPU[]) { + {"90 (PR120)", CPU_5K86, fpus_internal, 120000000, 2.0, 3520, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, + {"100 (PR133)", CPU_5K86, fpus_internal, 133333333, 2.0, 3520, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, + {"105 (PR150)", CPU_5K86, fpus_internal, 150000000, 2.5, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, + {"116.7 (PR166)", CPU_5K86, fpus_internal, 166666666, 2.5, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, + {"133 (PR200)", CPU_5K86, fpus_internal, 200000000, 3.0, 3520, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, + {"", 0} + } }, #endif { @@ -1763,12 +1771,12 @@ const cpu_family_t cpu_families[] = { .name = "Cx6x86", .internal_name = "cx6x86", .cpus = (const CPU[]) { - {"P90", CPU_Cx6x86, fpus_internal, 80000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10}, - {"PR120+", CPU_Cx6x86, fpus_internal, 100000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12}, - {"PR133+", CPU_Cx6x86, fpus_internal, 110000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, - {"PR150+", CPU_Cx6x86, fpus_internal, 120000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, - {"PR166+", CPU_Cx6x86, fpus_internal, 133333333, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"PR200+", CPU_Cx6x86, fpus_internal, 150000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, + {"80 (PR90+)", CPU_Cx6x86, fpus_internal, 80000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10}, + {"100 (PR120+)", CPU_Cx6x86, fpus_internal, 100000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12}, + {"110 (PR133+)", CPU_Cx6x86, fpus_internal, 110000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, + {"120 (PR150+)", CPU_Cx6x86, fpus_internal, 120000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"133 (PR166+)", CPU_Cx6x86, fpus_internal, 133333333, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"150 (PR200+)", CPU_Cx6x86, fpus_internal, 150000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, {"", 0} } }, { @@ -1777,10 +1785,10 @@ const cpu_family_t cpu_families[] = { .name = "Cx6x86L", .internal_name = "cx6x86l", .cpus = (const CPU[]) { - {"PR133+", CPU_Cx6x86L, fpus_internal, 110000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, - {"PR150+", CPU_Cx6x86L, fpus_internal, 120000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, - {"PR166+", CPU_Cx6x86L, fpus_internal, 133333333, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"PR200+", CPU_Cx6x86L, fpus_internal, 150000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, + {"110 (PR133+)", CPU_Cx6x86L, fpus_internal, 110000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, + {"120 (PR150+)", CPU_Cx6x86L, fpus_internal, 120000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, + {"133 (PR166+)", CPU_Cx6x86L, fpus_internal, 133333333, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"150 (PR200+)", CPU_Cx6x86L, fpus_internal, 150000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, {"", 0} } }, { @@ -1789,10 +1797,10 @@ const cpu_family_t cpu_families[] = { .name = "Cx6x86MX", .internal_name = "cx6x86mx", .cpus = (const CPU[]) { - {"PR166", CPU_Cx6x86MX, fpus_internal, 133333333, 2.0, 2900, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"PR200", CPU_Cx6x86MX, fpus_internal, 166666666, 2.5, 2900, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"PR233", CPU_Cx6x86MX, fpus_internal, 187500000, 2.5, 2900, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2}, - {"PR266", CPU_Cx6x86MX, fpus_internal, 208333333, 2.5, 2700, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25}, + {"133 (PR166)", CPU_Cx6x86MX, fpus_internal, 133333333, 2.0, 2900, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, + {"166 (PR200)", CPU_Cx6x86MX, fpus_internal, 166666666, 2.5, 2900, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, + {"187.5 (PR233)", CPU_Cx6x86MX, fpus_internal, 187500000, 2.5, 2900, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2}, + {"208.3 (PR266)", CPU_Cx6x86MX, fpus_internal, 208333333, 2.5, 2700, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25}, {"", 0} } }, { @@ -1801,11 +1809,11 @@ const cpu_family_t cpu_families[] = { .name = "MII", .internal_name = "mii", .cpus = (const CPU[]) { - {"PR300", CPU_Cx6x86MX, fpus_internal, 233333333, 3.5, 2900, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28}, - {"PR333", CPU_Cx6x86MX, fpus_internal, 250000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 9, 9, 30}, - {"PR366", CPU_Cx6x86MX, fpus_internal, 250000000, 2.5, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 7, 7, 30}, - {"PR400", CPU_Cx6x86MX, fpus_internal, 285000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 34}, - {"PR433", CPU_Cx6x86MX, fpus_internal, 300000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 36}, + {"233 (PR300)", CPU_Cx6x86MX, fpus_internal, 233333333, 3.5, 2900, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28}, + {"250/83 (PR333)", CPU_Cx6x86MX, fpus_internal, 250000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 9, 9, 30}, + {"250/100 (PR366)", CPU_Cx6x86MX, fpus_internal, 250000000, 2.5, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 7, 7, 30}, + {"285 (PR400)", CPU_Cx6x86MX, fpus_internal, 285000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 34}, + {"300 (PR433)", CPU_Cx6x86MX, fpus_internal, 300000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 36}, {"", 0} } }, @@ -1972,957 +1980,3 @@ const cpu_family_t cpu_families[] = { } // clang-format on }; - -/* Legacy CPU tables for backwards compatibility. */ - -static const cpu_legacy_table_t cpus_8088[] = { - {"8088", 4772728, 1}, - { "8088", 7159092, 1}, - { "8088", 8000000, 1}, - { "8088", 10000000, 1}, - { "8088", 12000000, 1}, - { "8088", 16000000, 1}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_pcjr[] = { - {"8088", 4772728, 1}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_europc[] = { - {"8088_europc", 4772728, 1}, - { "8088_europc", 7159092, 1}, - { "8088_europc", 9545456, 1}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_8086[] = { - {"8086", 7159092, 1}, - { "8086", 8000000, 1}, - { "8086", 9545456, 1}, - { "8086", 10000000, 1}, - { "8086", 12000000, 1}, - { "8086", 16000000, 1}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_pc1512[] = { - {"8086", 8000000, 1}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_286[] = { - {"286", 6000000, 1}, - { "286", 8000000, 1}, - { "286", 10000000, 1}, - { "286", 12500000, 1}, - { "286", 16000000, 1}, - { "286", 20000000, 1}, - { "286", 25000000, 1}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_ibmat[] = { - {"286", 6000000, 1}, - { "286", 8000000, 1}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_ibmxt286[] = { - {"286", 6000000, 1}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_ps1_m2011[] = { - {"286", 10000000, 1}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_ps2_m30_286[] = { - {"286", 10000000, 1}, - { "286", 12500000, 1}, - { "286", 16000000, 1}, - { "286", 20000000, 1}, - { "286", 25000000, 1}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_i386SX[] = { - {"i386sx", 16000000, 1}, - { "i386sx", 20000000, 1}, - { "i386sx", 25000000, 1}, - { "i386sx", 33333333, 1}, - { "i386sx", 40000000, 1}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_i386DX[] = { - {"i386dx", 16000000, 1}, - { "i386dx", 20000000, 1}, - { "i386dx", 25000000, 1}, - { "i386dx", 33333333, 1}, - { "i386dx", 40000000, 1}, - { "rapidcad", 25000000, 1}, - { "rapidcad", 33333333, 1}, - { "rapidcad", 40000000, 1}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_Am386SX[] = { - {"am386sx", 16000000, 1}, - { "am386sx", 20000000, 1}, - { "am386sx", 25000000, 1}, - { "am386sx", 33333333, 1}, - { "am386sx", 40000000, 1}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_Am386DX[] = { - {"am386dx", 25000000, 1}, - { "am386dx", 33333333, 1}, - { "am386dx", 40000000, 1}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_ALiM6117[] = { - {"m6117", 33333333, 1}, - { "m6117", 40000000, 1}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_486SLC[] = { - {"cx486slc", 20000000, 1}, - { "cx486slc", 25000000, 1}, - { "cx486slc", 33333333, 1}, - { "cx486srx2", 32000000, 2}, - { "cx486srx2", 40000000, 2}, - { "cx486srx2", 50000000, 2}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_IBM486SLC[] = { - {"ibm486slc", 33333333, 1}, - { "ibm486slc2", 40000000, 2}, - { "ibm486slc2", 50000000, 2}, - { "ibm486slc2", 66666666, 2}, - { "ibm486slc3", 60000000, 3}, - { "ibm486slc3", 75000000, 3}, - { "ibm486slc3", 100000000, 3}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_IBM486BL[] = { - {"ibm486bl2", 50000000, 2}, - { "ibm486bl2", 66666666, 2}, - { "ibm486bl3", 75000000, 3}, - { "ibm486bl3", 100000000, 3}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_486DLC[] = { - {"cx486dlc", 25000000, 1}, - { "cx486dlc", 33333333, 1}, - { "cx486dlc", 40000000, 1}, - { "cx486drx2", 32000000, 2}, - { "cx486drx2", 40000000, 2}, - { "cx486drx2", 50000000, 2}, - { "cx486drx2", 66666666, 2}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_i486S1[] = { - {"i486sx", 16000000, 1}, - { "i486sx", 20000000, 1}, - { "i486sx", 25000000, 1}, - { "i486sx", 33333333, 1}, - { "i486sx2", 50000000, 2}, - { "i486sx2", 66666666, 2}, - { "i486dx", 25000000, 1}, - { "i486dx", 33333333, 1}, - { "i486dx", 50000000, 1}, - { "i486dx2", 40000000, 2}, - { "i486dx2", 50000000, 2}, - { "i486dx2", 66666666, 2}, - { "idx4_od", 75000000, 3}, - { "idx4_od", 100000000, 3}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_Am486S1[] = { - {"am486sx", 33333333, 1}, - { "am486sx", 40000000, 1}, - { "am486sx2", 50000000, 2}, - { "am486sx2", 66666666, 2}, - { "am486dx", 33333333, 1}, - { "am486dx", 40000000, 1}, - { "am486dx2", 50000000, 2}, - { "am486dx2", 66666666, 2}, - { "am486dx2", 80000000, 2}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_Cx486S1[] = { - {"cx486s", 25000000, 1.0}, - { "cx486s", 33333333, 1.0}, - { "cx486s", 40000000, 1.0}, - { "cx486dx", 33333333, 1.0}, - { "cx486dx", 40000000, 1.0}, - { "cx486dx2", 50000000, 2.0}, - { "cx486dx2", 66666666, 2.0}, - { "cx486dx2", 80000000, 2.0}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_i486[] = { - {"i486sx", 16000000, 1.0}, - { "i486sx", 20000000, 1.0}, - { "i486sx", 25000000, 1.0}, - { "i486sx", 33333333, 1.0}, - { "i486sx2", 50000000, 2.0}, - { "i486sx2", 66666666, 2.0}, - { "i486dx", 25000000, 1.0}, - { "i486dx", 33333333, 1.0}, - { "i486dx", 50000000, 1.0}, - { "i486dx2", 40000000, 2.0}, - { "i486dx2", 50000000, 2.0}, - { "i486dx2", 66666666, 2.0}, - { "idx4", 75000000, 3.0}, - { "idx4", 100000000, 3.0}, - { "idx4_od", 75000000, 3.0}, - { "idx4_od", 100000000, 3.0}, - { "pentium_p24t", 62500000, 2.5}, - { "pentium_p24t", 83333333, 2.5}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_i486_PC330[] = { - {"i486dx2", 50000000, 2.0}, - { "i486dx2", 66666666, 2.0}, - { "idx4", 75000000, 3.0}, - { "idx4", 100000000, 3.0}, - { "pentium_p24t", 62500000, 2.5}, - { "pentium_p24t", 83333333, 2.5}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_Am486[] = { - {"am486sx", 33333333, 1.0}, - { "am486sx", 40000000, 1.0}, - { "am486sx2", 50000000, 2.0}, - { "am486sx2", 66666666, 2.0}, - { "am486dx", 33333333, 1.0}, - { "am486dx", 40000000, 1.0}, - { "am486dx2", 50000000, 2.0}, - { "am486dx2", 66666666, 2.0}, - { "am486dx2", 80000000, 2.0}, - { "am486dx4", 75000000, 3.0}, - { "am486dx4", 90000000, 3.0}, - { "am486dx4", 100000000, 3.0}, - { "am486dx4", 120000000, 3.0}, - { "am5x86", 133333333, 4.0}, - { "am5x86", 150000000, 3.0}, - { "am5x86", 160000000, 4.0}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_Cx486[] = { - {"cx486s", 25000000, 1.0}, - { "cx486s", 33333333, 1.0}, - { "cx486s", 40000000, 1.0}, - { "cx486dx", 33333333, 1.0}, - { "cx486dx", 40000000, 1.0}, - { "cx486dx2", 50000000, 2.0}, - { "cx486dx2", 66666666, 2.0}, - { "cx486dx2", 80000000, 2.0}, - { "cx486dx4", 75000000, 3.0}, - { "cx486dx4", 100000000, 3.0}, - { "cx5x86", 80000000, 2.0}, - { "cx5x86", 100000000, 3.0}, - { "cx5x86", 120000000, 3.0}, - { "cx5x86", 133333333, 4.0}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_STPCDX[] = { - {"stpc_dx", 66666666, 1.0}, - { "stpc_dx", 75000000, 1.0}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_STPCDX2[] = { - {"stpc_dx2", 133333333, 2.0}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_6x863V[] = { - {"cx6x86", 80000000, 2.0}, - { "cx6x86", 100000000, 2.0}, - { "cx6x86", 110000000, 2.0}, - { "cx6x86", 120000000, 2.0}, - { "cx6x86", 133333333, 2.0}, - { "cx6x86", 150000000, 2.0}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_6x86[] = { - {"cx6x86", 80000000, 2.0}, - { "cx6x86", 100000000, 2.0}, - { "cx6x86", 110000000, 2.0}, - { "cx6x86", 120000000, 2.0}, - { "cx6x86", 133333333, 2.0}, - { "cx6x86", 150000000, 2.0}, - { "cx6x86l", 110000000, 2.0}, - { "cx6x86l", 120000000, 2.0}, - { "cx6x86l", 133333333, 2.0}, - { "cx6x86l", 150000000, 2.0}, - { "cx6x86mx", 133333333, 2.0}, - { "cx6x86mx", 166666666, 2.5}, - { "cx6x86mx", 187500000, 2.5}, - { "cx6x86mx", 208333333, 2.5}, - { "mii", 233333333, 3.5}, - { "mii", 250000000, 3.0}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_6x86SS7[] = { - {"cx6x86", 80000000, 2.0}, - { "cx6x86", 100000000, 2.0}, - { "cx6x86", 110000000, 2.0}, - { "cx6x86", 120000000, 2.0}, - { "cx6x86", 133333333, 2.0}, - { "cx6x86", 150000000, 2.0}, - { "cx6x86l", 110000000, 2.0}, - { "cx6x86l", 120000000, 2.0}, - { "cx6x86l", 133333333, 2.0}, - { "cx6x86l", 150000000, 2.0}, - { "cx6x86mx", 133333333, 2.0}, - { "cx6x86mx", 166666666, 2.5}, - { "cx6x86mx", 187500000, 2.5}, - { "cx6x86mx", 208333333, 2.5}, - { "mii", 233333333, 3.5}, - { "mii", 250000000, 3.0}, - { "mii", 250000000, 2.5}, - { "mii", 285000000, 3.0}, - { "mii", 300000000, 3.0}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_WinChip[] = { - {"winchip", 75000000, 1.5}, - { "winchip", 90000000, 1.5}, - { "winchip", 100000000, 1.5}, - { "winchip", 120000000, 2.0}, - { "winchip", 133333333, 2.0}, - { "winchip", 150000000, 2.5}, - { "winchip", 166666666, 2.5}, - { "winchip", 180000000, 3.0}, - { "winchip", 200000000, 3.0}, - { "winchip", 225000000, 3.0}, - { "winchip", 240000000, 4.0}, - { "winchip2", 200000000, 3.0}, - { "winchip2", 225000000, 3.0}, - { "winchip2", 240000000, 4.0}, - { "winchip2", 250000000, 3.0}, - { "winchip2a", 200000000, 3.0}, - { "winchip2a", 233333333, 3.5}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_WinChip_SS7[] = { - {"winchip", 75000000, 1.5}, - { "winchip", 90000000, 1.5}, - { "winchip", 100000000, 1.5}, - { "winchip", 120000000, 2.0}, - { "winchip", 133333333, 2.0}, - { "winchip", 150000000, 2.5}, - { "winchip", 166666666, 2.5}, - { "winchip", 180000000, 3.0}, - { "winchip", 200000000, 3.0}, - { "winchip", 225000000, 3.0}, - { "winchip", 240000000, 4.0}, - { "winchip2", 200000000, 3.0}, - { "winchip2", 225000000, 3.0}, - { "winchip2", 240000000, 4.0}, - { "winchip2", 250000000, 3.0}, - { "winchip2a", 200000000, 3.0}, - { "winchip2a", 233333333, 3.5}, - { "winchip2a", 233333333, 7.0}, - { "winchip2a", 250000000, 2.5}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_Pentium5V[] = { - {"pentium_p5", 60000000, 1}, - { "pentium_p5", 66666666, 1}, - { "pentium_p54c_od5v", 120000000, 2}, - { "pentium_p54c_od5v", 133333333, 2}, - { NULL, 0, 0} -}; - -static const cpu_legacy_table_t cpus_PentiumS5[] = { - {"pentium_p54c", 75000000, 1.5}, - { "pentium_p55c_od", 75000000, 1.5}, - { "pentium_p54c", 90000000, 1.5}, - { "pentium_p54c", 100000000, 2.0}, - { "pentium_p54c", 100000000, 1.5}, - { "pentium_p54c", 120000000, 2.0}, - { "pentium_p54c", 133333333, 2.0}, - { "pentium_p54c_od3v", 125000000, 3.0}, - { "pentium_p54c_od3v", 150000000, 2.5}, - { "pentium_p54c_od3v", 166666666, 2.5}, - { "pentium_p55c_od", 125000000, 2.5}, - { "pentium_p55c_od", 150000000, 2.5}, - { "pentium_p55c_od", 166000000, 2.5}, - { "pentium_p55c_od", 180000000, 3.0}, - { "pentium_p55c_od", 200000000, 3.0}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_Pentium3V[] = { - {"pentium_p54c", 75000000, 1.5}, - { "pentium_p55c_od", 75000000, 1.5}, - { "pentium_p54c", 90000000, 1.5}, - { "pentium_p54c", 100000000, 2.0}, - { "pentium_p54c", 100000000, 1.5}, - { "pentium_p54c", 120000000, 2.0}, - { "pentium_p54c", 133333333, 2.0}, - { "pentium_p54c", 150000000, 2.5}, - { "pentium_p54c", 166666666, 2.5}, - { "pentium_p54c", 200000000, 3.0}, - { "pentium_p54c_od3v", 125000000, 2.5}, - { "pentium_p54c_od3v", 150000000, 2.5}, - { "pentium_p54c_od3v", 166666666, 2.5}, - { "pentium_p55c_od", 125000000, 2.5}, - { "pentium_p55c_od", 150000000, 2.5}, - { "pentium_p55c_od", 166000000, 2.5}, - { "pentium_p55c_od", 180000000, 3.0}, - { "pentium_p55c_od", 200000000, 3.0}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_Pentium[] = { - {"pentium_p54c", 75000000, 1.5}, - { "pentium_p55c_od", 75000000, 1.5}, - { "pentium_p54c", 90000000, 1.5}, - { "pentium_p54c", 100000000, 2.0}, - { "pentium_p54c", 100000000, 1.5}, - { "pentium_p54c", 120000000, 2.0}, - { "pentium_p54c", 133333333, 2.0}, - { "pentium_p54c", 150000000, 2.5}, - { "pentium_p54c", 166666666, 2.5}, - { "pentium_p54c", 200000000, 3.0}, - { "pentium_p55c", 166666666, 2.5}, - { "pentium_p55c", 200000000, 3.0}, - { "pentium_p55c", 233333333, 3.5}, - { "pentium_tillamook", 120000000, 2.0}, - { "pentium_tillamook", 133333333, 2.0}, - { "pentium_tillamook", 150000000, 2.5}, - { "pentium_tillamook", 166666666, 2.5}, - { "pentium_tillamook", 200000000, 3.0}, - { "pentium_tillamook", 233333333, 3.5}, - { "pentium_tillamook", 266666666, 4.0}, - { "pentium_tillamook", 300000000, 4.5}, - { "pentium_p54c_od3v", 125000000, 2.5}, - { "pentium_p54c_od3v", 150000000, 2.5}, - { "pentium_p54c_od3v", 166666666, 2.5}, - { "pentium_p55c_od", 125000000, 2.5}, - { "pentium_p55c_od", 150000000, 2.5}, - { "pentium_p55c_od", 166000000, 2.5}, - { "pentium_p55c_od", 180000000, 3.0}, - { "pentium_p55c_od", 200000000, 3.0}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_K5[] = { - {"k5_5k86", 75000000, 1.5}, - { "k5_ssa5", 75000000, 1.5}, - { "k5_5k86", 90000000, 1.5}, - { "k5_ssa5", 90000000, 1.5}, - { "k5_5k86", 100000000, 1.5}, - { "k5_ssa5", 100000000, 1.5}, - { "k5_5k86", 120000000, 2.0}, - { "k5_5k86", 133333333, 2.0}, - { "k5_5k86", 150000000, 2.5}, - { "k5_5k86", 166666666, 2.5}, - { "k5_5k86", 200000000, 3.0}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_K56[] = { - {"k6_m6", 66666666, 1.0}, - { "k6_m6", 100000000, 1.5}, - { "k6_m6", 133333333, 2.0}, - { "k6_m6", 166666666, 2.5}, - { "k6_m6", 200000000, 3.0}, - { "k6_m6", 233333333, 3.5}, - { "k6_m7", 100000000, 1.5}, - { "k6_m7", 133333333, 2.0}, - { "k6_m7", 166666666, 2.5}, - { "k6_m7", 200000000, 3.0}, - { "k6_m7", 233333333, 3.5}, - { "k6_m7", 266666666, 4.0}, - { "k6_m7", 300000000, 4.5}, - { "k6_2", 100000000, 1.5}, - { "k6_2", 133333333, 2.0}, - { "k6_2", 166666666, 2.5}, - { "k6_2", 200000000, 3.0}, - { "k6_2", 233333333, 3.5}, - { "k6_2", 266666666, 4.0}, - { "k6_2", 300000000, 4.5}, - { "k6_2", 366666666, 5.5}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_K56_SS7[] = { - {"k6_m6", 66666666, 1.0}, - { "k6_m6", 100000000, 1.5}, - { "k6_m6", 133333333, 2.0}, - { "k6_m6", 166666666, 2.5}, - { "k6_m6", 200000000, 3.0}, - { "k6_m6", 233333333, 3.5}, - { "k6_m7", 100000000, 1.5}, - { "k6_m7", 133333333, 2.0}, - { "k6_m7", 166666666, 2.5}, - { "k6_m7", 200000000, 3.0}, - { "k6_m7", 233333333, 3.5}, - { "k6_m7", 266666666, 4.0}, - { "k6_m7", 300000000, 4.5}, - { "k6_2", 100000000, 1.5}, - { "k6_2", 133333333, 2.0}, - { "k6_2", 166666666, 2.5}, - { "k6_2", 200000000, 3.0}, - { "k6_2", 233333333, 3.5}, - { "k6_2", 266666666, 4.0}, - { "k6_2", 300000000, 3.0}, - { "k6_2", 332500000, 3.5}, - { "k6_2", 350000000, 3.5}, - { "k6_2", 366666666, 5.5}, - { "k6_2", 380000000, 4.0}, - { "k6_2", 400000000, 4.0}, - { "k6_2", 450000000, 4.5}, - { "k6_2", 475000000, 5.0}, - { "k6_2", 500000000, 5.0}, - { "k6_2", 533333333, 5.5}, - { "k6_2", 550000000, 5.5}, - { "k6_2p", 100000000, 1.5}, - { "k6_2p", 133333333, 2.0}, - { "k6_2p", 166666666, 2.5}, - { "k6_2p", 200000000, 3.0}, - { "k6_2p", 233333333, 3.5}, - { "k6_2p", 266666666, 4.0}, - { "k6_2p", 300000000, 3.0}, - { "k6_2p", 332500000, 3.5}, - { "k6_2p", 350000000, 3.5}, - { "k6_2p", 366666666, 5.5}, - { "k6_2p", 380000000, 4.0}, - { "k6_2p", 400000000, 4.0}, - { "k6_2p", 450000000, 4.5}, - { "k6_2p", 475000000, 5.0}, - { "k6_2p", 500000000, 5.0}, - { "k6_2p", 533333333, 5.5}, - { "k6_2p", 550000000, 5.5}, - { "k6_3", 100000000, 1.5}, - { "k6_3", 133333333, 2.0}, - { "k6_3", 166666666, 2.5}, - { "k6_3", 200000000, 3.0}, - { "k6_3", 233333333, 3.5}, - { "k6_3", 266666666, 4.0}, - { "k6_3", 300000000, 3.0}, - { "k6_3", 332500000, 3.5}, - { "k6_3", 350000000, 3.5}, - { "k6_3", 366666666, 5.5}, - { "k6_3", 380000000, 4.0}, - { "k6_3", 400000000, 4.0}, - { "k6_3", 450000000, 4.5}, - { "k6_3p", 75000000, 1.5}, - { "k6_3p", 100000000, 1.5}, - { "k6_3p", 133333333, 2.0}, - { "k6_3p", 166666666, 2.5}, - { "k6_3p", 200000000, 3.0}, - { "k6_3p", 233333333, 3.5}, - { "k6_3p", 266666666, 4.0}, - { "k6_3p", 300000000, 3.0}, - { "k6_3p", 332500000, 3.5}, - { "k6_3p", 350000000, 3.5}, - { "k6_3p", 366666666, 5.5}, - { "k6_3p", 380000000, 4.0}, - { "k6_3p", 400000000, 4.0}, - { "k6_3p", 450000000, 4.5}, - { "k6_3p", 475000000, 5.0}, - { "k6_3p", 500000000, 5.0}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_PentiumPro[] = { - {"pentiumpro", 50000000, 1.0}, - { "pentiumpro", 60000000, 1.0}, - { "pentiumpro", 66666666, 1.0}, - { "pentiumpro", 75000000, 1.5}, - { "pentiumpro", 150000000, 2.5}, - { "pentiumpro", 166666666, 2.5}, - { "pentiumpro", 180000000, 3.0}, - { "pentiumpro", 200000000, 3.0}, - { "pentium2_od", 50000000, 1.0}, - { "pentium2_od", 60000000, 1.0}, - { "pentium2_od", 66666666, 1.0}, - { "pentium2_od", 75000000, 1.5}, - { "pentium2_od", 210000000, 3.5}, - { "pentium2_od", 233333333, 3.5}, - { "pentium2_od", 240000000, 4.0}, - { "pentium2_od", 266666666, 4.0}, - { "pentium2_od", 270000000, 4.5}, - { "pentium2_od", 300000000, 4.5}, - { "pentium2_od", 300000000, 5.0}, - { "pentium2_od", 333333333, 5.0}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_PentiumII66[] = { - {"pentium2_klamath", 50000000, 1.0}, - { "pentium2_klamath", 60000000, 1.0}, - { "pentium2_klamath", 66666666, 1.0}, - { "pentium2_klamath", 75000000, 1.5}, - { "pentium2_klamath", 233333333, 3.5}, - { "pentium2_klamath", 266666666, 4.0}, - { "pentium2_klamath", 300000000, 4.5}, - { "pentium2_deschutes", 50000000, 1.0}, - { "pentium2_deschutes", 60000000, 1.0}, - { "pentium2_deschutes", 66666666, 1.0}, - { "pentium2_deschutes", 75000000, 1.5}, - { "pentium2_deschutes", 266666666, 4.0}, - { "pentium2_deschutes", 300000000, 4.5}, - { "pentium2_deschutes", 333333333, 5.0}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_PentiumII[] = { - {"pentium2_klamath", 50000000, 1.0}, - { "pentium2_klamath", 60000000, 1.0}, - { "pentium2_klamath", 66666666, 1.0}, - { "pentium2_klamath", 75000000, 1.5}, - { "pentium2_klamath", 233333333, 3.5}, - { "pentium2_klamath", 266666666, 4.0}, - { "pentium2_klamath", 300000000, 4.5}, - { "pentium2_deschutes", 50000000, 1.0}, - { "pentium2_deschutes", 60000000, 1.0}, - { "pentium2_deschutes", 66666666, 1.0}, - { "pentium2_deschutes", 75000000, 1.5}, - { "pentium2_deschutes", 266666666, 4.0}, - { "pentium2_deschutes", 300000000, 4.5}, - { "pentium2_deschutes", 333333333, 5.0}, - { "pentium2_deschutes", 350000000, 3.5}, - { "pentium2_deschutes", 400000000, 4.0}, - { "pentium2_deschutes", 450000000, 4.5}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_Xeon[] = { - {"pentium2_xeon", 75000000, 1.5}, - { "pentium2_xeon", 100000000, 1.5}, - { "pentium2_xeon", 133333333, 2.0}, - { "pentium2_xeon", 166666666, 2.5}, - { "pentium2_xeon", 400000000, 4.0}, - { "pentium2_xeon", 450000000, 4.5}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_Celeron[] = { - {"celeron_mendocino", 66666666, 1.0}, - { "celeron_mendocino", 100000000, 1.5}, - { "celeron_mendocino", 133333333, 2.0}, - { "celeron_mendocino", 166666666, 2.5}, - { "celeron_mendocino", 300000000, 4.5}, - { "celeron_mendocino", 333333333, 5.0}, - { "celeron_mendocino", 366666666, 5.5}, - { "celeron_mendocino", 400000000, 6.0}, - { "celeron_mendocino", 433333333, 6.5}, - { "celeron_mendocino", 466666666, 7.0}, - { "celeron_mendocino", 500000000, 7.5}, - { "celeron_mendocino", 533333333, 8.0}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_PentiumIID[] = { - {"pentium2_deschutes", 50000000, 1.0}, - { "pentium2_deschutes", 60000000, 1.0}, - { "pentium2_deschutes", 66666666, 1.0}, - { "pentium2_deschutes", 75000000, 1.5}, - { "pentium2_deschutes", 266666666, 4.0}, - { "pentium2_deschutes", 300000000, 4.5}, - { "pentium2_deschutes", 333333333, 5.0}, - { "pentium2_deschutes", 350000000, 3.5}, - { "pentium2_deschutes", 400000000, 4.0}, - { "pentium2_deschutes", 450000000, 4.5}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t cpus_Cyrix3[] = { - {"c3_samuel", 66666666, 1.0}, - { "c3_samuel", 233333333, 3.5}, - { "c3_samuel", 266666666, 4.0}, - { "c3_samuel", 300000000, 4.5}, - { "c3_samuel", 333333333, 5.0}, - { "c3_samuel", 350000000, 3.5}, - { "c3_samuel", 400000000, 4.0}, - { "c3_samuel", 450000000, 4.5}, - { "c3_samuel", 500000000, 5.0}, - { "c3_samuel", 550000000, 5.5}, - { "c3_samuel", 600000000, 6.0}, - { "c3_samuel", 650000000, 6.5}, - { "c3_samuel", 700000000, 7.0}, - { NULL, 0, 0 } -}; - -static const cpu_legacy_table_t *cputables_8088[4] = { cpus_8088 }; -static const cpu_legacy_table_t *cputables_pcjr[4] = { cpus_pcjr }; -static const cpu_legacy_table_t *cputables_europc[4] = { cpus_europc }; -static const cpu_legacy_table_t *cputables_pc1512[4] = { cpus_pc1512 }; -static const cpu_legacy_table_t *cputables_8086[4] = { cpus_8086 }; -static const cpu_legacy_table_t *cputables_286[4] = { cpus_286 }; -static const cpu_legacy_table_t *cputables_ibmat[4] = { cpus_ibmat }; -static const cpu_legacy_table_t *cputables_ps1_m2011[4] = { cpus_ps1_m2011 }; -static const cpu_legacy_table_t *cputables_ps2_m30_286_IBM486SLC[4] = { cpus_ps2_m30_286, cpus_IBM486SLC }; -static const cpu_legacy_table_t *cputables_ibmxt286[4] = { cpus_ibmxt286 }; -static const cpu_legacy_table_t *cputables_i386SX_Am386SX_486SLC[4] = { cpus_i386SX, cpus_Am386SX, cpus_486SLC }; -static const cpu_legacy_table_t *cputables_ALiM6117[4] = { cpus_ALiM6117 }; -static const cpu_legacy_table_t *cputables_i386SX_Am386SX_486SLC_IBM486SLC[4] = { cpus_i386SX, cpus_Am386SX, cpus_486SLC, cpus_IBM486SLC }; -static const cpu_legacy_table_t *cputables_i386DX_Am386DX_486DLC[4] = { cpus_i386DX, cpus_Am386DX, cpus_486DLC }; -static const cpu_legacy_table_t *cputables_i386DX_Am386DX_486DLC_IBM486BL[4] = { cpus_i386DX, cpus_Am386DX, cpus_486DLC, cpus_IBM486BL }; -static const cpu_legacy_table_t *cputables_i486_Am486_Cx486[4] = { cpus_i486, cpus_Am486, cpus_Cx486 }; -static const cpu_legacy_table_t *cputables_i486S1_Am486S1_Cx486S1[4] = { cpus_i486S1, cpus_Am486S1, cpus_Cx486S1 }; -static const cpu_legacy_table_t *cputables_IBM486SLC[4] = { cpus_IBM486SLC }; -static const cpu_legacy_table_t *cputables_i486_PC330[4] = { cpus_i486_PC330 }; -static const cpu_legacy_table_t *cputables_STPCDX[4] = { cpus_STPCDX }; -static const cpu_legacy_table_t *cputables_STPCDX2[4] = { cpus_STPCDX2 }; -static const cpu_legacy_table_t *cputables_Pentium5V[4] = { cpus_Pentium5V }; -static const cpu_legacy_table_t *cputables_PentiumS5_WinChip_K5[4] = { cpus_PentiumS5, cpus_WinChip, cpus_K5 }; -static const cpu_legacy_table_t *cputables_Pentium3V_WinChip_K5_6x863V[4] = { cpus_Pentium3V, cpus_WinChip, cpus_K5, cpus_6x863V }; -static const cpu_legacy_table_t *cputables_Pentium3V_K5[4] = { cpus_Pentium3V, cpus_K5 }; -static const cpu_legacy_table_t *cputables_Pentium_WinChip_K56_6x86[4] = { cpus_Pentium, cpus_WinChip, cpus_K56, cpus_6x86 }; -static const cpu_legacy_table_t *cputables_Pentium_WinChip_SS7_K56_SS7_6x86SS7[4] = { cpus_Pentium, cpus_WinChip_SS7, cpus_K56_SS7, cpus_6x86SS7 }; -static const cpu_legacy_table_t *cputables_PentiumPro[4] = { cpus_PentiumPro }; -static const cpu_legacy_table_t *cputables_PentiumII66[4] = { cpus_PentiumII66 }; -static const cpu_legacy_table_t *cputables_PentiumII_Celeron_Cyrix3[4] = { cpus_PentiumII, cpus_Celeron, cpus_Cyrix3 }; -static const cpu_legacy_table_t *cputables_Xeon[4] = { cpus_Xeon }; -static const cpu_legacy_table_t *cputables_Celeron_Cyrix3[4] = { cpus_Celeron, cpus_Cyrix3 }; -static const cpu_legacy_table_t *cputables_Celeron[4] = { cpus_Celeron }; -static const cpu_legacy_table_t *cputables_PentiumIID_Celeron[4] = { cpus_PentiumIID, cpus_Celeron }; - -const cpu_legacy_machine_t cpu_legacy_table[] = { - {"ibmpc", cputables_8088 }, - { "ibmpc82", cputables_8088 }, - { "ibmpcjr", cputables_pcjr }, - { "ibmxt", cputables_8088 }, - { "ibmxt86", cputables_8088 }, - { "americxt", cputables_8088 }, - { "amixt", cputables_8088 }, - { "portable", cputables_8088 }, - { "dtk", cputables_8088 }, - { "genxt", cputables_8088 }, - { "jukopc", cputables_8088 }, - { "openxt", cputables_8088 }, - { "pxxt", cputables_8088 }, - { "europc", cputables_europc }, - { "tandy", cputables_europc }, - { "tandy1000hx", cputables_europc }, - { "t1000", cputables_8088 }, - { "ltxt", cputables_8088 }, - { "xi8088", cputables_8088 }, - { "zdsupers", cputables_8088 }, - { "pc1512", cputables_pc1512 }, - { "pc1640", cputables_8086 }, - { "pc2086", cputables_8086 }, - { "pc3086", cputables_8086 }, - { "pc200", cputables_8086 }, - { "ppc512", cputables_8086 }, - { "deskpro", cputables_8086 }, - { "m24", cputables_8086 }, - { "iskra3104", cputables_8086 }, - { "tandy1000sl2", cputables_8086 }, - { "t1200", cputables_8086 }, - { "lxt3", cputables_8086 }, - { "hed919", cputables_286 }, - { "ibmat", cputables_ibmat }, - { "ibmps1es", cputables_ps1_m2011 }, - { "ibmps2_m30_286", cputables_ps2_m30_286_IBM486SLC }, - { "ibmxt286", cputables_ibmxt286 }, - { "ibmatami", cputables_ibmat }, - { "cmdpc30", cputables_286 }, - { "portableii", cputables_286 }, - { "portableiii", cputables_286 }, - { "mr286", cputables_286 }, - { "open_at", cputables_286 }, - { "ibmatpx", cputables_ibmat }, - { "ibmatquadtel", cputables_ibmat }, - { "siemens", cputables_286 }, - { "t3100e", cputables_286 }, - { "quadt286", cputables_286 }, - { "tg286m", cputables_286 }, - { "ami286", cputables_286 }, - { "px286", cputables_286 }, - { "award286", cputables_286 }, - { "gw286ct", cputables_286 }, - { "gdc212m", cputables_286 }, - { "super286c", cputables_286 }, - { "super286tr", cputables_286 }, - { "spc4200p", cputables_286 }, - { "spc4216p", cputables_286 }, - { "deskmaster286", cputables_286 }, - { "ibmps2_m50", cputables_ps2_m30_286_IBM486SLC }, - { "ibmps1_2121", cputables_i386SX_Am386SX_486SLC }, - { "ibmps1_2121_isa", cputables_i386SX_Am386SX_486SLC }, - { "arb1375", cputables_ALiM6117 }, - { "pja511m", cputables_ALiM6117 }, - { "ama932j", cputables_i386SX_Am386SX_486SLC }, - { "adi386sx", cputables_i386SX_Am386SX_486SLC }, - { "shuttle386sx", cputables_i386SX_Am386SX_486SLC }, - { "dtk386", cputables_i386SX_Am386SX_486SLC }, - { "awardsx", cputables_i386SX_Am386SX_486SLC }, - { "cmdsl386sx25", cputables_i386SX_Am386SX_486SLC }, - { "kmxc02", cputables_i386SX_Am386SX_486SLC }, - { "megapc", cputables_i386SX_Am386SX_486SLC }, - { "ibmps2_m55sx", cputables_i386SX_Am386SX_486SLC_IBM486SLC }, - { "acc386", cputables_i386DX_Am386DX_486DLC }, - { "ecs386", cputables_i386DX_Am386DX_486DLC }, - { "portableiii386", cputables_i386DX_Am386DX_486DLC }, - { "micronics386", cputables_i386DX_Am386DX_486DLC }, - { "asus386", cputables_i386DX_Am386DX_486DLC }, - { "ustechnologies386", cputables_i386DX_Am386DX_486DLC }, - { "award386dx", cputables_i386DX_Am386DX_486DLC }, - { "ibmps2_m70_type3", cputables_i386DX_Am386DX_486DLC_IBM486BL }, - { "ibmps2_m80", cputables_i386DX_Am386DX_486DLC_IBM486BL }, - { "pb410a", cputables_i486_Am486_Cx486 }, - { "acera1g", cputables_i486_Am486_Cx486 }, - { "win486", cputables_i486_Am486_Cx486 }, - { "ali1429", cputables_i486S1_Am486S1_Cx486S1 }, - { "cs4031", cputables_i486S1_Am486S1_Cx486S1 }, - { "rycleopardlx", cputables_IBM486SLC }, - { "award486", cputables_i486S1_Am486S1_Cx486S1 }, - { "ami486", cputables_i486S1_Am486S1_Cx486S1 }, - { "mr486", cputables_i486_Am486_Cx486 }, - { "pc330_6571", cputables_i486_PC330 }, - { "403tg", cputables_i486_Am486_Cx486 }, - { "sis401", cputables_i486_Am486_Cx486 }, - { "valuepoint433", cputables_i486_Am486_Cx486 }, - { "ami471", cputables_i486_Am486_Cx486 }, - { "win471", cputables_i486_Am486_Cx486 }, - { "vi15g", cputables_i486_Am486_Cx486 }, - { "vli486sv2g", cputables_i486_Am486_Cx486 }, - { "dtk486", cputables_i486_Am486_Cx486 }, - { "px471", cputables_i486_Am486_Cx486 }, - { "486vchd", cputables_i486S1_Am486S1_Cx486S1 }, - { "ibmps1_2133", cputables_i486S1_Am486S1_Cx486S1 }, - { "vect486vl", cputables_i486S1_Am486S1_Cx486S1 }, - { "ibmps2_m70_type4", cputables_i486S1_Am486S1_Cx486S1 }, - { "abpb4", cputables_i486_Am486_Cx486 }, - { "486ap4", cputables_i486_Am486_Cx486 }, - { "486sp3g", cputables_i486_Am486_Cx486 }, - { "alfredo", cputables_i486_Am486_Cx486 }, - { "ls486e", cputables_i486_Am486_Cx486 }, - { "m4li", cputables_i486_Am486_Cx486 }, - { "r418", cputables_i486_Am486_Cx486 }, - { "4sa2", cputables_i486_Am486_Cx486 }, - { "4dps", cputables_i486_Am486_Cx486 }, - { "itoxstar", cputables_STPCDX }, - { "arb1479", cputables_STPCDX2 }, - { "pcm9340", cputables_STPCDX2 }, - { "pcm5330", cputables_STPCDX2 }, - { "486vipio2", cputables_i486_Am486_Cx486 }, - { "p5mp3", cputables_Pentium5V }, - { "dellxp60", cputables_Pentium5V }, - { "opti560l", cputables_Pentium5V }, - { "ambradp60", cputables_Pentium5V }, - { "valuepointp60", cputables_Pentium5V }, - { "revenge", cputables_Pentium5V }, - { "586mc1", cputables_Pentium5V }, - { "pb520r", cputables_Pentium5V }, - { "excalibur", cputables_Pentium5V }, - { "plato", cputables_PentiumS5_WinChip_K5 }, - { "ambradp90", cputables_PentiumS5_WinChip_K5 }, - { "430nx", cputables_PentiumS5_WinChip_K5 }, - { "acerv30", cputables_PentiumS5_WinChip_K5 }, - { "apollo", cputables_PentiumS5_WinChip_K5 }, - { "vectra54", cputables_PentiumS5_WinChip_K5 }, - { "zappa", cputables_PentiumS5_WinChip_K5 }, - { "powermate_v", cputables_PentiumS5_WinChip_K5 }, - { "mb500n", cputables_PentiumS5_WinChip_K5 }, - { "p54tp4xe", cputables_Pentium3V_WinChip_K5_6x863V }, - { "mr586", cputables_Pentium3V_WinChip_K5_6x863V }, - { "gw2katx", cputables_Pentium3V_WinChip_K5_6x863V }, - { "thor", cputables_Pentium3V_WinChip_K5_6x863V }, - { "mrthor", cputables_Pentium3V_WinChip_K5_6x863V }, - { "endeavor", cputables_Pentium3V_WinChip_K5_6x863V }, - { "pb640", cputables_Pentium3V_WinChip_K5_6x863V }, - { "chariot", cputables_Pentium3V_K5 }, - { "acerm3a", cputables_Pentium3V_WinChip_K5_6x863V }, - { "ap53", cputables_Pentium3V_WinChip_K5_6x863V }, - { "8500tuc", cputables_Pentium3V_WinChip_K5_6x863V }, - { "p55t2s", cputables_Pentium3V_WinChip_K5_6x863V }, - { "acerv35n", cputables_Pentium_WinChip_K56_6x86 }, - { "p55t2p4", cputables_Pentium_WinChip_K56_6x86 }, - { "m7shi", cputables_Pentium_WinChip_K56_6x86 }, - { "tc430hx", cputables_Pentium_WinChip_K56_6x86 }, - { "equium5200", cputables_Pentium_WinChip_K56_6x86 }, - { "pcv240", cputables_Pentium_WinChip_K56_6x86 }, - { "p65up5_cp55t2d", cputables_Pentium_WinChip_K56_6x86 }, - { "p55tvp4", cputables_Pentium_WinChip_K56_6x86 }, - { "8500tvxa", cputables_Pentium_WinChip_K56_6x86 }, - { "presario4500", cputables_Pentium_WinChip_K56_6x86 }, - { "p55va", cputables_Pentium_WinChip_K56_6x86 }, - { "gw2kte", cputables_Pentium_WinChip_K56_6x86 }, - { "brio80xx", cputables_Pentium_WinChip_K56_6x86 }, - { "pb680", cputables_Pentium_WinChip_K56_6x86 }, - { "430vx", cputables_Pentium_WinChip_K56_6x86 }, - { "nupro592", cputables_Pentium_WinChip_K56_6x86 }, - { "tx97", cputables_Pentium_WinChip_K56_6x86 }, - { "an430tx", cputables_Pentium_WinChip_K56_6x86 }, - { "ym430tx", cputables_Pentium_WinChip_K56_6x86 }, - { "mb540n", cputables_Pentium_WinChip_K56_6x86 }, - { "p5mms98", cputables_Pentium_WinChip_K56_6x86 }, - { "ficva502", cputables_Pentium_WinChip_K56_6x86 }, - { "ficpa2012", cputables_Pentium_WinChip_K56_6x86 }, - { "ax59pro", cputables_Pentium_WinChip_SS7_K56_SS7_6x86SS7}, - { "ficva503p", cputables_Pentium_WinChip_SS7_K56_SS7_6x86SS7}, - { "ficva503a", cputables_Pentium_WinChip_SS7_K56_SS7_6x86SS7}, - { "v60n", cputables_PentiumPro }, - { "p65up5_cp6nd", cputables_PentiumPro }, - { "8600ttc", cputables_PentiumPro }, - { "686nx", cputables_PentiumPro }, - { "ap440fx", cputables_PentiumPro }, - { "vs440fx", cputables_PentiumPro }, - { "m6mi", cputables_PentiumPro }, - { "mb600n", cputables_PentiumPro }, - { "p65up5_cpknd", cputables_PentiumII66 }, - { "kn97", cputables_PentiumII66 }, - { "lx6", cputables_PentiumII66 }, - { "spitfire", cputables_PentiumII66 }, - { "p6i440e2", cputables_PentiumII66 }, - { "p2bls", cputables_PentiumII_Celeron_Cyrix3 }, - { "p3bf", cputables_PentiumII_Celeron_Cyrix3 }, - { "bf6", cputables_PentiumII_Celeron_Cyrix3 }, - { "ax6bc", cputables_PentiumII_Celeron_Cyrix3 }, - { "atc6310bxii", cputables_PentiumII_Celeron_Cyrix3 }, - { "686bx", cputables_PentiumII_Celeron_Cyrix3 }, - { "tsunamiatx", cputables_PentiumII_Celeron_Cyrix3 }, - { "p6sba", cputables_PentiumII_Celeron_Cyrix3 }, - { "ergox365", cputables_PentiumII_Celeron_Cyrix3 }, - { "ficka6130", cputables_PentiumII_Celeron_Cyrix3 }, - { "6gxu", cputables_Xeon }, - { "fw6400gx", cputables_Xeon }, - { "s2dge", cputables_Xeon }, - { "s370slm", cputables_Celeron_Cyrix3 }, - { "awo671r", cputables_Celeron_Cyrix3 }, - { "cubx", cputables_Celeron_Cyrix3 }, - { "atc7020bxii", cputables_Celeron_Cyrix3 }, - { "ambx133", cputables_Celeron_Cyrix3 }, - { "trinity371", cputables_Celeron }, - { "63a", cputables_Celeron_Cyrix3 }, - { "apas3", cputables_Celeron_Cyrix3 }, - { "wcf681", cputables_Celeron_Cyrix3 }, - { "6via90ap", cputables_Celeron_Cyrix3 }, - { "p6bap", cputables_Celeron_Cyrix3 }, - { "603tcf", cputables_Celeron_Cyrix3 }, - { "vpc2007", cputables_PentiumIID_Celeron }, - { NULL, NULL } -}; diff --git a/src/cpu/x86.c b/src/cpu/x86.c index 64ff6be4c..2c8c29d49 100644 --- a/src/cpu/x86.c +++ b/src/cpu/x86.c @@ -270,11 +270,19 @@ reset_common(int hard) cr0 = 1 << 30; else cr0 = 0; + if (is386 && !is486 && (fpu_type == FPU_387)) + cr0 |= 0x10; cpu_cache_int_enabled = 0; cpu_update_waitstates(); cr4 = 0; cpu_state.eflags = 0; cgate32 = 0; + if (is386 && !is486) { + for (uint8_t i = 0; i < 4; i++) + dr[i] = 0x00000000; + dr[6] = 0xffff1ff0; + dr[7] = 0x00000400; + } if (is286) { if (is486) loadcs(0xF000); diff --git a/src/cpu/x86_ops_flag_2386.h b/src/cpu/x86_ops_flag_2386.h new file mode 100644 index 000000000..ba34ae5e7 --- /dev/null +++ b/src/cpu/x86_ops_flag_2386.h @@ -0,0 +1,323 @@ +static int +opCMC(uint32_t fetchdat) +{ + flags_rebuild(); + cpu_state.flags ^= C_FLAG; + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0); + return 0; +} + +static int +opCLC(uint32_t fetchdat) +{ + flags_rebuild(); + cpu_state.flags &= ~C_FLAG; + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0); + return 0; +} +static int +opCLD(uint32_t fetchdat) +{ + cpu_state.flags &= ~D_FLAG; + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0); + return 0; +} +static int +opCLI(uint32_t fetchdat) +{ + if (!IOPLp) { + if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) || ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME))) { + cpu_state.eflags &= ~VIF_FLAG; + } else { + x86gpf(NULL, 0); + return 1; + } + } else + cpu_state.flags &= ~I_FLAG; + + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; +} + +static int +opSTC(uint32_t fetchdat) +{ + flags_rebuild(); + cpu_state.flags |= C_FLAG; + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0); + return 0; +} +static int +opSTD(uint32_t fetchdat) +{ + cpu_state.flags |= D_FLAG; + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0); + return 0; +} +static int +opSTI(uint32_t fetchdat) +{ + if (!IOPLp) { + if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) || ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME))) { + if (cpu_state.eflags & VIP_FLAG) { + x86gpf(NULL, 0); + return 1; + } else + cpu_state.eflags |= VIF_FLAG; + } else { + x86gpf(NULL, 0); + return 1; + } + } else + cpu_state.flags |= I_FLAG; + + /*First instruction after STI will always execute, regardless of whether + there is a pending interrupt*/ + cpu_end_block_after_ins = 2; + + CLOCK_CYCLES(2); + PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0); + return 0; +} + +static int +opSAHF(uint32_t fetchdat) +{ + flags_rebuild(); + cpu_state.flags = (cpu_state.flags & 0xff00) | (AH & 0xd5) | 2; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + +#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) + codegen_flags_changed = 0; +#endif + + return 0; +} +static int +opLAHF(uint32_t fetchdat) +{ + flags_rebuild(); + AH = cpu_state.flags & 0xff; + CLOCK_CYCLES(3); + PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0); + return 0; +} + +static int +opPUSHF(uint32_t fetchdat) +{ + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { + if (cr4 & CR4_VME) { + uint16_t temp; + + flags_rebuild(); + temp = (cpu_state.flags & ~I_FLAG) | 0x3000; + if (cpu_state.eflags & VIF_FLAG) + temp |= I_FLAG; + PUSH_W(temp); + } else { + x86gpf(NULL, 0); + return 1; + } + } else { + flags_rebuild(); + PUSH_W(cpu_state.flags); + } + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0, 0, 1, 0, 0); + return cpu_state.abrt; +} +static int +opPUSHFD(uint32_t fetchdat) +{ + uint16_t tempw; + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { + x86gpf(NULL, 0); + return 1; + } + if (cpu_CR4_mask & CR4_VME) + tempw = cpu_state.eflags & 0x3c; + else if (CPUID) + tempw = cpu_state.eflags & 0x24; + else + tempw = cpu_state.eflags & 4; + flags_rebuild(); + PUSH_L(cpu_state.flags | (tempw << 16)); + CLOCK_CYCLES(4); + PREFETCH_RUN(4, 1, -1, 0, 0, 0, 1, 0); + return cpu_state.abrt; +} + +static int +opPOPF_186(uint32_t fetchdat) +{ + uint16_t tempw; + + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { + x86gpf(NULL, 0); + return 1; + } + + tempw = POP_W(); + if (cpu_state.abrt) + return 1; + + if (!(msw & 1)) + cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; + else if (!(CPL)) + cpu_state.flags = (tempw & 0x7fd5) | 2; + else if (IOPLp) + cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; + else + cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; + flags_extract(); + rf_flag_no_clear = 1; + + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); + +#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) + codegen_flags_changed = 0; +#endif + + return 0; +} +static int +opPOPF_286(uint32_t fetchdat) +{ + uint16_t tempw; + + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { + x86gpf(NULL, 0); + return 1; + } + + tempw = POP_W(); + if (cpu_state.abrt) + return 1; + + if (!(msw & 1)) + cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; + else if (!(CPL)) + cpu_state.flags = (tempw & 0x7fd5) | 2; + else if (IOPLp) + cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; + else + cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; + flags_extract(); + rf_flag_no_clear = 1; + + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); + +#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) + codegen_flags_changed = 0; +#endif + + return 0; +} +static int +opPOPF(uint32_t fetchdat) +{ + uint16_t tempw; + + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { + if (cr4 & CR4_VME) { + uint32_t old_esp = ESP; + + tempw = POP_W(); + if (cpu_state.abrt) { + + ESP = old_esp; + return 1; + } + + if ((tempw & T_FLAG) || ((tempw & I_FLAG) && (cpu_state.eflags & VIP_FLAG))) { + ESP = old_esp; + x86gpf(NULL, 0); + return 1; + } + if (tempw & I_FLAG) + cpu_state.eflags |= VIF_FLAG; + else + cpu_state.eflags &= ~VIF_FLAG; + cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; + } else { + x86gpf(NULL, 0); + return 1; + } + } else { + tempw = POP_W(); + if (cpu_state.abrt) + return 1; + + if (!(CPL) || !(msw & 1)) + cpu_state.flags = (tempw & 0x7fd5) | 2; + else if (IOPLp) + cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; + else + cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; + } + flags_extract(); + rf_flag_no_clear = 1; + + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0); + +#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) + codegen_flags_changed = 0; +#endif + + return 0; +} +static int +opPOPFD(uint32_t fetchdat) +{ + uint32_t templ; + + if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) { + x86gpf(NULL, 0); + return 1; + } + + templ = POP_L(); + if (cpu_state.abrt) + return 1; + + if (!(CPL) || !(msw & 1)) + cpu_state.flags = (templ & 0x7fd5) | 2; + else if (IOPLp) + cpu_state.flags = (cpu_state.flags & 0x3000) | (templ & 0x4fd5) | 2; + else + cpu_state.flags = (cpu_state.flags & 0x3200) | (templ & 0x4dd5) | 2; + + templ &= (is486 || isibm486) ? 0x3c0000 : 0; + templ |= ((cpu_state.eflags & 3) << 16); + if (cpu_CR4_mask & CR4_VME) + cpu_state.eflags = (templ >> 16) & 0x3f; + else if (CPUID) + cpu_state.eflags = (templ >> 16) & 0x27; + else if (is486 || isibm486) + cpu_state.eflags = (templ >> 16) & 7; + else + cpu_state.eflags = (templ >> 16) & 3; + + flags_extract(); + rf_flag_no_clear = 1; + + CLOCK_CYCLES(5); + PREFETCH_RUN(5, 1, -1, 0, 1, 0, 0, 0); + +#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) + codegen_flags_changed = 0; +#endif + + return 0; +} diff --git a/src/cpu/x86_ops_fpu_2386.h b/src/cpu/x86_ops_fpu_2386.h new file mode 100644 index 000000000..52c24d995 --- /dev/null +++ b/src/cpu/x86_ops_fpu_2386.h @@ -0,0 +1,113 @@ +/* Copyright holders: Sarah Walker + see COPYING for more details +*/ +static int +opESCAPE_d8_a16(uint32_t fetchdat) +{ + return x86_2386_opcodes_d8_a16[(fetchdat >> 3) & 0x1f](fetchdat); +} +static int +opESCAPE_d8_a32(uint32_t fetchdat) +{ + return x86_2386_opcodes_d8_a32[(fetchdat >> 3) & 0x1f](fetchdat); +} + +static int +opESCAPE_d9_a16(uint32_t fetchdat) +{ + return x86_2386_opcodes_d9_a16[fetchdat & 0xff](fetchdat); +} +static int +opESCAPE_d9_a32(uint32_t fetchdat) +{ + return x86_2386_opcodes_d9_a32[fetchdat & 0xff](fetchdat); +} + +static int +opESCAPE_da_a16(uint32_t fetchdat) +{ + return x86_2386_opcodes_da_a16[fetchdat & 0xff](fetchdat); +} +static int +opESCAPE_da_a32(uint32_t fetchdat) +{ + return x86_2386_opcodes_da_a32[fetchdat & 0xff](fetchdat); +} + +static int +opESCAPE_db_a16(uint32_t fetchdat) +{ + return x86_2386_opcodes_db_a16[fetchdat & 0xff](fetchdat); +} +static int +opESCAPE_db_a32(uint32_t fetchdat) +{ + return x86_2386_opcodes_db_a32[fetchdat & 0xff](fetchdat); +} + +static int +opESCAPE_dc_a16(uint32_t fetchdat) +{ + return x86_2386_opcodes_dc_a16[(fetchdat >> 3) & 0x1f](fetchdat); +} +static int +opESCAPE_dc_a32(uint32_t fetchdat) +{ + return x86_2386_opcodes_dc_a32[(fetchdat >> 3) & 0x1f](fetchdat); +} + +static int +opESCAPE_dd_a16(uint32_t fetchdat) +{ + return x86_2386_opcodes_dd_a16[fetchdat & 0xff](fetchdat); +} +static int +opESCAPE_dd_a32(uint32_t fetchdat) +{ + return x86_2386_opcodes_dd_a32[fetchdat & 0xff](fetchdat); +} + +static int +opESCAPE_de_a16(uint32_t fetchdat) +{ + return x86_2386_opcodes_de_a16[fetchdat & 0xff](fetchdat); +} +static int +opESCAPE_de_a32(uint32_t fetchdat) +{ + return x86_2386_opcodes_de_a32[fetchdat & 0xff](fetchdat); +} + +static int +opESCAPE_df_a16(uint32_t fetchdat) +{ + return x86_2386_opcodes_df_a16[fetchdat & 0xff](fetchdat); +} +static int +opESCAPE_df_a32(uint32_t fetchdat) +{ + return x86_2386_opcodes_df_a32[fetchdat & 0xff](fetchdat); +} + +static int +opWAIT(uint32_t fetchdat) +{ + if ((cr0 & 0xa) == 0xa) { + x86_int(7); + return 1; + } + +#if 0 + if (!cpu_use_dynarec && fpu_softfloat) { +#endif + if (fpu_softfloat) { + if (fpu_state.swd & FPU_SW_Summary) { + if (cr0 & 0x20) { + x86_int(16); + return 1; + } + } + } + CLOCK_CYCLES(4); + return 0; +} diff --git a/src/cpu/x86_ops_misc.h b/src/cpu/x86_ops_misc.h index e36fa4800..dd05fb9d9 100644 --- a/src/cpu/x86_ops_misc.h +++ b/src/cpu/x86_ops_misc.h @@ -129,7 +129,7 @@ opF6_a16(uint32_t fetchdat) if (dst && !(tempw & 0xff00)) { AH = src16 % dst; AL = (src16 / dst) & 0xff; - if (!cpu_iscyrix) { + if (!cpu_iscyrix && !is6117) { flags_rebuild(); cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ cpu_state.flags &= ~1; @@ -149,7 +149,7 @@ opF6_a16(uint32_t fetchdat) if (dst && ((int) temps == tempws2)) { AH = (tempws % (int) ((int8_t) dst)) & 0xff; AL = tempws2 & 0xff; - if (!cpu_iscyrix) { + if (!cpu_iscyrix && !is6117) { flags_rebuild(); cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ cpu_state.flags &= ~1; @@ -246,7 +246,7 @@ opF6_a32(uint32_t fetchdat) if (dst && !(tempw & 0xff00)) { AH = src16 % dst; AL = (src16 / dst) & 0xff; - if (!cpu_iscyrix) { + if (!cpu_iscyrix && !is6117) { flags_rebuild(); cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ cpu_state.flags &= ~1; @@ -266,7 +266,7 @@ opF6_a32(uint32_t fetchdat) if (dst && ((int) temps == tempws2)) { AH = (tempws % (int) ((int8_t) dst)) & 0xff; AL = tempws2 & 0xff; - if (!cpu_iscyrix) { + if (!cpu_iscyrix && !is6117) { flags_rebuild(); cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ cpu_state.flags &= ~1; @@ -366,7 +366,7 @@ opF7_w_a16(uint32_t fetchdat) if (dst && !(templ2 & 0xffff0000)) { DX = templ % dst; AX = (templ / dst) & 0xffff; - if (!cpu_iscyrix) + if (!cpu_iscyrix && !is6117) setznp16(AX); /*Not a Cyrix*/ } else { x86_int(0); @@ -383,7 +383,7 @@ opF7_w_a16(uint32_t fetchdat) if ((dst != 0) && ((int) temps16 == tempws2)) { DX = tempws % (int) ((int16_t) dst); AX = tempws2 & 0xffff; - if (!cpu_iscyrix) + if (!cpu_iscyrix && !is6117) setznp16(AX); /*Not a Cyrix*/ } else { x86_int(0); @@ -479,7 +479,7 @@ opF7_w_a32(uint32_t fetchdat) if (dst && !(templ2 & 0xffff0000)) { DX = templ % dst; AX = (templ / dst) & 0xffff; - if (!cpu_iscyrix) + if (!cpu_iscyrix && !is6117) setznp16(AX); /*Not a Cyrix*/ } else { // fatal("DIVw BY 0 %04X:%04X %i\n",cs>>4,pc,ins); @@ -497,7 +497,7 @@ opF7_w_a32(uint32_t fetchdat) if ((dst != 0) && ((int) temps16 == tempws2)) { DX = tempws % (int) ((int16_t) dst); AX = tempws2 & 0xffff; - if (!cpu_iscyrix) + if (!cpu_iscyrix && !is6117) setznp16(AX); /*Not a Cyrix*/ } else { x86_int(0); @@ -587,7 +587,7 @@ opF7_l_a16(uint32_t fetchdat) case 0x30: /*DIV EAX,l*/ if (divl(dst)) return 1; - if (!cpu_iscyrix) + if (!cpu_iscyrix && !is6117) setznp32(EAX); /*Not a Cyrix*/ CLOCK_CYCLES((is486) ? 40 : 38); PREFETCH_RUN(is486 ? 40 : 38, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0); @@ -595,7 +595,7 @@ opF7_l_a16(uint32_t fetchdat) case 0x38: /*IDIV EAX,l*/ if (idivl((int32_t) dst)) return 1; - if (!cpu_iscyrix) + if (!cpu_iscyrix && !is6117) setznp32(EAX); /*Not a Cyrix*/ CLOCK_CYCLES(43); PREFETCH_RUN(43, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0); @@ -680,7 +680,7 @@ opF7_l_a32(uint32_t fetchdat) case 0x30: /*DIV EAX,l*/ if (divl(dst)) return 1; - if (!cpu_iscyrix) + if (!cpu_iscyrix && !is6117) setznp32(EAX); /*Not a Cyrix*/ CLOCK_CYCLES((is486) ? 40 : 38); PREFETCH_RUN(is486 ? 40 : 38, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1); @@ -688,7 +688,7 @@ opF7_l_a32(uint32_t fetchdat) case 0x38: /*IDIV EAX,l*/ if (idivl((int32_t) dst)) return 1; - if (!cpu_iscyrix) + if (!cpu_iscyrix && !is6117) setznp32(EAX); /*Not a Cyrix*/ CLOCK_CYCLES(43); PREFETCH_RUN(43, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1); @@ -726,6 +726,59 @@ opHLT(uint32_t fetchdat) return 0; } +#ifdef OPS_286_386 +static int +opLOCK(uint32_t fetchdat) +{ + int legal; + fetch_dat_t fetch_dat; + fetchdat = fastreadl_fetch(cs + cpu_state.pc); + if (cpu_state.abrt) + return 0; + cpu_state.pc++; + + fetch_dat.fd = fetchdat; + + legal = lock_legal[fetch_dat.b[0]]; + if (legal == 1) + legal = ((fetch_dat.b[1] >> 6) != 0x03); /* reg is illegal */ + else if (legal == 2) { + legal = lock_legal_0f[fetch_dat.b[1]]; + if (legal == 1) + legal = ((fetch_dat.b[2] >> 6) != 0x03); /* reg,reg is illegal */ + else if (legal == 3) { + legal = lock_legal_ba[(fetch_dat.b[2] >> 3) & 0x07]; + if (legal == 1) + legal = ((fetch_dat.b[2] >> 6) != 0x03); /* reg,imm is illegal */ + } + } else if (legal == 3) switch(fetch_dat.b[0]) { + case 0x80 ... 0x83: + legal = lock_legal_80[(fetch_dat.b[1] >> 3) & 0x07]; + if (legal == 1) + legal = ((fetch_dat.b[1] >> 6) != 0x03); /* reg is illegal */ + break; + case 0xf6 ... 0xf7: + legal = lock_legal_f6[(fetch_dat.b[1] >> 3) & 0x07]; + if (legal == 1) + legal = ((fetch_dat.b[1] >> 6) != 0x03); /* reg is illegal */ + break; + case 0xfe ... 0xff: + legal = lock_legal_fe[(fetch_dat.b[1] >> 3) & 0x07]; + if (legal == 1) + legal = ((fetch_dat.b[1] >> 6) != 0x03); /* reg is illegal */ + break; + default: + legal = 0; + break; + } + + ILLEGAL_ON(legal == 0); + + CLOCK_CYCLES(4); + PREFETCH_PREFIX(); + return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +} +#else static int opLOCK(uint32_t fetchdat) { @@ -740,6 +793,7 @@ opLOCK(uint32_t fetchdat) PREFETCH_PREFIX(); return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); } +#endif static int opBOUND_w_a16(uint32_t fetchdat) diff --git a/src/cpu/x86_ops_mov_ctrl_2386.h b/src/cpu/x86_ops_mov_ctrl_2386.h new file mode 100644 index 000000000..cae6c9957 --- /dev/null +++ b/src/cpu/x86_ops_mov_ctrl_2386.h @@ -0,0 +1,500 @@ +static int +opMOV_r_CRx_a16(uint32_t fetchdat) +{ + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_16(fetchdat); + switch (cpu_reg) { + case 0: + cpu_state.regs[cpu_rm].l = cr0; + if (is486 || isibm486) + cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/ + else { + if (is386) + cpu_state.regs[cpu_rm].l |= 0x7fffffe0; + else + cpu_state.regs[cpu_rm].l |= 0x7ffffff0; + } + break; + case 2: + cpu_state.regs[cpu_rm].l = cr2; + break; + case 3: + cpu_state.regs[cpu_rm].l = cr3; + break; + case 4: + if (cpu_has_feature(CPU_FEATURE_CR4)) { + cpu_state.regs[cpu_rm].l = cr4; + break; + } + default: + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + break; + } + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); + return 0; +} +static int +opMOV_r_CRx_a32(uint32_t fetchdat) +{ + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_32(fetchdat); + switch (cpu_reg) { + case 0: + cpu_state.regs[cpu_rm].l = cr0; + if (is486 || isibm486) + cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/ + else { + if (is386) + cpu_state.regs[cpu_rm].l |= 0x7fffffe0; + else + cpu_state.regs[cpu_rm].l |= 0x7ffffff0; + } + break; + case 2: + cpu_state.regs[cpu_rm].l = cr2; + break; + case 3: + cpu_state.regs[cpu_rm].l = cr3; + break; + case 4: + if (cpu_has_feature(CPU_FEATURE_CR4)) { + cpu_state.regs[cpu_rm].l = cr4; + break; + } + default: + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + break; + } + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); + return 0; +} + +static int +opMOV_r_DRx_a16(uint32_t fetchdat) +{ + if ((CPL > 0) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + if ((dr[7] & 0x2000) && !(cpu_state.eflags & RF_FLAG)) { + trap |= 1; + return 1; + } + fetch_ea_16(fetchdat); + switch (cpu_reg) { + case 0 ... 3: + cpu_state.regs[cpu_rm].l = dr[cpu_reg]; + break; + case 4: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 6: + cpu_state.regs[cpu_rm].l = dr[6]; + break; + case 5: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 7: + cpu_state.regs[cpu_rm].l = dr[7]; + break; + default: + x86illegal(); + return 1; + } + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); + return 0; +} +static int +opMOV_r_DRx_a32(uint32_t fetchdat) +{ + if ((CPL > 0) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + if ((dr[7] & 0x2000) && !(cpu_state.eflags & RF_FLAG)) { + trap |= 1; + return 1; + } + fetch_ea_32(fetchdat); + switch (cpu_reg) { + case 0 ... 3: + cpu_state.regs[cpu_rm].l = dr[cpu_reg]; + break; + case 4: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 6: + cpu_state.regs[cpu_rm].l = dr[6]; + break; + case 5: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 7: + cpu_state.regs[cpu_rm].l = dr[7]; + break; + default: + x86illegal(); + return 1; + } + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); + return 0; +} + +static int +opMOV_CRx_r_a16(uint32_t fetchdat) +{ + uint32_t old_cr0 = cr0; + + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_16(fetchdat); + switch (cpu_reg) { + case 0: + if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000001) + flushmmucache(); + /* Make sure CPL = 0 when switching from real mode to protected mode. */ + if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01)) + cpu_state.seg_cs.access &= 0x9f; + cr0 = cpu_state.regs[cpu_rm].l; + if (cpu_16bitbus) + cr0 |= 0x10; + if (!(cr0 & 0x80000000)) + mmu_perm = 4; + if (hascache && !(cr0 & (1 << 30))) + cpu_cache_int_enabled = 1; + else + cpu_cache_int_enabled = 0; + if (hascache && ((cr0 ^ old_cr0) & (1 << 30))) + cpu_update_waitstates(); + if (cr0 & 1) + cpu_cur_status |= CPU_STATUS_PMODE; + else + cpu_cur_status &= ~CPU_STATUS_PMODE; + break; + case 2: + cr2 = cpu_state.regs[cpu_rm].l; + break; + case 3: + cr3 = cpu_state.regs[cpu_rm].l; + flushmmucache(); + break; + case 4: + if (cpu_has_feature(CPU_FEATURE_CR4)) { + if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PAE | CR4_PGE)) + flushmmucache(); + cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask; + break; + } + + default: + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + break; + } + CLOCK_CYCLES(10); + PREFETCH_RUN(10, 2, rmdat, 0, 0, 0, 0, 0); + return 0; +} +static int +opMOV_CRx_r_a32(uint32_t fetchdat) +{ + uint32_t old_cr0 = cr0; + + if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_32(fetchdat); + switch (cpu_reg) { + case 0: + if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000001) + flushmmucache(); + /* Make sure CPL = 0 when switching from real mode to protected mode. */ + if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01)) + cpu_state.seg_cs.access &= 0x9f; + cr0 = cpu_state.regs[cpu_rm].l; + if (cpu_16bitbus) + cr0 |= 0x10; + if (!(cr0 & 0x80000000)) + mmu_perm = 4; + if (hascache && !(cr0 & (1 << 30))) + cpu_cache_int_enabled = 1; + else + cpu_cache_int_enabled = 0; + if (hascache && ((cr0 ^ old_cr0) & (1 << 30))) + cpu_update_waitstates(); + if (cr0 & 1) + cpu_cur_status |= CPU_STATUS_PMODE; + else + cpu_cur_status &= ~CPU_STATUS_PMODE; + break; + case 2: + cr2 = cpu_state.regs[cpu_rm].l; + break; + case 3: + cr3 = cpu_state.regs[cpu_rm].l; + flushmmucache(); + break; + case 4: + if (cpu_has_feature(CPU_FEATURE_CR4)) { + if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PAE | CR4_PGE)) + flushmmucache(); + cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask; + break; + } + + default: + cpu_state.pc = cpu_state.oldpc; + x86illegal(); + break; + } + CLOCK_CYCLES(10); + PREFETCH_RUN(10, 2, rmdat, 0, 0, 0, 0, 1); + return 0; +} + +static int +opMOV_DRx_r_a16(uint32_t fetchdat) +{ + if ((CPL > 0) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + if ((dr[7] & 0x2000) && !(cpu_state.eflags & RF_FLAG)) { + trap |= 1; + return 1; + } + fetch_ea_16(fetchdat); + switch (cpu_reg) { + case 0 ... 3: + dr[cpu_reg] = cpu_state.regs[cpu_rm].l; + break; + case 4: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 6: + dr[6] = (dr[6] & 0xffff0ff0) | (cpu_state.regs[cpu_rm].l & 0x0000f00f); + break; + case 5: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 7: + dr[7] = cpu_state.regs[cpu_rm].l | 0x00000400; + break; + default: + x86illegal(); + return 1; + } + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); + CPU_BLOCK_END(); + return 0; +} +static int +opMOV_DRx_r_a32(uint32_t fetchdat) +{ + if ((CPL > 0) && (cr0 & 1)) { + x86gpf(NULL, 0); + return 1; + } + if ((dr[7] & 0x2000) && !(cpu_state.eflags & RF_FLAG)) { + trap |= 1; + return 1; + } + fetch_ea_32(fetchdat); + switch (cpu_reg) { + case 0 ... 3: + dr[cpu_reg] = cpu_state.regs[cpu_rm].l; + break; + case 4: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 6: + dr[6] = (dr[6] & 0xffff0ff0) | (cpu_state.regs[cpu_rm].l & 0x0000f00f); + break; + case 5: + if (cr4 & 0x8) { + x86illegal(); + return 1; + } + fallthrough; + case 7: + dr[7] = cpu_state.regs[cpu_rm].l | 0x00000400; + break; + default: + x86illegal(); + return 1; + } + CLOCK_CYCLES(6); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); + CPU_BLOCK_END(); + return 0; +} + +static void +opMOV_r_TRx(void) +{ +#if 0 + uint32_t base; + + base = _tr[4] & 0xfffff800; +#endif + + switch (cpu_reg) { + case 3: +#if 0 + pclog("[R] %08X cache = %08X\n", base + cache_index, _tr[3]); +#endif + _tr[3] = *(uint32_t *) &(_cache[cache_index]); + cache_index = (cache_index + 4) & 0xf; + break; + } + cpu_state.regs[cpu_rm].l = _tr[cpu_reg]; + CLOCK_CYCLES(6); +} +static int +opMOV_r_TRx_a16(uint32_t fetchdat) +{ + if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1))) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_16(fetchdat); + opMOV_r_TRx(); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); + return 0; +} +static int +opMOV_r_TRx_a32(uint32_t fetchdat) +{ + if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1))) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_32(fetchdat); + opMOV_r_TRx(); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); + return 0; +} + +static void +opMOV_TRx_r(void) +{ + uint32_t base; + int i; + int ctl; + + _tr[cpu_reg] = cpu_state.regs[cpu_rm].l; + base = _tr[4] & 0xfffff800; + ctl = _tr[5] & 3; + switch (cpu_reg) { + case 3: +#if 0 + pclog("[W] %08X cache = %08X\n", base + cache_index, _tr[3]); +#endif + *(uint32_t *) &(_cache[cache_index]) = _tr[3]; + cache_index = (cache_index + 4) & 0xf; + break; + case 4: +#if 0 + if (!(cr0 & 1) && !(_tr[5] & (1 << 19))) + pclog("TAG = %08X, DEST = %08X\n", base, base + cache_index - 16); +#endif + break; + case 5: +#if 0 + pclog("[16] EXT = %i (%i), SET = %04X\n", !!(_tr[5] & (1 << 19)), _tr[5] & 0x03, _tr[5] & 0x7f0); +#endif + if (!(_tr[5] & (1 << 19))) { + switch (ctl) { + case 0: +#if 0 + pclog(" Cache fill or read...\n", base); +#endif + break; + case 1: + base += (_tr[5] & 0x7f0); +#if 0 + pclog(" Writing 16 bytes to %08X...\n", base); +#endif + for (i = 0; i < 16; i += 4) + mem_writel_phys(base + i, *(uint32_t *) &(_cache[i])); + break; + case 2: + base += (_tr[5] & 0x7f0); +#if 0 + pclog(" Reading 16 bytes from %08X...\n", base); +#endif + for (i = 0; i < 16; i += 4) + *(uint32_t *) &(_cache[i]) = mem_readl_phys(base + i); + break; + case 3: +#if 0 + pclog(" Cache invalidate/flush...\n", base); +#endif + break; + } + } + break; + } + CLOCK_CYCLES(6); +} +static int +opMOV_TRx_r_a16(uint32_t fetchdat) +{ + if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1))) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_16(fetchdat); + opMOV_TRx_r(); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0); + return 0; +} +static int +opMOV_TRx_r_a32(uint32_t fetchdat) +{ + if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1))) { + x86gpf(NULL, 0); + return 1; + } + fetch_ea_32(fetchdat); + opMOV_TRx_r(); + PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1); + return 0; +} diff --git a/src/cpu/x86_ops_mov_seg.h b/src/cpu/x86_ops_mov_seg.h index 2a798db5c..7fcc92312 100644 --- a/src/cpu/x86_ops_mov_seg.h +++ b/src/cpu/x86_ops_mov_seg.h @@ -195,7 +195,11 @@ opMOV_seg_w_a16(uint32_t fetchdat) cpu_state.pc++; if (cpu_state.abrt) return 1; +#ifdef OPS_286_386 + x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +#else x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +#endif return 1; case 0x20: /*FS*/ op_loadseg(new_seg, &cpu_state.seg_fs); @@ -240,7 +244,11 @@ opMOV_seg_w_a32(uint32_t fetchdat) cpu_state.pc++; if (cpu_state.abrt) return 1; +#ifdef OPS_286_386 + x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +#else x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +#endif return 1; case 0x20: /*FS*/ op_loadseg(new_seg, &cpu_state.seg_fs); diff --git a/src/cpu/x86_ops_pmode.h b/src/cpu/x86_ops_pmode.h index 1254d7289..e84847a7b 100644 --- a/src/cpu/x86_ops_pmode.h +++ b/src/cpu/x86_ops_pmode.h @@ -367,6 +367,7 @@ op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) switch (rmdat & 0x38) { case 0x00: /*SGDT*/ + ILLEGAL_ON(cpu_mod == 3); if (cpu_mod != 3) SEG_CHECK_WRITE(cpu_state.ea_seg); seteaw(gdt.limit); @@ -389,6 +390,7 @@ op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) PREFETCH_RUN(7, 2, rmdat, 0, 0, 1, 1, ea32); break; case 0x10: /*LGDT*/ + ILLEGAL_ON(cpu_mod == 3); if ((CPL || cpu_state.eflags & VM_FLAG) && (cr0 & 1)) { x86gpf(NULL, 0); break; diff --git a/src/cpu/x86_ops_prefix_2386.h b/src/cpu/x86_ops_prefix_2386.h new file mode 100644 index 000000000..7c87f0bf3 --- /dev/null +++ b/src/cpu/x86_ops_prefix_2386.h @@ -0,0 +1,179 @@ +#define op_seg(name, seg, opcode_table, normal_opcode_table) \ + static int op##name##_w_a16(uint32_t fetchdat) \ + { \ + fetchdat = fastreadl(cs + cpu_state.pc); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.pc++; \ + \ + cpu_state.ea_seg = &seg; \ + cpu_state.ssegs = 1; \ + CLOCK_CYCLES(4); \ + PREFETCH_PREFIX(); \ + \ + if (opcode_table[fetchdat & 0xff]) \ + return opcode_table[fetchdat & 0xff](fetchdat >> 8); \ + return normal_opcode_table[fetchdat & 0xff](fetchdat >> 8); \ + } \ + \ + static int op##name##_l_a16(uint32_t fetchdat) \ + { \ + fetchdat = fastreadl(cs + cpu_state.pc); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.pc++; \ + \ + cpu_state.ea_seg = &seg; \ + cpu_state.ssegs = 1; \ + CLOCK_CYCLES(4); \ + PREFETCH_PREFIX(); \ + \ + if (opcode_table[(fetchdat & 0xff) | 0x100]) \ + return opcode_table[(fetchdat & 0xff) | 0x100](fetchdat >> 8); \ + return normal_opcode_table[(fetchdat & 0xff) | 0x100](fetchdat >> 8); \ + } \ + \ + static int op##name##_w_a32(uint32_t fetchdat) \ + { \ + fetchdat = fastreadl(cs + cpu_state.pc); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.pc++; \ + \ + cpu_state.ea_seg = &seg; \ + cpu_state.ssegs = 1; \ + CLOCK_CYCLES(4); \ + PREFETCH_PREFIX(); \ + \ + if (opcode_table[(fetchdat & 0xff) | 0x200]) \ + return opcode_table[(fetchdat & 0xff) | 0x200](fetchdat >> 8); \ + return normal_opcode_table[(fetchdat & 0xff) | 0x200](fetchdat >> 8); \ + } \ + \ + static int op##name##_l_a32(uint32_t fetchdat) \ + { \ + fetchdat = fastreadl(cs + cpu_state.pc); \ + if (cpu_state.abrt) \ + return 1; \ + cpu_state.pc++; \ + \ + cpu_state.ea_seg = &seg; \ + cpu_state.ssegs = 1; \ + CLOCK_CYCLES(4); \ + PREFETCH_PREFIX(); \ + \ + if (opcode_table[(fetchdat & 0xff) | 0x300]) \ + return opcode_table[(fetchdat & 0xff) | 0x300](fetchdat >> 8); \ + return normal_opcode_table[(fetchdat & 0xff) | 0x300](fetchdat >> 8); \ + } + +// clang-format off +op_seg(CS, cpu_state.seg_cs, x86_2386_opcodes, x86_2386_opcodes) +op_seg(DS, cpu_state.seg_ds, x86_2386_opcodes, x86_2386_opcodes) +op_seg(ES, cpu_state.seg_es, x86_2386_opcodes, x86_2386_opcodes) +op_seg(FS, cpu_state.seg_fs, x86_2386_opcodes, x86_2386_opcodes) +op_seg(GS, cpu_state.seg_gs, x86_2386_opcodes, x86_2386_opcodes) +op_seg(SS, cpu_state.seg_ss, x86_2386_opcodes, x86_2386_opcodes) + +op_seg(CS_REPE, cpu_state.seg_cs, x86_2386_opcodes_REPE, x86_2386_opcodes) +op_seg(DS_REPE, cpu_state.seg_ds, x86_2386_opcodes_REPE, x86_2386_opcodes) +op_seg(ES_REPE, cpu_state.seg_es, x86_2386_opcodes_REPE, x86_2386_opcodes) +op_seg(FS_REPE, cpu_state.seg_fs, x86_2386_opcodes_REPE, x86_2386_opcodes) +op_seg(GS_REPE, cpu_state.seg_gs, x86_2386_opcodes_REPE, x86_2386_opcodes) +op_seg(SS_REPE, cpu_state.seg_ss, x86_2386_opcodes_REPE, x86_2386_opcodes) + +op_seg(CS_REPNE, cpu_state.seg_cs, x86_2386_opcodes_REPNE, x86_2386_opcodes) +op_seg(DS_REPNE, cpu_state.seg_ds, x86_2386_opcodes_REPNE, x86_2386_opcodes) +op_seg(ES_REPNE, cpu_state.seg_es, x86_2386_opcodes_REPNE, x86_2386_opcodes) +op_seg(FS_REPNE, cpu_state.seg_fs, x86_2386_opcodes_REPNE, x86_2386_opcodes) +op_seg(GS_REPNE, cpu_state.seg_gs, x86_2386_opcodes_REPNE, x86_2386_opcodes) +op_seg(SS_REPNE, cpu_state.seg_ss, x86_2386_opcodes_REPNE, x86_2386_opcodes) + // clang-format on + +static int +op_66(uint32_t fetchdat) /*Data size select*/ +{ + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; + + cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200); + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +} +static int +op_67(uint32_t fetchdat) /*Address size select*/ +{ + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; + + cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100); + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +} + +static int +op_66_REPE(uint32_t fetchdat) /*Data size select*/ +{ + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; + + cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200); + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + if (x86_2386_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32]) + return x86_2386_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +} +static int +op_67_REPE(uint32_t fetchdat) /*Address size select*/ +{ + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; + + cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100); + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + if (x86_2386_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32]) + return x86_2386_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +} +static int +op_66_REPNE(uint32_t fetchdat) /*Data size select*/ +{ + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; + + cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200); + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + if (x86_2386_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32]) + return x86_2386_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +} +static int +op_67_REPNE(uint32_t fetchdat) /*Address size select*/ +{ + fetchdat = fastreadl(cs + cpu_state.pc); + if (cpu_state.abrt) + return 1; + cpu_state.pc++; + + cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100); + CLOCK_CYCLES(2); + PREFETCH_PREFIX(); + if (x86_2386_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32]) + return x86_2386_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); + return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +} diff --git a/src/cpu/x86_ops_rep_2386.h b/src/cpu/x86_ops_rep_2386.h index b6f64e90d..fe5048340 100644 --- a/src/cpu/x86_ops_rep_2386.h +++ b/src/cpu/x86_ops_rep_2386.h @@ -836,7 +836,7 @@ REP_OPS_CMPS_SCAS(a32_E, ECX, ESI, EDI, 1) static int opREPNE(uint32_t fetchdat) { - fetchdat = fastreadl(cs + cpu_state.pc); + fetchdat = fastreadl_fetch(cs + cpu_state.pc); if (cpu_state.abrt) return 1; cpu_state.pc++; @@ -850,7 +850,7 @@ opREPNE(uint32_t fetchdat) static int opREPE(uint32_t fetchdat) { - fetchdat = fastreadl(cs + cpu_state.pc); + fetchdat = fastreadl_fetch(cs + cpu_state.pc); if (cpu_state.abrt) return 1; cpu_state.pc++; diff --git a/src/cpu/x86_ops_ret_2386.h b/src/cpu/x86_ops_ret_2386.h new file mode 100644 index 000000000..ca85bf2b0 --- /dev/null +++ b/src/cpu/x86_ops_ret_2386.h @@ -0,0 +1,297 @@ +#ifdef USE_NEW_DYNAREC +# define CPU_SET_OXPC +#else +# define CPU_SET_OXPC oxpc = cpu_state.pc; +#endif + +#define RETF_a16(stack_offset) \ + if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) { \ + op_pmoderetf(0, stack_offset); \ + return 1; \ + } \ + CPU_SET_OXPC \ + if (stack32) { \ + cpu_state.pc = readmemw(ss, ESP); \ + op_loadcs(readmemw(ss, ESP + 2)); \ + } else { \ + cpu_state.pc = readmemw(ss, SP); \ + op_loadcs(readmemw(ss, SP + 2)); \ + } \ + if (cpu_state.abrt) \ + return 1; \ + if (stack32) \ + ESP += 4 + stack_offset; \ + else \ + SP += 4 + stack_offset; \ + cycles -= timing_retf_rm; + +#define RETF_a32(stack_offset) \ + if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) { \ + op_pmoderetf(1, stack_offset); \ + return 1; \ + } \ + CPU_SET_OXPC \ + if (stack32) { \ + cpu_state.pc = readmeml(ss, ESP); \ + op_loadcs(readmeml(ss, ESP + 4) & 0xffff); \ + } else { \ + cpu_state.pc = readmeml(ss, SP); \ + op_loadcs(readmeml(ss, SP + 4) & 0xffff); \ + } \ + if (cpu_state.abrt) \ + return 1; \ + if (stack32) \ + ESP += 8 + stack_offset; \ + else \ + SP += 8 + stack_offset; \ + cycles -= timing_retf_rm; + +static int +opRETF_a16(uint32_t fetchdat) +{ + int cycles_old = cycles; + UN_USED(cycles_old); + + CPU_BLOCK_END(); + RETF_a16(0); + + PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return 0; +} +static int +opRETF_a32(uint32_t fetchdat) +{ + int cycles_old = cycles; + UN_USED(cycles_old); + + CPU_BLOCK_END(); + RETF_a32(0); + + PREFETCH_RUN(cycles_old - cycles, 1, -1, 0, 2, 0, 0, 1); + PREFETCH_FLUSH(); + return 0; +} + +static int +opRETF_a16_imm(uint32_t fetchdat) +{ + uint16_t offset = getwordf(); + int cycles_old = cycles; + UN_USED(cycles_old); + + CPU_BLOCK_END(); + RETF_a16(offset); + + PREFETCH_RUN(cycles_old - cycles, 3, -1, 2, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return 0; +} +static int +opRETF_a32_imm(uint32_t fetchdat) +{ + uint16_t offset = getwordf(); + int cycles_old = cycles; + UN_USED(cycles_old); + + CPU_BLOCK_END(); + RETF_a32(offset); + + PREFETCH_RUN(cycles_old - cycles, 3, -1, 0, 2, 0, 0, 1); + PREFETCH_FLUSH(); + return 0; +} + +static int +opIRET_186(uint32_t fetchdat) +{ + int cycles_old = cycles; + UN_USED(cycles_old); + + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { + x86gpf(NULL, 0); + return 1; + } + if (msw & 1) { + optype = IRET; + op_pmodeiret(0); + optype = 0; + } else { + uint16_t new_cs; + CPU_SET_OXPC + if (stack32) { + cpu_state.pc = readmemw(ss, ESP); + new_cs = readmemw(ss, ESP + 2); + cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ESP + 4) & 0xffd5) | 2; + ESP += 6; + } else { + cpu_state.pc = readmemw(ss, SP); + new_cs = readmemw(ss, ((SP + 2) & 0xffff)); + cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ((SP + 4) & 0xffff)) & 0x0fd5) | 2; + SP += 6; + } + op_loadcs(new_cs); + cycles -= timing_iret_rm; + } + flags_extract(); + nmi_enable = 1; + rf_flag_no_clear = 1; + CPU_BLOCK_END(); + + PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return cpu_state.abrt; +} + +static int +opIRET_286(uint32_t fetchdat) +{ + int cycles_old = cycles; + UN_USED(cycles_old); + + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { + x86gpf(NULL, 0); + return 1; + } + if (msw & 1) { + optype = IRET; + op_pmodeiret(0); + optype = 0; + } else { + uint16_t new_cs; + CPU_SET_OXPC + if (stack32) { + cpu_state.pc = readmemw(ss, ESP); + new_cs = readmemw(ss, ESP + 2); + cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ESP + 4) & 0xffd5) | 2; + ESP += 6; + } else { + cpu_state.pc = readmemw(ss, SP); + new_cs = readmemw(ss, ((SP + 2) & 0xffff)); + cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ((SP + 4) & 0xffff)) & 0x0fd5) | 2; + SP += 6; + } + op_loadcs(new_cs); + cycles -= timing_iret_rm; + } + flags_extract(); + nmi_enable = 1; + rf_flag_no_clear = 1; + CPU_BLOCK_END(); + + PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return cpu_state.abrt; +} + +static int +opIRET(uint32_t fetchdat) +{ + int cycles_old = cycles; + UN_USED(cycles_old); + + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { + if (cr4 & CR4_VME) { + uint16_t new_pc; + uint16_t new_cs; + uint16_t new_flags; + + new_pc = readmemw(ss, SP); + new_cs = readmemw(ss, ((SP + 2) & 0xffff)); + new_flags = readmemw(ss, ((SP + 4) & 0xffff)); + if (cpu_state.abrt) + return 1; + + if ((new_flags & T_FLAG) || ((new_flags & I_FLAG) && (cpu_state.eflags & VIP_FLAG))) { + x86gpf(NULL, 0); + return 1; + } + SP += 6; + if (new_flags & I_FLAG) + cpu_state.eflags |= VIF_FLAG; + else + cpu_state.eflags &= ~VIF_FLAG; + cpu_state.flags = (cpu_state.flags & 0x3300) | (new_flags & 0x4cd5) | 2; + op_loadcs(new_cs); + cpu_state.pc = new_pc; + + cycles -= timing_iret_rm; + } else { + x86gpf_expected(NULL, 0); + return 1; + } + } else { + if (msw & 1) { + optype = IRET; + op_pmodeiret(0); + optype = 0; + } else { + uint16_t new_cs; + CPU_SET_OXPC + if (stack32) { + cpu_state.pc = readmemw(ss, ESP); + new_cs = readmemw(ss, ESP + 2); + cpu_state.flags = (readmemw(ss, ESP + 4) & 0xffd5) | 2; + ESP += 6; + } else { + cpu_state.pc = readmemw(ss, SP); + new_cs = readmemw(ss, ((SP + 2) & 0xffff)); + cpu_state.flags = (readmemw(ss, ((SP + 4) & 0xffff)) & 0xffd5) | 2; + SP += 6; + } + op_loadcs(new_cs); + cycles -= timing_iret_rm; + } + } + flags_extract(); + nmi_enable = 1; + rf_flag_no_clear = 1; + CPU_BLOCK_END(); + + PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0); + PREFETCH_FLUSH(); + return cpu_state.abrt; +} + +static int +opIRETD(uint32_t fetchdat) +{ + int cycles_old = cycles; + UN_USED(cycles_old); + + if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { + x86gpf_expected(NULL, 0); + return 1; + } + if (msw & 1) { + optype = IRET; + op_pmodeiret(1); + optype = 0; + } else { + uint16_t new_cs; + CPU_SET_OXPC + if (stack32) { + cpu_state.pc = readmeml(ss, ESP); + new_cs = readmemw(ss, ESP + 4); + cpu_state.flags = (readmemw(ss, ESP + 8) & 0xffd5) | 2; + cpu_state.eflags = readmemw(ss, ESP + 10); + ESP += 12; + } else { + cpu_state.pc = readmeml(ss, SP); + new_cs = readmemw(ss, ((SP + 4) & 0xffff)); + cpu_state.flags = (readmemw(ss, (SP + 8) & 0xffff) & 0xffd5) | 2; + cpu_state.eflags = readmemw(ss, (SP + 10) & 0xffff); + SP += 12; + } + op_loadcs(new_cs); + cycles -= timing_iret_rm; + } + flags_extract(); + nmi_enable = 1; + rf_flag_no_clear = 1; + CPU_BLOCK_END(); + + PREFETCH_RUN(cycles_old - cycles, 1, -1, 0, 2, 0, 0, 1); + PREFETCH_FLUSH(); + return cpu_state.abrt; +} diff --git a/src/cpu/x86_ops_stack.h b/src/cpu/x86_ops_stack.h index 13eb883d3..fbf603ddb 100644 --- a/src/cpu/x86_ops_stack.h +++ b/src/cpu/x86_ops_stack.h @@ -667,7 +667,11 @@ opPOP_SS_w(uint32_t fetchdat) cpu_state.pc++; if (cpu_state.abrt) return 1; +#ifdef OPS_286_386 + x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +#else x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +#endif return 1; } @@ -695,7 +699,11 @@ opPOP_SS_l(uint32_t fetchdat) cpu_state.pc++; if (cpu_state.abrt) return 1; +#ifdef OPS_286_386 + x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +#else x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); +#endif return 1; } diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index feaad5913..c50c97a39 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -2286,8 +2286,14 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32) op_loadseg(new_fs, &cpu_state.seg_fs); op_loadseg(new_gs, &cpu_state.seg_gs); + if (!cpu_use_exec) + rf_flag_no_clear = 1; + if (t_bit) { - trap = 2; + if (cpu_use_exec) + trap = 2; + else + trap |= 2; #ifdef USE_DYNAREC cpu_block_end = 1; #endif @@ -2467,6 +2473,8 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32) tr.limit = limit; tr.access = segdat[2] >> 8; tr.ar_high = segdat[3] & 0xff; + if (!cpu_use_exec) + dr[7] &= 0xFFFFFFAA; } void diff --git a/src/cpu/x86seg_common.c b/src/cpu/x86seg_common.c index 8926af0d7..12b698b1a 100644 --- a/src/cpu/x86seg_common.c +++ b/src/cpu/x86seg_common.c @@ -87,6 +87,12 @@ x86de(UNUSED(char *s), UNUSED(uint16_t error)) #endif } +void +x86gen(void) +{ + x86_int(1); +} + void x86gpf(UNUSED(char *s), uint16_t error) { diff --git a/src/cpu/x86seg_common.h b/src/cpu/x86seg_common.h index f4bffed40..9f9049322 100644 --- a/src/cpu/x86seg_common.h +++ b/src/cpu/x86seg_common.h @@ -41,6 +41,7 @@ extern int cgate32; extern int intgatesize; extern void x86seg_reset(void); +extern void x86gen(void); extern void x86de(char *s, uint16_t error); extern void x86gpf(char *s, uint16_t error); extern void x86gpf_expected(char *s, uint16_t error); diff --git a/src/cpu/x886seg_2386.c b/src/cpu/x886seg_2386.c deleted file mode 100644 index 335c757e4..000000000 --- a/src/cpu/x886seg_2386.c +++ /dev/null @@ -1,22 +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. - * - * x86 CPU segment emulation for the 286/386 interpreter. - * - * - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - */ -#ifndef OPS_286_386 -# define OPS_286_386 -#endif -#include "x86seg.c" diff --git a/src/device.c b/src/device.c index 6125674db..b934e7246 100644 --- a/src/device.c +++ b/src/device.c @@ -62,6 +62,7 @@ static device_t *devices[DEVICE_MAX]; static void *device_priv[DEVICE_MAX]; static device_context_t device_current; static device_context_t device_prev; +static void *device_common_priv; #ifdef ENABLE_DEVICE_LOG int device_do_log = ENABLE_DEVICE_LOG; @@ -209,6 +210,16 @@ device_add(const device_t *dev) return device_add_common(dev, dev, NULL, NULL, 0); } +void * +device_add_linked(const device_t *dev, void *priv) +{ + void *ret; + device_common_priv = priv; + ret = device_add_common(dev, dev, NULL, NULL, 0); + device_common_priv = NULL; + return ret; +} + void * device_add_parameters(const device_t *dev, void *params) { @@ -305,6 +316,12 @@ device_cadd_inst_ex_parameters(const device_t *dev, const device_t *cd, void *pr device_add_common(dev, cd, priv, params, inst); } +void * +device_get_common_priv(void) +{ + return device_common_priv; +} + void device_close_all(void) { diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index adb611c1e..94c4b68c4 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -19,7 +19,7 @@ add_library(dev OBJECT bugger.c cassette.c cartridge.c hasp.c hwm.c hwm_lm75.c h hwm_vt82c686.c ibm_5161.c intel_ich2_gpio.c intel_ich2_trap.c isamem.c isartc.c ../lpt.c pci_bridge.c postcard.c serial.c unittester.c clock_ics9xxx.c isapnp.c i2c.c i2c_gpio.c - smbus_piix4.c smbus_ali7101.c keyboard.c keyboard_xt.c + smbus_piix4.c smbus_ali7101.c smbus_sis5595.c keyboard.c keyboard_xt.c kbc_at.c kbc_at_dev.c keyboard_at.c mouse.c mouse_bus.c mouse_serial.c mouse_ps2.c nec_mate_unk.c phoenix_486_jumper.c diff --git a/src/device/ibm_5161.c b/src/device/ibm_5161.c index 07083873e..762a379a1 100644 --- a/src/device/ibm_5161.c +++ b/src/device/ibm_5161.c @@ -73,8 +73,8 @@ ibm_5161_in(uint16_t port, void *priv) 02-03 = not used 04-07 = switch position 1 = Off - 0 =On */ - ret = dev->regs[3] & 0x01; + 0 = On */ + ret = (dev->regs[3] & 0x01) | (((~(0xf - ((mem_size + isa_mem_size) >> 6))) & 0xf) << 4); break; default: @@ -95,8 +95,7 @@ ibm_5161_close(void *priv) static void * ibm_5161_init(UNUSED(const device_t *info)) { - ibm_5161_t *dev = (ibm_5161_t *) malloc(sizeof(ibm_5161_t)); - memset(dev, 0, sizeof(ibm_5161_t)); + ibm_5161_t *dev = (ibm_5161_t *) calloc(1, sizeof(ibm_5161_t)); /* Extender Card Registers */ io_sethandler(0x0210, 0x0004, diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index d2e6cf364..bc4a1f366 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -1787,6 +1787,9 @@ kbc_at_process_cmd(void *priv) if (dev->ib == 0xbb) break; + if (strstr(machine_get_internal_name(), "pb") != NULL) + cpu_override_dynarec = 1; + if (dev->misc_flags & FLAG_PS2) { set_enable_aux(dev, 1); if ((dev->ports[1] != NULL) && (dev->ports[1]->priv != NULL)) { @@ -1891,6 +1894,8 @@ kbc_at_read(uint16_t port, void *priv) This also means that in AT mode, the IRQ is level-triggered. */ if (!(dev->misc_flags & FLAG_PS2)) picintclevel(1 << 1, &dev->irq_state); + if ((strstr(machine_get_internal_name(), "pb") != NULL) && (cpu_override_dynarec == 1)) + cpu_override_dynarec = 0; break; case 0x64: diff --git a/src/device/kbc_at_dev.c b/src/device/kbc_at_dev.c index 1c1a0e91a..c1041e6e1 100644 --- a/src/device/kbc_at_dev.c +++ b/src/device/kbc_at_dev.c @@ -119,12 +119,13 @@ kbc_at_dev_poll(void *priv) break; case DEV_STATE_MAIN_2: /* Output from scan queue if needed and then return to main loop #1. */ - if (*dev->scan && (dev->port->out_new == -1) && (dev->queue_start != dev->queue_end)) { + if (!dev->ignore && *dev->scan && (dev->port->out_new == -1) && + (dev->queue_start != dev->queue_end)) { kbc_at_dev_log("%s: %02X (DATA) on channel 1\n", dev->name, dev->queue[dev->queue_start]); dev->port->out_new = dev->queue[dev->queue_start]; dev->queue_start = (dev->queue_start + 1) & dev->fifo_mask; } - if (!(*dev->scan) || dev->port->wantcmd) + if (dev->ignore || !(*dev->scan) || dev->port->wantcmd) dev->state = DEV_STATE_MAIN_1; break; case DEV_STATE_MAIN_OUT: @@ -199,8 +200,7 @@ kbc_at_dev_init(uint8_t inst) { atkbc_dev_t *dev; - dev = (atkbc_dev_t *) malloc(sizeof(atkbc_dev_t)); - memset(dev, 0x00, sizeof(atkbc_dev_t)); + dev = (atkbc_dev_t *) calloc(1, sizeof(atkbc_dev_t)); dev->port = kbc_at_ports[inst]; diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index f8eddb931..7accb2fd6 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -523,10 +523,12 @@ static void add_data_kbd(uint16_t val) { atkbc_dev_t *dev = SavedKbd; - uint8_t fake_shift[4]; + uint8_t fake_shift[4] = { 0 }; uint8_t num_lock = 0; uint8_t shift_states = 0; + dev->ignore = 1; + keyboard_get_states(NULL, &num_lock, NULL); shift_states = keyboard_get_shift() & STATE_SHIFT_MASK; @@ -541,12 +543,14 @@ add_data_kbd(uint16_t val) /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ switch (keyboard_mode & 0x02) { case 1: + keyboard_at_log("E0 2A\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0x2a; add_data_vals(dev, fake_shift, 2); break; case 2: + keyboard_at_log("E0 12\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0x12; add_data_vals(dev, fake_shift, 2); @@ -562,12 +566,14 @@ add_data_kbd(uint16_t val) /* Num lock off and left shift pressed. */ switch (keyboard_mode & 0x02) { case 1: + keyboard_at_log("E0 AA\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0xaa; add_data_vals(dev, fake_shift, 2); break; case 2: + keyboard_at_log("E0 F0 12\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0xf0; fake_shift[2] = 0x12; @@ -583,12 +589,14 @@ add_data_kbd(uint16_t val) /* Num lock off and right shift pressed. */ switch (keyboard_mode & 0x02) { case 1: + keyboard_at_log("E0 B6\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0xb6; add_data_vals(dev, fake_shift, 2); break; case 2: + keyboard_at_log("E0 F0 59\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0xf0; fake_shift[2] = 0x59; @@ -614,12 +622,14 @@ add_data_kbd(uint16_t val) /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ switch (keyboard_mode & 0x02) { case 1: + keyboard_at_log("E0 AA\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0xaa; add_data_vals(dev, fake_shift, 2); break; case 2: + keyboard_at_log("E0 F0 12\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0xf0; fake_shift[2] = 0x12; @@ -636,12 +646,14 @@ add_data_kbd(uint16_t val) /* Num lock off and left shift pressed. */ switch (keyboard_mode & 0x02) { case 1: + keyboard_at_log("E0 2A\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0x2a; add_data_vals(dev, fake_shift, 2); break; case 2: + keyboard_at_log("E0 12\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0x12; add_data_vals(dev, fake_shift, 2); @@ -656,12 +668,14 @@ add_data_kbd(uint16_t val) /* Num lock off and right shift pressed. */ switch (keyboard_mode & 0x02) { case 1: + keyboard_at_log("E0 36\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0x36; add_data_vals(dev, fake_shift, 2); break; case 2: + keyboard_at_log("E0 59\n"); fake_shift[0] = 0xe0; fake_shift[1] = 0x59; add_data_vals(dev, fake_shift, 2); @@ -680,6 +694,8 @@ add_data_kbd(uint16_t val) kbc_at_dev_queue_add(dev, val, 1); break; } + + dev->ignore = 0; } void @@ -860,7 +876,8 @@ keyboard_at_write(void *priv) case 0xf5: /* set defaults and disable keyboard */ case 0xf6: /* set defaults */ - keyboard_at_log("%s: set defaults%s\n", (val == 0xf6) ? "" : " and disable keyboard"); + keyboard_at_log("%s: set defaults%s\n", + dev->name, (val == 0xf6) ? "" : " and disable keyboard"); keyboard_scan = !(val & 0x01); keyboard_at_log("%s: val = %02X, keyboard_scan = %i\n", dev->name, val, keyboard_scan); diff --git a/src/device/mouse.c b/src/device/mouse.c index 193149bc8..da4ed1c04 100644 --- a/src/device/mouse.c +++ b/src/device/mouse.c @@ -454,6 +454,15 @@ mouse_scale(int x, int y) mouse_scale_y(y); } +void +mouse_scale_axis(int axis, int val) +{ + if (axis == 1) + mouse_scale_y(val); + else if (axis == 0) + mouse_scale_x(val); +} + void mouse_set_z(int z) { diff --git a/src/device/mouse_ps2.c b/src/device/mouse_ps2.c index 35f0cd9e8..c3a7310f0 100644 --- a/src/device/mouse_ps2.c +++ b/src/device/mouse_ps2.c @@ -21,6 +21,7 @@ #include #define HAVE_STDARG_H #include <86box/86box.h> +#include "cpu.h" #include <86box/device.h> #include <86box/keyboard.h> #include <86box/mouse.h> @@ -276,6 +277,7 @@ ps2_write(void *priv) break; default: + mouse_ps2_log("%s: Bad command: %02X\n", dev->name, val); kbc_at_dev_queue_add(dev, 0xfe, 0); } } diff --git a/src/device/pci_bridge.c b/src/device/pci_bridge.c index 14d6ae9be..c05e0783b 100644 --- a/src/device/pci_bridge.c +++ b/src/device/pci_bridge.c @@ -43,11 +43,14 @@ #define AGP_BRIDGE_VIA_598 0x11068598 #define AGP_BRIDGE_VIA_691 0x11068691 #define AGP_BRIDGE_VIA_8601 0x11068601 +#define AGP_BRIDGE_SIS_5XXX 0x10390001 #define AGP_BRIDGE_ALI(x) (((x) >> 16) == 0x10b9) #define AGP_BRIDGE_INTEL(x) ((((x) >> 16) == 0x8086) && ((x) != PCI_BRIDGE_INTEL_ICH2)) #define AGP_BRIDGE_VIA(x) (((x) >> 16) == 0x1106) -#define AGP_BRIDGE(x) (((x) >= AGP_BRIDGE_ALI_M5243) && ((x) != PCI_BRIDGE_INTEL_ICH2)) +#define AGP_BRIDGE_SIS(x) (((x) >> 16) == 0x1039) +//#define AGP_BRIDGE(x) (((x) >= AGP_BRIDGE_ALI_M5243) && ((x) != PCI_BRIDGE_INTEL_ICH2)) +#define AGP_BRIDGE(x) ((x) >= AGP_BRIDGE_SIS_5XXX) typedef struct pci_bridge_t { uint32_t local; @@ -140,6 +143,8 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) val |= 0x02; else if (dev->local == AGP_BRIDGE_ALI_M5247) val &= 0xc3; + else if (AGP_BRIDGE_SIS(dev->local)) + val &= 0x27; else val &= 0x67; break; @@ -211,7 +216,8 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) case 0x22: case 0x24: case 0x26: - val &= 0xf0; + val &= 0xf0; /* SiS datasheets say 0Fh for 1Ch but that's clearly an erratum since the + definition of the bits is identical to the other vendors' AGP bridges. */ break; case 0x3c: @@ -222,6 +228,8 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) case 0x3e: if (AGP_BRIDGE_VIA(dev->local)) val &= 0x0c; + else if (AGP_BRIDGE_SIS(dev->local)) + val &= 0x0e; else if (dev->local == AGP_BRIDGE_ALI_M5247) val &= 0x0f; else if (dev->local == AGP_BRIDGE_ALI_M5243) @@ -758,3 +766,17 @@ const device_t via_vt8601_agp_device = { .force_redraw = NULL, .config = NULL }; + +const device_t sis_5xxx_agp_device = { + .name = "SiS 5591/(5)600 AGP Bridge", + .internal_name = "via_5xxx_agp", + .flags = DEVICE_PCI, + .local = AGP_BRIDGE_SIS_5XXX, + .init = pci_bridge_init, + .close = NULL, + .reset = pci_bridge_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/device/smbus_sis5595.c b/src/device/smbus_sis5595.c new file mode 100644 index 000000000..b76b38e17 --- /dev/null +++ b/src/device/smbus_sis5595.c @@ -0,0 +1,386 @@ +/* + * 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 a generic SiS 5595-compatible SMBus host + * controller. + * + * Authors: RichardG, + * Miran Grca, + * + * Copyright 2020-2021 RichardG. + * Copyright 2021 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/timer.h> +#include <86box/i2c.h> +#include <86box/pci.h> +#include <86box/smbus.h> +#include <86box/plat_fallthrough.h> + +#ifdef ENABLE_SMBUS_SIS5595_LOG +int smbus_sis5595_do_log = ENABLE_SMBUS_SIS5595_LOG; + +static void +smbus_sis5595_log(const char *fmt, ...) +{ + va_list ap; + + if (smbus_sis5595_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define smbus_sis5595_log(fmt, ...) +#endif + +static void +smbus_sis5595_irq(smbus_sis5595_t *dev, int raise) +{ + if (dev->irq_enable) { + if (raise) + pci_set_mirq(6, 1, &dev->irq_state); + else + pci_clear_mirq(6, 1, &dev->irq_state); + } +} + +void +smbus_sis5595_irq_enable(void *priv, uint8_t enable) +{ + smbus_sis5595_t *dev = (smbus_sis5595_t *) priv; + + if (!enable && dev->irq_enable) + pci_clear_mirq(6, 1, &dev->irq_state); + + dev->irq_enable = enable; +} + +uint8_t +smbus_sis5595_read_index(void *priv) +{ + smbus_sis5595_t *dev = (smbus_sis5595_t *) priv; + + return dev->index; +} + +uint8_t +smbus_sis5595_read_data(void *priv) +{ + smbus_sis5595_t *dev = (smbus_sis5595_t *) priv; + uint8_t ret = 0x00; + + switch (dev->index) { + case 0x00: + ret = dev->stat & 0xff; + break; + case 0x01: + ret = dev->stat >> 8; + break; + + case 0x02: + ret = dev->ctl & 0xff; + break; + case 0x03: + ret = dev->ctl >> 8; + break; + + case 0x04: + ret = dev->addr; + break; + + case 0x05: + ret = dev->cmd; + break; + + case 0x06: + ret = dev->block_ptr; + break; + + case 0x07: + ret = dev->count; + break; + + case 0x08 ... 0x0f: + ret = dev->data[(dev->index & 0x07) + (dev->block_ptr << 3)]; + if (dev->index == 0x0f) { + dev->block_ptr = (dev->block_ptr + 1) & 3; + smbus_sis5595_irq(dev, dev->block_ptr != 0x00); + } + break; + + case 0x10: + ret = dev->saved_addr; + break; + + case 0x11: + ret = dev->data0; + break; + + case 0x12: + ret = dev->data1; + break; + + case 0x13: + ret = dev->alias; + break; + + case 0xff: + ret = dev->reg_ff & 0xc0; + break; + + default: + break; + } + + smbus_sis5595_log("SMBus SIS5595: read(%02X) = %02x\n", addr, ret); + + return ret; +} + +void +smbus_sis5595_write_index(void *priv, uint8_t val) +{ + smbus_sis5595_t *dev = (smbus_sis5595_t *) priv; + + dev->index = val; +} + +void +smbus_sis5595_write_data(void *priv, uint8_t val) +{ + smbus_sis5595_t *dev = (smbus_sis5595_t *) priv; + uint8_t smbus_addr; + uint8_t cmd; + uint8_t read; + uint16_t prev_stat; + uint16_t timer_bytes = 0; + + smbus_sis5595_log("SMBus SIS5595: write(%02X, %02X)\n", addr, val); + + prev_stat = dev->next_stat; + dev->next_stat = 0x0000; + switch (dev->index) { + case 0x00: + dev->stat &= ~(val & 0xf0); + /* Make sure IDLE is set if we're not busy or errored. */ + if (dev->stat == 0x04) + dev->stat = 0x00; + break; + case 0x01: + dev->stat &= ~(val & 0x07); + break; + + case 0x02: + dev->ctl = (dev->ctl & 0xff00) | val; + if (val & 0x20) { /* cancel an in-progress command if KILL is set */ + if (prev_stat) { /* cancel only if a command is in progress */ + timer_disable(&dev->response_timer); + dev->stat = 0x80; /* raise FAILED */ + } + } else if (val & 0x10) { + /* dispatch command if START is set */ + timer_bytes++; /* address */ + + smbus_addr = (dev->addr >> 1); + read = dev->addr & 0x01; + + cmd = (dev->ctl >> 1) & 0x7; + smbus_sis5595_log("SMBus SIS5595: addr=%02X read=%d protocol=%X cmd=%02X " + "data0=%02X data1=%02X\n", smbus_addr, read, cmd, dev->cmd, + dev->data0, dev->data1); + + /* Raise DEV_ERR if no device is at this address, or if the device returned + NAK when starting the transfer. */ + if (!i2c_start(i2c_smbus, smbus_addr, read)) { + dev->next_stat = 0x0020; + break; + } + + dev->next_stat = 0x0040; /* raise INTER (command completed) by default */ + + /* Decode the command protocol. */ + dev->block_ptr = 0x01; + switch (cmd) { + case 0x0: /* quick R/W */ + break; + + case 0x1: /* byte R/W */ + if (read) /* byte read */ + dev->data[0] = i2c_read(i2c_smbus, smbus_addr); + else /* byte write */ + i2c_write(i2c_smbus, smbus_addr, dev->data[0]); + timer_bytes++; + + break; + + case 0x2: /* byte data R/W */ + /* command write */ + i2c_write(i2c_smbus, smbus_addr, dev->cmd); + timer_bytes++; + + if (read) /* byte read */ + dev->data[0] = i2c_read(i2c_smbus, smbus_addr); + else /* byte write */ + i2c_write(i2c_smbus, smbus_addr, dev->data[0]); + timer_bytes++; + + break; + + case 0x3: /* word data R/W */ + /* command write */ + i2c_write(i2c_smbus, smbus_addr, dev->cmd); + timer_bytes++; + + if (read) { /* word read */ + dev->data[0] = i2c_read(i2c_smbus, smbus_addr); + dev->data[1] = i2c_read(i2c_smbus, smbus_addr); + } else { /* word write */ + i2c_write(i2c_smbus, smbus_addr, dev->data[0]); + i2c_write(i2c_smbus, smbus_addr, dev->data[1]); + } + timer_bytes += 2; + + break; + + case 0x5: /* block R/W */ + dev->block_ptr = 0x00; + timer_bytes++; /* count the SMBus length byte now */ + fallthrough; + + default: /* unknown */ + dev->next_stat = 0x0010; /* raise DEV_ERR */ + timer_bytes = 0; + break; + } + + /* Finish transfer. */ + i2c_stop(i2c_smbus, smbus_addr); + } + break; + case 0x03: + dev->ctl = (dev->ctl & 0x00ff) | (val << 8); + break; + + case 0x04: + dev->addr = val; + break; + + case 0x05: + dev->cmd = val; + break; + + case 0x08 ... 0x0f: + dev->data[dev->index & 0x07] = val; + break; + + case 0x10: + dev->saved_addr = val; + break; + + case 0x11: + dev->data0 = val; + break; + + case 0x12: + dev->data1 = val; + break; + + case 0x13: + dev->alias = val & 0xfe; + break; + + case 0xff: + dev->reg_ff = val & 0x3f; + break; + + default: + break; + } + + if (dev->next_stat != 0x04) { /* schedule dispatch of any pending status register update */ + dev->stat = 0x08; /* raise HOST_BUSY while waiting */ + timer_disable(&dev->response_timer); + /* delay = ((half clock for start + half clock for stop) + (bytes * (8 bits + ack))) * 60us period measured on real VIA 686B */ + timer_set_delay_u64(&dev->response_timer, (1 + (timer_bytes * 9)) * 60 * TIMER_USEC); + } +} + +static void +smbus_sis5595_response(void *priv) +{ + smbus_sis5595_t *dev = (smbus_sis5595_t *) priv; + + /* Dispatch the status register update. */ + dev->stat = dev->next_stat; +} + +static void +smbus_sis5595_reset(void *priv) +{ + smbus_sis5595_t *dev = (smbus_sis5595_t *) priv; + + timer_disable(&dev->response_timer); + dev->stat = 0x0000; + dev->block_ptr = 0x01; +} + +static void * +smbus_sis5595_init(const device_t *info) +{ + smbus_sis5595_t *dev = (smbus_sis5595_t *) malloc(sizeof(smbus_sis5595_t)); + memset(dev, 0, sizeof(smbus_sis5595_t)); + + dev->local = info->local; + + /* We save the I2C bus handle on dev but use i2c_smbus for all operations because + dev and therefore dev->i2c will be invalidated if a device triggers a hard reset. */ + i2c_smbus = dev->i2c = i2c_addbus("smbus_sis5595"); + + timer_add(&dev->response_timer, smbus_sis5595_response, dev, 0); + + smbus_sis5595_reset(dev); + + return dev; +} + +static void +smbus_sis5595_close(void *priv) +{ + smbus_sis5595_t *dev = (smbus_sis5595_t *) priv; + + if (i2c_smbus == dev->i2c) + i2c_smbus = NULL; + i2c_removebus(dev->i2c); + + free(dev); +} + +const device_t sis5595_smbus_device = { + .name = "SiS 5595-compatible SMBus Host Controller", + .internal_name = "sis5595_smbus", + .flags = DEVICE_AT, + .local = 0, + .init = smbus_sis5595_init, + .close = smbus_sis5595_close, + .reset = smbus_sis5595_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/disk/CMakeLists.txt b/src/disk/CMakeLists.txt index 00da385d4..310354ccf 100644 --- a/src/disk/CMakeLists.txt +++ b/src/disk/CMakeLists.txt @@ -16,7 +16,7 @@ add_library(hdd OBJECT hdd.c hdd_image.c hdd_table.c hdc.c hdc_st506_xt.c hdc_st506_at.c hdc_xta.c hdc_esdi_at.c hdc_esdi_mca.c hdc_xtide.c hdc_ide.c hdc_ide_ali5213.c hdc_ide_opti611.c hdc_ide_cmd640.c hdc_ide_cmd646.c - hdc_ide_sff8038i.c) + hdc_ide_sff8038i.c hdc_ide_um8673f.c hdc_ide_w83769f.c) add_library(zip OBJECT zip.c) diff --git a/src/disk/hdc.c b/src/disk/hdc.c index 07df9d0e6..7bfb7e05a 100644 --- a/src/disk/hdc.c +++ b/src/disk/hdc.c @@ -100,12 +100,10 @@ static const struct { { &ide_isa_device }, { &ide_isa_2ch_device }, { &xtide_at_device }, - { &xtide_at_386_device }, { &xtide_at_ps2_device }, { &xta_wdxt150_device }, { &xtide_acculogic_device }, { &xtide_device }, - { &xtide_plus_device }, { &esdi_ps2_device }, { &ide_pci_device }, { &ide_pci_2ch_device }, diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index 3f43f80e6..631afa931 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -436,9 +436,9 @@ sff_bus_master_set_irq(uint8_t status, void *priv) case IRQ_MODE_SIS_551X: /* SiS 551x mode. */ if (irq) - pci_set_mirq(2, 1, &dev->irq_state); + pci_set_mirq(dev->mirq, 1, &dev->irq_state); else - pci_clear_mirq(2, 1, &dev->irq_state); + pci_clear_mirq(dev->mirq, 1, &dev->irq_state); break; } } @@ -554,6 +554,12 @@ sff_set_irq_pin(sff8038i_t *dev, int irq_pin) dev->irq_pin = irq_pin; } +void +sff_set_mirq(sff8038i_t *dev, uint8_t mirq) +{ + dev->mirq = mirq; +} + static void sff_close(void *priv) { @@ -586,6 +592,7 @@ sff_init(UNUSED(const device_t *info)) dev->pci_irq_line = 14; dev->irq_level = 0; dev->irq_state = 0; + dev->mirq = 2; dev->channel = next_id; next_id++; diff --git a/src/disk/hdc_ide_um8673f.c b/src/disk/hdc_ide_um8673f.c new file mode 100644 index 000000000..9ee149c7f --- /dev/null +++ b/src/disk/hdc_ide_um8673f.c @@ -0,0 +1,212 @@ +/* + * 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 UMF8673F IDE controller. + * + * Authors: Miran Grca, + * + * Copyright 2024 Miran Grca. + */ +#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/hdc_ide.h> +#include <86box/hdc.h> +#include <86box/mem.h> +#include <86box/nmi.h> +#include <86box/pic.h> +#include <86box/pci.h> +#include <86box/plat_unused.h> +#include <86box/port_92.h> +#include <86box/smram.h> + +#include <86box/chipset.h> + +#ifdef ENABLE_UM8673F_LOG +int um8673f_do_log = ENABLE_UM8673F_LOG; + +static void +um8673f_log(const char *fmt, ...) +{ + va_list ap; + + if (um8673f_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define um8673f_log(fmt, ...) +#endif + +typedef struct um8673f_t { + uint8_t index; + uint8_t tries; + uint8_t unlocked; + + uint8_t regs[256]; +} um8673f_t; + +static void +um8673f_ide_handler(um8673f_t *dev) +{ + ide_pri_disable(); + ide_sec_disable(); + if (dev->regs[0xb0] & 0x80) + ide_pri_enable(); + if (dev->regs[0xb0] & 0x40) + ide_sec_enable(); +} + +static void +um8673f_write(uint16_t addr, uint8_t val, void *priv) +{ + um8673f_t *dev = (um8673f_t *) priv; + + um8673f_log("[%04X:%08X] [W] %02X = %02X (%i)\n", CS, cpu_state.pc, port, val, dev->tries); + + switch (addr) { + case 0x108: + if (dev->unlocked) { + if (dev->index == 0x34) { + dev->unlocked = 0; + dev->tries = 0; + } else + dev->index = val; + } else if (((dev->tries == 0) && (val == 0x4a)) || + ((dev->tries == 1) && (val == 0x6c))) { + dev->tries++; + if (dev->tries == 2) + dev->unlocked = 1; + } else + dev->tries = 0; + break; + + case 0x109: + switch (dev->index) { + case 0xb0: + dev->regs[dev->index] = val; + um8673f_ide_handler(dev); + break; + case 0xb1 ... 0xb8: + dev->regs[dev->index] = val; + break; + + default: + break; + } + break; + + default: + break; + } +} + +static uint8_t +um8673f_read(uint16_t addr, void *priv) +{ + um8673f_t *dev = (um8673f_t *) priv; + uint8_t ret = 0xff; + + switch (addr) { + case 0x108: + if (dev->unlocked) + ret = dev->index; + else + dev->tries = 0; + break; + case 0x109: + if ((dev->index >= 0xb0) && (dev->index <= 0xb8)) + ret = dev->regs[dev->index]; + break; + + default: + break; + } + + um8673f_log("[%04X:%08X] [R] %02X = %02X\n", CS, cpu_state.pc, port, ret); + + return ret; +} + +static void +um8673f_reset(void *priv) +{ + um8673f_t *dev = (um8673f_t *) priv; + + memset(dev->regs, 0x00, 256); + + ide_pri_disable(); + ide_sec_disable(); + + /* IDE registers */ + dev->regs[0xb0] = 0xc0; + + um8673f_ide_handler(dev); +} + +static void +um8673f_close(void *priv) +{ + um8673f_t *dev = (um8673f_t *) priv; + + free(dev); +} + +static void * +um8673f_init(UNUSED(const device_t *info)) +{ + um8673f_t *dev = (um8673f_t *) calloc(1, sizeof(um8673f_t)); + + io_sethandler(0x0108, 0x0002, um8673f_read, NULL, NULL, um8673f_write, NULL, NULL, dev); + + device_add(info->local ? &ide_pci_2ch_device : &ide_vlb_2ch_device); + + um8673f_reset(dev); + + return dev; +} + +const device_t ide_um8886af_device = { + .name = "UMC UM8886F IDE", + .internal_name = "um8886af_ide", + .flags = 0, + .local = 1, + .init = um8673f_init, + .close = um8673f_close, + .reset = um8673f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ide_um8673f_device = { + .name = "UMC UM8673F", + .internal_name = "um8673f", + .flags = 0, + .local = 0, + .init = um8673f_init, + .close = um8673f_close, + .reset = um8673f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/disk/hdc_ide_w83769f.c b/src/disk/hdc_ide_w83769f.c new file mode 100644 index 000000000..ed34bc9fc --- /dev/null +++ b/src/disk/hdc_ide_w83769f.c @@ -0,0 +1,460 @@ +/* + * 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 Winbond W83769F controller. + * + * Authors: Miran Grca, + * + * Copyright 2020 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/cdrom.h> +#include <86box/scsi_device.h> +#include <86box/scsi_cdrom.h> +#include <86box/dma.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/keyboard.h> +#include <86box/mem.h> +#include <86box/pci.h> +#include <86box/pic.h> +#include <86box/timer.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/zip.h> +#include <86box/mo.h> + +typedef struct w83769f_t { + uint8_t vlb_idx; + uint8_t id; + uint8_t in_cfg; + uint8_t channels; + uint8_t pci; + uint8_t pci_slot; + uint8_t pad; + uint8_t pad0; + uint8_t regs[256]; +} w83769f_t; + +static int next_id = 0; + +#ifdef ENABLE_W83769F_LOG +int w83769f_do_log = ENABLE_W83769F_LOG; + +static void +w83769f_log(const char *fmt, ...) +{ + va_list ap; + + if (cmd640_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define w83769f_log(fmt, ...) +#endif + +void +w83769f_set_irq_0(uint8_t status, void *priv) +{ + w83769f_t *dev = (w83769f_t *) priv; + int irq = !!(status & 0x04); + + if (!(dev->regs[0x50] & 0x04) || (status & 0x04)) + dev->regs[0x50] = (dev->regs[0x50] & ~0x04) | status; + + if (!(dev->channels & 1)) + return; + + if (irq) + picint(1 << 14); + else + picintc(1 << 14); +} + +void +w83769f_set_irq_1(uint8_t status, void *priv) +{ + w83769f_t *dev = (w83769f_t *) priv; + int irq = !!(status & 0x04); + + if (!(dev->regs[0x50] & 0x04) || (status & 0x04)) + dev->regs[0x50] = (dev->regs[0x50] & ~0x04) | status; + + if (!(dev->channels & 2)) + return; + + if (irq) + picint(1 << 15); + else + picintc(1 << 15); +} + +static void +w83769f_ide_handlers(w83769f_t *dev) +{ + if (dev->channels & 0x01) { + ide_pri_disable(); + + if (!dev->pci || (dev->regs[0x04] & 0x01)) + ide_pri_enable(); + } + + if (dev->channels & 0x02) { + ide_sec_disable(); + + if ((!dev->pci || (dev->regs[0x04] & 0x01)) && (dev->regs[0x57] & 0x01)) + ide_sec_enable(); + } +} + +static void +w83769f_common_write(int addr, uint8_t val, w83769f_t *dev) +{ + switch (addr) { + case 0x50: + case 0x57: + dev->regs[0x57] = val & 0x01; + w83769f_ide_handlers(dev); + break; + case 0x51: + dev->regs[addr] = val & 0x7f; + break; + case 0x52: + case 0x54: + case 0x56: + case 0x58 ... 0x59: + dev->regs[addr] = val; + break; + case 0x53: + case 0x55: + dev->regs[addr] = val & 0xcf; + break; + + default: + break; + } +} + +static void +w83769f_vlb_write(uint16_t addr, uint8_t val, void *priv) +{ + w83769f_t *dev = (w83769f_t *) priv; + + switch (addr) { + case 0x0034: + case 0x00b4: + dev->vlb_idx = val; + break; + case 0x0038: + case 0x00b8: + w83769f_common_write(dev->vlb_idx, val, dev); + break; + + default: + break; + } +} + +static void +w83769f_vlb_writew(uint16_t addr, uint16_t val, void *priv) +{ + w83769f_vlb_write(addr, val & 0xff, priv); + w83769f_vlb_write(addr + 1, val >> 8, priv); +} + +static void +w83769f_vlb_writel(uint16_t addr, uint32_t val, void *priv) +{ + w83769f_vlb_writew(addr, val & 0xffff, priv); + w83769f_vlb_writew(addr + 2, val >> 16, priv); +} + +static uint8_t +w83769f_vlb_read(uint16_t addr, void *priv) +{ + uint8_t ret = 0xff; + w83769f_t *dev = (w83769f_t *) priv; + + switch (addr) { + case 0x0034: + case 0x00b4: + ret = dev->vlb_idx; + break; + case 0x0038: + case 0x00b8: + ret = dev->regs[dev->vlb_idx]; + if (dev->vlb_idx == 0x50) + dev->regs[0x50] &= ~0x04; + break; + + default: + break; + } + + return ret; +} + +static uint16_t +w83769f_vlb_readw(uint16_t addr, void *priv) +{ + uint16_t ret = 0xffff; + + ret = w83769f_vlb_read(addr, priv); + ret |= (w83769f_vlb_read(addr + 1, priv) << 8); + + return ret; +} + +static uint32_t +w83769f_vlb_readl(uint16_t addr, void *priv) +{ + uint32_t ret = 0xffffffff; + + ret = w83769f_vlb_readw(addr, priv); + ret |= (w83769f_vlb_readw(addr + 2, priv) << 16); + + return ret; +} + +static void +w83769f_pci_write(int func, int addr, uint8_t val, void *priv) +{ + w83769f_t *dev = (w83769f_t *) priv; + + w83769f_log("w83769f_pci_write(%i, %02X, %02X)\n", func, addr, val); + + if (func == 0x00) + switch (addr) { + case 0x04: + dev->regs[addr] = (dev->regs[addr] & 0xbf) | (val & 0x40); + w83769f_ide_handlers(dev); + break; + case 0x07: + dev->regs[addr] &= ~(val & 0x80); + break; + } +} + +static uint8_t +w83769f_pci_read(int func, int addr, void *priv) +{ + w83769f_t *dev = (w83769f_t *) priv; + uint8_t ret = 0xff; + + if (func == 0x00) + ret = dev->regs[addr]; + + w83769f_log("w83769f_pci_read(%i, %02X, %02X)\n", func, addr, ret); + + return ret; +} + +static void +w83769f_reset(void *priv) +{ + w83769f_t *dev = (w83769f_t *) priv; + int i = 0; + int min_channel; + int max_channel; + + switch (dev->channels) { + default: + case 0x00: + min_channel = max_channel = 0; + break; + case 0x01: + min_channel = 0; + max_channel = 1; + break; + case 0x02: + min_channel = 2; + max_channel = 3; + break; + case 0x03: + min_channel = 0; + max_channel = 3; + break; + } + + for (i = 0; i < CDROM_NUM; i++) { + if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && (cdrom[i].ide_channel >= min_channel) && + (cdrom[i].ide_channel <= max_channel) && cdrom[i].priv) + scsi_cdrom_reset((scsi_common_t *) cdrom[i].priv); + } + for (i = 0; i < ZIP_NUM; i++) { + if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && (zip_drives[i].ide_channel >= min_channel) && + (zip_drives[i].ide_channel <= max_channel) && zip_drives[i].priv) + zip_reset((scsi_common_t *) zip_drives[i].priv); + } + for (i = 0; i < MO_NUM; i++) { + if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && (mo_drives[i].ide_channel >= min_channel) && + (mo_drives[i].ide_channel <= max_channel) && mo_drives[i].priv) + mo_reset((scsi_common_t *) mo_drives[i].priv); + } + + if (dev->channels & 0x01) + w83769f_set_irq_0(0x00, priv); + + if (dev->channels & 0x02) + w83769f_set_irq_1(0x00, priv); + + memset(dev->regs, 0x00, sizeof(dev->regs)); + + dev->regs[0x50] = (dev->id << 3); /* Device ID: 00 = 60h, 01 = 61h, 10 = 62h, 11 = 63h */ + dev->regs[0x51] = 0x40; + dev->regs[0x57] = 0x01; /* Required by the MSI MS-5109 */ + dev->regs[0x59] = 0x40; + + if (dev->pci) { + dev->regs[0x00] = 0xad; /* Winbond */ + dev->regs[0x01] = 0x10; + dev->regs[0x02] = 0x01; /* W83769 */ + dev->regs[0x03] = 0x00; + dev->regs[0x04] = 0x01; + dev->regs[0x07] = 0x02; /* DEVSEL timing: 01 medium */ + dev->regs[0x08] = 0x02; /* 00h for Rev BB, 02h for Rev A3C */ + dev->regs[0x09] = 0x00; /* Programming interface */ + dev->regs[0x0a] = 0x01; /* IDE controller */ + dev->regs[0x0b] = 0x01; /* Mass storage controller */ + dev->regs[0x3c] = 0x0e; /* IRQ 14 */ + dev->regs[0x3d] = 0x01; /* INTA */ + } else + dev->regs[0x04] = 0x01; /* To make sure the two channels get enabled. */ + + w83769f_ide_handlers(dev); +} + +static void +w83769f_close(void *priv) +{ + w83769f_t *dev = (w83769f_t *) priv; + + free(dev); + + next_id = 0; +} + +static void * +w83769f_init(const device_t *info) +{ + w83769f_t *dev = (w83769f_t *) malloc(sizeof(w83769f_t)); + memset(dev, 0x00, sizeof(w83769f_t)); + + dev->id = next_id | 0x60; + + dev->pci = !!(info->flags & DEVICE_PCI); + + dev->channels = ((info->local & 0x60000) >> 17) & 0x03; + + if (info->flags & DEVICE_PCI) { + device_add(&ide_pci_2ch_device); + + if (info->local & 0x80000) + pci_add_card(PCI_ADD_NORMAL, w83769f_pci_read, w83769f_pci_write, dev, &dev->pci_slot); + else + pci_add_card(PCI_ADD_IDE, w83769f_pci_read, w83769f_pci_write, dev, &dev->pci_slot); + } else if (info->flags & DEVICE_VLB) + device_add(&ide_vlb_2ch_device); + + if (dev->channels & 0x01) + ide_set_bus_master(0, NULL, w83769f_set_irq_0, dev); + + if (dev->channels & 0x02) + ide_set_bus_master(1, NULL, w83769f_set_irq_1, dev); + + /* The CMD PCI-0640B IDE controller has no DMA capability, + so set our devices IDE devices to force ATA-3 (no DMA). */ + if (dev->channels & 0x01) + ide_board_set_force_ata3(0, 1); + + if (dev->channels & 0x02) + ide_board_set_force_ata3(1, 1); + + io_sethandler(info->local & 0xffff, 0x0001, + w83769f_vlb_read, w83769f_vlb_readw, w83769f_vlb_readl, + w83769f_vlb_write, w83769f_vlb_writew, w83769f_vlb_writel, + dev); + io_sethandler((info->local & 0xffff) + 0x0004, 0x0001, + w83769f_vlb_read, w83769f_vlb_readw, w83769f_vlb_readl, + w83769f_vlb_write, w83769f_vlb_writew, w83769f_vlb_writel, + dev); + + next_id++; + + w83769f_reset(dev); + + return dev; +} + +const device_t ide_w83769f_vlb_device = { + .name = "Winbond W83769F VLB", + .internal_name = "ide_w83769f_vlb", + .flags = DEVICE_VLB, + .local = 0x600b4, + .init = w83769f_init, + .close = w83769f_close, + .reset = w83769f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ide_w83769f_vlb_34_device = { + .name = "Winbond W83769F VLB (Port 34h)", + .internal_name = "ide_w83769f_vlb_34", + .flags = DEVICE_VLB, + .local = 0x60034, + .init = w83769f_init, + .close = w83769f_close, + .reset = w83769f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ide_w83769f_pci_device = { + .name = "Winbond W83769F PCI", + .internal_name = "ide_w83769f_pci", + .flags = DEVICE_PCI, + .local = 0x600b4, + .init = w83769f_init, + .close = w83769f_close, + .reset = w83769f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t ide_w83769f_pci_34_device = { + .name = "Winbond W83769F PCI (Port 34h)", + .internal_name = "ide_w83769f_pci_34", + .flags = DEVICE_PCI, + .local = 0x60034, + .init = w83769f_init, + .close = w83769f_close, + .reset = w83769f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + diff --git a/src/disk/hdc_st506_xt.c b/src/disk/hdc_st506_xt.c index 79a5a8eba..fc20350b0 100644 --- a/src/disk/hdc_st506_xt.c +++ b/src/disk/hdc_st506_xt.c @@ -107,7 +107,7 @@ #define ST11_BIOS_FILE_OLD "roms/hdd/st506/st11_bios_vers_1.7.bin" #define ST11_BIOS_FILE_NEW "roms/hdd/st506/st11_bios_vers_2.0.bin" #define WD1002A_WX1_BIOS_FILE "roms/hdd/st506/wd1002a_wx1-62-000094-032.bin" -#define WD1004A_WX1_BIOS_FILE "roms/hdd/st506/wd1002a_wx1-62-000094-032.bin" +#define WD1004A_WX1_BIOS_FILE "roms/hdd/st506/western_digital_WD1004A-27X.bin" /* SuperBIOS was for both the WX1 and 27X, users jumpers readout to determine if to use 26 sectors per track, 26 -> 17 sectors per track translation, or 17 sectors per track. */ @@ -1667,7 +1667,7 @@ st506_init(const device_t *info) fn = WD1004A_WX1_BIOS_FILE; /* The switches are read in reverse: 0 = closed, 1 = open. Both open means MFM, 17 sectors per track. */ - dev->switches = 0x10; /* autobios */ + dev->switches = 0x30; /* autobios */ dev->base = device_get_config_hex16("base"); dev->irq = device_get_config_int("irq"); if (dev->irq == 2) diff --git a/src/disk/hdc_xtide.c b/src/disk/hdc_xtide.c index dfe5931f1..057d4f0ed 100644 --- a/src/disk/hdc_xtide.c +++ b/src/disk/hdc_xtide.c @@ -49,9 +49,9 @@ #define ROM_PATH_XT "roms/hdd/xtide/ide_xt.bin" #define ROM_PATH_XTP "roms/hdd/xtide/ide_xtp.bin" #define ROM_PATH_AT "roms/hdd/xtide/ide_at.bin" +#define ROM_PATH_AT_386 "roms/hdd/xtide/ide_386.bin" #define ROM_PATH_PS2 "roms/hdd/xtide/SIDE1V12.BIN" #define ROM_PATH_PS2AT "roms/hdd/xtide/ide_at_1_1_5.bin" -#define ROM_PATH_AT_386 "roms/hdd/xtide/ide_386.bin" typedef struct xtide_t { void *ide_board; @@ -136,13 +136,9 @@ xtide_init(const device_t *info) memset(xtide, 0x00, sizeof(xtide_t)); - if (info->local == 1) { - rom_init(&xtide->bios_rom, ROM_PATH_XTP, + rom_init(&xtide->bios_rom, + device_get_bios_file(info, device_get_config_bios("bios"), 0), 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); - } else { - rom_init(&xtide->bios_rom, ROM_PATH_XT, - 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); - } xtide->ide_board = ide_xtide_init(); @@ -153,18 +149,6 @@ xtide_init(const device_t *info) return xtide; } -static int -xtide_available(void) -{ - return (rom_present(ROM_PATH_XT)); -} - -static int -xtide_plus_available(void) -{ - return (rom_present(ROM_PATH_XTP)); -} - static void * xtide_at_init(const device_t *info) { @@ -172,31 +156,15 @@ xtide_at_init(const device_t *info) memset(xtide, 0x00, sizeof(xtide_t)); - if (info->local == 1) { - rom_init(&xtide->bios_rom, ROM_PATH_AT_386, + rom_init(&xtide->bios_rom, + device_get_bios_file(info, device_get_config_bios("bios"), 0), 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); - } else { - rom_init(&xtide->bios_rom, ROM_PATH_AT, - 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); - } device_add(&ide_isa_2ch_device); return xtide; } -static int -xtide_at_available(void) -{ - return (rom_present(ROM_PATH_AT)); -} - -static int -xtide_at_386_available(void) -{ - return (rom_present(ROM_PATH_AT_386)); -} - static void * xtide_acculogic_init(UNUSED(const device_t *info)) { @@ -261,6 +229,50 @@ xtide_at_close(void *priv) free(xtide); } +static const device_config_t xtide_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS", + .type = CONFIG_BIOS, + .default_string = "xt", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, /*W1*/ + .bios = { + { .name = "Regular XT", .internal_name = "xt", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_XT, "" } }, + { .name = "XT+ (V20/V30/8018x)", .internal_name = "xt_plus", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_XTP, "" } }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +static const device_config_t xtide_at_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS", + .type = CONFIG_BIOS, + .default_string = "at", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, /*W1*/ + .bios = { + { .name = "Regular AT", .internal_name = "at", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_AT, "" } }, + { .name = "386", .internal_name = "at_386", .bios_type = BIOS_NORMAL, + .files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_AT_386, "" } }, + { .files_no = 0 } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + const device_t xtide_device = { .name = "PC/XT XTIDE", .internal_name = "xtide", @@ -269,24 +281,10 @@ const device_t xtide_device = { .init = xtide_init, .close = xtide_close, .reset = NULL, - { .available = xtide_available }, + { .available = NULL }, .speed_changed = NULL, .force_redraw = NULL, - .config = NULL -}; - -const device_t xtide_plus_device = { - .name = "PC/XT XTIDE (V20/V30/8018x)", - .internal_name = "xtide_plus", - .flags = DEVICE_ISA, - .local = 1, - .init = xtide_init, - .close = xtide_close, - .reset = NULL, - { .available = xtide_plus_available }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL + .config = xtide_config }; const device_t xtide_at_device = { @@ -297,24 +295,10 @@ const device_t xtide_at_device = { .init = xtide_at_init, .close = xtide_at_close, .reset = NULL, - { .available = xtide_at_available }, + { .available = NULL }, .speed_changed = NULL, .force_redraw = NULL, - .config = NULL -}; - -const device_t xtide_at_386_device = { - .name = "PC/AT XTIDE (386)", - .internal_name = "xtide_at_386", - .flags = DEVICE_ISA | DEVICE_AT, - .local = 1, - .init = xtide_at_init, - .close = xtide_at_close, - .reset = NULL, - { .available = xtide_at_386_available }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL + .config = xtide_at_config }; const device_t xtide_acculogic_device = { diff --git a/src/dma.c b/src/dma.c index 1977a59be..3c81fcbac 100644 --- a/src/dma.c +++ b/src/dma.c @@ -950,16 +950,47 @@ dma_page_read(uint16_t addr, UNUSED(void *priv)) uint8_t convert[8] = CHANNELS; uint8_t ret = 0xff; - addr &= 0x0f; - ret = dmaregs[2][addr]; + if (((addr & 0xfffc) == 0x80) && (CS == 0xf000) && + ((cpu_state.pc & 0xfffffff8) == 0x00007278) && + !strcmp(machine_get_internal_name(), "megapc")) switch (addr) { + /* The Amstrad MegaPC Quadtel BIOS times a sequence of: + mov ax,di + div bx + And expects this value to be at least 0x06e0 for 20 MHz, + and at least 0x0898 for 25 MHz, everything below 0x06e0 + is assumed to be 16 MHz. Given that for some reason, this + does not occur on 86Box, we have to work around it here, + we return 0x0580 for 16 MHz, because it logically follows + in the sequence (0x06e0 = 0x0898 * (20 / 25), and + 0x0580 = 0x06e0 * (16 / 20)). */ + case 0x0081: + if (cpu_busspeed >= 25000000) + ret = 0x98; + else if (cpu_busspeed >= 20000000) + ret = 0xe0; + else + ret = 0x80; + break; + case 0x0082: + if (cpu_busspeed >= 25000000) + ret = 0x08; + else if (cpu_busspeed >= 20000000) + ret = 0x06; + else + ret = 0x05; + break; + } else { + addr &= 0x0f; + ret = dmaregs[2][addr]; - if (addr >= 8) - addr = convert[addr & 0x07] | 4; - else - addr = convert[addr & 0x07]; + if (addr >= 8) + addr = convert[addr & 0x07] | 4; + else + addr = convert[addr & 0x07]; - if (addr < 8) - ret = dma[addr].page_l; + if (addr < 8) + ret = dma[addr].page_l; + } return ret; } diff --git a/src/game/gameport.c b/src/game/gameport.c index 323555984..58d9a446f 100644 --- a/src/game/gameport.c +++ b/src/game/gameport.c @@ -31,10 +31,6 @@ #include <86box/timer.h> #include <86box/isapnp.h> #include <86box/gameport.h> -#include <86box/joystick_ch_flightstick_pro.h> -#include <86box/joystick_standard.h> -#include <86box/joystick_sw_pad.h> -#include <86box/joystick_tm_fcs.h> #include <86box/plat_unused.h> typedef struct g_axis_t { diff --git a/src/game/joystick_ch_flightstick_pro.c b/src/game/joystick_ch_flightstick_pro.c index 49ce824bc..8ca51d531 100644 --- a/src/game/joystick_ch_flightstick_pro.c +++ b/src/game/joystick_ch_flightstick_pro.c @@ -43,7 +43,6 @@ #include <86box/device.h> #include <86box/timer.h> #include <86box/gameport.h> -#include <86box/joystick_standard.h> #include <86box/plat_unused.h> static void * diff --git a/src/game/joystick_standard.c b/src/game/joystick_standard.c index b9c449f99..1d1568738 100644 --- a/src/game/joystick_standard.c +++ b/src/game/joystick_standard.c @@ -43,7 +43,6 @@ #include <86box/device.h> #include <86box/timer.h> #include <86box/gameport.h> -#include <86box/joystick_standard.h> #include <86box/plat_unused.h> static void * diff --git a/src/game/joystick_sw_pad.c b/src/game/joystick_sw_pad.c index 5c91ee1e9..7962c38e3 100644 --- a/src/game/joystick_sw_pad.c +++ b/src/game/joystick_sw_pad.c @@ -64,7 +64,6 @@ #include <86box/device.h> #include <86box/timer.h> #include <86box/gameport.h> -#include <86box/joystick_sw_pad.h> #include <86box/plat_unused.h> typedef struct sw_data { diff --git a/src/game/joystick_tm_fcs.c b/src/game/joystick_tm_fcs.c index d54d0e37d..f5c1e64e6 100644 --- a/src/game/joystick_tm_fcs.c +++ b/src/game/joystick_tm_fcs.c @@ -43,7 +43,6 @@ #include <86box/device.h> #include <86box/timer.h> #include <86box/gameport.h> -#include <86box/joystick_standard.h> #include <86box/plat_unused.h> static void * diff --git a/src/include/86box/acpi.h b/src/include/86box/acpi.h index bbad43616..6822e88a6 100644 --- a/src/include/86box/acpi.h +++ b/src/include/86box/acpi.h @@ -54,13 +54,15 @@ extern "C" { #define ACPI_ENABLE 0xf1 #define ACPI_DISABLE 0xf0 -#define VEN_ALI 0x010b9 -#define VEN_INTEL 0x08086 -#define VEN_INTEL_ICH2 0x18086 -#define VEN_SIS 0x01039 -#define VEN_SMC 0x01055 -#define VEN_VIA 0x01106 -#define VEN_VIA_596B 0x11106 +#define VEN_ALI 0x010b9 +#define VEN_INTEL 0x08086 +#define VEN_INTEL_ICH2 0x18086 +#define VEN_SIS_5582 0x01039 +#define VEN_SIS_5595_1997 0x11039 +#define VEN_SIS_5595 0x21039 +#define VEN_SMC 0x01055 +#define VEN_VIA 0x01106 +#define VEN_VIA_596B 0x11106 typedef struct acpi_regs_t { uint8_t acpitst; @@ -80,6 +82,25 @@ typedef struct acpi_regs_t { uint8_t gporeg[4]; uint8_t extiotrapsts; uint8_t extiotrapen; + uint8_t enter_c2_ps; + uint8_t enter_c3_ps; + uint8_t reg_12; + uint8_t reg_13; + uint8_t smi_cmd; + uint8_t reg_24; + uint8_t reg_25; + uint8_t reg_26; + uint8_t smi_en_val; + uint8_t smi_dis_val; + uint8_t mail_box; + uint8_t reg_2b; + uint8_t gp_tmr; + uint8_t leg_sts; + uint8_t leg_en; + uint8_t tst_ctl; + uint8_t reg_34; + uint8_t index; + uint8_t reg_ff; uint16_t pmsts; uint16_t pmen; uint16_t pmcntrl; @@ -99,6 +120,15 @@ typedef struct acpi_regs_t { uint16_t pscntrl; uint16_t gpscists; uint16_t mon_smi; + uint16_t reg_14; + uint16_t reg_16; + uint16_t reg_18; + uint16_t reg_1a; + uint16_t reg_1c; + uint16_t gpe_mul; + uint16_t gpe_ctl; + uint16_t gpe_smi; + uint16_t gpe_rl; int smi_lock; int smi_active; uint32_t pcntrl; @@ -118,6 +148,12 @@ typedef struct acpi_regs_t { uint32_t smi_en; uint32_t smi_sts; uint32_t pad0; + uint32_t reg_0c; + uint32_t gpe_sts; + uint32_t gpe_en; + uint32_t gpe_pin; + uint32_t gpe_io; + uint32_t gpe_pol; } acpi_regs_t; typedef struct acpi_t { @@ -138,12 +174,16 @@ typedef struct acpi_t { pc_timer_t timer; pc_timer_t resume_timer; pc_timer_t pwrbtn_timer; + pc_timer_t gp_timer; + pc_timer_t per_timer; nvr_t *nvr; apm_t *apm; tco_t *tco; void *i2c; void (*trap_update)(void *priv); void *trap_priv; + void *smbus; + void *priv; } acpi_t; /* Global variables. */ @@ -157,6 +197,9 @@ extern const device_t acpi_intel_ich2_device; extern const device_t acpi_smc_device; extern const device_t acpi_via_device; extern const device_t acpi_via_596b_device; +extern const device_t acpi_sis_5582_device; +extern const device_t acpi_sis_5595_1997_device; +extern const device_t acpi_sis_5595_device; /* Functions */ extern void acpi_update_irq(acpi_t *dev); @@ -176,6 +219,12 @@ extern void acpi_set_tco(acpi_t *dev, tco_t *tco); extern void acpi_set_trap_update(acpi_t *dev, void (*update)(void *priv), void *priv); extern uint8_t acpi_ali_soft_smi_status_read(acpi_t *dev); extern void acpi_ali_soft_smi_status_write(acpi_t *dev, uint8_t soft_smi); +extern void * acpi_get_smbus(void *priv); +extern void acpi_sis5582_pmu_event(void *priv); +extern void acpi_sis5595_smi_raise(void *priv); +extern void acpi_sis5595_pmu_event(void *priv); +extern void acpi_sis5595_smbus_event(void *priv); +extern void acpi_sis5595_software_smi(void *priv); #ifdef __cplusplus } diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index d188c9243..15127b06e 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -244,6 +244,7 @@ typedef struct cdrom { int prev_host_drive; int cd_buflen; int audio_op; + int audio_muted_soft; int sony_msf; const cdrom_ops_t *ops; diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index 2136e585e..17e25d301 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -134,8 +134,16 @@ extern const device_t sis_85c471_device; extern const device_t sis_85c496_device; extern const device_t sis_85c496_ls486e_device; extern const device_t sis_85c50x_device; +extern const device_t sis_550x_85c503_device; +extern const device_t sis_85c50x_5503_device; +extern const device_t sis_550x_device; extern const device_t sis_5511_device; extern const device_t sis_5571_device; +extern const device_t sis_5581_device; +extern const device_t sis_5591_1997_device; +extern const device_t sis_5591_device; +extern const device_t sis_5600_1997_device; +extern const device_t sis_5600_device; /* ST */ extern const device_t stpc_client_device; @@ -148,6 +156,8 @@ extern const device_t stpc_lpt_device; /* UMC */ extern const device_t umc_8886f_device; extern const device_t umc_8886af_device; +extern const device_t umc_8886bf_device; +extern const device_t umc_8890_device; extern const device_t umc_hb4_device; /* VIA */ diff --git a/src/include/86box/device.h b/src/include/86box/device.h index f5efb5dbb..bd39a02e4 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -41,23 +41,41 @@ #ifndef EMU_DEVICE_H #define EMU_DEVICE_H -#define CONFIG_END -1 -#define CONFIG_STRING 0 -#define CONFIG_INT 1 -#define CONFIG_BINARY 2 -#define CONFIG_SELECTION 3 -#define CONFIG_MIDI_OUT 4 -#define CONFIG_FNAME 5 -#define CONFIG_SPINNER 6 -#define CONFIG_HEX16 7 -#define CONFIG_HEX20 8 -#define CONFIG_MAC 9 -#define CONFIG_MIDI_IN 10 -#define CONFIG_BIOS 11 -#define CONFIG_SERPORT 12 +#define CONFIG_END -1 /* N/A */ -#define CONFIG_ONBOARD 256 /* only avaialble on the on-board variant */ -#define CONFIG_STANDALONE 257 /* not available on the on-board variant */ +#define CONFIG_SHIFT 4 + +#define CONFIG_TYPE_INT (0 << CONFIG_SHIFT) +#define CONFIG_TYPE_STRING (1 << CONFIG_SHIFT) +#define CONFIG_TYPE_HEX16 (2 << CONFIG_SHIFT) +#define CONFIG_TYPE_HEX20 (3 << CONFIG_SHIFT) +#define CONFIG_TYPE_MAC (4 << CONFIG_SHIFT) + +#define CONFIG_INT (0 | CONFIG_TYPE_INT) /* config_get_int() */ +#define CONFIG_BINARY (1 | CONFIG_TYPE_INT) /* config_get_int() */ +#define CONFIG_SELECTION (2 | CONFIG_TYPE_INT) /* config_get_int() */ +#define CONFIG_MIDI_OUT (3 | CONFIG_TYPE_INT) /* config_get_int() */ +#define CONFIG_SPINNER (4 | CONFIG_TYPE_INT) /* config_get_int() */ +#define CONFIG_MIDI_IN (5 | CONFIG_TYPE_INT) /* config_get_int() */ + +#define CONFIG_STRING (0 | CONFIG_TYPE_STRING) /* config_get_string() */ +#define CONFIG_FNAME (1 | CONFIG_TYPE_STRING) /* config_get_string() */ +#define CONFIG_SERPORT (2 | CONFIG_TYPE_STRING) /* config_get_string() */ +#define CONFIG_BIOS (3 | CONFIG_TYPE_STRING) /* config_get_string() */ + +#define CONFIG_HEX16 (0 | CONFIG_TYPE_HEX16) /* config_get_hex16() */ + +#define CONFIG_HEX20 (0 | CONFIG_TYPE_HEX20) /* config_get_hex20() */ + +#define CONFIG_MAC (0 | CONFIG_TYPE_MAC) /* N/A */ + +#define CONFIG_SUBTYPE_MASK (CONFIG_IS_STRING - 1) + +#define CONFIG_DEP (16 << CONFIG_SHIFT) +#define CONFIG_TYPE_MASK (CONFIG_DEP - 1) + +// #define CONFIG_ONBOARD 256 /* only avaialble on the on-board variant */ +// #define CONFIG_STANDALONE 257 /* not available on the on-board variant */ enum { DEVICE_PCJR = 2, /* requires an IBM PCjr */ @@ -100,38 +118,49 @@ enum { #define BIOS_INTERLEAVED_INVERT 8 #define BIOS_HIGH_BIT_INVERT 16 +#define device_common_config_t \ + const char *name; \ + const char *description; \ + int type; \ + const char *default_string; \ + int default_int; \ + const char *file_filter; \ + const device_config_spinner_t spinner; \ + const device_config_selection_t selection[32] + typedef struct device_config_selection_t { const char *description; int value; } device_config_selection_t; -typedef struct device_config_bios_t { - const char *name; - const char *internal_name; - int bios_type; - int files_no; - uint32_t local; - uint32_t size; - void *dev1; - void *dev2; - const char *files[9]; -} device_config_bios_t; - typedef struct device_config_spinner_t { int16_t min; int16_t max; int16_t step; } device_config_spinner_t; -typedef struct device_config_t { - const char *name; - const char *description; - int type; - const char *default_string; - int default_int; - const char *file_filter; - const device_config_spinner_t spinner; - const device_config_selection_t selection[32]; +typedef struct _device_dep_config_ { + device_common_config_t; +} device_dep_config_t; + +typedef struct device_config_bios_t { + const char *name; + const char *internal_name; + int bios_type; + int files_no; + uint32_t local; + uint32_t size; + void *dev1; + void *dev2; + const char *files[9]; + /* Configuration options that depend on the device variant. + To prevent excessive nesting, there is no CONFIG_BIOS + option a dep_config struct */ + const device_dep_config_t *dep_config; +} device_config_bios_t; + +typedef struct _device_config_ { + device_common_config_t; const device_config_bios_t bios[32]; } device_config_t; @@ -173,6 +202,7 @@ extern void device_context(const device_t *dev); extern void device_context_inst(const device_t *dev, int inst); extern void device_context_restore(void); extern void *device_add(const device_t *d); +extern void *device_add_linked(const device_t *d, void *priv); extern void *device_add_parameters(const device_t *dev, void *params); extern void device_add_ex(const device_t *dev, void *priv); extern void device_add_ex_parameters(const device_t *dev, void *priv, void *params); @@ -188,6 +218,7 @@ extern void *device_cadd_inst(const device_t *dev, const device_t *cd, int inst) extern void *device_cadd_inst_parameters(const device_t *dev, const device_t *cd, int inst, void *params); extern void device_cadd_inst_ex(const device_t *dev, const device_t *cd, void *priv, int inst); extern void device_cadd_inst_ex_parameters(const device_t *dev, const device_t *cd, void *priv, int inst, void *params); +extern void *device_get_common_priv(void); extern void device_close_all(void); extern void device_reset_all(uint32_t match_flags); extern void *device_find_first_priv(uint32_t match_flags); diff --git a/src/include/86box/flash.h b/src/include/86box/flash.h index d161d416b..6f0e1ff15 100644 --- a/src/include/86box/flash.h +++ b/src/include/86box/flash.h @@ -60,4 +60,6 @@ extern const device_t sst_flash_49lf080_device; extern const device_t sst_flash_49lf016_device; extern const device_t sst_flash_49lf160_device; +extern const device_t amd_flash_29f020a_device; + #endif /*EMU_FLASH_H*/ diff --git a/src/include/86box/gameport.h b/src/include/86box/gameport.h index ba3568464..d9c702394 100644 --- a/src/include/86box/gameport.h +++ b/src/include/86box/gameport.h @@ -24,6 +24,10 @@ #define MAX_PLAT_JOYSTICKS 8 #define MAX_JOYSTICKS 4 +#define MAX_JOY_AXES 16 +#define MAX_JOY_BUTTONS 32 +#define MAX_JOY_POVS 4 + #define JS_TYPE_NONE 0 #define JS_TYPE_2AXIS_4BUTTON 1 #define JS_TYPE_2AXIS_6BUTTON 2 @@ -36,7 +40,6 @@ #define POV_X 0x80000000 #define POV_Y 0x40000000 -#define SLIDER 0x20000000 #define AXIS_NOT_PRESENT -99999 @@ -47,46 +50,39 @@ typedef struct plat_joystick_t { char name[260]; - int a[8]; - int b[32]; - int p[4]; - int s[2]; + int a[MAX_JOY_AXES]; + int b[MAX_JOY_BUTTONS]; + int p[MAX_JOY_POVS]; struct { char name[260]; int id; - } axis[8]; + } axis[MAX_JOY_AXES]; struct { char name[260]; int id; - } button[32]; + } button[MAX_JOY_BUTTONS]; struct { char name[260]; int id; - } pov[4]; - - struct { - char name[260]; - int id; - } slider[2]; + } pov[MAX_JOY_POVS]; int nr_axes; int nr_buttons; int nr_povs; - int nr_sliders; } plat_joystick_t; typedef struct joystick_t { - int axis[8]; - int button[32]; - int pov[4]; + int axis[MAX_JOY_AXES]; + int button[MAX_JOY_BUTTONS]; + int pov[MAX_JOY_POVS]; int plat_joystick_nr; - int axis_mapping[8]; - int button_mapping[32]; - int pov_mapping[4][2]; + int axis_mapping[MAX_JOY_AXES]; + int button_mapping[MAX_JOY_BUTTONS]; + int pov_mapping[MAX_JOY_POVS][2]; } joystick_t; typedef struct joystick_if_t { @@ -104,9 +100,9 @@ typedef struct joystick_if_t { int button_count; int pov_count; int max_joysticks; - const char *axis_names[8]; - const char *button_names[32]; - const char *pov_names[4]; + const char *axis_names[MAX_JOY_AXES]; + const char *button_names[MAX_JOY_BUTTONS]; + const char *pov_names[MAX_JOY_POVS]; } joystick_if_t; #ifdef __cplusplus @@ -158,6 +154,19 @@ extern void gameport_update_joystick_type(void); extern void gameport_remap(void *priv, uint16_t address); extern void *gameport_add(const device_t *gameport_type); +extern const joystick_if_t joystick_2axis_2button; +extern const joystick_if_t joystick_2axis_4button; +extern const joystick_if_t joystick_3axis_2button; +extern const joystick_if_t joystick_3axis_4button; +extern const joystick_if_t joystick_4axis_4button; +extern const joystick_if_t joystick_2axis_6button; +extern const joystick_if_t joystick_2axis_8button; + +extern const joystick_if_t joystick_ch_flightstick_pro; + +extern const joystick_if_t joystick_sw_pad; + +extern const joystick_if_t joystick_tm_fcs; #ifdef __cplusplus } #endif diff --git a/src/include/86box/hdc.h b/src/include/86box/hdc.h index b0e775886..a3d562b62 100644 --- a/src/include/86box/hdc.h +++ b/src/include/86box/hdc.h @@ -77,8 +77,16 @@ extern const device_t ide_cmd646_device; /* CMD PCI-646 * extern const device_t ide_cmd646_legacy_only_device; /* CMD PCI-646 (Legacy Mode Only) */ extern const device_t ide_cmd646_single_channel_device; /* CMD PCI-646 (Only primary channel) */ -extern const device_t ide_opti611_vlb_device; /* OPTi 82c611/611A VLB */ -extern const device_t ide_opti611_vlb_sec_device; /* OPTi 82c611/611A VLB (Secondary channel) */ +extern const device_t ide_opti611_vlb_device; /* OPTi 82c611/611A VLB */ +extern const device_t ide_opti611_vlb_sec_device; /* OPTi 82c611/611A VLB (Secondary channel) */ + +extern const device_t ide_um8673f_device; /* UMC UM8673F */ +extern const device_t ide_um8886af_device; /* UMC UM8886AF */ + +extern const device_t ide_w83769f_vlb_device; /* Winbond W83769F VLB */ +extern const device_t ide_w83769f_vlb_34_device; /* Winbond W83769F VLB (Port 34h) */ +extern const device_t ide_w83769f_pci_device; /* Winbond W83769F PCI */ +extern const device_t ide_w83769f_pci_34_device; /* Winbond W83769F PCI (Port 34h) */ extern const device_t ide_ter_device; extern const device_t ide_ter_pnp_device; @@ -89,9 +97,7 @@ extern const device_t xta_wdxt150_device; /* xta_wdxt150 */ extern const device_t xta_hd20_device; /* EuroPC internal */ extern const device_t xtide_device; /* xtide_xt */ -extern const device_t xtide_plus_device; /* xtide_xt_plus */ extern const device_t xtide_at_device; /* xtide_at */ -extern const device_t xtide_at_386_device; /* xtide_at_386 */ extern const device_t xtide_acculogic_device; /* xtide_ps2 */ extern const device_t xtide_at_ps2_device; /* xtide_at_ps2 */ diff --git a/src/include/86box/hdc_ide_sff8038i.h b/src/include/86box/hdc_ide_sff8038i.h index 2283497bb..3a69fdfac 100644 --- a/src/include/86box/hdc_ide_sff8038i.h +++ b/src/include/86box/hdc_ide_sff8038i.h @@ -43,6 +43,7 @@ typedef struct sff8038i_t uint8_t irq_state; uint8_t channel; uint8_t irq_line; + uint8_t mirq; uint16_t base; uint16_t pad; uint32_t ptr; @@ -72,10 +73,9 @@ extern void sff_bus_master_reset(sff8038i_t *dev); extern void sff_set_slot(sff8038i_t *dev, int slot); extern void sff_set_irq_line(sff8038i_t *dev, int irq_line); - extern void sff_set_irq_mode(sff8038i_t *dev, int irq_mode); extern void sff_set_irq_pin(sff8038i_t *dev, int irq_pin); - extern void sff_set_irq_level(sff8038i_t *dev, int irq_level); +extern void sff_set_mirq(sff8038i_t *dev, uint8_t mirq); #endif /*EMU_HDC_IDE_SFF8038I_H*/ diff --git a/src/include/86box/joystick_ch_flightstick_pro.h b/src/include/86box/joystick_ch_flightstick_pro.h deleted file mode 100644 index b49800ecb..000000000 --- a/src/include/86box/joystick_ch_flightstick_pro.h +++ /dev/null @@ -1,43 +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. - * - * Definitions for the Flight Stick Pro driver. - * - * - * - * Authors: Miran Grca, - * Sarah Walker, - * - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ - -#ifndef EMU_JOYSTICK_CH_FLIGHTSTICK_PRO_H -#define EMU_JOYSTICK_CH_FLIGHTSTICK_PRO_H - -extern const joystick_if_t joystick_ch_flightstick_pro; - -#endif /*EMU_JOYSTICK_CH_FLIGHTSTICK_PRO_H*/ diff --git a/src/include/86box/joystick_standard.h b/src/include/86box/joystick_standard.h deleted file mode 100644 index c874677ea..000000000 --- a/src/include/86box/joystick_standard.h +++ /dev/null @@ -1,49 +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. - * - * Definitions for the joystick driver. - * - * - * - * Authors: Miran Grca, - * Sarah Walker, - * - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ - -#ifndef EMU_JOYSTICK_STANDARD_H -#define EMU_JOYSTICK_STANDARD_H - -extern const joystick_if_t joystick_2axis_2button; -extern const joystick_if_t joystick_2axis_4button; -extern const joystick_if_t joystick_3axis_2button; -extern const joystick_if_t joystick_3axis_4button; -extern const joystick_if_t joystick_4axis_4button; -extern const joystick_if_t joystick_2axis_6button; -extern const joystick_if_t joystick_2axis_8button; - -#endif /*EMU_JOYSTICK_STANDARD_H*/ diff --git a/src/include/86box/joystick_sw_pad.h b/src/include/86box/joystick_sw_pad.h deleted file mode 100644 index a75d802de..000000000 --- a/src/include/86box/joystick_sw_pad.h +++ /dev/null @@ -1,43 +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. - * - * Definitions for the Sidewinder Pro driver. - * - * - * - * Authors: Miran Grca, - * Sarah Walker, - * - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ - -#ifndef EMU_JOYSTICK_SW_PAD_H -#define EMU_JOYSTICK_SW_PAD_H - -extern const joystick_if_t joystick_sw_pad; - -#endif /*EMU_JOYSTICK_SW_PAD_H*/ diff --git a/src/include/86box/joystick_tm_fcs.h b/src/include/86box/joystick_tm_fcs.h deleted file mode 100644 index 65e734a40..000000000 --- a/src/include/86box/joystick_tm_fcs.h +++ /dev/null @@ -1,43 +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. - * - * Definitions for the Flight Control System driver. - * - * - * - * Authors: Miran Grca, - * Sarah Walker, - * - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ - -#ifndef EMU_JOYSTICK_TM_FCS_H -#define EMU_JOYSTICK_TM_FCS_H - -extern const joystick_if_t joystick_tm_fcs; - -#endif /*EMU_JOYSTICK_TM_FCS_H*/ diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index a4b079760..759fad714 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -79,6 +79,7 @@ typedef struct atkbc_dev_t { int y; int z; int b; + int ignore; int *scan; diff --git a/src/include/86box/language.h b/src/include/86box/language.h index af459c0ff..3c96e711f 100644 --- a/src/include/86box/language.h +++ b/src/include/86box/language.h @@ -97,7 +97,6 @@ #define IDS_2108 2108 // "%u MB (CHS: %i, %i, %i)" #define IDS_2109 2109 // "Floppy %i (%s): %ls" #define IDS_2110 2110 // "All floppy images (*.0??;*.." -#define IDS_2112 2112 // "Unable to initialize SDL..." #define IDS_2113 2113 // "Are you sure you want to..." #define IDS_2114 2114 // "Are you sure you want to..." #define IDS_2115 2115 // "Unable to initialize Ghostscript..." diff --git a/src/include/86box/lpt.h b/src/include/86box/lpt.h index a9a9eac65..4e95b64c3 100644 --- a/src/include/86box/lpt.h +++ b/src/include/86box/lpt.h @@ -83,6 +83,8 @@ extern lpt_port_t lpt_ports[PARALLEL_MAX]; extern void lpt_write(uint16_t port, uint8_t val, void *priv); extern uint8_t lpt_read(uint16_t port, void *priv); +extern uint8_t lpt_read_port(int port, uint16_t reg); + extern uint8_t lpt_read_status(int port); extern void lpt_irq(void *priv, int raise); diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 3176d1898..ebf29d540 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -49,37 +49,38 @@ #define MACHINE_BUS_AGP 0x00080000 /* sys has AGP bus */ #define MACHINE_BUS_AC97 0x00100000 /* sys has AC97 bus (ACR/AMR/CNR slot) */ /* Aliases. */ -#define MACHINE_CASSETTE (MACHINE_BUS_CASSETTE) /* sys has cassette port */ -#define MACHINE_CARTRIDGE (MACHINE_BUS_CARTRIDGE) /* sys has two cartridge bays */ +#define MACHINE_CASSETTE (MACHINE_BUS_CASSETTE) /* sys has cassette port */ +#define MACHINE_CARTRIDGE (MACHINE_BUS_CARTRIDGE) /* sys has two cartridge bays */ /* Combined flags. */ -#define MACHINE_PC (MACHINE_BUS_ISA) /* sys is PC/XT-compatible (ISA) */ -#define MACHINE_AT (MACHINE_BUS_ISA | MACHINE_BUS_ISA16) /* sys is AT-compatible (ISA + ISA16) */ -#define MACHINE_PC98 (MACHINE_BUS_CBUS) /* sys is NEC PC-98x1 series */ -#define MACHINE_EISA (MACHINE_BUS_EISA | MACHINE_AT) /* sys is AT-compatible with EISA */ -#define MACHINE_VLB (MACHINE_BUS_VLB | MACHINE_AT) /* sys is AT-compatible with VLB */ -#define MACHINE_VLB98 (MACHINE_BUS_VLB | MACHINE_PC98) /* sys is NEC PC-98x1 series with VLB (did that even exist?) */ -#define MACHINE_VLBE (MACHINE_BUS_VLB | MACHINE_EISA) /* sys is AT-compatible with EISA and VLB */ -#define MACHINE_MCA (MACHINE_BUS_MCA) /* sys is MCA */ -#define MACHINE_PCI (MACHINE_BUS_PCI | MACHINE_AT) /* sys is AT-compatible with PCI */ -#define MACHINE_PCI98 (MACHINE_BUS_PCI | MACHINE_PC98) /* sys is NEC PC-98x1 series with PCI */ -#define MACHINE_PCIE (MACHINE_BUS_PCI | MACHINE_EISA) /* sys is AT-compatible with PCI, and EISA */ -#define MACHINE_PCIV (MACHINE_BUS_PCI | MACHINE_VLB) /* sys is AT-compatible with PCI and VLB */ -#define MACHINE_PCIVE (MACHINE_BUS_PCI | MACHINE_VLBE) /* sys is AT-compatible with PCI, VLB, and EISA */ -#define MACHINE_PCMCIA (MACHINE_BUS_PCMCIA | MACHINE_AT) /* sys is AT-compatible laptop with PCMCIA */ -#define MACHINE_AGP (MACHINE_BUS_AGP | MACHINE_PCI) /* sys is AT-compatible with AGP */ -#define MACHINE_AGP98 (MACHINE_BUS_AGP | MACHINE_PCI98) /* sys is NEC PC-98x1 series with AGP (did that even exist?) */ +#define MACHINE_PC (MACHINE_BUS_ISA) /* sys is PC/XT-compatible (ISA) */ +#define MACHINE_AT (MACHINE_BUS_ISA | MACHINE_BUS_ISA16) /* sys is AT-compatible (ISA + ISA16) */ +#define MACHINE_PC98 (MACHINE_BUS_CBUS) /* sys is NEC PC-98x1 series */ +#define MACHINE_EISA (MACHINE_BUS_EISA | MACHINE_AT) /* sys is AT-compatible with EISA */ +#define MACHINE_VLB (MACHINE_BUS_VLB | MACHINE_AT) /* sys is AT-compatible with VLB */ +#define MACHINE_VLB98 (MACHINE_BUS_VLB | MACHINE_PC98) /* sys is NEC PC-98x1 series with VLB (did that even exist?) */ +#define MACHINE_VLBE (MACHINE_BUS_VLB | MACHINE_EISA) /* sys is AT-compatible with EISA and VLB */ +#define MACHINE_MCA (MACHINE_BUS_MCA) /* sys is MCA */ +#define MACHINE_PCI (MACHINE_BUS_PCI | MACHINE_AT) /* sys is AT-compatible with PCI */ +#define MACHINE_PCI98 (MACHINE_BUS_PCI | MACHINE_PC98) /* sys is NEC PC-98x1 series with PCI */ +#define MACHINE_PCIE (MACHINE_BUS_PCI | MACHINE_EISA) /* sys is AT-compatible with PCI, and EISA */ +#define MACHINE_PCIV (MACHINE_BUS_PCI | MACHINE_VLB) /* sys is AT-compatible with PCI and VLB */ +#define MACHINE_PCIVE (MACHINE_BUS_PCI | MACHINE_VLBE) /* sys is AT-compatible with PCI, VLB, and EISA */ +#define MACHINE_PCMCIA (MACHINE_BUS_PCMCIA | MACHINE_AT) /* sys is AT-compatible laptop with PCMCIA */ +#define MACHINE_AGP (MACHINE_BUS_AGP | MACHINE_PCI) /* sys is AT-compatible with AGP */ +#define MACHINE_AGP98 (MACHINE_BUS_AGP | MACHINE_PCI98) /* sys is NEC PC-98x1 series with AGP (did that even exist?) */ -#define MACHINE_PC5150 (MACHINE_PC | MACHINE_CASSETTE) /* sys is IBM PC 5150 */ -#define MACHINE_PCJR (MACHINE_PC | MACHINE_CASSETTE | MACHINE_CARTRIDGE) /* sys is PCjr */ -#define MACHINE_PS2 (MACHINE_AT | MACHINE_BUS_PS2) /* sys is PS/2 */ -#define MACHINE_PS2_MCA (MACHINE_MCA | MACHINE_BUS_PS2) /* sys is MCA PS/2 */ -#define MACHINE_PS2_VLB (MACHINE_VLB | MACHINE_BUS_PS2) /* sys is VLB PS/2 */ -#define MACHINE_PS2_PCI (MACHINE_PCI | MACHINE_BUS_PS2) /* sys is PCI PS/2 */ -#define MACHINE_PS2_PCIV (MACHINE_PCIV | MACHINE_BUS_PS2) /* sys is VLB/PCI PS/2 */ -#define MACHINE_PS2_AGP (MACHINE_AGP | MACHINE_BUS_PS2) /* sys is AGP PS/2 */ -#define MACHINE_PS2_A97 (MACHINE_PS2_AGP | MACHINE_BUS_AC97) /* sys is AGP/AC97 PS/2 */ -#define MACHINE_PS2_NOISA (MACHINE_PS2_AGP & ~MACHINE_AT) /* sys is AGP PS/2 without ISA */ -#define MACHINE_PS2_NOI97 (MACHINE_PS2_A97 & ~MACHINE_AT) /* sys is AGP/AC97 PS/2 without ISA */ +#define MACHINE_PC5150 (MACHINE_PC | MACHINE_CASSETTE) /* sys is IBM PC 5150 */ +#define MACHINE_PCJR (MACHINE_PC | MACHINE_CASSETTE | MACHINE_CARTRIDGE) /* sys is PCjr */ +#define MACHINE_PS2 (MACHINE_AT | MACHINE_BUS_PS2) /* sys is PS/2 */ +#define MACHINE_PS2_MCA (MACHINE_MCA | MACHINE_BUS_PS2) /* sys is MCA PS/2 */ +#define MACHINE_PS2_VLB (MACHINE_VLB | MACHINE_BUS_PS2) /* sys is VLB PS/2 */ +#define MACHINE_PS2_PCI (MACHINE_PCI | MACHINE_BUS_PS2) /* sys is PCI PS/2 */ +#define MACHINE_PS2_PCIV (MACHINE_PCIV | MACHINE_BUS_PS2) /* sys is VLB/PCI PS/2 */ +#define MACHINE_PS2_AGP (MACHINE_AGP | MACHINE_BUS_PS2) /* sys is AGP PS/2 */ +#define MACHINE_PS2_A97 (MACHINE_PS2_AGP | MACHINE_BUS_AC97) /* sys is AGP/AC97 PS/2 */ +#define MACHINE_PS2_NOISA (MACHINE_PS2_AGP & ~MACHINE_AT) /* sys is AGP PS/2 without ISA */ +#define MACHINE_PS2_PCIONLY (MACHINE_PS2_NOISA & ~MACHINE_BUS_AGP) /* sys is PCI PS/2 without ISA */ +#define MACHINE_PS2_NOI97 (MACHINE_PS2_A97 & ~MACHINE_AT) /* sys is AGP/AC97 PS/2 without ISA */ /* Feature flags for miscellaneous internal devices. */ #define MACHINE_FLAGS_NONE 0x00000000 /* sys has no int devices */ #define MACHINE_SOFTFLOAT_ONLY 0x00000001 /* sys requires SoftFloat FPU */ @@ -245,8 +246,12 @@ enum { MACHINE_CHIPSET_SIS_471, MACHINE_CHIPSET_SIS_496, MACHINE_CHIPSET_SIS_501, + MACHINE_CHIPSET_SIS_5501, MACHINE_CHIPSET_SIS_5511, MACHINE_CHIPSET_SIS_5571, + MACHINE_CHIPSET_SIS_5581, + MACHINE_CHIPSET_SIS_5591, + MACHINE_CHIPSET_SIS_5600, MACHINE_CHIPSET_SMSC_VICTORYBX_66, MACHINE_CHIPSET_STPC_CLIENT, MACHINE_CHIPSET_STPC_CONSUMER_II, @@ -472,6 +477,7 @@ extern int machine_at_wd76c10_init(const machine_t *); extern int machine_at_arb1374_init(const machine_t *); extern int machine_at_sbc350a_init(const machine_t *); extern int machine_at_flytech386_init(const machine_t *); +extern int machine_at_325ax_init(const machine_t *); extern int machine_at_mr1217_init(const machine_t *); extern int machine_at_pja511m_init(const machine_t *); extern int machine_at_prox1332_init(const machine_t *); @@ -486,6 +492,7 @@ 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_micronics386_init(const machine_t *); +extern int machine_at_ecs386v_init(const machine_t *); extern int machine_at_rycleopardlx_init(const machine_t *); @@ -505,6 +512,7 @@ extern int machine_at_winbios1429_init(const machine_t *); extern int machine_at_opti495_init(const machine_t *); extern int machine_at_opti495_ami_init(const machine_t *); extern int machine_at_opti495_mr_init(const machine_t *); +extern int machine_at_exp4349_init(const machine_t *); extern int machine_at_vect486vl_init(const machine_t *); extern int machine_at_d824_init(const machine_t *); @@ -512,6 +520,8 @@ extern int machine_at_d824_init(const machine_t *); extern int machine_at_403tg_init(const machine_t *); extern int machine_at_403tg_d_init(const machine_t *); extern int machine_at_403tg_d_mr_init(const machine_t *); +extern int machine_at_pb450_init(const machine_t *); +extern int machine_at_pb450_init(const machine_t *); extern int machine_at_pc330_6573_init(const machine_t *); extern int machine_at_mvi486_init(const machine_t *); @@ -525,16 +535,23 @@ extern int machine_at_ami471_init(const machine_t *); extern int machine_at_dtk486_init(const machine_t *); extern int machine_at_px471_init(const machine_t *); extern int machine_at_win471_init(const machine_t *); +extern int machine_at_pci400ca_init(const machine_t *); extern int machine_at_vi15g_init(const machine_t *); extern int machine_at_greenb_init(const machine_t *); +extern int machine_at_4gpv5_init(const machine_t *); extern int machine_at_r418_init(const machine_t *); extern int machine_at_ls486e_init(const machine_t *); extern int machine_at_4dps_init(const machine_t *); +extern int machine_at_ms4144_init(const machine_t *); extern int machine_at_4saw2_init(const machine_t *); extern int machine_at_m4li_init(const machine_t *); extern int machine_at_alfredo_init(const machine_t *); +extern int machine_at_amis76_init(const machine_t *); extern int machine_at_ninja_init(const machine_t *); +extern int machine_at_bat4ip3e_init(const machine_t *); +extern int machine_at_486pi_init(const machine_t *); +extern int machine_at_sb486p_init(const machine_t *); extern int machine_at_486sp3_init(const machine_t *); extern int machine_at_486sp3c_init(const machine_t *); extern int machine_at_486sp3g_init(const machine_t *); @@ -546,6 +563,7 @@ extern int machine_at_win486pci_init(const machine_t *); extern int machine_at_ms4145_init(const machine_t *); extern int machine_at_sbc490_init(const machine_t *); extern int machine_at_tf486_init(const machine_t *); +extern int machine_at_arb1476_init(const machine_t *); extern int machine_at_pci400cb_init(const machine_t *); extern int machine_at_g486ip_init(const machine_t *); @@ -553,18 +571,24 @@ extern int machine_at_g486ip_init(const machine_t *); extern int machine_at_itoxstar_init(const machine_t *); extern int machine_at_arb1423c_init(const machine_t *); extern int machine_at_arb1479_init(const machine_t *); +extern int machine_at_iach488_init(const machine_t *); extern int machine_at_pcm9340_init(const machine_t *); extern int machine_at_pcm5330_init(const machine_t *); extern int machine_at_ecs486_init(const machine_t *); -extern int machine_at_hot433_init(const machine_t *); +extern int machine_at_hot433a_init(const machine_t *); extern int machine_at_atc1415_init(const machine_t *); extern int machine_at_actionpc2600_init(const machine_t *); +extern int machine_at_actiontower8400_init(const machine_t *); extern int machine_at_m919_init(const machine_t *); extern int machine_at_spc7700plw_init(const machine_t *); extern int machine_at_ms4134_init(const machine_t *); extern int machine_at_tg486gp_init(const machine_t *); extern int machine_at_tg486g_init(const machine_t *); +extern int machine_at_dvent4xx_init(const machine_t *); +extern int machine_at_ecsal486_init(const machine_t *); +extern int machine_at_ap4100aa_init(const machine_t *); +extern int machine_at_atc1762_init(const machine_t *); /* m_at_commodore.c */ extern int machine_at_cmdpc_init(const machine_t *); @@ -589,7 +613,7 @@ extern int machine_at_opti560l_init(const machine_t *); extern int machine_at_ambradp60_init(const machine_t *); extern int machine_at_valuepointp60_init(const machine_t *); extern int machine_at_revenge_init(const machine_t *); -extern int machine_at_586mc1_init(const machine_t *); +extern int machine_at_586is_init(const machine_t *); extern int machine_at_pb520r_init(const machine_t *); extern int machine_at_excalibur_init(const machine_t *); @@ -603,22 +627,30 @@ extern int machine_at_p5sp4_init(const machine_t *); extern int machine_at_plato_init(const machine_t *); extern int machine_at_dellplato_init(const machine_t *); extern int machine_at_ambradp90_init(const machine_t *); -extern int machine_at_430nx_init(const machine_t *); +extern int machine_at_586ip_init(const machine_t *); +extern int machine_at_tek932_init(const machine_t *); extern int machine_at_acerv30_init(const machine_t *); extern int machine_at_apollo_init(const machine_t *); extern int machine_at_zappa_init(const machine_t *); extern int machine_at_powermatev_init(const machine_t *); extern int machine_at_hawk_init(const machine_t *); +extern int machine_at_pt2000_init(const machine_t *); extern int machine_at_pat54pv_init(const machine_t *); extern int machine_at_hot543_init(const machine_t *); +extern int machine_at_ncselp90_init(const machine_t *); extern int machine_at_p54sp4_init(const machine_t *); extern int machine_at_sq588_init(const machine_t *); extern int machine_at_p54sps_init(const machine_t *); +extern int machine_at_ms5109_init(const machine_t *); +extern int machine_at_torino_init(const machine_t *); + +extern int machine_at_hot539_init(const machine_t *); + /* m_at_socket7_3v.c */ extern int machine_at_p54tp4xe_init(const machine_t *); extern int machine_at_p54tp4xe_mr_init(const machine_t *); @@ -639,13 +671,16 @@ extern int machine_at_8500tuc_init(const machine_t *); extern int machine_at_p55t2s_init(const machine_t *); extern int machine_at_p5vxb_init(const machine_t *); -extern int machine_at_dell_430vx_init(const machine_t *); +extern int machine_at_dellhannibalp_init(const machine_t *); extern int machine_at_gw2kte_init(const machine_t *); extern int machine_at_ap5s_init(const machine_t *); extern int machine_at_ms5124_init(const machine_t *); +extern int machine_at_amis727_init(const machine_t *); extern int machine_at_vectra54_init(const machine_t *); +extern int machine_at_5sbm2_init(const machine_t *); + /* m_at_socket7.c */ extern int machine_at_acerv35n_init(const machine_t *); extern int machine_at_p55t2p4_init(const machine_t *); @@ -656,6 +691,7 @@ extern int machine_at_cu430hx_init(const machine_t *); extern int machine_at_equium5200_init(const machine_t *); extern int machine_at_pcv90_init(const machine_t *); extern int machine_at_p65up5_cp55t2d_init(const machine_t *); +extern int machine_at_epc2102_init(const machine_t *); extern int machine_at_ap5vm_init(const machine_t *); extern int machine_at_p55tvp4_init(const machine_t *); @@ -680,6 +716,8 @@ extern int machine_at_thunderbolt_init(const machine_t *); extern int machine_at_mb540n_init(const machine_t *); extern int machine_at_56a5_init(const machine_t *); extern int machine_at_p5mms98_init(const machine_t *); +extern int machine_at_richmond_init(const machine_t *); +extern int machine_at_tomahawk_init(const machine_t *); extern int machine_at_ficva502_init(const machine_t *); @@ -687,14 +725,21 @@ extern int machine_at_ficpa2012_init(const machine_t *); extern int machine_at_r534f_init(const machine_t *); extern int machine_at_ms5146_init(const machine_t *); -extern int machine_at_cb52x_si_init(const machine_t *); +extern int machine_at_cb52xsi_init(const machine_t *); extern int machine_at_m560_init(const machine_t *); extern int machine_at_ms5164_init(const machine_t *); +extern int machine_at_sp97xv_init(const machine_t *); +extern int machine_at_sq578_init(const machine_t *); + +extern int machine_at_5sg100_init(const machine_t *); +extern int machine_at_ms5172_init(const machine_t *); + /* m_at_sockets7.c */ extern int machine_at_p5a_init(const machine_t *); extern int machine_at_m579_init(const machine_t *); +extern int machine_at_gwlucas_init(const machine_t *); extern int machine_at_5aa_init(const machine_t *); extern int machine_at_5ax_init(const machine_t *); @@ -704,12 +749,12 @@ extern int machine_at_ficva503a_init(const machine_t *); extern int machine_at_5emapro_init(const machine_t *); /* m_at_socket8.c */ +extern int machine_at_ap61_init(const machine_t *); extern int machine_at_p6rp4_init(const machine_t *); -extern int machine_at_aurora_init(const machine_t *); extern int machine_at_686nx_init(const machine_t *); extern int machine_at_acerv60n_init(const machine_t *); -extern int machine_at_lgibm440fx_init(const machine_t *); +extern int machine_at_lgibmx61_init(const machine_t *); extern int machine_at_vs440fx_init(const machine_t *); extern int machine_at_gw2kvenus_init(const machine_t *); extern int machine_at_ap440fx_init(const machine_t *); @@ -730,12 +775,12 @@ extern int machine_at_kn97_init(const machine_t *); extern int machine_at_lx6_init(const machine_t *); extern int machine_at_spitfire_init(const machine_t *); -extern int machine_at_mate_nx_ma30d_23d_init(const machine_t *); +extern int machine_at_ma30d_init(const machine_t *); extern int machine_at_p6i440e2_init(const machine_t *); extern int machine_at_p2bls_init(const machine_t *); -extern int machine_at_lgibm440bx_init(const machine_t *); +extern int machine_at_lgibmx7g_init(const machine_t *); extern int machine_at_p3bf_init(const machine_t *); extern int machine_at_bf6_init(const machine_t *); extern int machine_at_ax6bc_init(const machine_t *); @@ -753,6 +798,8 @@ extern int machine_at_vei8_init(const machine_t *); extern int machine_at_borapro_init(const machine_t *); extern int machine_at_ms6168_init(const machine_t *); +extern int machine_at_p6f99_init(const machine_t *); + /* m_at_slot2.c */ extern int machine_at_6gxu_init(const machine_t *); extern int machine_at_s2dge_init(const machine_t *); diff --git a/src/include/86box/mem.h b/src/include/86box/mem.h index 69a2b5de8..bc949834f 100644 --- a/src/include/86box/mem.h +++ b/src/include/86box/mem.h @@ -303,6 +303,7 @@ extern int mmu_perm; extern uint8_t high_page; /* if a high (> 4 gb) page was detected */ extern uint32_t pages_sz; /* #pages in table */ +extern int read_type; extern int mem_a20_state; extern int mem_a20_alt; @@ -398,6 +399,7 @@ extern void mem_mapping_disable(mem_mapping_t *); extern void mem_mapping_enable(mem_mapping_t *); extern void mem_mapping_recalc(uint64_t base, uint64_t size); +extern void mem_set_wp(uint64_t base, uint64_t size, uint8_t flags, uint8_t wp); extern void mem_set_access(uint8_t bitmap, int mode, uint32_t base, uint32_t size, uint16_t access); extern uint8_t mem_readb_phys(uint32_t addr); @@ -439,6 +441,8 @@ extern void mem_reset_page_blocks(void); extern void flushmmucache(void); extern void flushmmucache_nopc(void); +extern void mem_debug_check_addr(uint32_t addr, int write); + extern void mem_a20_init(void); extern void mem_a20_recalc(void); @@ -447,6 +451,8 @@ extern void mem_close(void); extern void mem_reset(void); extern void mem_remap_top(int kb); +extern void umc_smram_recalc(uint32_t start, int set); + extern mem_mapping_t *read_mapping[MEM_MAPPINGS_NO]; extern mem_mapping_t *write_mapping[MEM_MAPPINGS_NO]; diff --git a/src/include/86box/midi.h b/src/include/86box/midi.h index 4bc678817..7f7ad89ae 100644 --- a/src/include/86box/midi.h +++ b/src/include/86box/midi.h @@ -102,7 +102,9 @@ extern void midi_in_sysex(uint8_t *buffer, uint32_t len); #ifdef EMU_DEVICE_H extern const device_t rtmidi_output_device; extern const device_t rtmidi_input_device; +# if defined(DEV_BRANCH) && defined(USE_OPL4ML) extern const device_t opl4_midi_device; +# endif # ifdef USE_FLUIDSYNTH extern const device_t fluidsynth_device; # endif diff --git a/src/include/86box/mouse.h b/src/include/86box/mouse.h index 3ed6b2126..786b86f41 100644 --- a/src/include/86box/mouse.h +++ b/src/include/86box/mouse.h @@ -93,6 +93,7 @@ extern void mouse_scale_x(int x); extern void mouse_scale_y(int y); extern void mouse_scalef(double x, double y); extern void mouse_scale(int x, int y); +extern void mouse_scale_axis(int axis, int val); extern void mouse_set_z(int z); extern void mouse_clear_z(void); extern void mouse_subtract_z(int *delta_z, int min, int max, int invert); diff --git a/src/include/86box/net_3c501.h b/src/include/86box/net_3c501.h deleted file mode 100644 index c55151ab8..000000000 --- a/src/include/86box/net_3c501.h +++ /dev/null @@ -1,45 +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 Project. - * - * Implementation of the following network controller: - * - 3Com Etherlink 3c500/3c501 (ISA 8-bit). - * - * - * - * Based on @(#)Dev3C501.cpp Oracle (VirtualBox) - * - * Authors: TheCollector1995, - * Oracle - * - * Copyright 2022 TheCollector1995. - * Portions Copyright (C) 2022 Oracle and/or its affilitates. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#ifndef NET_3C501_H -#define NET_3C501_H - -extern const device_t threec501_device; - -#endif /*NET_3C501_H*/ diff --git a/src/include/86box/net_3c503.h b/src/include/86box/net_3c503.h deleted file mode 100644 index 44024850f..000000000 --- a/src/include/86box/net_3c503.h +++ /dev/null @@ -1,49 +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 following network controllers: - * - 3Com Etherlink II 3c503 (ISA 8-bit). - * - * - * - * Based on @(#)3c503.cpp Carl (MAME) - * - * Authors: TheCollector1995, - * Miran Grca, - * Fred N. van Kempen, - * Carl, - * - * Copyright 2018 TheCollector1995. - * Copyright 2018 Miran Grca. - * Copyright 2017-2018 Fred N. van Kempen. - * Portions Copyright (C) 2018 MAME Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#ifndef NET_3C503_H -#define NET_3C503_H - -extern const device_t threec503_device; - -#endif /*NET_3C503_H*/ diff --git a/src/include/86box/net_ne2000.h b/src/include/86box/net_ne2000.h index 350668ccb..fe1a71934 100644 --- a/src/include/86box/net_ne2000.h +++ b/src/include/86box/net_ne2000.h @@ -37,18 +37,15 @@ #define NET_NE2000_H enum { - NE2K_NONE = 0, - NE2K_NE1000 = 1, /* 8-bit ISA NE1000 */ - NE2K_NE2000 = 2, /* 16-bit ISA NE2000 */ - NE2K_ETHERNEXT_MC = 3, /* 16-bit MCA EtherNext/MC */ - NE2K_RTL8019AS = 4, /* 16-bit ISA PnP Realtek 8019AS */ - NE2K_RTL8029AS = 5 /* 32-bit PCI Realtek 8029AS */ + NE2K_NONE = 0, + NE2K_NE1000 = 1, /* 8-bit ISA NE1000 */ + NE2K_NE1000_COMPAT = 2, /* 16-bit ISA NE2000-Compatible */ + NE2K_NE2000 = 3, /* 16-bit ISA NE2000 */ + NE2K_NE2000_COMPAT = 4, /* 16-bit ISA NE2000-Compatible */ + NE2K_ETHERNEXT_MC = 5, /* 16-bit MCA EtherNext/MC */ + NE2K_RTL8019AS = 6, /* 16-bit ISA PnP Realtek 8019AS */ + NE2K_DE220P = 7, /* 16-bit ISA PnP D-Link DE-220P */ + NE2K_RTL8029AS = 8 /* 32-bit PCI Realtek 8029AS */ }; -extern const device_t ne1000_device; -extern const device_t ne2000_device; -extern const device_t ethernext_mc_device; -extern const device_t rtl8019as_device; -extern const device_t rtl8029as_device; - #endif /*NET_NE2000_H*/ diff --git a/src/include/86box/net_pcnet.h b/src/include/86box/net_pcnet.h index ccdc7e832..994d88c75 100644 --- a/src/include/86box/net_pcnet.h +++ b/src/include/86box/net_pcnet.h @@ -30,11 +30,4 @@ enum { DEV_AM79C973 = 6 /* PCnet-FAST III (PCI, 10/100 Mbps) */ }; -extern const device_t pcnet_am79c960_device; -extern const device_t pcnet_am79c960_eb_device; -extern const device_t pcnet_am79c960_vlb_device; -extern const device_t pcnet_am79c961_device; -extern const device_t pcnet_am79c970a_device; -extern const device_t pcnet_am79c973_device; - #endif /*NET_PCNET_H*/ diff --git a/src/include/86box/net_plip.h b/src/include/86box/net_plip.h deleted file mode 100644 index 83c33e4c6..000000000 --- a/src/include/86box/net_plip.h +++ /dev/null @@ -1,26 +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. - * - * Definitions for the PLIP parallel port network device. - * - * - * - * Authors: RichardG, - * - * Copyright 2020 RichardG. - */ - -#ifndef NET_PLIP_H -#define NET_PLIP_H -#include <86box/device.h> -#include <86box/lpt.h> - -extern const lpt_device_t lpt_plip_device; -extern const device_t plip_device; - -#endif /*NET_PLIP_H*/ diff --git a/src/include/86box/net_rtl8139.h b/src/include/86box/net_rtl8139.h deleted file mode 100644 index f44d0facb..000000000 --- a/src/include/86box/net_rtl8139.h +++ /dev/null @@ -1 +0,0 @@ -extern const device_t rtl8139c_plus_device; diff --git a/src/include/86box/net_tulip.h b/src/include/86box/net_tulip.h deleted file mode 100644 index 3e14deeea..000000000 --- a/src/include/86box/net_tulip.h +++ /dev/null @@ -1,3 +0,0 @@ -extern const device_t dec_tulip_device; -extern const device_t dec_tulip_21140_device; -extern const device_t dec_tulip_21140_vpc_device; diff --git a/src/include/86box/net_wd8003.h b/src/include/86box/net_wd8003.h index 726510cdb..6797c7d88 100644 --- a/src/include/86box/net_wd8003.h +++ b/src/include/86box/net_wd8003.h @@ -54,11 +54,4 @@ enum { WD8013EPA = 6 }; -extern const device_t wd8003e_device; -extern const device_t wd8003eb_device; -extern const device_t wd8013ebt_device; -extern const device_t wd8003eta_device; -extern const device_t wd8003ea_device; -extern const device_t wd8013epa_device; - #endif /*NET_WD8003_H*/ diff --git a/src/include/86box/network.h b/src/include/86box/network.h index e9b703ee0..d0af3f09b 100644 --- a/src/include/86box/network.h +++ b/src/include/86box/network.h @@ -192,12 +192,63 @@ extern int network_card_available(int); extern int network_card_has_config(int); extern const char *network_card_get_internal_name(int); extern int network_card_get_from_internal_name(char *); +#ifdef EMU_DEVICE_H extern const device_t *network_card_getdevice(int); +#endif extern int network_tx_pop(netcard_t *card, netpkt_t *out_pkt); extern int network_tx_popv(netcard_t *card, netpkt_t *pkt_vec, int vec_size); extern int network_rx_put(netcard_t *card, uint8_t *bufp, int len); extern int network_rx_put_pkt(netcard_t *card, netpkt_t *pkt); + +#ifdef EMU_DEVICE_H +/* 3Com Etherlink */ +extern const device_t threec501_device; +extern const device_t threec503_device; + +/* Novell NE2000 and compatibles */ +extern const device_t ne1000_device; +extern const device_t ne1000_compat_device; +extern const device_t ne2000_device; +extern const device_t ne2000_compat_device; +extern const device_t ethernext_mc_device; +extern const device_t rtl8019as_device; +extern const device_t de220p_device; +extern const device_t rtl8029as_device; + +/* AMD PCnet*/ +extern const device_t pcnet_am79c960_device; +extern const device_t pcnet_am79c960_eb_device; +extern const device_t pcnet_am79c960_vlb_device; +extern const device_t pcnet_am79c961_device; +extern const device_t pcnet_am79c970a_device; +extern const device_t pcnet_am79c973_device; +extern const device_t pcnet_am79c973_onboard_device; + +/* PLIP */ +#ifdef EMU_LPT_H +extern const lpt_device_t lpt_plip_device; +#endif +extern const device_t plip_device; + +/* Realtek RTL8139C+ */ +extern const device_t rtl8139c_plus_device; + +/* DEC Tulip */ +extern const device_t dec_tulip_device; +extern const device_t dec_tulip_21140_device; +extern const device_t dec_tulip_21140_vpc_device; +extern const device_t dec_tulip_21040_device; + +/* WD 80x3 */ +extern const device_t wd8003e_device; +extern const device_t wd8003eb_device; +extern const device_t wd8013ebt_device; +extern const device_t wd8003eta_device; +extern const device_t wd8003ea_device; +extern const device_t wd8013epa_device; +#endif + #ifdef __cplusplus } #endif diff --git a/src/include/86box/nvr.h b/src/include/86box/nvr.h index d24ca903c..85e0954f0 100644 --- a/src/include/86box/nvr.h +++ b/src/include/86box/nvr.h @@ -122,6 +122,8 @@ extern void nvr_at_handler(int set, uint16_t base, nvr_t *nvr); extern void nvr_at_sec_handler(int set, uint16_t base, nvr_t *nvr); extern void nvr_at_index_read_handler(int set, uint16_t base, nvr_t *nvr); extern void nvr_read_addr_set(int set, nvr_t *nvr); +extern uint8_t nvr_get_index(void *priv, uint8_t addr_id); +extern void nvr_at_data_port(int set, nvr_t *nvr); extern void nvr_wp_set(int set, int h, nvr_t *nvr); extern void nvr_via_wp_set(int set, int reg, nvr_t *nvr); extern void nvr_bank_set(int base, uint8_t bank, nvr_t *nvr); diff --git a/src/include/86box/pci.h b/src/include/86box/pci.h index cb6c90429..82d896f66 100644 --- a/src/include/86box/pci.h +++ b/src/include/86box/pci.h @@ -289,6 +289,7 @@ extern const device_t via_vp3_agp_device; extern const device_t via_mvp3_agp_device; extern const device_t via_apro_agp_device; extern const device_t via_vt8601_agp_device; +extern const device_t sis_5xxx_agp_device; #endif #endif /*EMU_PCI_H*/ diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index 1f5f2b695..84f0318c2 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -107,7 +107,6 @@ extern int infocus; extern char emu_version[200]; /* version ID string */ extern int rctrl_is_lalt; extern int update_icons; -extern int status_icons_fullscreen; extern int kbd_req_capture; extern int hide_status_bar; diff --git a/src/include/86box/resource.h b/src/include/86box/resource.h index 20067aa40..2e6628c77 100644 --- a/src/include/86box/resource.h +++ b/src/include/86box/resource.h @@ -79,10 +79,10 @@ #define IDT_JOYSTICK 1718 /* Joystick: */ /* DLG_CFG_SOUND */ -#define IDT_SOUND1 1719 /* Sound card 1: */ -#define IDT_SOUND2 1720 /* Sound card 2: */ -#define IDT_SOUND3 1721 /* Sound card 3: */ -#define IDT_SOUND4 1722 /* Sound card 4: */ +#define IDT_SOUND1 1719 /* Sound card #1: */ +#define IDT_SOUND2 1720 /* Sound card #2: */ +#define IDT_SOUND3 1721 /* Sound card #3: */ +#define IDT_SOUND4 1722 /* Sound card #4: */ #define IDT_MIDI_OUT 1723 /* MIDI Out Device: */ #define IDT_MIDI_IN 1724 /* MIDI In Device: */ diff --git a/src/include/86box/serial.h b/src/include/86box/serial.h index bd7e85a91..08f77ea13 100644 --- a/src/include/86box/serial.h +++ b/src/include/86box/serial.h @@ -124,11 +124,11 @@ extern void serial_set_next_inst(int ni); extern void serial_standalone_init(void); extern void serial_set_clock_src(serial_t *dev, double clock_src); extern void serial_reset_port(serial_t *dev); +extern uint8_t serial_read(uint16_t addr, void *priv); extern void serial_device_timeout(void *priv); - -extern void serial_set_cts(serial_t *dev, uint8_t enabled); -extern void serial_set_dsr(serial_t *dev, uint8_t enabled); -extern void serial_set_dcd(serial_t *dev, uint8_t enabled); +extern void serial_set_cts(serial_t *dev, uint8_t enabled); +extern void serial_set_dsr(serial_t *dev, uint8_t enabled); +extern void serial_set_dcd(serial_t *dev, uint8_t enabled); extern const device_t ns8250_device; extern const device_t ns8250_pcjr_device; diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index a3f8f2267..4663c077c 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -26,11 +26,14 @@ extern const device_t f82c606_device; extern const device_t fdc37c651_device; extern const device_t fdc37c651_ide_device; extern const device_t fdc37c661_device; +extern const device_t fdc37c661_ide_device; +extern const device_t fdc37c661_ide_sec_device; extern const device_t fdc37c663_device; extern const device_t fdc37c663_ide_device; extern const device_t fdc37c665_device; extern const device_t fdc37c665_ide_device; extern const device_t fdc37c665_ide_pri_device; +extern const device_t fdc37c665_ide_sec_device; extern const device_t fdc37c666_device; extern const device_t fdc37c67x_device; extern const device_t fdc37c669_device; @@ -80,6 +83,12 @@ extern const device_t ps1_m2133_sio; #if defined(DEV_BRANCH) && defined(USE_SIO_DETECT) extern const device_t sio_detect_device; #endif +extern const device_t um8663af_device; +extern const device_t um8663af_ide_device; +extern const device_t um8663af_sec_device; +extern const device_t um8663bf_device; +extern const device_t um8663bf_ide_device; +extern const device_t um8663bf_sec_device; extern const device_t um8669f_device; extern const device_t um8669f_ide_device; extern const device_t um8669f_ide_sec_device; diff --git a/src/include/86box/sis_55xx.h b/src/include/86box/sis_55xx.h new file mode 100644 index 000000000..99ccf7dfa --- /dev/null +++ b/src/include/86box/sis_55xx.h @@ -0,0 +1,78 @@ +/* + * 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. + * + * Header for the implementation of the SiS 55xx Pentium + * PCI/ISA Chipsets. + * + * Authors: Miran Grca, + * + * Copyright 2019-2020 Miran Grca. + */ +#ifndef EMU_SIS_55XX_H +#define EMU_SIS_55XX_H + +typedef struct +{ + uint8_t sb_pci_slot; + uint8_t ide_bits_1_3_writable; + uint8_t usb_enabled; + + uint8_t *pmu_regs; + + sff8038i_t *bm[2]; + acpi_t *acpi; +} sis_55xx_common_t; + +extern void sis_5511_host_to_pci_write(int addr, uint8_t val, void *priv); +extern uint8_t sis_5511_host_to_pci_read(int addr, void *priv); +extern void sis_5571_host_to_pci_write(int addr, uint8_t val, void *priv); +extern uint8_t sis_5571_host_to_pci_read(int addr, void *priv); +extern void sis_5581_host_to_pci_write(int addr, uint8_t val, void *priv); +extern uint8_t sis_5581_host_to_pci_read(int addr, void *priv); +extern void sis_5591_host_to_pci_write(int addr, uint8_t val, void *priv); +extern uint8_t sis_5591_host_to_pci_read(int addr, void *priv); +extern void sis_5600_host_to_pci_write(int addr, uint8_t val, void *priv); +extern uint8_t sis_5600_host_to_pci_read(int addr, void *priv); + +extern void sis_5513_pci_to_isa_write(int addr, uint8_t val, void *priv); +extern uint8_t sis_5513_pci_to_isa_read(int addr, void *priv); +extern void sis_5513_ide_write(int addr, uint8_t val, void *priv); +extern uint8_t sis_5513_ide_read(int addr, void *priv); +extern void sis_5572_usb_write(int addr, uint8_t val, void *priv); +extern uint8_t sis_5572_usb_read(int addr, void *priv); +extern void sis_5595_pmu_write(int addr, uint8_t val, void *priv); +extern uint8_t sis_5595_pmu_read(int addr, void *priv); + +extern const device_t sis_5511_h2p_device; +extern const device_t sis_5571_h2p_device; +extern const device_t sis_5581_h2p_device; +extern const device_t sis_5591_h2p_device; +extern const device_t sis_5600_h2p_device; + +extern const device_t sis_5513_p2i_device; +extern const device_t sis_5572_p2i_device; +extern const device_t sis_5582_p2i_device; +extern const device_t sis_5595_1997_p2i_device; +extern const device_t sis_5595_p2i_device; + +extern const device_t sis_5513_ide_device; +extern const device_t sis_5572_ide_device; +extern const device_t sis_5582_ide_device; +extern const device_t sis_5591_5600_ide_device; + +extern const device_t sis_5572_usb_device; +extern const device_t sis_5582_usb_device; +extern const device_t sis_5595_usb_device; + +extern const device_t sis_5595_pmu_device; +extern const device_t sis_5595_1997_pmu_device; + +extern const device_t sis_55xx_common_device; + + +#endif /*EMU_SIS_55XX_H*/ diff --git a/src/include/86box/smbus.h b/src/include/86box/smbus.h index a5fd4cc6c..c2dad14b9 100644 --- a/src/include/86box/smbus.h +++ b/src/include/86box/smbus.h @@ -15,8 +15,8 @@ * Copyright 2020 RichardG. */ -#ifndef EMU_SMBUS_PIIX4_H -#define EMU_SMBUS_PIIX4_H +#ifndef EMU_SMBUS_H +#define EMU_SMBUS_H #include <86box/apm.h> #include <86box/nvr.h> @@ -28,6 +28,9 @@ #define SMBUS_ALI7101_BLOCK_DATA_SIZE 32 #define SMBUS_ALI7101_BLOCK_DATA_MASK (SMBUS_ALI7101_BLOCK_DATA_SIZE - 1) +#define SMBUS_SIS5595_BLOCK_DATA_SIZE 32 +#define SMBUS_SIS5595_BLOCK_DATA_MASK (SMBUS_ALI7101_BLOCK_DATA_SIZE - 1) + enum { SMBUS_PIIX4 = 0, SMBUS_INTEL_ICH2 = 1, @@ -73,14 +76,43 @@ typedef struct smbus_ali7101_t { void *i2c; } smbus_ali7101_t; -extern void smbus_piix4_get_acpi(smbus_piix4_t *dev, acpi_t *acpi); -extern void smbus_piix4_get_irq(uint8_t irq, smbus_piix4_t *dev); -extern void smbus_piix4_smi_en(uint8_t smi_en, smbus_piix4_t *dev); +typedef struct smbus_sis5595_t { + uint32_t local; + uint16_t stat; + uint16_t next_stat; + uint16_t ctl; + uint8_t cmd; + uint8_t addr; + uint8_t saved_addr; + uint8_t block_ptr; + uint8_t count; + uint8_t data0; + uint8_t data1; + uint8_t alias; + uint8_t reg_ff; + uint8_t index; + uint8_t irq_enable; + uint8_t irq_state; + uint8_t data[SMBUS_SIS5595_BLOCK_DATA_SIZE]; + pc_timer_t response_timer; + void *i2c; +} smbus_sis5595_t; -extern void smbus_piix4_remap(smbus_piix4_t *dev, uint16_t new_io_base, uint8_t enable); -extern void smbus_piix4_setclock(smbus_piix4_t *dev, int clock); +extern void smbus_piix4_get_acpi(smbus_piix4_t *dev, acpi_t *acpi); +extern void smbus_piix4_get_irq(uint8_t irq, smbus_piix4_t *dev); +extern void smbus_piix4_smi_en(uint8_t smi_en, smbus_piix4_t *dev); -extern void smbus_ali7101_remap(smbus_ali7101_t *dev, uint16_t new_io_base, uint8_t enable); +extern void smbus_piix4_remap(smbus_piix4_t *dev, uint16_t new_io_base, uint8_t enable); +extern void smbus_piix4_setclock(smbus_piix4_t *dev, int clock); + +extern void smbus_ali7101_remap(smbus_ali7101_t *dev, uint16_t new_io_base, uint8_t enable); + +extern void smbus_sis5595_irq_enable(void *priv, uint8_t enable); + +extern uint8_t smbus_sis5595_read_index(void *priv); +extern uint8_t smbus_sis5595_read_data(void *priv); +extern void smbus_sis5595_write_index(void *priv, uint8_t val); +extern void smbus_sis5595_write_data(void *priv, uint8_t val); #ifdef EMU_DEVICE_H extern const device_t piix4_smbus_device; @@ -88,6 +120,8 @@ extern const device_t intel_ich2_smbus_device; extern const device_t via_smbus_device; extern const device_t ali7101_smbus_device; + +extern const device_t sis5595_smbus_device; #endif -#endif /*EMU_SMBUS_PIIX4_H*/ +#endif /*EMU_SMBUS_H*/ diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index 4d7483f30..fab504bbe 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -33,6 +33,8 @@ typedef struct hwcursor8514_t { } hwcursor8514_t; typedef struct ibm8514_t { + rom_t bios_rom; + rom_t bios_rom2; hwcursor8514_t hwcursor; hwcursor8514_t hwcursor_latch; uint8_t pos_regs[8]; @@ -60,12 +62,15 @@ typedef struct ibm8514_t { int dac_b; int internal_pitch; int hwcursor_on; + int modechange; + + uint64_t dispontime; + uint64_t dispofftime; struct { uint16_t subsys_cntl; uint16_t setup_md; uint16_t advfunc_cntl; - uint8_t ext_advfunc_cntl; uint16_t cur_y; uint16_t cur_x; int16_t destx; @@ -142,14 +147,23 @@ typedef struct ibm8514_t { uint16_t test; int vendor_mode[2]; + int h_blankstart; + int h_blank_end_val; + int hblankstart; + int hblank_end_val; + int hblankend; + int hblank_ext; + int hblank_sub; + int v_total_reg; int v_total; int dispend; + int v_sync_start; int v_syncstart; int split; int h_disp; - int h_disp_old; int h_total; + int h_sync_width; int h_disp_time; int rowoffset; int dispon; @@ -176,20 +190,17 @@ typedef struct ibm8514_t { uint8_t data_available; uint8_t data_available2; - uint8_t scanmodulos; uint8_t rowcount; + int hsync_start; + int hsync_width; int htotal; int hdisp; - int vtadj; - int vdadj; - int vsadj; + int hdisped; int sc; - int vtb; - int vdb; - int vsb; int vsyncstart; int vsyncwidth; int vtotal; + int v_disp; int vdisp; int disp_cntl; int interlace; @@ -205,6 +216,7 @@ typedef struct ibm8514_t { int pitch; int ext_pitch; int ext_crt_pitch; + int extensions; } ibm8514_t; #endif /*VIDEO_8514A_H*/ diff --git a/src/include/86box/vid_ati_mach8.h b/src/include/86box/vid_ati_mach8.h new file mode 100644 index 000000000..7b5862f35 --- /dev/null +++ b/src/include/86box/vid_ati_mach8.h @@ -0,0 +1,162 @@ +/* + * 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 8514/A-compatible Mach8 and Mach32 graphics + * chips from ATI for the ISA/VLB/MCA/PCI buses. + * + * + * + * Authors: TheCollector1995. + * + * Copyright 2022-2024 TheCollector1995. + */ +#ifndef VIDEO_ATI_MACH8_H +#define VIDEO_ATI_MACH8_H + +typedef struct mach_t { + ati_eeprom_t eeprom; + svga_t svga; + + rom_t bios_rom; + rom_t bios_rom2; + mem_mapping_t mmio_linear_mapping; + + int mca_bus; + int pci_bus; + int vlb_bus; + int has_bios; + + uint8_t regs[256]; + uint8_t pci_regs[256]; + uint8_t int_line; + uint8_t pci_slot; + uint8_t irq_state; + + int index; + int ramdac_type; + int old_mode; + + uint32_t memory; + + uint16_t config1; + uint16_t config2; + + uint8_t pos_regs[8]; + uint8_t pci_cntl_reg; + uint8_t cursor_col_0; + uint8_t cursor_col_1; + uint8_t ext_cur_col_0_r; + uint8_t ext_cur_col_1_r; + uint8_t ext_cur_col_0_g; + uint8_t ext_cur_col_1_g; + uint16_t cursor_col_0_rg; + uint16_t cursor_col_1_rg; + uint16_t cursor_col_b; + uint16_t cursor_offset_lo; + uint16_t cursor_offset_lo_reg; + uint16_t cursor_offset_hi; + uint16_t cursor_offset_hi_reg; + uint16_t cursor_vh_offset; + uint16_t cursor_x; + uint16_t cursor_y; + uint16_t misc; + uint16_t memory_aperture; + uint16_t local_cntl; + uint32_t linear_base; + uint8_t ap_size; + uint8_t bank_w; + uint8_t bank_r; + uint16_t shadow_set; + uint16_t shadow_cntl; + int ext_on[2]; + int compat_mode; + + struct { + uint8_t line_idx; + int16_t line_array[6]; + uint8_t patt_idx; + uint8_t patt_len; + uint8_t pix_trans[2]; + uint8_t eeprom_control; + uint16_t dest_x_end; + uint16_t dest_x_start; + uint16_t dest_y_end; + uint16_t src_x_end; + uint16_t src_x_start; + uint16_t src_x; + uint16_t src_y; + int16_t bres_count; + uint16_t clock_sel; + uint16_t crt_pitch; + uint16_t ge_pitch; + uint16_t dest_cmp_fn; + uint16_t dp_config; + uint16_t ext_ge_config; + uint16_t ge_offset_lo; + uint16_t ge_offset_hi; + uint16_t linedraw_opt; + uint16_t max_waitstates; + uint8_t patt_data_idx; + uint8_t patt_data[0x18]; + uint16_t scan_to_x; + uint16_t scratch0; + uint16_t scratch1; + uint16_t test; + uint16_t pattern; + uint16_t test2; + int src_y_dir; + int cmd_type; + int block_write_mono_pattern_enable; + int mono_pattern_enable; + int16_t cx_end_line; + int16_t cy_end_line; + int16_t cx; + int16_t cx_end; + int16_t cy_end; + int16_t dx; + int16_t dx_end; + int16_t dy; + int16_t dy_end; + int16_t dx_start; + int16_t dy_start; + int16_t cy; + int16_t sx_start; + int16_t sx_end; + int16_t sx; + int16_t x_count; + int16_t xx_count; + int16_t xxx_count; + int16_t sy; + int16_t y_count; + int16_t err; + int16_t width; + int16_t src_width; + int16_t height; + int16_t bleft, bright, btop, bbottom; + int poly_src; + int temp_cnt; + int stepx; + int stepy; + int src_stepx; + uint8_t color_pattern[16]; + uint8_t color_pattern_full[32]; + uint16_t color_pattern_word[8]; + int mono_pattern[8][8]; + uint32_t ge_offset; + uint32_t crt_offset; + uint32_t patt_len_reg; + int poly_fill; + uint16_t dst_clr_cmp_mask; + int clip_overrun; + int color_pattern_idx; + } accel; + + atomic_int force_busy; +} mach_t; + +#endif /*VIDEO_ATI_MACH8_H*/ diff --git a/src/include/86box/vid_ega.h b/src/include/86box/vid_ega.h index ec241d613..0bccd607e 100644 --- a/src/include/86box/vid_ega.h +++ b/src/include/86box/vid_ega.h @@ -56,6 +56,8 @@ typedef struct ega_t { uint8_t *vram; + uint16_t light_pen; + int vidclock; int fast; int extvram; diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 880f79003..2f8a83a1d 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -118,16 +118,16 @@ typedef struct svga_t { int vram_display_mask; int vidclock; int dots_per_clock; - int hblank_ext; int hwcursor_on; int dac_hwcursor_on; int overlay_on; int set_override; int hblankstart; int hblankend; - int hblank_sub; int hblank_end_val; int hblank_end_len; + int hblank_end_mask; + int hblank_sub; int packed_4bpp; int ati_4color; @@ -166,8 +166,12 @@ typedef struct svga_t { latch_t latch; pc_timer_t timer; + pc_timer_t timer8514; double clock; + double clock8514; + + double multiplier; hwcursor_t hwcursor; hwcursor_t hwcursor_latch; @@ -281,12 +285,13 @@ typedef struct svga_t { uint32_t (*conv_16to32)(struct svga_t *svga, uint16_t color, uint8_t bpp); void * dev8514; + void * ext8514; void * xga; } svga_t; extern int vga_on; -extern void ibm8514_poll(void *priv, svga_t *svga); +extern void ibm8514_poll(void *priv); extern void ibm8514_recalctimings(svga_t *svga); extern uint8_t ibm8514_ramdac_in(uint16_t port, void *priv); extern void ibm8514_ramdac_out(uint16_t port, uint8_t val, void *priv); @@ -296,6 +301,13 @@ extern void ibm8514_accel_out_pixtrans(svga_t *svga, uint16_t port, uint32_t extern void ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, uint8_t ssv, int len); extern void ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, int len); +#ifdef ATI_8514_ULTRA +extern void ati8514_recalctimings(svga_t *svga); +extern uint8_t ati8514_mca_read(int port, void *priv); +extern void ati8514_mca_write(int port, uint8_t val, void *priv); +extern void ati8514_init(svga_t *svga, void *ext8514, void *dev8514); +#endif + extern void xga_poll(void *priv, svga_t *svga); extern void xga_recalctimings(svga_t *svga); diff --git a/src/include/86box/vid_svga_render.h b/src/include/86box/vid_svga_render.h index 33bb13bbf..224d96c8e 100644 --- a/src/include/86box/vid_svga_render.h +++ b/src/include/86box/vid_svga_render.h @@ -53,7 +53,7 @@ extern void svga_render_4bpp_lowres(svga_t *svga); extern void svga_render_4bpp_highres(svga_t *svga); extern void svga_render_8bpp_lowres(svga_t *svga); extern void svga_render_8bpp_highres(svga_t *svga); -extern void svga_render_8bpp_incompatible_highres(svga_t *svga); +extern void svga_render_8bpp_clone_highres(svga_t *svga); extern void svga_render_8bpp_tseng_lowres(svga_t *svga); extern void svga_render_8bpp_tseng_highres(svga_t *svga); extern void svga_render_8bpp_gs_lowres(svga_t *svga); @@ -75,6 +75,7 @@ extern void svga_render_ABGR8888_highres(svga_t *svga); extern void svga_render_RGBA8888_lowres(svga_t *svga); extern void svga_render_RGBA8888_highres(svga_t *svga); +extern void ibm8514_render_blank(svga_t *svga); extern void ibm8514_render_8bpp(svga_t *svga); extern void ibm8514_render_15bpp(svga_t *svga); extern void ibm8514_render_16bpp(svga_t *svga); diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 0f0a13182..65d96a4b6 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -306,7 +306,7 @@ extern void xga_device_add(void); /* IBM 8514/A and clones*/ extern void ibm8514_device_add(void); -extern const device_t mach8_isa_device; +extern const device_t mach8_vga_isa_device; extern const device_t mach32_isa_device; extern const device_t mach32_vlb_device; extern const device_t mach32_mca_device; @@ -348,6 +348,7 @@ extern const device_t gd5426_diamond_speedstar_pro_a1_isa_device; extern const device_t gd5426_vlb_device; extern const device_t gd5426_onboard_device; extern const device_t gd5428_isa_device; +extern const device_t gd5428_vlb_onboard_device; extern const device_t gd5428_vlb_device; extern const device_t gd5428_diamond_speedstar_pro_b1_vlb_device; extern const device_t gd5428_boca_isa_device; @@ -367,8 +368,9 @@ extern const device_t gd5434_onboard_pci_device; extern const device_t gd5434_vlb_device; extern const device_t gd5434_pci_device; extern const device_t gd5436_pci_device; -extern const device_t gd5440_onboard_pci_device; +extern const device_t gd5436_onboard_pci_device; extern const device_t gd5440_pci_device; +extern const device_t gd5440_onboard_pci_device; extern const device_t gd5446_pci_device; extern const device_t gd5446_stb_pci_device; extern const device_t gd5480_pci_device; @@ -458,6 +460,7 @@ extern const device_t paradise_wd90c11_device; extern const device_t paradise_wd90c30_device; /* Realtek (S)VGA */ +extern const device_t realtek_rtg3105_device; extern const device_t realtek_rtg3106_device; /* S3 9XX/8XX/Vision/Trio */ @@ -478,7 +481,9 @@ extern const device_t s3_bahamas64_vlb_device; extern const device_t s3_bahamas64_pci_device; extern const device_t s3_9fx_vlb_device; extern const device_t s3_9fx_pci_device; +extern const device_t s3_phoenix_trio32_onboard_vlb_device; extern const device_t s3_phoenix_trio32_vlb_device; +extern const device_t s3_phoenix_trio32_onboard_pci_device; extern const device_t s3_phoenix_trio32_pci_device; extern const device_t s3_diamond_stealth_se_vlb_device; extern const device_t s3_diamond_stealth_se_pci_device; @@ -486,6 +491,7 @@ extern const device_t s3_spea_mirage_p64_vlb_device; extern const device_t s3_phoenix_trio64_vlb_device; extern const device_t s3_phoenix_trio64_onboard_pci_device; extern const device_t s3_phoenix_trio64_pci_device; +extern const device_t s3_stb_powergraph_64_video_vlb_device; extern const device_t s3_phoenix_trio64vplus_pci_device; extern const device_t s3_phoenix_trio64vplus_onboard_pci_device; extern const device_t s3_cardex_trio64vplus_pci_device; @@ -535,6 +541,7 @@ extern const device_t tgui9440_vlb_device; extern const device_t tgui9440_pci_device; extern const device_t tgui9440_onboard_pci_device; extern const device_t tgui9660_pci_device; +extern const device_t tgui9660_onboard_pci_device; extern const device_t tgui9680_pci_device; /* IBM PS/1 (S)VGA */ @@ -573,6 +580,10 @@ extern const device_t velocity_200_agp_device; /* Wyse 700 */ extern const device_t wy700_device; +/* Chips & Technologies */ +extern const device_t chips_69000_device; +extern const device_t chips_69000_onboard_device; + #endif #endif /*EMU_VIDEO_H*/ diff --git a/src/lpt.c b/src/lpt.c index 5bbf79875..419e5ad3d 100644 --- a/src/lpt.c +++ b/src/lpt.c @@ -11,7 +11,10 @@ #include <86box/pic.h> #include <86box/sound.h> #include <86box/prt_devs.h> -#include <86box/net_plip.h> +#include <86box/thread.h> +#include <86box/timer.h> +#include <86box/device.h> +#include <86box/network.h> lpt_port_t lpt_ports[PARALLEL_MAX]; @@ -165,6 +168,15 @@ lpt_read(uint16_t port, void *priv) return ret; } +uint8_t +lpt_read_port(int port, uint16_t reg) +{ + lpt_port_t *dev = &(lpt_ports[port]); + uint8_t ret = lpt_read(reg, dev); + + return ret; +} + uint8_t lpt_read_status(int port) { diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index 4bc53c9b4..dfeb1fa0f 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -2124,7 +2124,6 @@ kbd_write(uint16_t port, uint8_t val, void *priv) case 0x66: softresetx86(); - cpu_set_edx(); break; default: diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 79a82595f..a688181b4 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -304,6 +304,8 @@ machine_at_award286_init(const machine_t *model) if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); + device_add(&ide_isa_device); + return ret; } @@ -406,6 +408,8 @@ machine_at_spc4200p_init(const machine_t *model) if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); + device_add(&ide_isa_device); + return ret; } @@ -449,6 +453,8 @@ machine_at_spc4620p_init(const machine_t *model) if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); + device_add(&ide_isa_device); + return ret; } @@ -483,6 +489,8 @@ machine_at_deskmaster286_init(const machine_t *model) if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); + + device_add(&ide_isa_device); return ret; } @@ -546,7 +554,7 @@ machine_at_wd76c10_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); if (gfxcard[0] == VID_INTERNAL) device_add(¶dise_wd90c11_megapc_device); @@ -711,7 +719,7 @@ machine_at_sbc350a_init(const machine_t *model) device_add(&ali1217_device); device_add(&fdc37c665_ide_device); - device_add(&keyboard_at_device); + device_add(&keyboard_ps2_ami_device); return ret; } @@ -735,7 +743,27 @@ machine_at_flytech386_init(const machine_t *model) if (gfxcard[0] == VID_INTERNAL) device_add(&tvga8900d_device); - device_add(&keyboard_ps2_device); + device_add(&keyboard_at_ami_device); + + return ret; +} + +int +machine_at_325ax_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/325ax/M27C512.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&ali1217_device); + device_add(&fdc_at_device); + device_add(&keyboard_at_ami_device); return ret; } @@ -751,11 +779,11 @@ machine_at_mr1217_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_ide_init(model); + machine_at_common_init(model); device_add(&ali1217_device); device_add(&fdc_at_device); - device_add(&keyboard_ps2_device); + device_add(&keyboard_at_ami_device); return ret; } diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 2f92676c9..1dd63ce32 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -93,7 +93,7 @@ machine_at_asus386_init(const machine_t *model) static void machine_at_sis401_common_init(const machine_t *model) { - machine_at_common_ide_init(model); + machine_at_common_init(model); device_add(&sis_85c401_device); device_add(&keyboard_at_ami_device); @@ -144,7 +144,7 @@ machine_at_av4_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_ide_init(model); + machine_at_common_init(model); device_add(&sis_85c460_device); device_add(&keyboard_at_ami_device); @@ -224,6 +224,27 @@ machine_at_spc6000a_init(const machine_t *model) return ret; } +int +machine_at_ecs386v_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ecs386v/PANDA_386V.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&ali1429_device); + device_add(&keyboard_ps2_intel_ami_pci_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + int machine_at_rycleopardlx_init(const machine_t *model) { @@ -403,7 +424,7 @@ machine_at_acerv10_init(const machine_t *model) device_add(&sis_85c461_device); device_add(&keyboard_ps2_acer_pci_device); - device_add(&ide_isa_2ch_device); + device_add(&ide_isa_device); if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); @@ -440,7 +461,7 @@ machine_at_decpclpv_init(const machine_t *model) static void machine_at_ali1429_common_init(const machine_t *model, int is_green) { - machine_at_common_ide_init(model); + machine_at_common_init(model); if (is_green) device_add(&ali1429g_device); @@ -496,7 +517,7 @@ machine_at_opti495_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_ide_init(model); + machine_at_common_init(model); device_add(&opti495_device); @@ -511,7 +532,7 @@ machine_at_opti495_init(const machine_t *model) static void machine_at_opti495_ami_common_init(const machine_t *model) { - machine_at_common_ide_init(model); + machine_at_common_init(model); device_add(&opti495_device); @@ -553,6 +574,27 @@ machine_at_opti495_mr_init(const machine_t *model) return ret; } +int +machine_at_exp4349_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/exp4349/biosdump.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&ali1429g_device); + device_add(&keyboard_at_ami_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + return ret; +} + static void machine_at_403tg_common_init(const machine_t *model, int nvr_hack) { @@ -618,6 +660,39 @@ machine_at_403tg_d_mr_init(const machine_t *model) return ret; } +int +machine_at_pb450_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/pb450/OPTI802.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 5, 4, 3, 2); + pci_register_slot(0x12, PCI_CARD_NORMAL, 9, 8, 7, 6); + + device_add(&opti895_device); + device_add(&opti822_device); + device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&fdc37c661_ide_device); + device_add(&ide_opti611_vlb_sec_device); + device_add(&ide_vlb_2ch_device); + device_add(&intel_flash_bxt_device); + device_add(&phoenix_486_jumper_pci_device); + + if (gfxcard[0] == VID_INTERNAL) + device_add(&gd5428_vlb_onboard_device); + + return ret; +} + int machine_at_pc330_6573_init(const machine_t *model) /* doesn't like every CPU other than the iDX4 and the Intel OverDrive, hangs without a PS/2 mouse */ { @@ -699,7 +774,6 @@ machine_at_ami471_init(const machine_t *model) return ret; machine_at_sis_85c471_common_init(model); - device_add(&ide_vlb_device); device_add(&keyboard_at_ami_device); return ret; @@ -717,8 +791,7 @@ machine_at_vli486sv2g_init(const machine_t *model) return ret; machine_at_sis_85c471_common_init(model); - device_add(&ide_vlb_2ch_device); - device_add(&keyboard_ps2_ami_device); + device_add(&keyboard_at_ami_device); return ret; } @@ -735,7 +808,6 @@ machine_at_dtk486_init(const machine_t *model) return ret; machine_at_sis_85c471_common_init(model); - device_add(&ide_vlb_device); device_add(&keyboard_at_device); return ret; @@ -771,12 +843,44 @@ machine_at_win471_init(const machine_t *model) return ret; machine_at_sis_85c471_common_init(model); - device_add(&ide_vlb_device); device_add(&keyboard_at_ami_device); return ret; } +int +machine_at_pci400ca_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/pci400ca/486-AA008851.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SCSI, 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(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&keyboard_ps2_ami_device); + device_add(&sio_device); + device_add(&intel_flash_bxt_ami_device); + + device_add(&i420tx_device); + device_add(&ncr53c810_onboard_pci_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + int machine_at_vi15g_init(const machine_t *model) { @@ -789,7 +893,6 @@ machine_at_vi15g_init(const machine_t *model) return ret; machine_at_sis_85c471_common_init(model); - device_add(&ide_vlb_device); device_add(&keyboard_at_ami_device); return ret; @@ -818,6 +921,29 @@ machine_at_greenb_init(const machine_t *model) return ret; } +int +machine_at_4gpv5_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/4gpv5/4GPV5.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + device_add(&contaq_82c596a_device); + + device_add(&keyboard_at_device); + + return ret; +} + static void machine_at_sis_85c496_common_init(UNUSED(const machine_t *model)) { @@ -938,6 +1064,33 @@ machine_at_4dps_init(const machine_t *model) return ret; } +int +machine_at_ms4144_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ms4144/ms-4144-1.4.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + machine_at_sis_85c496_common_init(model); + device_add(&sis_85c496_ls486e_device); + pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + + device_add(&w83787f_device); + device_add(&keyboard_at_ami_device); + + device_add(&sst_flash_29ee010_device); + + return ret; +} + int machine_at_486sp3c_init(const machine_t *model) { @@ -1005,7 +1158,7 @@ machine_at_alfredo_init(const machine_t *model) return ret; machine_at_common_init(model); - device_add(&ide_pci_2ch_device); + device_add(&ide_pci_device); pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1037,7 +1190,7 @@ machine_at_ninja_init(const machine_t *model) machine_at_common_init(model); - pci_init(PCI_CONFIG_TYPE_1 | PCI_NO_IRQ_STEERING); + pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x05, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 1, 2); pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 2, 1); @@ -1051,6 +1204,86 @@ machine_at_ninja_init(const machine_t *model) return ret; } +int +machine_at_bat4ip3e_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/bat4ip3e/404C.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x05, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_IDE, 0xfe, 0xff, 0, 0); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 1, 2, 1); + pci_register_slot(0x0a, PCI_CARD_NORMAL, 1, 2, 1, 2); + + device_add(&phoenix_486_jumper_pci_device); + device_add(&keyboard_ps2_pci_device); + device_add(&i420ex_device); + device_add(&ide_cmd640_pci_device); + device_add(&fdc37c665_device); + + return ret; +} + +int +machine_at_486pi_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/486pi/486pi.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x05, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 1, 2); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 2, 1); + pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 1, 2); + + device_add(&keyboard_ps2_ami_pci_device); + device_add(&fdc37c665_device); + device_add(&i420ex_device); + + return ret; +} + +int +machine_at_sb486p_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/sb486p/amiboot.rom", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x05, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 1, 2); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 2, 1); + + device_add(&keyboard_ps2_ami_pci_device); + device_add(&i82091aa_device); + device_add(&i420ex_device); + + return ret; +} + int machine_at_486sp3_init(const machine_t *model) { @@ -1084,6 +1317,36 @@ machine_at_486sp3_init(const machine_t *model) return ret; } +int +machine_at_amis76_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_inverted("roms/machines/s76p/s76p.rom", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + // pci_register_slot(0x01, PCI_CARD_IDE, 1, 2, 3 ,4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sio_device); + device_add(&fdc37c665_device); + device_add(&intel_flash_bxt_ami_device); + + device_add(&i420tx_device); + // device_add(&ide_cmd640_pci_device); /* is this actually cmd640? is it single channel? */ + device_add(&ide_pci_device); + + return ret; +} + int machine_at_pci400cb_init(const machine_t *model) { @@ -1097,7 +1360,6 @@ machine_at_pci400cb_init(const machine_t *model) machine_at_common_init_ex(model, 2); device_add(&ami_1994_nvr_device); - device_add(&ide_isa_device); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1129,7 +1391,6 @@ machine_at_g486ip_init(const machine_t *model) machine_at_common_init_ex(model, 2); device_add(&ami_1992_nvr_device); - device_add(&ide_isa_device); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -1191,7 +1452,7 @@ machine_at_486ap4_init(const machine_t *model) machine_at_common_init(model); - pci_init(PCI_CONFIG_TYPE_1 | PCI_NO_IRQ_STEERING); + pci_init(PCI_CONFIG_TYPE_1); /* Excluded: 5, 6, 7, 8 */ pci_register_slot(0x05, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 09 = Slot 1 */ @@ -1402,6 +1663,29 @@ machine_at_tf486_init(const machine_t *model) device_add(&ali1489_device); device_add(&w83977ef_device); + device_add(&keyboard_at_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + +int +machine_at_arb1476_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/arb1476/w1476b.v21", + 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); + + device_add(&ali1489_device); + device_add(&fdc37c669_device); device_add(&keyboard_ps2_device); device_add(&sst_flash_29ee010_device); @@ -1491,6 +1775,30 @@ machine_at_arb1479_init(const machine_t *model) return ret; } +int +machine_at_iach488_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/iach488/FH48800B.980", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x0B, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&w83977f_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&stpc_consumer2_device); + device_add(&sst_flash_29ee020_device); + + return ret; +} + int machine_at_pcm9340_init(const machine_t *model) { @@ -1579,7 +1887,7 @@ machine_at_ecs486_init(const machine_t *model) } int -machine_at_hot433_init(const machine_t *model) +machine_at_hot433a_init(const machine_t *model) { int ret; @@ -1600,7 +1908,7 @@ machine_at_hot433_init(const machine_t *model) pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); device_add(&umc_hb4_device); - device_add(&umc_8886af_device); + device_add(&umc_8886bf_device); device_add(&um8669f_device); device_add(&winbond_flash_w29c010_device); device_add(&keyboard_at_ami_device); @@ -1629,7 +1937,7 @@ machine_at_atc1415_init(const machine_t *model) pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); device_add(&umc_hb4_device); - device_add(&umc_8886af_device); + device_add(&umc_8886bf_device); device_add(&intel_flash_bxt_device); device_add(&keyboard_at_ami_device); @@ -1653,19 +1961,53 @@ machine_at_actionpc2600_init(const machine_t *model) machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 3); pci_register_slot(0x12, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_VIDEO, 0, 0, 0, 0); pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); device_add(&umc_hb4_device); - device_add(&umc_8886af_device); - device_add(&um8669f_device); + device_add(&umc_8886bf_device); + device_add(&fdc37c665_device); device_add(&intel_flash_bxt_device); device_add(&keyboard_ps2_tg_ami_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&tgui9440_onboard_pci_device); + + return ret; +} + +int +machine_at_actiontower8400_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/actiontower8400/V31C.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x12, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x15, PCI_CARD_VIDEO, 0, 0, 0, 0); + pci_register_slot(0x16, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x14, PCI_CARD_NORMAL, 2, 3, 4, 1); + + device_add(&umc_hb4_device); + device_add(&umc_8886f_device); + device_add(&fdc37c665_device); + device_add(&ide_cmd640_pci_device); + device_add(&intel_flash_bxt_device); // The ActionPC 2600 has this so I'm gonna assume this does too. + device_add(&keyboard_ps2_ami_pci_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&gd5430_onboard_pci_device); + return ret; } @@ -1690,8 +2032,8 @@ machine_at_m919_init(const machine_t *model) pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); device_add(&umc_hb4_device); - device_add(&umc_8886af_device); - device_add(&um8669f_device); + device_add(&umc_8886af_device); /* AF is correct - the BIOS does IDE writes to ports 108h and 109h. */ + device_add(&um8663bf_device); device_add(&sst_flash_29ee010_device); device_add(&keyboard_at_ami_device); @@ -1820,3 +2162,92 @@ machine_at_tg486g_init(const machine_t *model) return ret; } + +int +machine_at_dvent4xx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/dvent4xx/Venturis466_BIOS.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&sis_85c471_device); + device_add(&ide_cmd640_vlb_pri_device); + device_add(&fdc37c665_ide_device); + device_add(&keyboard_ps2_device); + + if (gfxcard[0] == VID_INTERNAL) + device_add(&s3_phoenix_trio32_onboard_vlb_device); + + return ret; +} + +int +machine_at_ecsal486_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ecsal486/ECS_AL486.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&ali1429g_device); + device_add(&keyboard_ps2_ami_pci_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + +int +machine_at_ap4100aa_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ap4100aa/M27C512DIP28.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + device_add(&ami_1994_nvr_device); + device_add(&ali1429g_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&ide_vlb_device); + device_add(&um8663bf_device); + + return ret; +} + +int +machine_at_atc1762_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/atc1762/atc1762.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&ali1429g_device); + device_add(&keyboard_ps2_ami_pci_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + + return ret; +} \ No newline at end of file diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 86656b181..428199de7 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -795,11 +795,6 @@ machine_at_compaq_init(const machine_t *model, int type) break; case COMPAQ_PORTABLEIII: - if (gfxcard[0] == VID_INTERNAL) - device_add(&compaq_plasma_device); - machine_at_init(model); - break; - case COMPAQ_PORTABLEIII386: if (hdc_current == 1) device_add(&ide_isa_device); @@ -810,8 +805,6 @@ machine_at_compaq_init(const machine_t *model, int type) case COMPAQ_DESKPRO386: case COMPAQ_DESKPRO386_05_1988: - if (hdc_current == 1) - device_add(&ide_isa_device); device_add(&compaq_386_device); machine_at_common_init(model); device_add(&keyboard_at_compaq_device); diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index 83e9b74a9..d31d763d4 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -153,11 +153,11 @@ machine_at_spitfire_init(const machine_t *model) } int -machine_at_mate_nx_ma30d_23d_init(const machine_t *model) +machine_at_ma30d_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/mate_nx_ma30d_23d/BIOS.ROM", + ret = bios_load_linear("roms/machines/ma30d/BIOS.ROM", 0x000c0000, 262144, 0); if (bios_only || !ret) @@ -183,8 +183,7 @@ machine_at_mate_nx_ma30d_23d_init(const machine_t *model) device_add(&keyboard_ps2_ami_pci_device); device_add(&fdc37c67x_device); device_add(&intel_flash_bxt_device); - spd_register(SPD_TYPE_SDRAM, 0xF, 256); - device_add(&lm78_device); /* no reporting in BIOS */ + spd_register(SPD_TYPE_SDRAM, 0x7, 256); return ret; } @@ -261,11 +260,11 @@ machine_at_p2bls_init(const machine_t *model) } int -machine_at_lgibm440bx_init(const machine_t *model) +machine_at_lgibmx7g_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/lgibm440bx/ms6119.331", + ret = bios_load_linear("roms/machines/lgibmx7g/ms6119.331", 0x000c0000, 262144, 0); if (bios_only || !ret) @@ -808,3 +807,37 @@ machine_at_m729_init(const machine_t *model) return ret; } + +int +machine_at_p6f99_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/p6f99/99-8.BIN", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0C, PCI_CARD_SOUND, 2, 3, 4, 1); + pci_register_slot(0x02, PCI_CARD_AGPBRIDGE, 0, 0, 0, 0); + device_add(&sis_5600_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&it8661f_device); + device_add(&winbond_flash_w29c020_device); + + if (sound_card_current[0] == SOUND_INTERNAL) + device_add(&es1371_onboard_device); + + return ret; +} + diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index c6ec7c907..dd8a10eef 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -141,6 +141,9 @@ machine_at_p6bap_init(const machine_t *model) device_add(&sst_flash_39sf020_device); spd_register(SPD_TYPE_SDRAM, 0x7, 256); + if (sound_card_current[0] == SOUND_INTERNAL) + device_add(&cmi8738_onboard_device); + return ret; } @@ -351,6 +354,9 @@ machine_at_awo671r_init(const machine_t *model) device_add_inst(&w83977ef_device, 2); device_add(&keyboard_ps2_pci_device); device_add(&sst_flash_39sf020_device); + if (gfxcard[0] == VID_INTERNAL) { + device_add(&chips_69000_onboard_device); + } spd_register(SPD_TYPE_SDRAM, 0x3, 256); return ret; diff --git a/src/machine/m_at_socket4.c b/src/machine/m_at_socket4.c index a32617de4..02018949c 100644 --- a/src/machine/m_at_socket4.c +++ b/src/machine/m_at_socket4.c @@ -45,7 +45,7 @@ void machine_at_premiere_common_init(const machine_t *model, int pci_switch) { machine_at_common_init(model); - device_add(&ide_pci_2ch_device); + device_add(&ide_pci_device); pci_init(PCI_CONFIG_TYPE_2 | pci_switch); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -60,31 +60,6 @@ machine_at_premiere_common_init(const machine_t *model, int pci_switch) device_add(&intel_flash_bxt_ami_device); } -void -machine_at_award_common_init(const machine_t *model) -{ - machine_at_common_init(model); - device_add(&ide_pci_2ch_device); - - pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x01, PCI_CARD_IDE, 0, 0, 0, 0); - pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 03 = Slot 1 */ - pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 04 = Slot 2 */ - pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 05 = Slot 3 */ - pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); /* 06 = Slot 4 */ - pci_register_slot(0x07, PCI_CARD_SCSI, 1, 2, 3, 4); /* 07 = SCSI */ - pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - - if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); - -#if 0 - device_add(&keyboard_ps2_pci_device); -#endif - device_add(&keyboard_ps2_ami_pci_device); -} - void machine_at_sp4_common_init(const machine_t *model) { @@ -181,7 +156,7 @@ machine_at_dellxp60_init(const machine_t *model) return ret; machine_at_common_init(model); - device_add(&ide_pci_2ch_device); + device_add(&ide_pci_device); pci_init(PCI_CONFIG_TYPE_2); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -304,12 +279,34 @@ machine_at_revenge_init(const machine_t *model) return ret; } +void +machine_at_award_common_init(const machine_t *model) +{ + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 03 = Slot 1 */ + pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 04 = Slot 2 */ + pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 05 = Slot 3 */ + pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); /* 06 = Slot 4 */ + pci_register_slot(0x07, PCI_CARD_SCSI, 1, 2, 3, 4); /* 07 = SCSI */ + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sio_zb_device); + device_add(&intel_flash_bxt_device); +} + int -machine_at_586mc1_init(const machine_t *model) +machine_at_586is_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/586mc1/IS.34", + ret = bios_load_linear("roms/machines/586is/IS.34", 0x000e0000, 131072, 0); if (bios_only || !ret) @@ -317,8 +314,6 @@ machine_at_586mc1_init(const machine_t *model) machine_at_award_common_init(model); - device_add(&sio_device); - device_add(&intel_flash_bxt_device); device_add(&i430lx_device); return ret; diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index 0b67976af..916f8490b 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -98,11 +98,11 @@ machine_at_ambradp90_init(const machine_t *model) } int -machine_at_430nx_init(const machine_t *model) +machine_at_586ip_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/430nx/IP.20", + ret = bios_load_linear("roms/machines/586ip/IP.20", 0x000e0000, 131072, 0); if (bios_only || !ret) @@ -110,13 +110,41 @@ machine_at_430nx_init(const machine_t *model) machine_at_award_common_init(model); - device_add(&sio_device); - device_add(&intel_flash_bxt_device); device_add(&i430nx_device); return ret; } +int +machine_at_tek932_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/tek932/B932_019.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_2 | PCI_CAN_SWITCH_TYPE); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); + device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&i430nx_device); + device_add(&sio_zb_device); + device_add(&fdc37c665_ide_device); + device_add(&ide_vlb_device); + device_add(&intel_flash_bxt_ami_device); + + return ret; +} + int machine_at_acerv30_init(const machine_t *model) { @@ -297,6 +325,35 @@ machine_at_hawk_init(const machine_t *model) return ret; } +int +machine_at_pt2000_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ficpt2000/PT2000_v1.01.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(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&i430fx_device); + device_add(&piix_device); + device_add(&pc87332_398_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + int machine_at_pat54pv_init(const machine_t *model) { @@ -349,6 +406,36 @@ machine_at_hot543_init(const machine_t *model) return ret; } +int +machine_at_ncselp90_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ncselp90/elegancep90.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); + + device_add(&opti5x7_pci_device); + device_add(&opti822_device); + device_add(&sst_flash_29ee010_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&ide_opti611_vlb_device); + device_add(&fdc37c665_ide_sec_device); + device_add(&ide_vlb_2ch_device); + + return ret; +} + int machine_at_p54sp4_init(const machine_t *model) { @@ -424,3 +511,99 @@ machine_at_p54sps_init(const machine_t *model) return ret; } + +int +machine_at_ms5109_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ms5109/A778.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + device_add(&ami_1994_nvr_device); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 3, 2, 4); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 3, 2, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); + device_add(&sis_550x_85c503_device); + device_add(&ide_w83769f_pci_device); + device_add(&keyboard_ps2_ami_device); + device_add(&w83787f_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + +int +machine_at_torino_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_inverted("roms/machines/torino/PER113.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + device_add(&ami_1994_nvr_device); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_VIDEO, 0, 0, 0, 0); + pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + device_add(&sis_550x_85c503_device); + device_add(&ide_um8673f_device); + device_add(&keyboard_ps2_tg_ami_device); + device_add(&fdc37c665_device); + device_add(&intel_flash_bxt_ami_device); + + return ret; +} + +int +machine_at_hot539_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/hot539/539_R17.ROM", + 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(0x12, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x15, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x16, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 4, 1, 2, 3); + device_add(&umc_8890_device); + device_add(&umc_8886af_device); + device_add(&sst_flash_29ee010_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&um8663af_device); + + return ret; +} diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index a3e777dbd..09441ad4f 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -43,6 +43,8 @@ #include <86box/fdc.h> #include <86box/nvr.h> #include <86box/scsi_ncr53c8xx.h> +#include <86box/thread.h> +#include <86box/network.h> int machine_at_acerv35n_init(const machine_t *model) @@ -433,6 +435,35 @@ machine_at_p65up5_cp55t2d_init(const machine_t *model) return ret; } +int +machine_at_epc2102_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/epc2102/P5000HX.ROM", + 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(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&i430hx_device); + device_add(&piix3_device); + device_add(&keyboard_ps2_pci_device); + device_add(&i82091aa_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + int machine_at_p55tvp4_init(const machine_t *model) { @@ -532,7 +563,7 @@ machine_at_presario2240_init(const machine_t *model) machine_at_common_init_ex(model, 2); - pci_init(PCI_CONFIG_TYPE_1); + pci_init(PCI_CONFIG_TYPE_1 | FLAG_NO_BRIDGES); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); pci_register_slot(0x14, PCI_CARD_VIDEO, 3, 0, 0, 0); @@ -563,7 +594,7 @@ machine_at_presario4500_init(const machine_t *model) machine_at_common_init_ex(model, 2); - pci_init(PCI_CONFIG_TYPE_1); + pci_init(PCI_CONFIG_TYPE_1 | FLAG_NO_BRIDGES); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); pci_register_slot(0x14, PCI_CARD_VIDEO, 3, 0, 0, 0); @@ -1014,6 +1045,80 @@ machine_at_p5mms98_init(const machine_t *model) return ret; } +int +machine_at_richmond_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/richmond/RICHMOND.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); /* PIIX4 */ + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); + device_add(&i430tx_device); + device_add(&piix4_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&it8671f_device); + device_add(&intel_flash_bxt_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 128); + device_add(&lm78_device); /* fans: Thermal, CPU, Chassis; temperature: unused */ + device_add(&lm75_1_4a_device); /* temperature: CPU */ + + return ret; +} + +int +machine_at_tomahawk_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/tomahawk/0AAGT046.ROM", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); /* PIIX4 */ + pci_register_slot(0x0D, PCI_CARD_VIDEO, 3, 0, 0, 0); + pci_register_slot(0x0E, PCI_CARD_NETWORK, 4, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x07, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x08, PCI_CARD_NORMAL, 3, 4, 1, 2); + device_add(&i430tx_device); + device_add(&piix4_device); + device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&fdc37c67x_device); + device_add(&amd_flash_29f020a_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 128); + device_add(&lm78_device); /* fans: Thermal, CPU, Chassis; temperature: unused */ + device_add(&lm75_1_4a_device); /* temperature: CPU */ + + if ((gfxcard[0] == VID_INTERNAL) && machine_get_vid_device(machine)) + device_add(machine_get_vid_device(machine)); + + if ((sound_card_current[0] == SOUND_INTERNAL) && machine_get_snd_device(machine)) + device_add(machine_get_snd_device(machine)); + + if ((net_cards_conf[0].device_num == NET_INTERNAL) && machine_get_net_device(machine)) + device_add(machine_get_net_device(machine)); + + return ret; +} + int machine_at_ficva502_init(const machine_t *model) { @@ -1135,11 +1240,11 @@ machine_at_ms5146_init(const machine_t *model) } int -machine_at_cb52x_si_init(const machine_t *model) +machine_at_cb52xsi_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/cb52x_si/CD5205S.ROM", + ret = bios_load_linear("roms/machines/cb52xsi/CD5205S.ROM", 0x000e0000, 131072, 0); if (bios_only || !ret) @@ -1163,6 +1268,119 @@ machine_at_cb52x_si_init(const machine_t *model) return ret; } +int +machine_at_sp97xv_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/sp97xv/0109XVJ2.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x13, PCI_CARD_VIDEO, 1, 2, 3, 4); /* On-chip SiS graphics, absent here. */ + device_add(&sis_5581_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83877f_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + +int +machine_at_sq578_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/sq578/578b03.rom", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); + device_add(&sis_5581_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83877tf_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + +int +machine_at_5sg100_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/5sg100/5sg.20g", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x02, PCI_CARD_AGPBRIDGE, 0, 0, 0, 0); + device_add(&sis_5591_1997_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83877tf_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + +int +machine_at_ms5172_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ms5172/A572MS15.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x02, PCI_CARD_AGPBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); + device_add(&sis_5591_1997_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83877tf_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + int machine_at_m560_init(const machine_t *model) { @@ -1242,7 +1460,7 @@ machine_at_thunderbolt_init(const machine_t *model) pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 1, 2, 3); /* PIIX4 */ + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 1, 2, 3); /* PIIX4 */ pci_register_slot(0x11, PCI_CARD_NORMAL, 0, 1, 2, 3); pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 0); pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 0, 1); diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 0e420aa3b..676f50fb1 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -547,7 +547,7 @@ machine_at_acerm3a_init(const machine_t *model) device_add(&i430hx_device); device_add(&piix3_device); device_add(&keyboard_ps2_pci_device); - device_add(&fdc37c932fr_device); + device_add(&fdc37c935_device); device_add(&sst_flash_29ee010_device); @@ -672,15 +672,15 @@ machine_at_p5vxb_init(const machine_t *model) } int -machine_at_dell_430vx_init(const machine_t *model) +machine_at_dellhannibalp_init(const machine_t *model) { int ret; - ret = bios_load_linear_combined2("roms/machines/dell_430vx/1003DY0J.BIO", - "roms/machines/dell_430vx/1003DY0J.BI1", - "roms/machines/dell_430vx/1003DY0J.BI2", - "roms/machines/dell_430vx/1003DY0J.BI3", - "roms/machines/dell_430vx/1003DY0J.RCV", + ret = bios_load_linear_combined2("roms/machines/dellhannibalp/1003DY0J.BIO", + "roms/machines/dellhannibalp/1003DY0J.BI1", + "roms/machines/dellhannibalp/1003DY0J.BI2", + "roms/machines/dellhannibalp/1003DY0J.BI3", + "roms/machines/dellhannibalp/1003DY0J.RCV", 0x3a000, 128); if (bios_only || !ret) @@ -797,6 +797,35 @@ machine_at_ms5124_init(const machine_t *model) return ret; } +int +machine_at_amis727_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/amis727/S727p.rom", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0xFE, 0xFF, 0, 0); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); + + device_add(&sis_5511_device); + device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&fdc37c665_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + int machine_at_vectra54_init(const machine_t *model) { @@ -829,3 +858,31 @@ machine_at_vectra54_init(const machine_t *model) return ret; } + +int +machine_at_5sbm2_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/5sbm2/5SBM0717.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); + + device_add(&keyboard_at_ami_device); + device_add(&sis_550x_device); + device_add(&um8663af_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index 6e63af732..e1dad68e7 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -39,6 +39,39 @@ #include "cpu.h" #include <86box/machine.h> +int +machine_at_ap61_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ap61/ap61r120.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x19, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x14, PCI_CARD_NORTHBRIDGE_SEC, 0, 0, 0, 0); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_IDE, 0xFE, 0xFF, 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); + pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); + device_add(&i450kx_device); + device_add(&sio_zb_device); + device_add(&ide_cmd646_device); + device_add(&keyboard_ps2_acer_pci_device); + device_add(&fdc37c665_device); + device_add(&sst_flash_29ee010_device); + // device_add(&intel_flash_bxt_device); + + return ret; +} + int machine_at_p6rp4_init(const machine_t *model) { @@ -162,11 +195,11 @@ machine_at_acerv60n_init(const machine_t *model) } int -machine_at_lgibm440fx_init(const machine_t *model) +machine_at_lgibmx61_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/lgibm440fx/bios.rom", + ret = bios_load_linear("roms/machines/lgibmx61/bios.rom", 0x000e0000, 131072, 0); if (bios_only || !ret) @@ -183,8 +216,10 @@ machine_at_lgibm440fx_init(const machine_t *model) pci_register_slot(0x0F, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&i440fx_device); device_add(&piix3_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&w83787f_device); + // device_add(&keyboard_ps2_ami_pci_device); + device_add(&keyboard_ps2_ami_device); + // device_add(&w83787f_device); + device_add(&w83877f_president_device); device_add(&sst_flash_29ee010_device); return ret; diff --git a/src/machine/m_at_sockets7.c b/src/machine/m_at_sockets7.c index 382a4f327..8ff1a367d 100644 --- a/src/machine/m_at_sockets7.c +++ b/src/machine/m_at_sockets7.c @@ -106,6 +106,38 @@ machine_at_m579_init(const machine_t *model) return ret; } +int +machine_at_gwlucas_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/gwlucas/gw2kboot.rom", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_SOUTHBRIDGE_IDE, 1, 2, 3, 4); + pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE_PMU, 1, 2, 3, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE_USB, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_SOUND, 1, 2, 3, 4); // ES1373 + pci_register_slot(0x14, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); + device_add(&ali1541_device); + device_add(&ali1543c_device); /* +0 */ + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 512); + + return ret; +} + int machine_at_5aa_init(const machine_t *model) { diff --git a/src/machine/m_elt.c b/src/machine/m_elt.c index 95ca52a3e..a69b62184 100644 --- a/src/machine/m_elt.c +++ b/src/machine/m_elt.c @@ -50,6 +50,7 @@ #include <86box/rom.h> #include <86box/video.h> #include <86box/vid_cga.h> +#include <86box/hdc.h> #include <86box/plat_fallthrough.h> #include <86box/plat_unused.h> diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 20a7da6ae..9a0b39a89 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -646,7 +646,7 @@ machine_xt_glabios_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/glabios/GLABIOS_0.2.5_8E.ROM", + ret = bios_load_linear("roms/machines/glabios/GLABIOS_0.2.6_8X_012324.ROM", 0x000fe000, 8192, 0); if (bios_only || !ret) @@ -655,4 +655,4 @@ machine_xt_glabios_init(const machine_t *model) machine_xt_init_ex(model); return ret; -} \ No newline at end of file +} diff --git a/src/machine/machine.c b/src/machine/machine.c index 1684f312a..9e530eb3b 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -169,6 +169,7 @@ void machine_common_init(UNUSED(const machine_t *model)) { uint8_t cpu_requires_fast_pit = is486 || (!is286 && is8086 && (cpu_s->rspeed >= 8000000)); + cpu_requires_fast_pit = cpu_requires_fast_pit && !cpu_16bitbus; /* System devices first. */ pic_init(); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 0959a061f..44f9236b6 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -33,6 +33,9 @@ #include <86box/sound.h> #include <86box/video.h> #include <86box/plat_unused.h> +#include <86box/thread.h> +#include <86box/timer.h> +#include <86box/network.h> // Temporarily here till we move everything out into the right files extern const device_t pcjr_device; @@ -137,8 +140,12 @@ const machine_filter_t machine_chipsets[] = { { "SiS 471", MACHINE_CHIPSET_SIS_471 }, { "SiS 496", MACHINE_CHIPSET_SIS_496 }, { "SiS 501", MACHINE_CHIPSET_SIS_501 }, + { "SiS 5501", MACHINE_CHIPSET_SIS_5501 }, { "SiS 5511", MACHINE_CHIPSET_SIS_5511 }, { "SiS 5571", MACHINE_CHIPSET_SIS_5571 }, + { "SiS 5581", MACHINE_CHIPSET_SIS_5581 }, + { "SiS 5591", MACHINE_CHIPSET_SIS_5591 }, + { "SiS (5)600", MACHINE_CHIPSET_SIS_5600 }, { "SMSC VictoryBX-66", MACHINE_CHIPSET_SMSC_VICTORYBX_66 }, { "STPC Client", MACHINE_CHIPSET_STPC_CLIENT }, { "STPC Consumer-II", MACHINE_CHIPSET_STPC_CONSUMER_II }, @@ -709,6 +716,45 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + { + .name = "[8088] GLaBIOS", + .internal_name = "glabios", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_glabios_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 64, + .max = 640, + .step = 64 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xt_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, { .name = "[8088] Hyosung Topstar 88T", .internal_name = "top88", @@ -1804,45 +1850,6 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - { - .name = "[8088] GLaBIOS", - .internal_name = "glabios", - .type = MACHINE_TYPE_8088, - .chipset = MACHINE_CHIPSET_DISCRETE, - .init = machine_xt_glabios_init, - .p1_handler = NULL, - .gpio_handler = NULL, - .available_flag = MACHINE_AVAILABLE, - .gpio_acpi_handler = NULL, - .cpu = { - .package = CPU_PKG_8088, - .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, - .min_voltage = 0, - .max_voltage = 0, - .min_multi = 0, - .max_multi = 0 - }, - .bus_flags = MACHINE_PC, - .flags = MACHINE_FLAGS_NONE, - .ram = { - .min = 64, - .max = 640, - .step = 64 - }, - .nvrmask = 0, - .kbc_device = &keyboard_xt_device, - .kbc_p1 = 0xff, - .gpio = 0xffffffff, - .gpio_acpi = 0xffffffff, - .device = NULL, - .fdc_device = NULL, - .sio_device = NULL, - .vid_device = NULL, - .snd_device = NULL, - .net_device = NULL - }, { .name = "[GC100A] Philips P3120", .internal_name = "p3120", @@ -2579,7 +2586,7 @@ const machine_t machines[] = { .flags = MACHINE_XTA | MACHINE_VIDEO_FIXED, .ram = { .min = 512, - .max = 16384, + .max = 15360, .step = 512 }, .nvrmask = 63, @@ -2729,8 +2736,8 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_286, .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, + .min_bus = 6000000, + .max_bus = 12500000, .min_voltage = 0, .max_voltage = 0, .min_multi = 0, @@ -2740,8 +2747,8 @@ const machine_t machines[] = { .flags = MACHINE_FLAGS_NONE, .ram = { .min = 640, - .max = 16384, - .step = 128 + .max = 14912, + .step = 64 }, .nvrmask = 127, .kbc_device = NULL, @@ -2769,8 +2776,8 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_286, .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, + .min_bus = 6000000, + .max_bus = 16000000, .min_voltage = 0, .max_voltage = 0, .min_multi = 0, @@ -2809,15 +2816,15 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_286, .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, + .min_bus = 6000000, + .max_bus = 16000000, .min_voltage = 0, .max_voltage = 0, .min_multi = 0, .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_VIDEO, + .flags = MACHINE_IDE | MACHINE_VIDEO, .ram = { .min = 640, .max = 16384, @@ -3093,8 +3100,8 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_286, .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, + .min_bus = 6000000, + .max_bus = 12500000, .min_voltage = 0, .max_voltage = 0, .min_multi = 0, @@ -3341,7 +3348,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_VIDEO, + .flags = MACHINE_IDE | MACHINE_VIDEO, .ram = { .min = 512, .max = 16384, @@ -3361,7 +3368,7 @@ const machine_t machines[] = { }, /* Has IBM AT KBC firmware. */ { - .name = "[NEAT] Phoenix 286 clone", + .name = "[NEAT] Arche AMA-2010", .internal_name = "px286", .type = MACHINE_TYPE_286, .chipset = MACHINE_CHIPSET_NEAT, @@ -3501,10 +3508,10 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_FLAGS_NONE, + .flags = MACHINE_IDE, .ram = { .min = 512, - .max = 16384, + .max = 8192, .step = 128 }, .nvrmask = 127, @@ -3544,7 +3551,7 @@ const machine_t machines[] = { .flags = MACHINE_FLAGS_NONE, .ram = { .min = 512, - .max = 16384, + .max = 8192, .step = 128 }, .nvrmask = 127, @@ -3581,7 +3588,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2, - .flags = MACHINE_FLAGS_NONE, + .flags = MACHINE_IDE, /* Has internal video: C&T VGA 411 */ .ram = { .min = 512, .max = 2048, @@ -3661,7 +3668,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2, - .flags = MACHINE_VIDEO, + .flags = MACHINE_IDE | MACHINE_VIDEO, .ram = { .min = 1024, .max = 5120, @@ -3700,11 +3707,11 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_AT, - .flags = MACHINE_FLAGS_NONE, + .bus_flags = MACHINE_PS2, + .flags = MACHINE_IDE, /* Has internal video: C&T VGA 411 */ .ram = { .min = 512, - .max = 16384, + .max = 8192, .step = 128 }, .nvrmask = 127, @@ -3964,7 +3971,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has the AMIKey KBC firmware, which is an updated 'F' type. */ + /* Has the AMIKey-2 KBC. */ { .name = "[ALi M1217] AAEON SBC-350A", .internal_name = "sbc350a", @@ -4004,11 +4011,9 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has an AMI KBC firmware, the only photo of this is too low resolution - for me to read what's on the KBC chip, so I'm going to assume AMI 'F' - based on the other known HT18 AMI BIOS strings. */ + /* Has a VIA VT82C42N KBC. */ { - .name = "[ALi M1217] Flytech 386", + .name = "[ALi M1217] Flytech A36", .internal_name = "flytech386", .type = MACHINE_TYPE_386SX, .chipset = MACHINE_CHIPSET_ALI_M1217, @@ -4027,7 +4032,7 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_PS2, + .bus_flags = MACHINE_AT, .flags = MACHINE_IDE | MACHINE_VIDEO, .ram = { .min = 1024, @@ -4046,10 +4051,49 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* I'm going to assume this has a standard/generic IBM-compatible AT KBC - firmware until the board is identified. */ + /* Has a JetKey KBC without version, shows up as a 'H'. */ { - .name = "[ALi M1217] MR BIOS 386SX clone", + .name = "[ALi M1217] Chaintech 325AX", + .internal_name = "325ax", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_ALI_M1217, + .init = machine_at_325ax_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_AT, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 1024, + .max = 16384, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Has a JetKey KBC without version, shows up as a 'H'. */ + { + .name = "[ALi M1217] Chaintech 325AX (MR BIOS)", .internal_name = "mr1217", .type = MACHINE_TYPE_386SX, .chipset = MACHINE_CHIPSET_ALI_M1217, @@ -4069,7 +4113,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_IDE, + .flags = MACHINE_FLAGS_NONE, .ram = { .min = 1024, .max = 16384, @@ -4539,7 +4583,7 @@ const machine_t machines[] = { /* Has an unknown AMI KBC firmware, I'm going to assume 'F' until a photo or real hardware BIOS string is found. */ { - .name = "[SCAT] KMX-C-02", + .name = "[SCAT] Kaimei KMX-C-02", .internal_name = "kmxc02", .type = MACHINE_TYPE_386SX, .chipset = MACHINE_CHIPSET_SCAT, @@ -4591,8 +4635,8 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_386SX, .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, + .min_bus = 16000000, + .max_bus = 25000000, .min_voltage = 0, .max_voltage = 0, .min_multi = 0, @@ -4744,8 +4788,9 @@ const machine_t machines[] = { }, /* 386DX machines */ + /* Has a Jetkey V3, which identifies as a 'B'. */ { - .name = "[ACC 2168] AMI 386DX clone", + .name = "[ACC 2168] Juko AT046DX3", .internal_name = "acc386", .type = MACHINE_TYPE_386DX, .chipset = MACHINE_CHIPSET_ACC_2168, @@ -4875,17 +4920,17 @@ const machine_t machines[] = { .available_flag = MACHINE_AVAILABLE, .gpio_acpi_handler = NULL, .cpu = { - .package = CPU_PKG_386DX, - .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, + .package = CPU_PKG_386DX_DESKPRO386, + .block = CPU_BLOCK(CPU_486DLC, CPU_RAPIDCAD), + .min_bus = 16000000, + .max_bus = 25000000, .min_voltage = 0, .max_voltage = 0, .min_multi = 0, .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_IDE, + .flags = MACHINE_FLAGS_NONE, .ram = { .min = 1024, .max = 16384, @@ -4914,17 +4959,17 @@ const machine_t machines[] = { .available_flag = MACHINE_AVAILABLE, .gpio_acpi_handler = NULL, .cpu = { - .package = CPU_PKG_386DX, - .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, + .package = CPU_PKG_386DX_DESKPRO386, + .block = CPU_BLOCK(CPU_486DLC, CPU_RAPIDCAD), + .min_bus = 16000000, + .max_bus = 25000000, .min_voltage = 0, .max_voltage = 0, .min_multi = 0, .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_IDE, + .flags = MACHINE_FLAGS_NONE, .ram = { .min = 1024, .max = 16384, @@ -4955,8 +5000,8 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_386DX, .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, + .min_bus = 20000000, + .max_bus = 20000000, .min_voltage = 0, .max_voltage = 0, .min_multi = 0, @@ -5021,6 +5066,86 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has a Lance LT38C41 with AMI Megakey P KBC firmware */ + { + .name = "[ALi M1429] ECS Panda 386V", + .internal_name = "ecs386v", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_ALI_M1429, + .init = machine_at_ecs386v_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386DX, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0, + }, + .bus_flags = MACHINE_VLB, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 1024, + .max = 32768, + .step = 1024, + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* The board has a "ASII KB-100" which I was not able to find any information about, + but the BIOS sends commands C9 without a parameter and D5, both of which are + Phoenix MultiKey commands. */ + { + .name = "[OPTi 495] U-Board OPTi 495SLC", + .internal_name = "award495", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_OPTI_495, + .init = machine_at_opti495_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386DX, /* Actual machine only supports 386DXes */ + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_AT, + .flags = MACHINE_APM, + .ram = { + .min = 1024, + .max = 32768, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has AMIKey F KBC firmware. */ { .name = "[SiS 310] ASUS ISA-386C", @@ -5105,47 +5230,6 @@ const machine_t machines[] = { }, /* 386DX/486 machines */ - /* The BIOS sends commands C9 without a parameter and D5, both of which are - Phoenix MultiKey commands. */ - { - .name = "[OPTi 495] Award 486 clone", - .internal_name = "award495", - .type = MACHINE_TYPE_386DX_486, - .chipset = MACHINE_CHIPSET_OPTI_495, - .init = machine_at_opti495_init, - .p1_handler = NULL, - .gpio_handler = NULL, - .available_flag = MACHINE_AVAILABLE, - .gpio_acpi_handler = NULL, - .cpu = { - .package = CPU_PKG_386DX | CPU_PKG_SOCKET1, - .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, - .min_voltage = 0, - .max_voltage = 0, - .min_multi = 0, - .max_multi = 0 - }, - .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE | MACHINE_APM, - .ram = { - .min = 1024, - .max = 32768, - .step = 1024 - }, - .nvrmask = 127, - .kbc_device = NULL, - .kbc_p1 = 0xff, - .gpio = 0xffffffff, - .gpio_acpi = 0xffffffff, - .device = NULL, - .fdc_device = NULL, - .sio_device = NULL, - .vid_device = NULL, - .snd_device = NULL, - .net_device = NULL - }, /* Has AMIKey F KBC firmware. */ { .name = "[OPTi 495] DataExpert SX495", @@ -5168,7 +5252,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 32768, @@ -5208,7 +5292,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 32768, @@ -5226,6 +5310,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Winbond W83C42 with unknown firmware. */ + { + .name = "[ALi M1429G] DataExpert EXP4349", + .internal_name = "exp4349", + .type = MACHINE_TYPE_386DX_486, + .chipset = MACHINE_CHIPSET_ALI_M1429G, + .init = machine_at_exp4349_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386DX | CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_VLB, + .flags = MACHINE_APM, + .ram = { + .min = 1024, + .max = 49152, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM PS/2 Type 1 KBC firmware. */ { .name = "[MCA] IBM PS/2 model 70 (type 3)", @@ -5334,7 +5458,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 32768, @@ -5417,7 +5541,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 1024, .max = 65536, @@ -5457,7 +5581,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 65536, @@ -5497,7 +5621,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 65536, @@ -5538,7 +5662,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 65536, @@ -5556,7 +5680,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has a MR (!) KBC firmware, which is a clone of the standard IBM PS/2 KBC firmware. */ + /* Uses an NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware. */ + { + .name = "[SiS 461] Acer V10", + .internal_name = "acerv10", + .type = MACHINE_TYPE_486, + .chipset = MACHINE_CHIPSET_SIS_461, + .init = machine_at_acerv10_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET1, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PS2_VLB, + .flags = MACHINE_IDE | MACHINE_APM, /* Machine has internal SCSI: Adaptec AIC-6360 */ + .ram = { + .min = 1024, + .max = 32768, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Has MR (!) KBC firmware, which is a clone of the standard IBM PS/2 KBC firmware. */ { .name = "[SiS 471] SiS VL-BUS 471 REV. A1", .internal_name = "px471", @@ -5639,9 +5803,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* According to Deksor on the Win3x.org forum, the BIOS string ends in a -0, - indicating an unknown KBC firmware. But it does send the AMIKey get version - command, so it must expect an AMIKey. */ + /* Has a VLSI VL82C113A SCAMP Combination I/O which holds the KBC. */ { .name = "[VLSI 82C480] HP Vectra 486VL", .internal_name = "vect486vl", @@ -5676,7 +5838,7 @@ const machine_t machines[] = { .gpio_acpi = 0xffffffff, .device = NULL, .fdc_device = NULL, - .sio_device = NULL, + .sio_device = NULL, /*Has SIO (sorta): VLSI VL82C113A SCAMP Combination I/O*/ .vid_device = &gd5428_onboard_device, .snd_device = NULL, .net_device = NULL @@ -5786,7 +5948,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2, - .flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM | MACHINE_GAMEPORT, .ram = { .min = 4096, .max = 36864, @@ -5826,7 +5988,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2, - .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM, .ram = { .min = 4096, .max = 36864, @@ -5866,7 +6028,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 32768, @@ -5884,6 +6046,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* This has a standalone AMI Megakey 1993, which is type 'P'. */ + { + .name = "[IMS 8848] Tekram G486IP", + .internal_name = "g486ip", + .type = MACHINE_TYPE_486_S2, + .chipset = MACHINE_CHIPSET_IMS_8848, + .init = machine_at_g486ip_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_APM, + .ram = { + .min = 2048, + .max = 131072, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Uses an Intel KBC with Phoenix MultiKey KBC firmware. */ { .name = "[SiS 461] DEC DECpc LPV", @@ -5906,7 +6108,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2, - .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM, .ram = { .min = 1024, .max = 32768, @@ -5924,46 +6126,6 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Uses an NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware. */ - { - .name = "[SiS 461] Acer V10", - .internal_name = "acerv10", - .type = MACHINE_TYPE_486_S2, - .chipset = MACHINE_CHIPSET_SIS_461, - .init = machine_at_acerv10_init, - .p1_handler = NULL, - .gpio_handler = NULL, - .available_flag = MACHINE_AVAILABLE, - .gpio_acpi_handler = NULL, - .cpu = { - .package = CPU_PKG_SOCKET3, - .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, - .min_voltage = 0, - .max_voltage = 0, - .min_multi = 0, - .max_multi = 0 - }, - .bus_flags = MACHINE_PS2, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, - .ram = { - .min = 1024, - .max = 32768, - .step = 1024 - }, - .nvrmask = 127, - .kbc_device = NULL, - .kbc_p1 = 0xff, - .gpio = 0xffffffff, - .gpio_acpi = 0xffffffff, - .device = NULL, - .fdc_device = NULL, - .sio_device = NULL, - .vid_device = NULL, - .snd_device = NULL, - .net_device = NULL - }, /* The BIOS does not send any non-standard keyboard controller commands and wants a PS/2 mouse, so it's an IBM PS/2 KBC (Type 1) firmware. */ { @@ -6005,15 +6167,57 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* The BIOS string ends in -U, unless command 0xA1 (AMIKey get version) returns an - 'F', in which case, it ends in -F, so it has an AMIKey F KBC firmware. - The photo of the board shows an AMIKey KBC which is indeed F. */ + /* Has AMI MegaKey KBC. */ { - .name = "[SiS 471] ABit AB-AH4", - .internal_name = "win471", + .name = "[i420TX] J-Bond PCI400C-A", + .internal_name = "pci400ca", .type = MACHINE_TYPE_486_S2, - .chipset = MACHINE_CHIPSET_SIS_471, - .init = machine_at_win471_init, + .chipset = MACHINE_CHIPSET_INTEL_420TX, + .init = machine_at_pci400ca_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_SCSI, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = &keyboard_ps2_ami_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + + + /* 486 machines - Socket 3 */ + /* 486 machines with just the ISA slot */ + /* Has a Fujitsu MBL8042H KBC. */ + { + .name = "[Contaq 82C596A] A-Trend 4GPV5", + .internal_name = "4gpv5", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_CONTAQ_82C596, + .init = machine_at_4gpv5_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -6029,7 +6233,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 65536, @@ -6047,12 +6251,9 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - - /* 486 machines - Socket 3 */ - /* 486 machines with just the ISA slot */ /* Has AMI MegaKey KBC firmware. */ { - .name = "[Contaq 82C597] Green-B", + .name = "[Contaq 82C597] Visionex Green-B", .internal_name = "greenb", .type = MACHINE_TYPE_486_S3, .chipset = MACHINE_CHIPSET_CONTAQ_82C597, @@ -6090,7 +6291,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has a VIA VT82C42N KBC. */ + /* Version 1.0 has an AMIKEY-2, version 2.0 has a VIA VT82C42N KBC. */ { .name = "[OPTi 895] Jetway J-403TG", .internal_name = "403tg", @@ -6210,7 +6411,89 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has AMIKey H keyboard BIOS. */ + /* has a Phoenix PLCC Multikey copyrighted 1993, version unknown. */ + { + .name = "[OPTi 895] Packard Bell PB450", + .internal_name = "pb450", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_OPTI_895_802G, + .init = machine_at_pb450_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_SUPER_IO | MACHINE_IDE_DUAL | MACHINE_VIDEO, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = &gd5428_vlb_onboard_device, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* The BIOS string ends in -U, unless command 0xA1 (AMIKey get version) returns an + 'F', in which case, it ends in -F, so it has an AMIKey F KBC firmware. + The photo of the board shows an AMIKey KBC which is indeed F. */ + { + .name = "[SiS 471] ABIT AB-AH4", + .internal_name = "win471", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_SIS_471, + .init = machine_at_win471_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_VLB, + .flags = MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Has AMIKey-2 'H' keyboard BIOS. */ { .name = "[SiS 471] AOpen Vi15G", .internal_name = "vi15g", @@ -6232,7 +6515,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 65536, @@ -6272,7 +6555,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2_VLB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 65536, @@ -6312,7 +6595,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 65536, @@ -6330,9 +6613,9 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Unknown Epox VLB Socket 3 board, has AMIKey F keyboard BIOS. */ + /* Has a Lance LT38C41L with AMIKey F keyboard BIOS. */ { - .name = "[SiS 471] Epox 486SX/DX Green", + .name = "[SiS 471] Epox GXA486SG", .internal_name = "ami471", .type = MACHINE_TYPE_486_S3, .chipset = MACHINE_CHIPSET_SIS_471, @@ -6352,7 +6635,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 65536, @@ -6392,7 +6675,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2_VLB, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_APM, /* Has internal video: Western Digital WD90C33-ZZ */ .ram = { .min = 1024, .max = 65536, @@ -6410,9 +6693,170 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Unknown revision phoenix 1993 multikey */ + { + .name = "[SiS 471] DEC Venturis 4xx", + .internal_name = "dvent4xx", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_SIS_471, + .init = machine_at_dvent4xx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PS2, + .flags = MACHINE_IDE_DUAL | MACHINE_SUPER_IO | MACHINE_APM | MACHINE_VIDEO, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = &s3_phoenix_trio32_onboard_vlb_device, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ + { + .name = "[ALi M1429G] ECS AL486", + .internal_name = "ecsal486", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_ALI_M1429G, + .init = machine_at_ecsal486_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_VLB, + .flags = MACHINE_APM, + .ram = { + .min = 1024, + .max = 98304, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* This uses a VIA VT82C42N KBC, which is a clone of type 'F' with additional commands */ + { + .name = "[ALi M1429G] Lanner Electronics AP-4100AA", + .internal_name = "ap4100aa", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_ALI_M1429G, + .init = machine_at_ap4100aa_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_AT, + .flags = MACHINE_SUPER_IO | MACHINE_IDE | MACHINE_APM, + .ram = { + .min = 1024, + .max = 32768, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* JETKey V5.0 */ + { + .name = "[ALi M1429G] A-Trend ATC-1762", + .internal_name = "atc1762", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_ALI_M1429G, + .init = machine_at_atc1762_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_VLB, + .flags = MACHINE_APM, + .ram = { + .min = 1024, + .max = 40960, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 486 machines which utilize the PCI bus */ /* Machine with ALi M1429G chipset and M1435 southbridge */ + /* Has an AMIKEY-2 KBC. */ { .name = "[ALi M1429G] MSI MS-4134", .internal_name = "ms4134", @@ -6433,8 +6877,8 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_PS2_PCIV, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .bus_flags = MACHINE_PCIV, + .flags = MACHINE_APM, .ram = { .min = 1024, .max = 131072, @@ -6474,7 +6918,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2_PCIV, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 1024, .max = 131072, @@ -6525,10 +6969,10 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &tgui9440_onboard_pci_device, .fdc_device = NULL, .sio_device = NULL, - .vid_device = &tgui9440_onboard_pci_device, + .vid_device = NULL, .snd_device = NULL, .net_device = NULL }, @@ -6554,7 +6998,7 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_PCI, + .bus_flags = MACHINE_PCI, /* Machine has a PISA slot */ .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 1024, @@ -6701,6 +7145,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has an ALi M5042 with phoenix firmware like the ESA TF-486. */ + { + .name = "[ALi M1489] Acrosser AR-B1476", + .internal_name = "arb1476", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_ALI_M1489, + .init = machine_at_arb1476_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PS2, + .flags = MACHINE_SUPER_IO | MACHINE_IDE | MACHINE_APM, /* Has onboard video: C&T F65545 */ + .ram = { + .min = 1024, + .max = 32768, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has IBM PS/2 Type 1 KBC firmware. */ { .name = "[OPTi 802G] IBM PC 330 (type 6573)", @@ -6763,7 +7247,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2_PCIV, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 1024, .max = 131072, @@ -6802,8 +7286,128 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_IDE | MACHINE_APM, + .ram = { + .min = 1024, + .max = 131072, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Has Phoenix Multikey/42 PS/2 KBC, but unknown version */ + { + .name = "[i420EX] Anigma BAT4IP3e", + .internal_name = "bat4ip3e", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_INTEL_420EX, + .init = machine_at_bat4ip3e_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_SUPER_IO | MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 131072, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ + { + .name = "[i420EX] Advanced Integration Research 486PI", + .internal_name = "486pi", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_INTEL_420EX, + .init = machine_at_486pi_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PCIV, + .flags = MACHINE_SUPER_IO | MACHINE_IDE | MACHINE_APM, + .ram = { + .min = 1024, + .max = 131072, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* absolutely no KBC info */ + { + .name = "[i420EX] ICS SB486P", + .internal_name = "sb486p", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_INTEL_420EX, + .init = machine_at_sb486p_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_SUPER_IO | MACHINE_IDE | MACHINE_APM, .ram = { .min = 1024, .max = 131072, @@ -6843,7 +7447,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_SCSI | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_SCSI | MACHINE_APM, .ram = { .min = 1024, .max = 131072, @@ -6883,7 +7487,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -6901,6 +7505,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* According to another string seen on the UH19 website, this has AMI 'H' KBC. */ + { + .name = "[i420TX] AMI Super Voyager PCI", + .internal_name = "amis76", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_INTEL_420TX, + .init = machine_at_amis76_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_SUPER_IO | MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 1024, + .max = 131072, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has an AMIKey-2, which is an updated version of type 'H'. Also has a SST 29EE010 Flash chip. */ { @@ -6924,7 +7568,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_SCSI | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_SCSI | MACHINE_APM, .ram = { .min = 1024, .max = 131072, @@ -6963,48 +7607,8 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, - .ram = { - .min = 2048, - .max = 131072, - .step = 2048 - }, - .nvrmask = 127, - .kbc_device = NULL, - .kbc_p1 = 0xff, - .gpio = 0xffffffff, - .gpio_acpi = 0xffffffff, - .device = NULL, - .fdc_device = NULL, - .sio_device = NULL, - .vid_device = NULL, - .snd_device = NULL, - .net_device = NULL - }, - /* This has a standalone AMI Megakey 1993, which is type 'P'. */ - { - .name = "[IMS 8848] Tekram G486IP", - .internal_name = "g486ip", - .type = MACHINE_TYPE_486_S3, - .chipset = MACHINE_CHIPSET_IMS_8848, - .init = machine_at_g486ip_init, - .p1_handler = NULL, - .gpio_handler = NULL, - .available_flag = MACHINE_AVAILABLE, - .gpio_acpi_handler = NULL, - .cpu = { - .package = CPU_PKG_SOCKET3, - .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, - .min_voltage = 0, - .max_voltage = 0, - .min_multi = 0, - .max_multi = 0 - }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .bus_flags = MACHINE_PCIV, + .flags = MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -7102,7 +7706,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* The BIOS does not send a single non-standard KBC command, so it has a standard PS/2 KBC. */ + /* Has a VIA VT82C42N KBC. */ { .name = "[SiS 496] Micronics M4Li", .internal_name = "m4li", @@ -7142,7 +7746,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has a BestKey KBC which clones AMI type 'H'. */ + /* Revision 1 has a Lance LT38C41L, revision 2 has a Holtek HT6542B. Another variant with a Bestkey KBC might exist as well. */ { .name = "[SiS 496] Rise Computer R418", .internal_name = "r418", @@ -7182,7 +7786,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* This has a Holtek KBC and the BIOS does not send a single non-standard KBC command, so it + /* This has a Holtek HT6542B KBC and the BIOS does not send a single non-standard KBC command, so it must be an ASIC that clones the standard IBM PS/2 KBC. */ { .name = "[SiS 496] Soyo 4SAW2", @@ -7224,7 +7828,7 @@ const machine_t machines[] = { .net_device = NULL }, /* According to MrKsoft, his real 4DPS has an AMIKey-2, which is an updated version - of type 'H'. */ + of type 'H'. There are other variants of the board with Holtek HT6542B KBCs. */ { .name = "[SiS 496] Zida Tomato 4DP", .internal_name = "4dps", @@ -7246,7 +7850,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT, .ram = { .min = 2048, .max = 261120, @@ -7264,6 +7868,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* AMIKEY-2 */ + { + .name = "[SiS 496] MSI MS-4144", + .internal_name = "ms4144", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_SIS_496, + .init = machine_at_ms4144_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_SUPER_IO | MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 5120, /* Hack: machine seems to break with less than 5 MBs of RAM */ + .max = 131072, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has the UMC 88xx on-chip KBC. */ { .name = "[UMC 8881] A-Trend ATC-1415", @@ -7306,7 +7950,7 @@ const machine_t machines[] = { }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ { - .name = "[UMC 8881] ECS Elite UM8810PAIO", + .name = "[UMC 8881] ECS Elite UM8810P-AIO", .internal_name = "ecs486", .type = MACHINE_TYPE_486_S3, .chipset = MACHINE_CHIPSET_UMC_UM8881, @@ -7346,7 +7990,7 @@ const machine_t machines[] = { }, /* Has AMIKey Z(!) KBC firmware. */ { - .name = "[UMC 8881] Epson Action PC 2600", + .name = "[UMC 8881] Epson ActionPC 2600", .internal_name = "actionpc2600", .type = MACHINE_TYPE_486_S3, .chipset = MACHINE_CHIPSET_UMC_UM8881, @@ -7366,7 +8010,48 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_VIDEO, + .ram = { + .min = 1024, + .max = 262144, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* This has the UMC 88xx on-chip KBC. All the copies of the BIOS string I can find, end in + in -H, so the UMC on-chip KBC likely emulates the AMI 'H' KBC firmware. */ + { + .name = "[UMC 8881] Epson ActionTower 8400", + .internal_name = "actiontower8400", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_UMC_UM8881, + .init = machine_at_actiontower8400_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_SUPER_IO | MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_VIDEO, .ram = { .min = 1024, .max = 262144, @@ -7468,10 +8153,10 @@ const machine_t machines[] = { /* This has a Holtek KBC. */ { .name = "[UMC 8881] Shuttle HOT-433A", - .internal_name = "hot433", + .internal_name = "hot433a", .type = MACHINE_TYPE_486_S3, .chipset = MACHINE_CHIPSET_UMC_UM8881, - .init = machine_at_hot433_init, + .init = machine_at_hot433a_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -7526,7 +8211,7 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_PCIV, + .bus_flags = MACHINE_PS2_PCIV, .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 1024, @@ -7567,7 +8252,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2_PCIV, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT, .ram = { .min = 1024, .max = 131072, @@ -7652,7 +8337,7 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, /* Machine has internal video: ST STPC Atlas */ .ram = { .min = 32768, .max = 163840, @@ -7693,7 +8378,7 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, /* Machine has internal video: ST STPC Atlas */ .ram = { .min = 32768, .max = 163840, @@ -7711,6 +8396,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ + { + .name = "[STPC Consumer-II] Lanner Electronics IAC-H488", + .internal_name = "iach488", + .type = MACHINE_TYPE_486_MISC, + .chipset = MACHINE_CHIPSET_STPC_CONSUMER_II, + .init = machine_at_iach488_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_STPC, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 66666667, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 2.0, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2, + .flags = MACHINE_IDE | MACHINE_APM, /* Machine has internal video: ST STPC Atlas and NIC: Realtek RTL8139C+ */ + .ram = { + .min = 32768, + .max = 131072, + .step = 32768 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ { @@ -7822,7 +8548,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE | MACHINE_APM, /* Machine has internal SCSI */ .ram = { .min = 2048, .max = 131072, @@ -7861,8 +8587,8 @@ const machine_t machines[] = { .min_multi = MACHINE_MULTIPLIER_FIXED, .max_multi = MACHINE_MULTIPLIER_FIXED }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_APM, .ram = { .min = 2048, .max = 196608, @@ -7901,8 +8627,8 @@ const machine_t machines[] = { .min_multi = MACHINE_MULTIPLIER_FIXED, .max_multi = MACHINE_MULTIPLIER_FIXED }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -7942,7 +8668,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -7984,7 +8710,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -8024,7 +8750,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_VIDEO_8514A | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_VIDEO_8514A | MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -8064,7 +8790,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -8082,13 +8808,13 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has AMI MegaKey KBC firmware. */ + /* Has AMI MegaKey 'H' KBC firmware. */ { - .name = "[i430LX] Micro Star 586MC1", - .internal_name = "586mc1", + .name = "[i430LX] Gigabyte GA-586IS", + .internal_name = "586is", .type = MACHINE_TYPE_SOCKET4, .chipset = MACHINE_CHIPSET_INTEL_430LX, - .init = machine_at_586mc1_init, + .init = machine_at_586is_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -8103,8 +8829,8 @@ const machine_t machines[] = { .min_multi = MACHINE_MULTIPLIER_FIXED, .max_multi = MACHINE_MULTIPLIER_FIXED }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -8144,7 +8870,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM, .ram = { .min = 8192, .max = 139264, @@ -8188,7 +8914,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PS2_VLB, - .flags = MACHINE_IDE | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 2048, .max = 65536, @@ -8230,7 +8956,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PCIV, - .flags = MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8272,7 +8998,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8312,7 +9038,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8330,7 +9056,6 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Socket 5 machines */ /* 430NX */ /* This has the Phoenix MultiKey KBC firmware. */ @@ -8355,7 +9080,7 @@ const machine_t machines[] = { .max_multi = 1.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -8395,7 +9120,7 @@ const machine_t machines[] = { .max_multi = 1.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -8436,7 +9161,7 @@ const machine_t machines[] = { .max_multi = 1.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 2048, .max = 131072, @@ -8454,13 +9179,13 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has AMI MegaKey KBC firmware. */ + /* Has AMI 'H' KBC firmware. */ { .name = "[i430NX] Gigabyte GA-586IP", - .internal_name = "430nx", + .internal_name = "586ip", .type = MACHINE_TYPE_SOCKET5, .chipset = MACHINE_CHIPSET_INTEL_430NX, - .init = machine_at_430nx_init, + .init = machine_at_586ip_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -8476,7 +9201,47 @@ const machine_t machines[] = { .max_multi = 1.5 }, .bus_flags = MACHINE_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_APM, + .ram = { + .min = 2048, + .max = 262144, + .step = 2048 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Has AMI MegaKey KBC firmware. */ + { + .name = "[i430NX] Teknor TEK-932", + .internal_name = "tek932", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_INTEL_430NX, + .init = machine_at_tek932_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 3520, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 1.5 + }, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 2048, .max = 262144, @@ -8518,7 +9283,7 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8558,7 +9323,7 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8600,7 +9365,7 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8640,7 +9405,7 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8680,7 +9445,47 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* KBC On-Chip the VT82C406MV. */ + { + .name = "[i430FX] FIC PT-2000", + .internal_name = "pt2000", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_INTEL_430FX, + .init = machine_at_pt2000_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8724,7 +9529,7 @@ const machine_t machines[] = { .max_multi = 1.5 }, .bus_flags = MACHINE_VLB, - .flags = MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_APM, .ram = { .min = 2048, .max = 65536, @@ -8765,7 +9570,46 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PCIV, - .flags = MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_APM, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[OPTi 597] Northgate Computer Systems Elegance Pentium 90", + .internal_name = "ncselp90", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_OPTI_547_597, + .init = machine_at_ncselp90_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3520, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCIV, + .flags = MACHINE_APM | MACHINE_IDE_DUAL | MACHINE_SUPER_IO, .ram = { .min = 8192, .max = 131072, @@ -8807,7 +9651,7 @@ const machine_t machines[] = { .max_multi = 1.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8847,7 +9691,7 @@ const machine_t machines[] = { .max_multi = 1.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8887,7 +9731,7 @@ const machine_t machines[] = { .max_multi = 1.5 }, .bus_flags = MACHINE_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8905,12 +9749,135 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ + { + .name = "[SiS 5501] MSI MS-5109", + .internal_name = "ms5109", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_SIS_5501, + .init = machine_at_ms5109_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + CPU_BLOCK(CPU_PENTIUMMMX), + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3520, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 1.5 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Has AMIKey Z(!) KBC firmware. */ + { + .name = "[SiS 5501] TriGem Torino", + .internal_name = "torino", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_SIS_5501, + .init = machine_at_torino_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + CPU_BLOCK(CPU_PENTIUMMMX), + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3520, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 1.5 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &tgui9660_onboard_pci_device, + .snd_device = NULL, + .net_device = NULL + }, + + /* UMC 889x */ + /* This has an AMIKey-2, which is an updated version of type 'H'. */ + { + .name = "[UMC 889x] Shuttle HOT-539", + .internal_name = "hot539", + .type = MACHINE_TYPE_SOCKET5, + .chipset = MACHINE_CHIPSET_UMC_UM8890BF, + .init = machine_at_hot539_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK(CPU_K5, CPU_5K86), + .min_bus = 40000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3600, + .min_multi = 1.5, + .max_multi = 2.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 8192, + .max = 262144, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Socket 7 (Single Voltage) machines */ /* 430FX */ - /* This has an AMIKey-2, which is an updated version of type 'H'. */ + /* This has an AMIKey-2, which is an updated version of type 'H'. + This also seems to be revision 2.1 with the FDC37C665 SIO. */ { - .name = "[i430FX] ASUS P/I-P54TP4XE", + .name = "[i430FX] ASUS P/I-P55TP4XE", .internal_name = "p54tp4xe", .type = MACHINE_TYPE_SOCKET7_3V, .chipset = MACHINE_CHIPSET_INTEL_430FX, @@ -8930,7 +9897,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8950,7 +9917,7 @@ const machine_t machines[] = { }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ { - .name = "[i430FX] ASUS P/I-P54TP4XE (MR BIOS)", + .name = "[i430FX] ASUS P/I-P55TP4XE (MR BIOS)", .internal_name = "p54tp4xe_mr", .type = MACHINE_TYPE_SOCKET7_3V, .chipset = MACHINE_CHIPSET_INTEL_430FX, @@ -8970,7 +9937,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -8988,7 +9955,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has AMIKey H KBC firmware. */ + /* Has AMIKey H KBC firmware. The KBC itself seems to differ between an AMIKEY-2 and a Winbond W83C42. */ { .name = "[i430FX] DataExpert EXP8551", .internal_name = "exp8551", @@ -9010,7 +9977,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_GAMEPORT | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -9052,7 +10019,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT, .ram = { .min = 8192, .max = 131072, @@ -9093,7 +10060,7 @@ const machine_t machines[] = { .max_multi = 2.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -9135,7 +10102,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM | MACHINE_GAMEPORT, .ram = { .min = 8192, .max = 131072, @@ -9177,7 +10144,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT, .ram = { .min = 8192, .max = 131072, @@ -9219,7 +10186,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_SOUND | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -9259,7 +10226,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -9300,7 +10267,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -9340,7 +10307,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -9358,7 +10325,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has an AMI 'H' KBC firmware (1992). */ + /* Has an AMI MegaKey 'H' KBC firmware (1992). */ { .name = "[i430FX] QDI FMB", .internal_name = "fmb", @@ -9380,7 +10347,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT, .ram = { .min = 8192, .max = 131072, @@ -9400,9 +10367,7 @@ const machine_t machines[] = { }, /* 430HX */ - /* I can't determine what KBC firmware this has, but given that the Acer V35N and - V60 have Phoenix MultiKey KBC firmware on the chip, I'm going to assume so - does the M3A. */ + /* Has a Phoenix Multikey KBC in the SM(S)C SIO. */ { .name = "[i430HX] Acer M3A", .internal_name = "acerm3a", @@ -9424,7 +10389,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, /* Machine has internal SCSI */ .ram = { .min = 8192, .max = 196608, @@ -9442,7 +10407,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has AMIKey F KBC firmware. */ + /* Has AMIKey-2 or VIA VT82C42N KBC (depending on the revision) with AMIKEY 'F' KBC firmware. */ { .name = "[i430HX] AOpen AP53", .internal_name = "ap53", @@ -9464,7 +10429,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 524288, @@ -9504,7 +10469,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -9522,8 +10487,8 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* [TEST] Unable to determine what KBC this has. A list on a Danish site shows - the BIOS as having a -0 string, indicating non-AMI KBC firmware. */ + /* [TEST] The board doesn't seem to have a KBC at all, which probably means it's an on-chip one on the PC87306 SIO. + A list on a Danish site shows the BIOS as having a -0 string, indicating non-AMI KBC firmware. */ { .name = "[i430HX] Supermicro P55T2S", .internal_name = "p55t2s", @@ -9545,7 +10510,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -9570,10 +10535,10 @@ const machine_t machines[] = { Command 0xA0 copyright string: (C)1994 AMI . */ { .name = "[i430VX] Dell Hannibal+", - .internal_name = "dell_430vx", + .internal_name = "dellhannibalp", .type = MACHINE_TYPE_SOCKET7_3V, .chipset = MACHINE_CHIPSET_INTEL_430VX, - .init = machine_at_dell_430vx_init, + .init = machine_at_dellhannibalp_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -9589,7 +10554,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -9629,7 +10594,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -9671,7 +10636,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -9690,6 +10655,48 @@ const machine_t machines[] = { .net_device = NULL }, + /* SiS 5501 */ + /* Has the Lance LT38C41 KBC. */ + { + .name = "[SiS 5501] Chaintech 5SBM2 (M103)", + .internal_name = "5sbm2", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_SIS_5501, + .init = machine_at_5sbm2_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 8192, + .max = 262144, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* SiS 5511 */ /* Has AMIKey H KBC firmware (AMIKey-2). */ { @@ -9713,7 +10720,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 524288, @@ -9753,7 +10760,47 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Has Megakey 'R' KBC */ + { + .name = "[SiS 5511] AMI Atlas PCI-II", + .internal_name = "amis727", + .type = MACHINE_TYPE_SOCKET7_3V, + .chipset = MACHINE_CHIPSET_SIS_5511, + .init = machine_at_amis727_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 3380, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 524288, @@ -9796,7 +10843,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 196608, @@ -9836,7 +10883,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 262144, @@ -9876,7 +10923,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -9918,7 +10965,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_VIDEO | MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_VIDEO | MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, /* Has internal sound: Yamaha YMF701-S */ .ram = { .min = 8192, .max = 131072, @@ -9958,7 +11005,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_VIDEO | MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_VIDEO | MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, /* Has internal sound: Yamaha YMF701-S */ .ram = { .min = 8192, .max = 131072, @@ -9998,7 +11045,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 196608, @@ -10038,7 +11085,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 196608, @@ -10081,7 +11128,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 196608, @@ -10099,7 +11146,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* The base board has AMIKey-2 (updated 'H') KBC firmware. */ + /* The base board has a Holtek HT6542B with the AMIKey-2 (updated 'H') KBC firmware. */ { .name = "[i430HX] ASUS P/I-P65UP5 (C-P55T2D)", .internal_name = "p65up5_cp55t2d", @@ -10120,8 +11167,8 @@ const machine_t machines[] = { .min_multi = 1.5, .max_multi = 3.0 }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_PS2_PCI, /* Machine has AMB */ + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -10139,9 +11186,49 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Unknown PS/2 KBC. */ + { + .name = "[i430HX] Radisys EPC-2102", + .internal_name = "epc2102", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430HX, + .init = machine_at_epc2102_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 83333333, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 8192, + .max = 262144, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 430VX */ - /* This has the VIA VT82C42N KBC. */ + /* This has the VIA VT82C42N or Holtek HT6542B KBC. */ { .name = "[i430VX] AOpen AP5VM", .internal_name = "ap5vm", @@ -10163,7 +11250,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_SCSI | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_SCSI | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -10181,7 +11268,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has AMIKey H KBC firmware (AMIKey-2). */ + /* Has AMIKey H KBC firmware (AMIKey-2) on a BestKey KBC. */ { .name = "[i430VX] ASUS P/I-P55TVP4", .internal_name = "p55tvp4", @@ -10202,8 +11289,8 @@ const machine_t machines[] = { .min_multi = 1.5, .max_multi = 3.0 }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_PS2_PCI, /* Machine has AMB */ + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -10244,7 +11331,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -10262,7 +11349,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* [TEST] Has AMIKey 'F' KBC firmware. */ + /* [TEST] Has AMIKey 'F' KBC firmware on a VIA VT82C42N KBC. */ { .name = "[i430VX] Biostar MB-8500TVX-A", .internal_name = "8500tvxa", @@ -10284,7 +11371,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -10405,7 +11492,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -10445,9 +11532,9 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { - .min = 8192, + .min = 16384, .max = 131072, .step = 8192 }, @@ -10487,7 +11574,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_VIDEO | MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_VIDEO | MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -10527,7 +11614,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM, .ram = { .min = 8192, .max = 131072, @@ -10568,7 +11655,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -10609,7 +11696,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_GAMEPORT | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_GAMEPORT | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -10651,7 +11738,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, /* Has internal video: C&T B69000 */ .ram = { .min = 8192, .max = 262144, @@ -10691,7 +11778,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 262144, @@ -10709,6 +11796,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* [TEST] Has AMI Megakey '5' KBC firmware on the SM(S)C FDC37C67x Super I/O chip. */ + { + .name = "[i430TX] Gateway Tomahawk", + .internal_name = "tomahawk", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430TX, + .init = machine_at_tomahawk_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2100, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_VIDEO | MACHINE_SOUND | MACHINE_NIC | MACHINE_USB, + .ram = { + .min = 8192, + .max = 262144, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &s3_trio64v2_dx_onboard_pci_device, + .snd_device = &cs4236b_device, + .net_device = &pcnet_am79c973_onboard_device + }, #if defined(DEV_BRANCH) && defined(USE_AN430TX) /* This has the Phoenix MultiKey KBC firmware. */ { @@ -10773,7 +11900,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 262144, @@ -10813,7 +11940,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, /* Machine has internal sound: Yamaha YMF701-S */ .ram = { .min = 8192, .max = 262144, @@ -10831,7 +11958,8 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* The BIOS sends KBC command BB and expects it to output a byte, which is AMI KBC behavior. */ + /* The BIOS sends KBC command BB and expects it to output a byte, which is AMI KBC behavior. + A picture shows a VIA VT82C42N KBC though, so it could be a case of that KBC with AMI firmware. */ { .name = "[i430TX] PC Partner MB540N", .internal_name = "mb540n", @@ -10853,7 +11981,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 262144, @@ -10893,7 +12021,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 262144, @@ -10933,7 +12061,47 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, + .ram = { + .min = 8192, + .max = 262144, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* [TEST] Has AMIKey 'H' KBC firmware. */ + { + .name = "[i430TX] TriGem Richmond", + .internal_name = "richmond", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430TX, + .init = machine_at_richmond_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2100, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 262144, @@ -10976,7 +12144,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -11019,7 +12187,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -11042,10 +12210,10 @@ const machine_t machines[] = { /* Has the SiS 5571 chipset with on-chip KBC. */ { .name = "[SiS 5571] Daewoo CB52X-SI", - .internal_name = "cb52x_si", + .internal_name = "cb52xsi", .type = MACHINE_TYPE_SOCKET7, .chipset = MACHINE_CHIPSET_SIS_5571, - .init = machine_at_cb52x_si_init, + .init = machine_at_cb52xsi_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -11061,7 +12229,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 262144, @@ -11101,7 +12269,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 262144, @@ -11141,7 +12309,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 393216, @@ -11160,6 +12328,171 @@ const machine_t machines[] = { .net_device = NULL }, + /* SiS 5581 */ + /* Has the SiS 5581 chipset with on-chip KBC. */ + { + .name = "[SiS 5581] ASUS SP97-XV", + .internal_name = "sp97xv", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_SIS_5581, + .init = machine_at_sp97xv_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 75000000, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 8192, + .max = 1572864, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Has the SiS 5581 chipset with on-chip KBC. */ + { + .name = "[SiS 5581] BCM SQ-578", + .internal_name = "sq578", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_SIS_5581, + .init = machine_at_sq578_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 75000000, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 8192, + .max = 1572864, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + + + /* SiS 5591 */ + /* Has the SiS 5591 chipset with on-chip KBC. */ + { + .name = "[SiS 5591] Gigabyte GA-5SG100", + .internal_name = "5sg100", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_SIS_5591, + .init = machine_at_5sg100_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 75000000, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 8192, + .max = 786432, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Has the SiS 5591 chipset with on-chip KBC. */ + { + .name = "[SiS 5591] MSI MS-5172", + .internal_name = "ms5172", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_SIS_5591, + .init = machine_at_ms5172_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 75000000, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 8192, + .max = 786432, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* ALi ALADDiN IV+ */ /* Has the ALi M1543 southbridge with on-chip KBC. */ { @@ -11183,7 +12516,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -11223,7 +12556,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -11266,9 +12599,9 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, .ram = { - .min = 1024, + .min = 8192, .max = 1572864, .step = 8192 }, @@ -11307,7 +12640,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 1024, .max = 1572864, @@ -11325,6 +12658,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* M1534c kbc */ + { + .name = "[ALi ALADDiN V] Gateway Lucas", + .internal_name = "gwlucas", + .type = MACHINE_TYPE_SOCKETS7, + .chipset = MACHINE_CHIPSET_ALI_ALADDIN_V, + .init = machine_at_gwlucas_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 100000000, + .min_voltage = 2000, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 5.5 + }, + .bus_flags = MACHINE_PS2_PCIONLY, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, /* Has internal video: ATI 3D Rage Pro Turbo AGP and sound: Ensoniq ES1373*/ + .ram = { + .min = 8192, + .max = 262144, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has the ALi M1543C southbridge with on-chip KBC. */ { .name = "[ALi ALADDiN V] Gigabyte GA-5AA", @@ -11347,7 +12720,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 1024, .max = 1572864, @@ -11387,7 +12760,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 1024, .max = 1572864, @@ -11430,7 +12803,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -11471,7 +12844,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -11512,7 +12885,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_A97, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -11553,7 +12926,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -11575,6 +12948,46 @@ const machine_t machines[] = { /* Socket 8 machines */ /* 450KX */ /* This has an AMIKey-2, which is an updated version of type 'H'. */ + { + .name = "[i450KX] AOpen AP61", + .internal_name = "ap61", + .type = MACHINE_TYPE_SOCKET8, + .chipset = MACHINE_CHIPSET_INTEL_450KX, + .init = machine_at_ap61_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET8, + .block = CPU_BLOCK_NONE, + .min_bus = 60000000, + .max_bus = 66666667, + .min_voltage = 2100, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ { .name = "[i450KX] ASUS P/I-P6RP4", .internal_name = "p6rp4", @@ -11595,8 +13008,8 @@ const machine_t machines[] = { .min_multi = 1.5, .max_multi = 8.0 }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_PS2_PCI, /* Machine has AMB */ + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 524288, @@ -11638,7 +13051,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -11656,7 +13069,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* The base board has AMIKey-2 (updated 'H') KBC firmware. */ + /* The base board has a Holtek HT6542B with AMIKey-2 (updated 'H') KBC firmware. */ { .name = "[i440FX] ASUS P/I-P65UP5 (C-P6ND)", .internal_name = "p65up5_cp6nd", @@ -11677,8 +13090,8 @@ const machine_t machines[] = { .min_multi = 1.5, .max_multi = 8.0 }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_PS2_PCI, /* Machine has AMB */ + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -11696,8 +13109,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* The MB-8600TTX has an AMIKey 'F' KBC firmware, so I'm going to assume so does - the MB-8600TTC until someone can actually identify it. */ + /* Has a VIA VT82C42N with likely AMIKey 'F' KBC firmware. */ { .name = "[i440FX] Biostar MB-8600TTC", .internal_name = "8600ttc", @@ -11719,7 +13131,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -11759,7 +13171,7 @@ const machine_t machines[] = { .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -11799,7 +13211,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -11841,7 +13253,7 @@ const machine_t machines[] = { .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, /* Machine has internal video: S3 ViRGE/DX and sound: Crystal CS4236B */ .ram = { .min = 8192, .max = 131072, @@ -11883,7 +13295,7 @@ const machine_t machines[] = { .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -11904,10 +13316,10 @@ const machine_t machines[] = { /* Has the AMIKey-2 (updated 'H') KBC firmware. */ { .name = "[i440FX] LG IBM Multinet x61 (MSI MS-6106)", - .internal_name = "lgibm440fx", + .internal_name = "lgibmx61", .type = MACHINE_TYPE_SOCKET8, .chipset = MACHINE_CHIPSET_INTEL_440FX, - .init = machine_at_lgibm440fx_init, + .init = machine_at_lgibmx61_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -11923,7 +13335,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, /* Machine has internal SCSI: Adaptec AIC-78xx */ .ram = { .min = 40960, .max = 524288, @@ -11963,7 +13375,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -11981,9 +13393,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* I found a BIOS string of it that ends in -S, but it could be a typo for -5 - (there's quite a few AMI BIOS strings around with typo'd KBC codes), so I'm - going to give it an AMI MegaKey. */ + /* Has a VIA VT82C42N KBC with likely AMI MegaKey firmware. */ { .name = "[i440FX] PC Partner MB600N", .internal_name = "mb600n", @@ -12005,7 +13415,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -12048,7 +13458,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, /* Machine has internal sound: C-Media CMI8330 */ .ram = { .min = 1024, .max = 1572864, @@ -12068,7 +13478,7 @@ const machine_t machines[] = { }, /* 440FX */ - /* The base board has AMIKey-2 (updated 'H') KBC firmware. */ + /* The base board has a Holtek HT6542B KBC with AMIKey-2 (updated 'H') KBC firmware. */ { .name = "[i440FX] ASUS P/I-P65UP5 (C-PKND)", .internal_name = "p65up5_cpknd", @@ -12090,7 +13500,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -12131,7 +13541,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -12174,7 +13584,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -12215,7 +13625,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -12237,10 +13647,10 @@ const machine_t machines[] = { AMIKey-2 KBC firmware. */ { .name = "[i440LX] NEC Mate NX MA30D/23D", - .internal_name = "mate_nx_ma30d_23d", + .internal_name = "ma30d", .type = MACHINE_TYPE_SLOT1, .chipset = MACHINE_CHIPSET_INTEL_440LX, - .init = machine_at_mate_nx_ma30d_23d_init, + .init = machine_at_ma30d_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -12256,10 +13666,10 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, - .max = 1048576, + .max = 786432, .step = 8192 }, .nvrmask = 255, @@ -12299,7 +13709,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -12342,7 +13752,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, /* Machine has internal SCSI: Adaptec AIC-7890AB */ .ram = { .min = 8192, .max = 1048576, @@ -12383,7 +13793,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -12424,7 +13834,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -12465,7 +13875,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -12506,7 +13916,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -12547,7 +13957,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, /* Machine has internal video: Matrox MGA-G200 and sound: Crystal CS4820 */ .ram = { .min = 8192, .max = 1048576, @@ -12565,13 +13975,13 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has the AMIKey-2 (updated 'H') KBC firmware. */ + /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 (updated 'H') KBC firmware. */ { .name = "[i440BX] LG IBM Multinet i x7G (MSI MS-6119)", - .internal_name = "lgibm440bx", + .internal_name = "lgibmx7g", .type = MACHINE_TYPE_SLOT1, .chipset = MACHINE_CHIPSET_INTEL_440BX, - .init = machine_at_lgibm440bx_init, + .init = machine_at_lgibmx7g_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -12579,18 +13989,18 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_SLOT1, .block = CPU_BLOCK_NONE, - .min_bus = 50000000, - .max_bus = 112121212, - .min_voltage = 1300, + .min_bus = 66666667, + .max_bus = 100000000, + .min_voltage = 1800, .max_voltage = 3500, .min_multi = 1.5, .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, - .max = 1048576, + .max = 786432, .step = 8192 }, .nvrmask = 255, @@ -12628,7 +14038,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, /* Machine has internal sound: Ensoniq ES1373 */ .ram = { .min = 8192, .max = 1048576, @@ -12669,7 +14079,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -12711,8 +14121,8 @@ const machine_t machines[] = { .min_multi = 1.5, .max_multi = 8.0 }, - .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_AV | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_PS2_AGP, /* AGP is reserved for the internal video */ + .flags = MACHINE_IDE_DUAL | MACHINE_AV | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -12752,8 +14162,8 @@ const machine_t machines[] = { .min_multi = 1.5, .max_multi = 8.0 }, - .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_AV | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_PS2_AGP, /* AGP is reserved for the internal video */ + .flags = MACHINE_IDE_DUAL | MACHINE_AV | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -12776,7 +14186,7 @@ const machine_t machines[] = { /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ { - .name = "[SMSC VictoryBX-66] A-Trend ATC6310BXII", + .name = "[SMSC VictoryBX-66] A-Trend ATC-6310BXII", .internal_name = "atc6310bxii", .type = MACHINE_TYPE_SLOT1, .chipset = MACHINE_CHIPSET_SMSC_VICTORYBX_66, @@ -12796,7 +14206,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -12839,7 +14249,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, /* Machine has internal sound: ESS ES1938S */ .ram = { .min = 8192, .max = 524288, @@ -12880,7 +14290,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1572864, @@ -12921,7 +14331,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 2097152, @@ -12962,7 +14372,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, /* Machine has internal sound: Ensoniq ES1373 */ .ram = { .min = 8192, .max = 3145728, @@ -12981,6 +14391,48 @@ const machine_t machines[] = { .net_device = NULL }, + /* SiS (5)600 */ + /* Has the SiS (5)600 chipset with on-chip KBC. */ + { + .name = "[SiS 5600] Freetech/Flexus P6F99", + .internal_name = "p6f99", + .type = MACHINE_TYPE_SLOT1, + .chipset = MACHINE_CHIPSET_SIS_5600, + .init = machine_at_p6f99_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SLOT1, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 100000000, + .min_voltage = 1300, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, /* Machine has internal sound: Ensoniq ES1373 */ + .ram = { + .min = 8192, + .max = 1572864, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = &es1371_onboard_device, /* ES1373 but we currently don't emulate that. */ + .net_device = NULL + }, + /* Slot 1/2 machines */ /* 440GX */ /* Has a National Semiconductors PC87309 Super I/O chip with on-chip KBC @@ -13006,7 +14458,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_NOISA, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 16384, .max = 2097152, @@ -13050,7 +14502,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -13092,7 +14544,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -13136,7 +14588,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, /* Machine has internal SCSI */ .ram = { .min = 16384, .max = 2097152, @@ -13177,7 +14629,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 16384, .max = 2097152, @@ -13221,7 +14673,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED, }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -13263,8 +14715,8 @@ const machine_t machines[] = { .min_multi = 1.5, .max_multi = 8.0 /* limits assumed */ }, - .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_PS2_PCI, /* Machine has EISA, possibly for a riser? */ + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB | MACHINE_VIDEO, /* Machine has internal video: C&T B69000, sound: ESS ES1938S and NIC: Realtek RTL8139C */ .ram = { .min = 8192, .max = 524288, @@ -13305,7 +14757,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, /* Machine has quad channel IDE with internal controller: CMD PCI-0648 */ .ram = { .min = 8192, .max = 1048576, @@ -13346,7 +14798,7 @@ const machine_t machines[] = { .max_multi = 8.0 /* limits assumed */ }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -13389,7 +14841,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -13412,7 +14864,7 @@ const machine_t machines[] = { /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ { - .name = "[SMSC VictoryBX-66] A-Trend ATC7020BXII", + .name = "[SMSC VictoryBX-66] A-Trend ATC-7020BXII", .internal_name = "atc7020bxii", .type = MACHINE_TYPE_SOCKET370, .chipset = MACHINE_CHIPSET_SMSC_VICTORYBX_66, @@ -13432,7 +14884,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, @@ -13473,7 +14925,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -13516,7 +14968,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -13557,7 +15009,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB | MACHINE_SOUND, .ram = { .min = 8192, .max = 1572864, @@ -13572,7 +15024,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = NULL, + .snd_device = &cmi8738_onboard_device, .net_device = NULL }, /* Has the VIA VT82C686B southbridge with on-chip KBC identical to the VIA @@ -13598,7 +15050,7 @@ const machine_t machines[] = { .max_multi = MACHINE_MULTIPLIER_FIXED }, .bus_flags = MACHINE_PS2_A97, - .flags = MACHINE_IDE_DUAL | MACHINE_AG | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_AG | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 16384, .max = 3145728, @@ -13638,8 +15090,8 @@ const machine_t machines[] = { .min_multi = 1.5, .max_multi = 8.0 }, - .bus_flags = MACHINE_PS2_NOI97, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI, + .bus_flags = MACHINE_PS2_NOI97, /* Has Asus-proprietary LAN/SCSI slot */ + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 16384, .max = 4194304, @@ -13682,7 +15134,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 1048576, diff --git a/src/mem/mem.c b/src/mem/mem.c index 0b002b302..188aa49d0 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -132,6 +132,8 @@ static mem_mapping_t *last_mapping; static mem_mapping_t *read_mapping_bus[MEM_MAPPINGS_NO]; static mem_mapping_t *write_mapping_bus[MEM_MAPPINGS_NO]; static uint8_t *_mem_exec[MEM_MAPPINGS_NO]; +static uint8_t _mem_wp[MEM_MAPPINGS_NO]; +static uint8_t _mem_wp_bus[MEM_MAPPINGS_NO]; static uint8_t ff_pccache[4] = { 0xff, 0xff, 0xff, 0xff }; static mem_state_t _mem_state[MEM_MAPPINGS_NO]; static uint32_t remap_start_addr; @@ -1585,40 +1587,38 @@ do_mmutranslate(uint32_t addr, uint32_t *a64, int num, int write) for (i = 0; i < num; i++) a64[i] = (uint64_t) addr; - for (i = 0; i < num; i++) { - if (cr0 >> 31) { - if (write && ((i == 0) || !(addr & 0xfff))) - cond = (!page_lookup[addr >> 12] || !page_lookup[addr >> 12]->write_b); + if (cr0 >> 31) for (i = 0; i < num; i++) { + if (write && ((i == 0) || !(addr & 0xfff))) + cond = (!page_lookup[addr >> 12] || !page_lookup[addr >> 12]->write_b); - if (cond) { - /* If we have encountered at least one page fault, mark all subsequent addresses as - having page faulted, prevents false negatives in readmem*l_no_mmut. */ - if ((i > 0) && cpu_state.abrt && !high_page) - a64[i] = a64[i - 1]; - /* If we are on the same page, there is no need to translate again, as we can just - reuse the previous result. */ - else if (i == 0) { - a = mmutranslatereal(addr, write); - a64[i] = (uint32_t) a; + if (cond) { + /* If we have encountered at least one page fault, mark all subsequent addresses as + having page faulted, prevents false negatives in readmem*l_no_mmut. */ + if ((i > 0) && cpu_state.abrt && !high_page) + a64[i] = a64[i - 1]; + /* If we are on the same page, there is no need to translate again, as we can just + reuse the previous result. */ + else if (i == 0) { + a = mmutranslatereal(addr, write); + a64[i] = (uint32_t) a; - high_page = high_page || (!cpu_state.abrt && (a > 0xffffffffULL)); - } else if (!(addr & 0xfff)) { - a = mmutranslatereal(last_addr, write); - a64[i] = (uint32_t) a; + high_page = high_page || (!cpu_state.abrt && (a > 0xffffffffULL)); + } else if (!(addr & 0xfff)) { + a = mmutranslatereal(last_addr, write); + a64[i] = (uint32_t) a; - high_page = high_page || (!cpu_state.abrt && (a64[i] > 0xffffffffULL)); + high_page = high_page || (!cpu_state.abrt && (a64[i] > 0xffffffffULL)); - if (!cpu_state.abrt) { - a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); - a64[i] = (uint32_t) a; - } - } else { + if (!cpu_state.abrt) { a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); a64[i] = (uint32_t) a; } - } else - mmu_perm = page_lookupp[addr >> 12]; - } + } else { + a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); + a64[i] = (uint32_t) a; + } + } else + mmu_perm = page_lookupp[addr >> 12]; addr++; } @@ -1633,7 +1633,7 @@ mem_readb_phys(uint32_t addr) mem_logical_addr = 0xffffffff; if (map) { - if (map->exec) + if (cpu_use_exec && map->exec) ret = map->exec[(addr - map->base) & map->mask]; else if (map->read_b) ret = map->read_b(addr, map->priv); @@ -1651,7 +1651,7 @@ mem_readw_phys(uint32_t addr) mem_logical_addr = 0xffffffff; - if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->exec)) { + if (cpu_use_exec && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->exec)) { p = (uint16_t *) &(map->exec[(addr - map->base) & map->mask]); ret = *p; } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->read_w)) @@ -1673,7 +1673,7 @@ mem_readl_phys(uint32_t addr) mem_logical_addr = 0xffffffff; - if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->exec)) { + if (cpu_use_exec && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->exec)) { p = (uint32_t *) &(map->exec[(addr - map->base) & map->mask]); ret = *p; } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->read_l)) @@ -1713,7 +1713,7 @@ mem_writeb_phys(uint32_t addr, uint8_t val) mem_logical_addr = 0xffffffff; if (map) { - if (map->exec) + if (cpu_use_exec && map->exec) map->exec[(addr - map->base) & map->mask] = val; else if (map->write_b) map->write_b(addr, val, map->priv); @@ -1728,7 +1728,7 @@ mem_writew_phys(uint32_t addr, uint16_t val) mem_logical_addr = 0xffffffff; - if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->exec)) { + if (cpu_use_exec && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->exec)) { p = (uint16_t *) &(map->exec[(addr - map->base) & map->mask]); *p = val; } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->write_w)) @@ -1747,7 +1747,7 @@ mem_writel_phys(uint32_t addr, uint32_t val) mem_logical_addr = 0xffffffff; - if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->exec)) { + if (cpu_use_exec && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->exec)) { p = (uint32_t *) &(map->exec[(addr - map->base) & map->mask]); *p = val; } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->write_l)) @@ -1785,7 +1785,7 @@ mem_read_ram(uint32_t addr, UNUSED(void *priv)) mem_log("Read B %02X from %08X\n", ram[addr], addr); #endif - if (is286) + if (cpu_use_exec) addreadlookup(mem_logical_addr, addr); return ram[addr]; @@ -1799,7 +1799,7 @@ mem_read_ramw(uint32_t addr, UNUSED(void *priv)) mem_log("Read W %04X from %08X\n", *(uint16_t *) &ram[addr], addr); #endif - if (is286) + if (cpu_use_exec) addreadlookup(mem_logical_addr, addr); return *(uint16_t *) &ram[addr]; @@ -1813,7 +1813,7 @@ mem_read_raml(uint32_t addr, UNUSED(void *priv)) mem_log("Read L %08X from %08X\n", *(uint32_t *) &ram[addr], addr); #endif - if (is286) + if (cpu_use_exec) addreadlookup(mem_logical_addr, addr); return *(uint32_t *) &ram[addr]; @@ -2045,7 +2045,7 @@ mem_write_ram(uint32_t addr, uint8_t val, UNUSED(void *priv)) if ((addr >= 0xa0000) && (addr <= 0xbffff)) mem_log("Write B %02X to %08X\n", val, addr); #endif - if (is286) { + if (cpu_use_exec) { addwritelookup(mem_logical_addr, addr); mem_write_ramb_page(addr, val, &pages[addr >> 12]); } else @@ -2059,7 +2059,7 @@ mem_write_ramw(uint32_t addr, uint16_t val, UNUSED(void *priv)) if ((addr >= 0xa0000) && (addr <= 0xbffff)) mem_log("Write W %04X to %08X\n", val, addr); #endif - if (is286) { + if (cpu_use_exec) { addwritelookup(mem_logical_addr, addr); mem_write_ramw_page(addr, val, &pages[addr >> 12]); } else @@ -2073,7 +2073,7 @@ mem_write_raml(uint32_t addr, uint32_t val, UNUSED(void *priv)) if ((addr >= 0xa0000) && (addr <= 0xbffff)) mem_log("Write L %08X to %08X\n", val, addr); #endif - if (is286) { + if (cpu_use_exec) { addwritelookup(mem_logical_addr, addr); mem_write_raml_page(addr, val, &pages[addr >> 12]); } else @@ -2084,7 +2084,7 @@ static uint8_t mem_read_remapped(uint32_t addr, UNUSED(void *priv)) { addr = 0xA0000 + (addr - remap_start_addr); - if (is286) + if (cpu_use_exec) addreadlookup(mem_logical_addr, addr); return ram[addr]; } @@ -2093,7 +2093,7 @@ static uint16_t mem_read_remappedw(uint32_t addr, UNUSED(void *priv)) { addr = 0xA0000 + (addr - remap_start_addr); - if (is286) + if (cpu_use_exec) addreadlookup(mem_logical_addr, addr); return *(uint16_t *) &ram[addr]; } @@ -2102,7 +2102,7 @@ static uint32_t mem_read_remappedl(uint32_t addr, UNUSED(void *priv)) { addr = 0xA0000 + (addr - remap_start_addr); - if (is286) + if (cpu_use_exec) addreadlookup(mem_logical_addr, addr); return *(uint32_t *) &ram[addr]; } @@ -2111,7 +2111,7 @@ static uint8_t mem_read_remapped2(uint32_t addr, UNUSED(void *priv)) { addr = 0xD0000 + (addr - remap_start_addr2); - if (is286) + if (cpu_use_exec) addreadlookup(mem_logical_addr, addr); return ram[addr]; } @@ -2120,7 +2120,7 @@ static uint16_t mem_read_remappedw2(uint32_t addr, UNUSED(void *priv)) { addr = 0xD0000 + (addr - remap_start_addr2); - if (is286) + if (cpu_use_exec) addreadlookup(mem_logical_addr, addr); return *(uint16_t *) &ram[addr]; } @@ -2129,7 +2129,7 @@ static uint32_t mem_read_remappedl2(uint32_t addr, UNUSED(void *priv)) { addr = 0xD0000 + (addr - remap_start_addr2); - if (is286) + if (cpu_use_exec) addreadlookup(mem_logical_addr, addr); return *(uint32_t *) &ram[addr]; } @@ -2139,7 +2139,7 @@ mem_write_remapped(uint32_t addr, uint8_t val, UNUSED(void *priv)) { uint32_t oldaddr = addr; addr = 0xA0000 + (addr - remap_start_addr); - if (is286) { + if (cpu_use_exec) { addwritelookup(mem_logical_addr, addr); mem_write_ramb_page(addr, val, &pages[oldaddr >> 12]); } else @@ -2151,7 +2151,7 @@ mem_write_remappedw(uint32_t addr, uint16_t val, UNUSED(void *priv)) { uint32_t oldaddr = addr; addr = 0xA0000 + (addr - remap_start_addr); - if (is286) { + if (cpu_use_exec) { addwritelookup(mem_logical_addr, addr); mem_write_ramw_page(addr, val, &pages[oldaddr >> 12]); } else @@ -2163,7 +2163,7 @@ mem_write_remappedl(uint32_t addr, uint32_t val, UNUSED(void *priv)) { uint32_t oldaddr = addr; addr = 0xA0000 + (addr - remap_start_addr); - if (is286) { + if (cpu_use_exec) { addwritelookup(mem_logical_addr, addr); mem_write_raml_page(addr, val, &pages[oldaddr >> 12]); } else @@ -2175,7 +2175,7 @@ mem_write_remapped2(uint32_t addr, uint8_t val, UNUSED(void *priv)) { uint32_t oldaddr = addr; addr = 0xD0000 + (addr - remap_start_addr2); - if (is286) { + if (cpu_use_exec) { addwritelookup(mem_logical_addr, addr); mem_write_ramb_page(addr, val, &pages[oldaddr >> 12]); } else @@ -2187,7 +2187,7 @@ mem_write_remappedw2(uint32_t addr, uint16_t val, UNUSED(void *priv)) { uint32_t oldaddr = addr; addr = 0xD0000 + (addr - remap_start_addr2); - if (is286) { + if (cpu_use_exec) { addwritelookup(mem_logical_addr, addr); mem_write_ramw_page(addr, val, &pages[oldaddr >> 12]); } else @@ -2199,7 +2199,7 @@ mem_write_remappedl2(uint32_t addr, uint32_t val, UNUSED(void *priv)) { uint32_t oldaddr = addr; addr = 0xD0000 + (addr - remap_start_addr2); - if (is286) { + if (cpu_use_exec) { addwritelookup(mem_logical_addr, addr); mem_write_raml_page(addr, val, &pages[oldaddr >> 12]); } else @@ -2284,6 +2284,7 @@ mem_mapping_recalc(uint64_t base, uint64_t size) mem_mapping_t *map; int n; uint64_t c; + uint8_t wp; if (!size || (base_mapping == NULL)) return; @@ -2302,27 +2303,42 @@ mem_mapping_recalc(uint64_t base, uint64_t size) /* Walk mapping list. */ while (map != NULL) { /* In range? */ - if (map->enable && (uint64_t) map->base < ((uint64_t) base + (uint64_t) size) && ((uint64_t) map->base + (uint64_t) map->size) > (uint64_t) base) { + if (map->enable && (uint64_t) map->base < ((uint64_t) base + (uint64_t) size) && + ((uint64_t) map->base + (uint64_t) map->size) > (uint64_t) base) { uint64_t start = (map->base < base) ? map->base : base; - uint64_t end = (((uint64_t) map->base + (uint64_t) map->size) < (base + size)) ? ((uint64_t) map->base + (uint64_t) map->size) : (base + size); + uint64_t end = (((uint64_t) map->base + (uint64_t) map->size) < (base + size)) ? + ((uint64_t) map->base + (uint64_t) map->size) : (base + size); if (start < map->base) start = map->base; for (c = start; c < end; c += MEM_GRANULARITY_SIZE) { /* CPU */ n = !!in_smm; - if (map->exec && mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].x)) + wp = _mem_wp[c >> MEM_GRANULARITY_BITS]; + + if (map->exec && mem_mapping_access_allowed(map->flags, + _mem_state[c >> MEM_GRANULARITY_BITS].states[n].x)) _mem_exec[c >> MEM_GRANULARITY_BITS] = map->exec + (c - map->base); - if ((map->write_b || map->write_w || map->write_l) && mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].w)) + if (!wp && (map->write_b || map->write_w || map->write_l) && + mem_mapping_access_allowed(map->flags, + _mem_state[c >> MEM_GRANULARITY_BITS].states[n].w)) write_mapping[c >> MEM_GRANULARITY_BITS] = map; - if ((map->read_b || map->read_w || map->read_l) && mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].r)) + if ((map->read_b || map->read_w || map->read_l) && + mem_mapping_access_allowed(map->flags, + _mem_state[c >> MEM_GRANULARITY_BITS].states[n].r)) read_mapping[c >> MEM_GRANULARITY_BITS] = map; /* Bus */ n |= STATE_BUS; - if ((map->write_b || map->write_w || map->write_l) && mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].w)) + wp = _mem_wp_bus[c >> MEM_GRANULARITY_BITS]; + + if (!wp && (map->write_b || map->write_w || map->write_l) && + mem_mapping_access_allowed(map->flags, + _mem_state[c >> MEM_GRANULARITY_BITS].states[n].w)) write_mapping_bus[c >> MEM_GRANULARITY_BITS] = map; - if ((map->read_b || map->read_w || map->read_l) && mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].r)) + if ((map->read_b || map->read_w || map->read_l) && + mem_mapping_access_allowed(map->flags, + _mem_state[c >> MEM_GRANULARITY_BITS].states[n].r)) read_mapping_bus[c >> MEM_GRANULARITY_BITS] = map; } } @@ -2382,6 +2398,22 @@ mem_mapping_recalc(uint64_t base, uint64_t size) #endif } +void +mem_set_wp(uint64_t base, uint64_t size, uint8_t flags, uint8_t wp) +{ + uint64_t c; + uint64_t end = base + size; + + for (c = base; c < end; c += MEM_GRANULARITY_SIZE) { + if (flags & ACCESS_BUS) + _mem_wp_bus[c >> MEM_GRANULARITY_BITS] = wp; + if (flags & ACCESS_CPU) + _mem_wp[c >> MEM_GRANULARITY_BITS] = wp; + } + + mem_mapping_recalc(base, size); +} + void mem_mapping_set(mem_mapping_t *map, uint32_t base, @@ -2792,6 +2824,8 @@ mem_reset(void) } memset(_mem_exec, 0x00, sizeof(_mem_exec)); + memset(_mem_wp, 0x00, sizeof(_mem_wp)); + memset(_mem_wp_bus, 0x00, sizeof(_mem_wp_bus)); memset(write_mapping, 0x00, sizeof(write_mapping)); memset(read_mapping, 0x00, sizeof(read_mapping)); memset(write_mapping_bus, 0x00, sizeof(write_mapping_bus)); @@ -2871,6 +2905,35 @@ mem_init(void) writelookupp = malloc((1 << 20) * sizeof(uint8_t)); } +static void +umc_page_recalc(uint32_t c, int set) +{ + if (set) { + pages[c].mem = &ram[(c & 0xff) << 12]; + pages[c].write_b = mem_write_ramb_page; + pages[c].write_w = mem_write_ramw_page; + pages[c].write_l = mem_write_raml_page; + } else { + pages[c].mem = page_ff; + pages[c].write_b = NULL; + pages[c].write_w = NULL; + pages[c].write_l = NULL; + } + +#ifdef USE_NEW_DYNAREC + pages[c].evict_prev = EVICT_NOT_IN_LIST; + pages[c].byte_dirty_mask = &byte_dirty_mask[(c & 0xff) * 64]; + pages[c].byte_code_present_mask = &byte_code_present_mask[(c & 0xff) * 64]; +#endif +} + +void +umc_smram_recalc(uint32_t start, int set) +{ + for (uint32_t c = start; c < (start + 0x0020); c++) + umc_page_recalc(c, set); +} + void mem_remap_top(int kb) { diff --git a/src/mem/mmu_2386.c b/src/mem/mmu_2386.c index 21c62b833..abc34ff96 100644 --- a/src/mem/mmu_2386.c +++ b/src/mem/mmu_2386.c @@ -39,6 +39,44 @@ #include <86box/rom.h> #include <86box/gdbstub.h> +/* As below, 1 = exec, 4 = read. */ +int read_type = 4; + +/* Set trap for data address breakpoints - 1 = exec, 2 = write, 4 = read. */ +void +mem_debug_check_addr(uint32_t addr, int flags) +{ + uint32_t bp_addr; + uint32_t bp_mask; + uint32_t len_type_pair; + int bp_enabled; + uint8_t match_flags[4] = { 0, 2, 0, 6 }; + + if (cpu_state.abrt || ((flags == 1) && (cpu_state.eflags & RF_FLAG))) + return; + + if (dr[7] & 0x000000ff) for (uint8_t i = 0; i < 4; i++) { + bp_addr = dr[i]; + bp_enabled = (dr[7] >> (i << 1)) & 0x03; + len_type_pair = (dr[7] >> (16 + (i << 2))) & 0x0f; + bp_mask = ~((len_type_pair >> 2) & 0x03); + + if ((flags & match_flags[len_type_pair & 0x03]) && ((bp_addr & bp_mask) == (addr & bp_mask))) { + /* + From the Intel i386 documemntation: + + (Note that the processor sets Bn regardless of whether Gn or + Ln is set. If more than one breakpoint condition occurs at one time and if + the breakpoint trap occurs due to an enabled condition other than n, Bn may + be set, even though neither Gn nor Ln is set.) + */ + dr[6] |= (1 << i); + if (bp_enabled) + trap |= (read_type == 1) ? 8 : 4; + } + } +} + uint8_t mem_readb_map(uint32_t addr) { @@ -243,6 +281,7 @@ readmembl_2386(uint32_t addr) GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); + mem_debug_check_addr(addr, read_type); addr64 = (uint64_t) addr; mem_logical_addr = addr; @@ -270,6 +309,7 @@ writemembl_2386(uint32_t addr, uint8_t val) mem_mapping_t *map; uint64_t a; + mem_debug_check_addr(addr, 2); GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); addr64 = (uint64_t) addr; @@ -347,6 +387,8 @@ readmemwl_2386(uint32_t addr) addr64a[0] = addr; addr64a[1] = addr + 1; + mem_debug_check_addr(addr, read_type); + mem_debug_check_addr(addr + 1, read_type); GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 2); mem_logical_addr = addr; @@ -367,7 +409,8 @@ readmemwl_2386(uint32_t addr) } } - return readmembl_no_mmut(addr, addr64a[0]) | (((uint16_t) readmembl_no_mmut(addr + 1, addr64a[1])) << 8); + return readmembl_no_mmut_2386(addr, addr64a[0]) | + (((uint16_t) readmembl_no_mmut_2386(addr + 1, addr64a[1])) << 8); } } @@ -402,6 +445,8 @@ writememwl_2386(uint32_t addr, uint16_t val) addr64a[0] = addr; addr64a[1] = addr + 1; + mem_debug_check_addr(addr, 2); + mem_debug_check_addr(addr + 1, 2); GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 2); mem_logical_addr = addr; @@ -428,8 +473,8 @@ writememwl_2386(uint32_t addr, uint16_t val) /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass their result as a parameter to be used if needed. */ - writemembl_no_mmut(addr, addr64a[0], val); - writemembl_no_mmut(addr + 1, addr64a[1], val >> 8); + writemembl_no_mmut_2386(addr, addr64a[0], val); + writemembl_no_mmut_2386(addr + 1, addr64a[1], val >> 8); return; } } @@ -477,7 +522,8 @@ readmemwl_no_mmut_2386(uint32_t addr, uint32_t *a64) return 0xffff; } - return readmembl_no_mmut(addr, a64[0]) | (((uint16_t) readmembl_no_mmut(addr + 1, a64[1])) << 8); + return readmembl_no_mmut_2386(addr, a64[0]) | + (((uint16_t) readmembl_no_mmut_2386(addr + 1, a64[1])) << 8); } } @@ -520,8 +566,8 @@ writememwl_no_mmut_2386(uint32_t addr, uint32_t *a64, uint16_t val) return; } - writemembl_no_mmut(addr, a64[0], val); - writemembl_no_mmut(addr + 1, a64[1], val >> 8); + writemembl_no_mmut_2386(addr, a64[0], val); + writemembl_no_mmut_2386(addr + 1, a64[1], val >> 8); return; } } @@ -555,16 +601,18 @@ readmemll_2386(uint32_t addr) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 4; i++) + for (i = 0; i < 4; i++) { addr64a[i] = (uint64_t) (addr + i); + mem_debug_check_addr(addr + i, read_type); + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 4); mem_logical_addr = addr; high_page = 0; - if (addr & 3) { - if (!cpu_cyrix_alignment || (addr & 7) > 4) + if (cpu_16bitbus || (addr & 3)) { + if ((addr & 3) && (!cpu_cyrix_alignment || (addr & 7) > 4)) cycles -= timing_misaligned; if ((addr & 0xfff) > 0xffc) { if (cr0 >> 31) { @@ -591,7 +639,8 @@ readmemll_2386(uint32_t addr) /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass their result as a parameter to be used if needed. */ - return readmemwl_no_mmut(addr, addr64a) | (((uint32_t) readmemwl_no_mmut(addr + 2, &(addr64a[2]))) << 16); + return readmemwl_no_mmut_2386(addr, addr64a) | + (((uint32_t) readmemwl_no_mmut(addr + 2, &(addr64a[2]))) << 16); } } @@ -626,16 +675,18 @@ writememll_2386(uint32_t addr, uint32_t val) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 4; i++) + for (i = 0; i < 4; i++) { addr64a[i] = (uint64_t) (addr + i); + mem_debug_check_addr(addr + i, 2); + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 4); mem_logical_addr = addr; high_page = 0; - if (addr & 3) { - if (!cpu_cyrix_alignment || (addr & 7) > 4) + if (cpu_16bitbus || (addr & 3)) { + if ((addr & 3) && (!cpu_cyrix_alignment || (addr & 7) > 4)) cycles -= timing_misaligned; if ((addr & 0xfff) > 0xffc) { if (cr0 >> 31) { @@ -666,8 +717,8 @@ writememll_2386(uint32_t addr, uint32_t val) /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass their result as a parameter to be used if needed. */ - writememwl_no_mmut(addr, &(addr64a[0]), val); - writememwl_no_mmut(addr + 2, &(addr64a[2]), val >> 16); + writememwl_no_mmut_2386(addr, &(addr64a[0]), val); + writememwl_no_mmut_2386(addr + 2, &(addr64a[2]), val >> 16); return; } } @@ -712,8 +763,8 @@ readmemll_no_mmut_2386(uint32_t addr, uint32_t *a64) mem_logical_addr = addr; - if (addr & 3) { - if (!cpu_cyrix_alignment || (addr & 7) > 4) + if (cpu_16bitbus || (addr & 3)) { + if ((addr & 3) && (!cpu_cyrix_alignment || (addr & 7) > 4)) cycles -= timing_misaligned; if ((addr & 0xfff) > 0xffc) { if (cr0 >> 31) { @@ -721,7 +772,8 @@ readmemll_no_mmut_2386(uint32_t addr, uint32_t *a64) return 0xffffffff; } - return readmemwl_no_mmut(addr, a64) | ((uint32_t) (readmemwl_no_mmut(addr + 2, &(a64[2]))) << 16); + return readmemwl_no_mmut_2386(addr, a64) | + ((uint32_t) (readmemwl_no_mmut_2386(addr + 2, &(a64[2]))) << 16); } } @@ -757,8 +809,8 @@ writememll_no_mmut_2386(uint32_t addr, uint32_t *a64, uint32_t val) mem_logical_addr = addr; - if (addr & 3) { - if (!cpu_cyrix_alignment || (addr & 7) > 4) + if (cpu_16bitbus || (addr & 3)) { + if ((addr & 3) && (!cpu_cyrix_alignment || (addr & 7) > 4)) cycles -= timing_misaligned; if ((addr & 0xfff) > 0xffc) { if (cr0 >> 31) { @@ -766,8 +818,8 @@ writememll_no_mmut_2386(uint32_t addr, uint32_t *a64, uint32_t val) return; } - writememwl_no_mmut(addr, &(a64[0]), val); - writememwl_no_mmut(addr + 2, &(a64[2]), val >> 16); + writememwl_no_mmut_2386(addr, &(a64[0]), val); + writememwl_no_mmut_2386(addr + 2, &(a64[2]), val >> 16); return; } } @@ -807,8 +859,10 @@ readmemql_2386(uint32_t addr) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { addr64a[i] = (uint64_t) (addr + i); + mem_debug_check_addr(addr + i, read_type); + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 8); mem_logical_addr = addr; @@ -842,7 +896,8 @@ readmemql_2386(uint32_t addr) /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass their result as a parameter to be used if needed. */ - return readmemll_no_mmut(addr, addr64a) | (((uint64_t) readmemll_no_mmut(addr + 4, &(addr64a[4]))) << 32); + return readmemll_no_mmut_2386(addr, addr64a) | + (((uint64_t) readmemll_no_mmut_2386(addr + 4, &(addr64a[4]))) << 32); } } @@ -870,8 +925,10 @@ writememql_2386(uint32_t addr, uint64_t val) int i; uint64_t a = 0x0000000000000000ULL; - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { addr64a[i] = (uint64_t) (addr + i); + mem_debug_check_addr(addr + i, 2); + } GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 8); mem_logical_addr = addr; @@ -909,8 +966,8 @@ writememql_2386(uint32_t addr, uint64_t val) /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass their result as a parameter to be used if needed. */ - writememll_no_mmut(addr, addr64a, val); - writememll_no_mmut(addr + 4, &(addr64a[4]), val >> 32); + writememll_no_mmut_2386(addr, addr64a, val); + writememll_no_mmut_2386(addr + 4, &(addr64a[4]), val >> 32); return; } } @@ -957,32 +1014,35 @@ do_mmutranslate_2386(uint32_t addr, uint32_t *a64, int num, int write) uint32_t last_addr = addr + (num - 1); uint64_t a = 0x0000000000000000ULL; + mem_debug_check_addr(addr, write ? 2 : read_type); + for (i = 0; i < num; i++) a64[i] = (uint64_t) addr; - for (i = 0; i < num; i++) { - if (cr0 >> 31) { - /* If we have encountered at least one page fault, mark all subsequent addresses as - having page faulted, prevents false negatives in readmem*l_no_mmut. */ - if ((i > 0) && cpu_state.abrt && !high_page) - a64[i] = a64[i - 1]; - /* If we are on the same page, there is no need to translate again, as we can just - reuse the previous result. */ - else if (i == 0) { - a = mmutranslatereal_2386(addr, write); - a64[i] = (uint32_t) a; - } else if (!(addr & 0xfff)) { - a = mmutranslatereal_2386(last_addr, write); - a64[i] = (uint32_t) a; + if (!(cr0 >> 31)) + return; - if (!cpu_state.abrt) { - a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); - a64[i] = (uint32_t) a; - } - } else { + for (i = 0; i < num; i++) { + /* If we have encountered at least one page fault, mark all subsequent addresses as + having page faulted, prevents false negatives in readmem*l_no_mmut. */ + if ((i > 0) && cpu_state.abrt && !high_page) + a64[i] = a64[i - 1]; + /* If we are on the same page, there is no need to translate again, as we can just + reuse the previous result. */ + else if (i == 0) { + a = mmutranslatereal_2386(addr, write); + a64[i] = (uint32_t) a; + } else if (!(addr & 0xfff)) { + a = mmutranslatereal_2386(last_addr, write); + a64[i] = (uint32_t) a; + + if (!cpu_state.abrt) { a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); a64[i] = (uint32_t) a; } + } else { + a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); + a64[i] = (uint32_t) a; } addr++; diff --git a/src/mem/rom.c b/src/mem/rom.c index 4a20e8ebc..f9718b7ce 100644 --- a/src/mem/rom.c +++ b/src/mem/rom.c @@ -296,6 +296,12 @@ rom_load_linear_inverted(const char *fn, uint32_t addr, int sz, int off, uint8_t fatal("rom_load_linear_inverted(): Error reading the upper half of the data\n"); if (fread(ptr + addr, sz >> 1, 1, fp) > (sz >> 1)) fatal("rom_load_linear_inverted(): Error reading the lower half of the data\n"); + if (sz == 0x40000) { + if (fread(ptr + addr + 0x30000, 1, sz >> 1, fp) > (sz >> 1)) + fatal("rom_load_linear_inverted(): Error reading the upper half of the data\n"); + if (fread(ptr + addr + 0x20000, sz >> 1, 1, fp) > (sz >> 1)) + fatal("rom_load_linear_inverted(): Error reading the lower half of the data\n"); + } } (void) fclose(fp); diff --git a/src/mem/sst_flash.c b/src/mem/sst_flash.c index 472a042d1..cd6ec7cd9 100644 --- a/src/mem/sst_flash.c +++ b/src/mem/sst_flash.c @@ -131,6 +131,9 @@ static char flash_path[1024]; #define W29C020 0x4500 #define W29C040 0x4600 +#define AMD 0x01 /* AMD Manufacturer's ID */ +#define AMD29F020A 0xb000 + #define SIZE_512K 0x010000 #define SIZE_1M 0x020000 #define SIZE_2M 0x040000 @@ -144,12 +147,32 @@ sst_sector_erase(sst_t *dev, uint32_t addr) { uint32_t base = addr & (dev->mask & ~0xfff); - if ((base < 0x2000) && (dev->bbp_first_8k & 0x01)) - return; - else if ((base >= (dev->size - 0x2000)) && (dev->bbp_last_8k & 0x01)) - return; + if (dev->manufacturer == AMD) { + base = addr & biosmask; + + if ((base >= 0x00000) && (base <= 0x0ffff)) + memset(&dev->array[0x00000], 0xff, 65536); + else if ((base >= 0x10000) && (base <= 0x1ffff)) + memset(&dev->array[0x10000], 0xff, 65536); + else if ((base >= 0x20000) && (base <= 0x2ffff)) + memset(&dev->array[0x20000], 0xff, 65536); + else if ((base >= 0x30000) && (base <= 0x37fff)) + memset(&dev->array[0x30000], 0xff, 32768); + else if ((base >= 0x38000) && (base <= 0x39fff)) + memset(&dev->array[0x38000], 0xff, 8192); + else if ((base >= 0x3a000) && (base <= 0x3bfff)) + memset(&dev->array[0x3a000], 0xff, 8192); + else if ((base >= 0x3c000) && (base <= 0x3ffff)) + memset(&dev->array[0x3c000], 0xff, 16384); + } else { + if ((base < 0x2000) && (dev->bbp_first_8k & 0x01)) + return; + else if ((base >= (dev->size - 0x2000)) && (dev->bbp_last_8k & 0x01)) + return; + + memset(&dev->array[base], 0xff, 4096); + } - memset(&dev->array[base], 0xff, 4096); dev->dirty = 1; } @@ -262,10 +285,14 @@ sst_read_id(uint32_t addr, void *priv) { const sst_t *dev = (sst_t *) priv; uint8_t ret = 0x00; + uint32_t mask = 0xffff; - if ((addr & 0xffff) == 0) + if (dev->manufacturer == AMD) + mask >>= 8; + + if ((addr & mask) == 0) ret = dev->manufacturer; - else if ((addr & 0xffff) == 1) + else if ((addr & mask) == 1) ret = dev->id; #ifdef UNKNOWN_FLASH else if ((addr & 0xffff) == 0x100) @@ -278,6 +305,9 @@ sst_read_id(uint32_t addr, void *priv) ret = dev->bbp_first_8k; else if (addr == 0x3fff2) ret = dev->bbp_last_8k; + } else if (dev->manufacturer == AMD) { + if ((addr & mask) == 2) + ret = 0x00; } return ret; @@ -300,6 +330,15 @@ static void sst_write(uint32_t addr, uint8_t val, void *priv) { sst_t *dev = (sst_t *) priv; + uint32_t mask = 0x7fff; + uint32_t addr0 = 0x5555; + uint32_t addr1 = 0x2aaa; + + if (dev->manufacturer == AMD) { + mask >>= 4; + addr0 >>= 4; + addr1 >>= 4; + } switch (dev->command_state) { case 0: @@ -309,7 +348,7 @@ sst_write(uint32_t addr, uint8_t val, void *priv) if (dev->id_mode) dev->id_mode = 0; dev->command_state = 0; - } else if (((addr & 0x7fff) == 0x5555) && (val == 0xaa)) + } else if (((addr & mask) == addr0) && (val == 0xaa)) dev->command_state++; else { if (!dev->is_39 && !dev->sdp && (dev->command_state == 0)) { @@ -326,7 +365,7 @@ sst_write(uint32_t addr, uint8_t val, void *priv) case 1: case 4: /* 2nd and 5th Bus Write Cycle */ - if (((addr & 0x7fff) == 0x2aaa) && (val == 0x55)) + if (((addr & mask) == addr1) && (val == 0x55)) dev->command_state++; else dev->command_state = 0; @@ -337,7 +376,7 @@ sst_write(uint32_t addr, uint8_t val, void *priv) if ((dev->command_state == 5) && (val == SST_SECTOR_ERASE)) { /* Sector erase - can be on any address. */ sst_new_command(dev, addr, val); - } else if ((addr & 0x7fff) == 0x5555) + } else if ((addr & mask) == addr0) sst_new_command(dev, addr, val); else dev->command_state = 0; @@ -481,6 +520,8 @@ sst_init(const device_t *info) dev->id = (info->local >> 8) & 0xff; dev->has_bbp = (dev->manufacturer == WINBOND) && ((info->local & 0xff00) >= W29C020); dev->is_39 = (dev->manufacturer == SST) && ((info->local & 0xff00) >= SST39SF512); + if (dev->manufacturer == AMD) + dev->is_39 = 1; dev->size = info->local & 0xffff0000; if ((dev->size == 0x20000) && (strstr(machine_get_internal_name_ex(machine), "xi8088")) && !xi8088_bios_128kb()) @@ -941,3 +982,17 @@ const device_t sst_flash_49lf160_device = { .force_redraw = NULL, .config = NULL }; + +const device_t amd_flash_29f020a_device = { + .name = "AMD 29F020a Flash BIOS", + .internal_name = "amd_flash_29f020a", + .flags = 0, + .local = AMD | AMD29F020A | SIZE_2M, + .init = sst_init, + .close = sst_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/network/net_3c501.c b/src/network/net_3c501.c index 5b9fc0cac..868ee036f 100644 --- a/src/network/net_3c501.c +++ b/src/network/net_3c501.c @@ -56,7 +56,6 @@ #include <86box/thread.h> #include <86box/timer.h> #include <86box/network.h> -#include <86box/net_3c501.h> #include <86box/bswap.h> #include <86box/plat_unused.h> diff --git a/src/network/net_3c503.c b/src/network/net_3c503.c index d01b423ae..11e823326 100644 --- a/src/network/net_3c503.c +++ b/src/network/net_3c503.c @@ -60,7 +60,6 @@ #include <86box/timer.h> #include <86box/network.h> #include <86box/net_dp8390.h> -#include <86box/net_3c503.h> #include <86box/bswap.h> #include <86box/plat_unused.h> diff --git a/src/network/net_eeprom_nmc93cxx.c b/src/network/net_eeprom_nmc93cxx.c index 1e2fd1645..681263717 100644 --- a/src/network/net_eeprom_nmc93cxx.c +++ b/src/network/net_eeprom_nmc93cxx.c @@ -263,6 +263,8 @@ nmc93cxx_eeprom_close(void *priv) uint16_t * nmc93cxx_eeprom_data(nmc93cxx_eeprom_t *eeprom) { + if (UNLIKELY(!eeprom)) + return NULL; /* Get EEPROM data array. */ return &eeprom->dev.data[0]; } diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index c7fba404f..03327ac0c 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -82,19 +82,6 @@ #define PCI_DEVID 0x8029 /* RTL8029AS */ #define PCI_REGSIZE 256 /* size of PCI space */ -static uint8_t rtl8019as_pnp_rom[] = { - 0x4a, 0x8c, 0x80, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, /* RTL8019, dummy checksum (filled in by isapnp_add_card) */ - 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ - 0x82, 0x22, 0x00, 'R', 'E', 'A', 'L', 'T', 'E', 'K', ' ', 'P', 'L', 'U', 'G', ' ', '&', ' ', 'P', 'L', 'A', 'Y', ' ', 'E', 'T', 'H', 'E', 'R', 'N', 'E', 'T', ' ', 'C', 'A', 'R', 'D', 0x00, /* ANSI identifier */ - - 0x16, 0x4a, 0x8c, 0x80, 0x19, 0x02, 0x00, /* logical device RTL8019 */ - 0x1c, 0x41, 0xd0, 0x80, 0xd6, /* compatible device PNP80D6 */ - 0x47, 0x00, 0x20, 0x02, 0x80, 0x03, 0x20, 0x20, /* I/O 0x220-0x380, decodes 10-bit, 32-byte alignment, 32 addresses */ - 0x23, 0x38, 0x9e, 0x01, /* IRQ 3/4/5/9/10/11/12/15, high true edge sensitive */ - - 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ -}; - typedef struct nic_t { dp8390_t *dp8390; @@ -947,7 +934,7 @@ nic_init(const device_t *info) if (dev->board != NE2K_ETHERNEXT_MC) { dev->base_address = device_get_config_hex16("base"); dev->base_irq = device_get_config_int("irq"); - if (dev->board == NE2K_NE2000) { + if ((dev->board == NE2K_NE2000) || (dev->board == NE2K_NE2000_COMPAT)) { dev->bios_addr = device_get_config_hex20("bios_addr"); dev->has_bios = !!dev->bios_addr; } else { @@ -993,6 +980,16 @@ nic_init(const device_t *info) dp8390_mem_alloc(dev->dp8390, 0x2000, 0x2000); break; + case NE2K_NE1000_COMPAT: + dev->maclocal[0] = 0x00; /* 00:86:B0 (86Box OID) */ + dev->maclocal[1] = 0x86; + dev->maclocal[2] = 0xB0; + dev->is_8bit = 1; + rom = NULL; + dp8390_set_defaults(dev->dp8390, DP8390_FLAG_CHECK_CR | DP8390_FLAG_CLEAR_IRQ); + dp8390_mem_alloc(dev->dp8390, 0x2000, 0x2000); + break; + case NE2K_NE2000: dev->maclocal[0] = 0x00; /* 00:00:D8 (Novell OID) */ dev->maclocal[1] = 0x00; @@ -1002,6 +999,15 @@ nic_init(const device_t *info) dp8390_mem_alloc(dev->dp8390, 0x4000, 0x4000); break; + case NE2K_NE2000_COMPAT: + dev->maclocal[0] = 0x00; /* 00:86:B0 (86Box OID) */ + dev->maclocal[1] = 0x86; + dev->maclocal[2] = 0xB0; + rom = ROM_PATH_NE2000; + dp8390_set_defaults(dev->dp8390, DP8390_FLAG_EVEN_MAC | DP8390_FLAG_CHECK_CR | DP8390_FLAG_CLEAR_IRQ); + dp8390_mem_alloc(dev->dp8390, 0x4000, 0x4000); + break; + case NE2K_ETHERNEXT_MC: dev->maclocal[0] = 0x00; /* 00:00:D8 (Networth Inc. OID) */ dev->maclocal[1] = 0x00; @@ -1013,6 +1019,16 @@ nic_init(const device_t *info) dp8390_mem_alloc(dev->dp8390, 0x4000, 0x4000); break; + case NE2K_DE220P: + dev->maclocal[0] = 0x00; /* 00:80:C8 (D-Link OID) */ + dev->maclocal[1] = 0x80; + dev->maclocal[2] = 0xC8; + rom = NULL; + dp8390_set_defaults(dev->dp8390, DP8390_FLAG_EVEN_MAC | DP8390_FLAG_CLEAR_IRQ); + dp8390_set_id(dev->dp8390, 0x50, 0x70); + dp8390_mem_alloc(dev->dp8390, 0x4000, 0x8000); + break; + case NE2K_RTL8019AS: case NE2K_RTL8029AS: dev->is_pci = (dev->board == NE2K_RTL8029AS) ? 1 : 0; @@ -1043,7 +1059,7 @@ nic_init(const device_t *info) * Make this device known to the I/O system. * PnP and PCI devices start with address spaces inactive. */ - if (dev->board < NE2K_RTL8019AS && dev->board != NE2K_ETHERNEXT_MC) + if ((dev->board < NE2K_RTL8019AS) && (dev->board != NE2K_ETHERNEXT_MC)) nic_ioset(dev, dev->base_address); /* Set up our BIOS ROM space, if any. */ @@ -1108,9 +1124,44 @@ nic_init(const device_t *info) dev->eeprom[0x78] = dev->eeprom[0x7C] = (PCI_VENDID & 0xff); dev->eeprom[0x79] = dev->eeprom[0x7D] = (PCI_VENDID >> 8); } else { - memcpy(&dev->eeprom[0x12], rtl8019as_pnp_rom, sizeof(rtl8019as_pnp_rom)); + const char *pnp_rom_file = NULL; + int pnp_rom_len = 0x4a; + switch (dev->board) { + case NE2K_RTL8019AS: + pnp_rom_file = "roms/network/rtl8019as/RTL8019A.BIN"; + break; - dev->pnp_card = isapnp_add_card(&dev->eeprom[0x12], sizeof(rtl8019as_pnp_rom), nic_pnp_config_changed, nic_pnp_csn_changed, nic_pnp_read_vendor_reg, nic_pnp_write_vendor_reg, dev); + case NE2K_DE220P: + pnp_rom_file = "roms/network/de220p/dlk2201a.bin"; + pnp_rom_len = 0x43; + break; + + default: + break; + } + + uint8_t *pnp_rom = NULL; + if (pnp_rom_file) { + FILE *fp = rom_fopen(pnp_rom_file, "rb"); + if (fp) { + if (fread(&dev->eeprom[0x12], 1, pnp_rom_len, fp) == pnp_rom_len) + pnp_rom = &dev->eeprom[0x12]; + fclose(fp); + } + } + + switch (info->local) { + case NE2K_RTL8019AS: + case NE2K_DE220P: + dev->pnp_card = isapnp_add_card(pnp_rom, pnp_rom_len, + nic_pnp_config_changed, nic_pnp_csn_changed, + nic_pnp_read_vendor_reg, nic_pnp_write_vendor_reg, + dev); + break; + + default: + break; + } } } @@ -1137,6 +1188,18 @@ nic_close(void *priv) free(dev); } +static int +rtl8019as_available(void) +{ + return rom_present("roms/network/rtl8019as/RTL8019A.BIN"); +} + +static int +de220p_available(void) +{ + return rom_present("roms/network/de220p/dlk2201a.bin"); +} + // clang-format off static const device_config_t ne1000_config[] = { { @@ -1148,12 +1211,11 @@ static const device_config_t ne1000_config[] = { .file_filter = "", .spinner = { 0 }, .selection = { - { .description = "0x280", .value = 0x280 }, + /* Source: Windows 95 .INF file. */ { .description = "0x300", .value = 0x300 }, { .description = "0x320", .value = 0x320 }, { .description = "0x340", .value = 0x340 }, { .description = "0x360", .value = 0x360 }, - { .description = "0x380", .value = 0x380 }, { .description = "" } }, }, @@ -1166,12 +1228,71 @@ static const device_config_t ne1000_config[] = { .file_filter = "", .spinner = { 0 }, .selection = { + /* Source: Windows 95 .INF file. */ { .description = "IRQ 2", .value = 2 }, { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 9", .value = 9 }, + { .description = "" } + }, + }, + { + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1 + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + +static const device_config_t ne1000_compat_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x300, + .file_filter = "", + .spinner = { 0 }, + .selection = { + /* Source: Windows 95 .INF file. */ + { .description = "0x200", .value = 0x200 }, + { .description = "0x220", .value = 0x220 }, + { .description = "0x240", .value = 0x240 }, + { .description = "0x260", .value = 0x260 }, + { .description = "0x280", .value = 0x280 }, + { .description = "0x2a0", .value = 0x2a0 }, + { .description = "0x2c0", .value = 0x2c0 }, + { .description = "0x2e0", .value = 0x2e0 }, + { .description = "0x300", .value = 0x300 }, + { .description = "0x320", .value = 0x320 }, + { .description = "0x340", .value = 0x340 }, + { .description = "0x360", .value = 0x360 }, + { .description = "0x380", .value = 0x380 }, + { .description = "0x3a0", .value = 0x3a0 }, + { .description = "0x3c0", .value = 0x3c0 }, + { .description = "0x3e0", .value = 0x3e0 }, + { .description = "" } + }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 3, + .file_filter = "", + .spinner = { 0 }, + .selection = { + /* Source: Windows 95 .INF file. */ + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, { .description = "IRQ 5", .value = 5 }, { .description = "IRQ 7", .value = 7 }, - { .description = "IRQ 10", .value = 10 }, - { .description = "IRQ 11", .value = 11 }, + { .description = "IRQ 9", .value = 9 }, { .description = "" } }, }, @@ -1195,12 +1316,11 @@ static const device_config_t ne2000_config[] = { .file_filter = "", .spinner = { 0 }, .selection = { - { .description = "0x280", .value = 0x280 }, + /* Source: Windows 95 .INF file. */ { .description = "0x300", .value = 0x300 }, { .description = "0x320", .value = 0x320 }, { .description = "0x340", .value = 0x340 }, { .description = "0x360", .value = 0x360 }, - { .description = "0x380", .value = 0x380 }, { .description = "" } }, }, @@ -1213,12 +1333,92 @@ static const device_config_t ne2000_config[] = { .file_filter = "", .spinner = { 0 }, .selection = { + /* Source: Windows 95 .INF file. */ { .description = "IRQ 2", .value = 2 }, { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 9", .value = 9 }, + { .description = "" } + }, + }, + { + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1 + }, + { + .name = "bios_addr", + .description = "BIOS address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0x00000 }, + { .description = "D000", .value = 0xD0000 }, + { .description = "D800", .value = 0xD8000 }, + { .description = "C800", .value = 0xC8000 }, + { .description = "" } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + +static const device_config_t ne2000_compat_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x300, + .file_filter = "", + .spinner = { 0 }, + .selection = { + /* Source: Windows 95 .INF file. */ + { .description = "0x200", .value = 0x200 }, + { .description = "0x220", .value = 0x220 }, + { .description = "0x240", .value = 0x240 }, + { .description = "0x260", .value = 0x260 }, + { .description = "0x280", .value = 0x280 }, + { .description = "0x2a0", .value = 0x2a0 }, + { .description = "0x2c0", .value = 0x2c0 }, + { .description = "0x2e0", .value = 0x2e0 }, + { .description = "0x300", .value = 0x300 }, + { .description = "0x320", .value = 0x320 }, + { .description = "0x340", .value = 0x340 }, + { .description = "0x360", .value = 0x360 }, + { .description = "0x380", .value = 0x380 }, + { .description = "0x3a0", .value = 0x3a0 }, + { .description = "0x3c0", .value = 0x3c0 }, + { .description = "0x3e0", .value = 0x3e0 }, + { .description = "" } + }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 10, + .file_filter = "", + .spinner = { 0 }, + .selection = { + /* Source: Windows 95 .INF file - not giving impossible IRQ's + such as 6, 8, or 13. */ + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, { .description = "IRQ 5", .value = 5 }, { .description = "IRQ 7", .value = 7 }, + { .description = "IRQ 9", .value = 9 }, { .description = "IRQ 10", .value = 10 }, { .description = "IRQ 11", .value = 11 }, + { .description = "IRQ 12", .value = 12 }, + { .description = "IRQ 14", .value = 14 }, + { .description = "IRQ 15", .value = 15 }, { .description = "" } }, }, @@ -1291,7 +1491,7 @@ static const device_config_t mca_mac_config[] = { const device_t ne1000_device = { .name = "Novell NE1000", - .internal_name = "ne1k", + .internal_name = "novell_ne1k", .flags = DEVICE_ISA, .local = NE2K_NE1000, .init = nic_init, @@ -1303,9 +1503,23 @@ const device_t ne1000_device = { .config = ne1000_config }; +const device_t ne1000_compat_device = { + .name = "NE1000 Compatible", + .internal_name = "ne1k", + .flags = DEVICE_ISA, + .local = NE2K_NE1000_COMPAT, + .init = nic_init, + .close = nic_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ne1000_compat_config +}; + const device_t ne2000_device = { .name = "Novell NE2000", - .internal_name = "ne2k", + .internal_name = "novell_ne2k", .flags = DEVICE_ISA | DEVICE_AT, .local = NE2K_NE2000, .init = nic_init, @@ -1317,6 +1531,20 @@ const device_t ne2000_device = { .config = ne2000_config }; +const device_t ne2000_compat_device = { + .name = "NE2000 Compatible", + .internal_name = "ne2k", + .flags = DEVICE_ISA | DEVICE_AT, + .local = NE2K_NE2000_COMPAT, + .init = nic_init, + .close = nic_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ne2000_compat_config +}; + const device_t ethernext_mc_device = { .name = "NetWorth EtherNext/MC", .internal_name = "ethernextmc", @@ -1339,7 +1567,21 @@ const device_t rtl8019as_device = { .init = nic_init, .close = nic_close, .reset = NULL, - { .available = NULL }, + { .available = rtl8019as_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = rtl8019as_config +}; + +const device_t de220p_device = { + .name = "D-Link DE-220P", + .internal_name = "de220p", + .flags = DEVICE_ISA | DEVICE_AT, + .local = NE2K_DE220P, + .init = nic_init, + .close = nic_close, + .reset = NULL, + { .available = de220p_available }, .speed_changed = NULL, .force_redraw = NULL, .config = rtl8019as_config diff --git a/src/network/net_pcnet.c b/src/network/net_pcnet.c index 02e3d32e7..9ddcfe29d 100644 --- a/src/network/net_pcnet.c +++ b/src/network/net_pcnet.c @@ -2896,7 +2896,7 @@ pcnet_init(const device_t *info) dev = malloc(sizeof(nic_t)); memset(dev, 0x00, sizeof(nic_t)); dev->name = info->name; - dev->board = info->local; + dev->board = info->local & 0xff; dev->is_pci = !!(info->flags & DEVICE_PCI); dev->is_vlb = !!(info->flags & DEVICE_VLB); @@ -2997,7 +2997,10 @@ pcnet_init(const device_t *info) pcnet_pci_regs[0x04] = 3; /* Add device to the PCI bus, keep its slot number. */ - pci_add_card(PCI_ADD_NORMAL, pcnet_pci_read, pcnet_pci_write, dev, &dev->pci_slot); + if (info->local & 0x0100) + pci_add_card(PCI_ADD_NETWORK, pcnet_pci_read, pcnet_pci_write, dev, &dev->pci_slot); + else + pci_add_card(PCI_ADD_NORMAL, pcnet_pci_read, pcnet_pci_write, dev, &dev->pci_slot); } else if (dev->board == DEV_AM79C961) { dev->dma_channel = -1; @@ -3269,3 +3272,17 @@ const device_t pcnet_am79c973_device = { .force_redraw = NULL, .config = pcnet_pci_config }; + +const device_t pcnet_am79c973_onboard_device = { + .name = "AMD PCnet-FAST III", + .internal_name = "pcnetfast_onboard", + .flags = DEVICE_PCI, + .local = DEV_AM79C973 | 0x0100, + .init = pcnet_init, + .close = pcnet_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = pcnet_pci_config +}; diff --git a/src/network/net_plip.c b/src/network/net_plip.c index f622d455b..41e5502a6 100644 --- a/src/network/net_plip.c +++ b/src/network/net_plip.c @@ -34,7 +34,6 @@ #include <86box/thread.h> #include <86box/timer.h> #include <86box/network.h> -#include <86box/net_plip.h> #include <86box/plat_unused.h> enum { diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index 74a1f90ff..a7c007115 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -43,7 +43,6 @@ #include <86box/bswap.h> #include <86box/nvr.h> #include "cpu.h" -#include <86box/net_rtl8139.h> #include <86box/plat_unused.h> #define PCI_PERIOD 30 /* 30 ns period = 33.333333 Mhz frequency */ @@ -308,6 +307,8 @@ enum CSCRBits { #endif enum CSCRBits { CSCR_Testfun = 1 << 15, /* 1 = Auto-neg speeds up internal timer, WO, def 0 */ + CSCR_Cable_Changed = 1 << 11, /* Undocumented: 1 = Cable status changed, 0 = No change */ + CSCR_Cable = 1 << 10, /* Undocumented: 1 = Cable connected, 0 = Cable disconnected */ CSCR_LD = 1 << 9, /* Active low TPI link disable signal. When low, TPI still transmits link pulses and TPI stays in good link state. def 1*/ CSCR_HEART_BIT = 1 << 8, /* 1 = HEART BEAT enable, 0 = HEART BEAT disable. HEART BEAT function is only valid in 10Mbps mode. def 1*/ CSCR_JBEN = 1 << 7, /* 1 = enable jabber function. 0 = disable jabber function, def 1*/ @@ -2285,7 +2286,17 @@ rtl8139_TSAD_read(RTL8139State *s) static uint16_t rtl8139_CSCR_read(RTL8139State *s) { - uint16_t ret = s->CSCR; + static uint16_t old_ret = 0xffff; + uint16_t ret = s->CSCR | + ((net_cards_conf[s->nic->card_num].link_state & NET_LINK_DOWN) ? 0 : CSCR_Cable); + + if (old_ret != 0xffff) { + ret &= ~CSCR_Cable_Changed; + if ((ret ^ old_ret) & CSCR_Cable) + ret |= CSCR_Cable_Changed; + } + + old_ret = ret; rtl8139_log("CSCR read val=0x%04x\n", ret); @@ -2736,6 +2747,13 @@ rtl8139_io_readb(uint32_t addr, void *priv) rtl8139_log("RTL8139C TxConfig at 0x43 read(b) val=0x%02x\n", ret); break; + case CSCR: + ret = rtl8139_CSCR_read(s) & 0xff; + break; + case CSCR + 1: + ret = rtl8139_CSCR_read(s) >> 8; + break; + default: rtl8139_log("not implemented read(b) addr=0x%x\n", addr); ret = 0; @@ -3105,6 +3123,12 @@ rtl8139_pci_read(UNUSED(int func), int addr, void *priv) return 1; case 0x14: return 0; + case 0x15: +#ifdef USE_256_BYTE_BAR + return s->pci_conf[addr & 0xFF]; +#else + return s->pci_conf[addr & 0xFF] & 0xf0; +#endif case 0x2c: return 0xEC; case 0x2d: @@ -3164,15 +3188,27 @@ rtl8139_pci_write(int func, int addr, uint8_t val, void *priv) rtl8139_io_writeb_ioport, rtl8139_io_writew_ioport, rtl8139_io_writel_ioport, priv); break; +#ifndef USE_256_BYTE_BAR case 0x14: +#endif case 0x15: case 0x16: case 0x17: s->pci_conf[addr & 0xFF] = val; - s->mem_base = (s->pci_conf[0x15] << 8) | (s->pci_conf[0x16] << 16) | (s->pci_conf[0x17] << 24); + s->mem_base = (s->pci_conf[0x15] << 8) | (s->pci_conf[0x16] << 16) | + (s->pci_conf[0x17] << 24); +#ifndef USE_256_BYTE_BAR + s->mem_base &= 0xfffff000; +#endif rtl8139_log("New memory base: %08X\n", s->mem_base); if (s->pci_conf[0x4] & PCI_COMMAND_MEM) - mem_mapping_set_addr(&s->bar_mem, (s->pci_conf[0x15] << 8) | (s->pci_conf[0x16] << 16) | (s->pci_conf[0x17] << 24), 256); +#ifdef USE_256_BYTE_BAR + mem_mapping_set_addr(&s->bar_mem, (s->pci_conf[0x15] << 8) | (s->pci_conf[0x16] << 16) | + (s->pci_conf[0x17] << 24), 256); +#else + mem_mapping_set_addr(&s->bar_mem, ((s->pci_conf[0x15] & 0xf0) << 8) | + (s->pci_conf[0x16] << 16) | (s->pci_conf[0x17] << 24), 4096); +#endif break; case 0x3c: s->pci_conf[addr & 0xFF] = val; diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index b74b345bc..ffc342e81 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -32,7 +32,6 @@ #include <86box/thread.h> #include <86box/network.h> #include <86box/net_eeprom_nmc93cxx.h> -#include <86box/net_tulip.h> #include <86box/bswap.h> #include <86box/plat_fallthrough.h> #include <86box/plat_unused.h> @@ -323,6 +322,9 @@ struct TULIPState { uint32_t mii_word; uint32_t mii_bitcnt; + /* 21040 ROM read address. */ + uint8_t rom_read_addr; + uint32_t current_rx_desc; uint32_t current_tx_desc; @@ -666,6 +668,9 @@ tulip_mii(TULIPState *s) static uint32_t tulip_csr9_read(TULIPState *s) { + if (s->device_info->local == 3) { + return s->eeprom_data[s->rom_read_addr++]; + } if (s->csr[9] & CSR9_SR) { if (nmc93cxx_eeprom_read(s->eeprom)) { s->csr[9] |= CSR9_SR_DO; @@ -698,6 +703,10 @@ tulip_read(uint32_t addr, void *opaque) break; case CSR(12): + if (s->device_info->local == 3) { + data = 0; + break; + } /* Fake autocompletion complete until we have PHY emulation */ data = 5 << CSR12_ANS_SHIFT; break; @@ -884,8 +893,10 @@ tulip_reset(void *priv) s->csr[13] = 0xffff0000; s->csr[14] = 0xffffffff; s->csr[15] = 0x8ff00000; - s->subsys_id = eeprom_data[1]; - s->subsys_ven_id = eeprom_data[0]; + if (s->device_info->local != 3) { + s->subsys_id = eeprom_data[1]; + s->subsys_ven_id = eeprom_data[0]; + } } static void @@ -955,12 +966,16 @@ tulip_write(uint32_t addr, uint32_t data, void *opaque) break; case CSR(9): - tulip_csr9_write(s, s->csr[9], data); - /* don't clear MII read data */ - s->csr[9] &= CSR9_MDI; - s->csr[9] |= (data & ~CSR9_MDI); - tulip_mii(s); - s->old_csr9 = s->csr[9]; + if (s->device_info->local != 3) { + tulip_csr9_write(s, s->csr[9], data); + /* don't clear MII read data */ + s->csr[9] &= CSR9_MDI; + s->csr[9] |= (data & ~CSR9_MDI); + tulip_mii(s); + s->old_csr9 = s->csr[9]; + } else { + s->rom_read_addr = 0; + } break; case CSR(10): @@ -978,6 +993,11 @@ tulip_write(uint32_t addr, uint32_t data, void *opaque) case CSR(13): s->csr[13] = data; + if (s->device_info->local == 3 && (data & 0x4)) { + s->csr[13] = 0x8f01; + s->csr[14] = 0xfffd; + s->csr[15] = 0; + } break; case CSR(14): @@ -1017,37 +1037,55 @@ tulip_writel_io(uint16_t addr, uint32_t data, void *opaque) static void tulip_mem_writeb(uint32_t addr, uint8_t data, void *opaque) { - return tulip_write(addr, data, opaque); + if ((addr & 0xfff) < 0x100) + tulip_write(addr, data, opaque); } static void tulip_mem_writew(uint32_t addr, uint16_t data, void *opaque) { - return tulip_write(addr, data, opaque); + if ((addr & 0xfff) < 0x100) + tulip_write(addr, data, opaque); } static void tulip_mem_writel(uint32_t addr, uint32_t data, void *opaque) { - return tulip_write(addr, data, opaque); + if ((addr & 0xfff) < 0x100) + tulip_write(addr, data, opaque); } static uint8_t tulip_mem_readb(uint32_t addr, void *opaque) { - return tulip_read(addr, opaque); + uint8_t ret = 0xff; + + if ((addr & 0xfff) < 0x100) + ret = tulip_read(addr, opaque); + + return ret; } static uint16_t tulip_mem_readw(uint32_t addr, void *opaque) { - return tulip_read(addr, opaque); + uint16_t ret = 0xffff; + + if ((addr & 0xfff) < 0x100) + ret = tulip_read(addr, opaque); + + return ret; } static uint32_t tulip_mem_readl(uint32_t addr, void *opaque) { - return tulip_read(addr, opaque); + uint32_t ret = 0xffffffff; + + if ((addr & 0xfff) < 0x100) + ret = tulip_read(addr, opaque); + + return ret; } static uint8_t @@ -1141,7 +1179,9 @@ tulip_pci_read(UNUSED(int func), int addr, void *priv) ret = 0x10; break; case 0x02: - if (s->device_info->local) + if (s->device_info->local == 3) + ret = 0x02; + else if (s->device_info->local) ret = 0x09; else ret = 0x19; @@ -1185,11 +1225,17 @@ tulip_pci_read(UNUSED(int func), int addr, void *priv) case 0x13: ret = tulip_pci_bar[0].addr_regs[3]; break; +#ifdef USE_128_BYTE_BAR case 0x14: ret = (tulip_pci_bar[1].addr_regs[0] & 0x80); break; +#endif case 0x15: +#ifdef USE_128_BYTE_BAR ret = tulip_pci_bar[1].addr_regs[1]; +#else + ret = tulip_pci_bar[1].addr_regs[1] & 0xf0; +#endif break; case 0x16: ret = tulip_pci_bar[1].addr_regs[2]; @@ -1229,6 +1275,7 @@ tulip_pci_read(UNUSED(int func), int addr, void *priv) break; case 0x3E: case 0x3F: + case 0x41: ret = s->pci_conf[addr & 0xff]; break; } @@ -1259,7 +1306,7 @@ tulip_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) //pclog("PCI write cmd: IOBase=%04x, MMIOBase=%08x, val=%02x.\n", s->PCIBase, s->MMIOBase, s->pci_conf[0x04]); mem_mapping_disable(&s->memory); if ((s->MMIOBase != 0) && (val & PCI_COMMAND_MEM)) - mem_mapping_set_addr(&s->memory, s->MMIOBase, 128); + mem_mapping_enable(&s->memory); break; case 0x05: s->pci_conf[0x05] = val & 1; @@ -1284,18 +1331,28 @@ tulip_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) priv); } break; +#ifndef USE_128_BYTE_BAR case 0x14: +#endif case 0x15: case 0x16: case 0x17: mem_mapping_disable(&s->memory); tulip_pci_bar[1].addr_regs[addr & 3] = val; +#ifdef USE_128_BYTE_BAR tulip_pci_bar[1].addr &= 0xffffff80; +#else + tulip_pci_bar[1].addr &= 0xfffff000; +#endif s->MMIOBase = tulip_pci_bar[1].addr; if (s->pci_conf[0x4] & PCI_COMMAND_MEM) { //pclog("PCI write=%02x, mmiobase=%08x, mmio?=%x.\n", addr, s->PCIBase, s->pci_conf[0x4] & PCI_COMMAND_MEM); if (s->MMIOBase != 0) +#ifdef USE_128_BYTE_BAR mem_mapping_set_addr(&s->memory, s->MMIOBase, 128); +#else + mem_mapping_set_addr(&s->memory, s->MMIOBase, 4096); +#endif } break; case 0x30: /* PCI_ROMBAR */ @@ -1319,6 +1376,7 @@ tulip_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) return; case 0x3E: case 0x3F: + case 0x41: s->pci_conf[addr & 0xff] = val; return; } @@ -1336,7 +1394,7 @@ nic_init(const device_t *info) if (!s) return NULL; - if (info->local) { + if (info->local && info->local != 3) { s->bios_addr = 0xD0000; s->has_bios = device_get_config_int("bios"); } else { @@ -1344,152 +1402,219 @@ nic_init(const device_t *info) s->has_bios = 0; } +#ifdef USE_128_BYTE_BAR mem_mapping_add(&s->memory, 0x0fffff00, 128, tulip_mem_readb, tulip_mem_readw, tulip_mem_readl, tulip_mem_writeb, tulip_mem_writew, tulip_mem_writel, NULL, MEM_MAPPING_EXTERNAL, s); +#else + mem_mapping_add(&s->memory, 0x0ffff000, 4096, tulip_mem_readb, tulip_mem_readw, tulip_mem_readl, tulip_mem_writeb, tulip_mem_writew, tulip_mem_writel, NULL, MEM_MAPPING_EXTERNAL, s); +#endif mem_mapping_disable(&s->memory); s->device_info = info; - /*Subsystem Vendor ID*/ - s->eeprom_data[0] = info->local ? 0x25 : 0x11; - s->eeprom_data[1] = 0x10; + if (info->local != 3) { + if (info->local == 2) { + /*Subsystem Vendor ID*/ + s->eeprom_data[0] = 0x00; + s->eeprom_data[1] = 0x0a; - /*Subsystem ID*/ - s->eeprom_data[2] = info->local ? 0x10 : 0x0a; - s->eeprom_data[3] = info->local ? 0x03 : 0x50; + /*Subsystem ID*/ + s->eeprom_data[2] = 0x14; + s->eeprom_data[3] = 0x21; + } else { + /*Subsystem Vendor ID*/ + s->eeprom_data[0] = info->local ? 0x25 : 0x11; + s->eeprom_data[1] = 0x10; - /*Cardbus CIS Pointer low*/ - s->eeprom_data[4] = 0x00; - s->eeprom_data[5] = 0x00; + /*Subsystem ID*/ + s->eeprom_data[2] = info->local ? 0x10 : 0x0a; + s->eeprom_data[3] = info->local ? 0x03 : 0x50; + } - /*Cardbus CIS Pointer high*/ - s->eeprom_data[6] = 0x00; - s->eeprom_data[7] = 0x00; + /*Cardbus CIS Pointer low*/ + s->eeprom_data[4] = 0x00; + s->eeprom_data[5] = 0x00; - /*ID Reserved1*/ - for (int i = 0; i < 7; i++) - s->eeprom_data[8 + i] = 0x00; + /*Cardbus CIS Pointer high*/ + s->eeprom_data[6] = 0x00; + s->eeprom_data[7] = 0x00; - /*MiscHwOptions*/ - s->eeprom_data[15] = 0x00; + /*ID Reserved1*/ + for (int i = 0; i < 7; i++) + s->eeprom_data[8 + i] = 0x00; - /*ID_BLOCK_CRC*/ - tulip_idblock_crc((uint16_t *) s->eeprom_data); + /*MiscHwOptions*/ + s->eeprom_data[15] = 0x00; - /*Func0_HwOptions*/ - s->eeprom_data[17] = 0x00; + /*ID_BLOCK_CRC*/ + tulip_idblock_crc((uint16_t *) s->eeprom_data); - /*SROM Format Version 1, compatible with older guests*/ - s->eeprom_data[18] = 0x01; + /*Func0_HwOptions*/ + s->eeprom_data[17] = 0x00; - /*Controller Count*/ - s->eeprom_data[19] = 0x01; + /*SROM Format Version 1, compatible with older guests*/ + s->eeprom_data[18] = 0x01; - /*DEC OID*/ - s->eeprom_data[20] = 0x00; - s->eeprom_data[21] = 0x00; - s->eeprom_data[22] = 0xf8; + /*Controller Count*/ + s->eeprom_data[19] = 0x01; - if (info->local == 2) { - /* Microsoft VPC DEC Tulip. */ + /*DEC OID*/ s->eeprom_data[20] = 0x00; - s->eeprom_data[21] = 0x03; - s->eeprom_data[22] = 0x0f; - } + s->eeprom_data[21] = 0x00; + s->eeprom_data[22] = 0xf8; - /* See if we have a local MAC address configured. */ - mac = device_get_config_mac("mac", -1); + if (info->local == 2) { + /* Microsoft VPC DEC Tulip. */ + s->eeprom_data[20] = 0x00; + s->eeprom_data[21] = 0x03; + s->eeprom_data[22] = 0x0f; + } - /* Set up our BIA. */ - if (mac & 0xff000000) { - /* Generate new local MAC. */ - s->eeprom_data[23] = random_generate(); - s->eeprom_data[24] = random_generate(); - s->eeprom_data[25] = random_generate(); - mac = (((int) s->eeprom_data[23]) << 16); - mac |= (((int) s->eeprom_data[24]) << 8); - mac |= ((int) s->eeprom_data[25]); - device_set_config_mac("mac", mac); + /* See if we have a local MAC address configured. */ + mac = device_get_config_mac("mac", -1); + + /* Set up our BIA. */ + if (mac & 0xff000000) { + /* Generate new local MAC. */ + s->eeprom_data[23] = random_generate(); + s->eeprom_data[24] = random_generate(); + s->eeprom_data[25] = random_generate(); + mac = (((int) s->eeprom_data[23]) << 16); + mac |= (((int) s->eeprom_data[24]) << 8); + mac |= ((int) s->eeprom_data[25]); + device_set_config_mac("mac", mac); + } else { + s->eeprom_data[23] = (mac >> 16) & 0xff; + s->eeprom_data[24] = (mac >> 8) & 0xff; + s->eeprom_data[25] = (mac & 0xff); + } + + /*Controller_0 Device_Number*/ + s->eeprom_data[26] = 0x00; + + /*Controller_0 Info Leaf_Offset*/ + s->eeprom_data[27] = 0x1e; + s->eeprom_data[28] = 0x00; + + /*Selected Connection Type, Powerup AutoSense and Dynamic AutoSense if the board supports it*/ + s->eeprom_data[30] = 0x00; + s->eeprom_data[31] = 0x08; + + if (info->local) { + /*General Purpose Control*/ + s->eeprom_data[32] = 0xff; + + /*Block Count*/ + s->eeprom_data[33] = 0x01; + + /*Extended Format (first part)*/ + /*Length (0:6) and Format Indicator (7)*/ + s->eeprom_data[34] = 0x81; + + /*Block Type (first part)*/ + s->eeprom_data[35] = 0x01; + + /*Extended Format (second part) - Block Type 0 for 21140*/ + /*Length (0:6) and Format Indicator (7)*/ + s->eeprom_data[36] = 0x85; + + /*Block Type (second part)*/ + s->eeprom_data[37] = 0x00; + + /*Media Code (0:5), EXT (6), Reserved (7)*/ + s->eeprom_data[38] = 0x01; + + /*General Purpose Data*/ + s->eeprom_data[39] = 0x00; + + /*Command*/ + s->eeprom_data[40] = 0x00; + s->eeprom_data[41] = 0x00; + } else { + /*Block Count*/ + s->eeprom_data[32] = 0x01; + + /*Extended Format - Block Type 2 for 21142/21143*/ + /*Length (0:6) and Format Indicator (7)*/ + s->eeprom_data[33] = 0x86; + + /*Block Type*/ + s->eeprom_data[34] = 0x02; + + /*Media Code (0:5), EXT (6), Reserved (7)*/ + s->eeprom_data[35] = 0x01; + + /*General Purpose Control*/ + s->eeprom_data[36] = 0xff; + s->eeprom_data[37] = 0xff; + + /*General Purpose Data*/ + s->eeprom_data[38] = 0x00; + s->eeprom_data[39] = 0x00; + } + + s->eeprom_data[126] = tulip_srom_crc(s->eeprom_data) & 0xff; + s->eeprom_data[127] = tulip_srom_crc(s->eeprom_data) >> 8; } else { - s->eeprom_data[23] = (mac >> 16) & 0xff; - s->eeprom_data[24] = (mac >> 8) & 0xff; - s->eeprom_data[25] = (mac & 0xff); + uint32_t checksum = 0; + /* 21040 is supposed to only have MAC address in its serial ROM if Linux is correct. */ + memset(s->eeprom_data, 0, sizeof(s->eeprom_data)); + /* See if we have a local MAC address configured. */ + mac = device_get_config_mac("mac", -1); + /*DEC OID*/ + s->eeprom_data[0] = 0x00; + s->eeprom_data[1] = 0x00; + s->eeprom_data[2] = 0xF8; + if (mac & 0xff000000) { + /* Generate new local MAC. */ + s->eeprom_data[3] = random_generate(); + s->eeprom_data[4] = random_generate(); + s->eeprom_data[5] = random_generate(); + mac = (((int) s->eeprom_data[3]) << 16); + mac |= (((int) s->eeprom_data[4]) << 8); + mac |= ((int) s->eeprom_data[5]); + device_set_config_mac("mac", mac); + } else { + s->eeprom_data[3] = (mac >> 16) & 0xff; + s->eeprom_data[4] = (mac >> 8) & 0xff; + s->eeprom_data[5] = (mac & 0xff); + } + + /* Generate checksum. */ + checksum = (s->eeprom_data[0] * 256) | s->eeprom_data[1]; + checksum *= 2; + if (checksum > 65535) + checksum = checksum % 65535; + + /* 2nd pair. */ + checksum += (s->eeprom_data[2] * 256) | s->eeprom_data[3]; + if (checksum > 65535) + checksum = checksum % 65535; + checksum *= 2; + if (checksum > 65535) + checksum = checksum % 65535; + + /* 3rd pair. */ + checksum += (s->eeprom_data[4] * 256) | s->eeprom_data[5]; + if (checksum > 65535) + checksum = checksum % 65535; + + if (checksum >= 65535) + checksum = 0; + + s->eeprom_data[6] = (checksum >> 8) & 0xFF; + s->eeprom_data[7] = checksum & 0xFF; } - /*Controller_0 Device_Number*/ - s->eeprom_data[26] = 0x00; - - /*Controller_0 Info Leaf_Offset*/ - s->eeprom_data[27] = 0x1e; - s->eeprom_data[28] = 0x00; - - /*Selected Connection Type, Powerup AutoSense and Dynamic AutoSense if the board supports it*/ - s->eeprom_data[30] = 0x00; - s->eeprom_data[31] = 0x08; - - if (info->local) { - /*General Purpose Control*/ - s->eeprom_data[32] = 0xff; - - /*Block Count*/ - s->eeprom_data[33] = 0x01; - - /*Extended Format (first part)*/ - /*Length (0:6) and Format Indicator (7)*/ - s->eeprom_data[34] = 0x81; - - /*Block Type (first part)*/ - s->eeprom_data[35] = 0x01; - - /*Extended Format (second part) - Block Type 0 for 21140*/ - /*Length (0:6) and Format Indicator (7)*/ - s->eeprom_data[36] = 0x85; - - /*Block Type (second part)*/ - s->eeprom_data[37] = 0x00; - - /*Media Code (0:5), EXT (6), Reserved (7)*/ - s->eeprom_data[38] = 0x01; - - /*General Purpose Data*/ - s->eeprom_data[39] = 0x00; - - /*Command*/ - s->eeprom_data[40] = 0x00; - s->eeprom_data[41] = 0x00; - } else { - /*Block Count*/ - s->eeprom_data[32] = 0x01; - - /*Extended Format - Block Type 2 for 21142/21143*/ - /*Length (0:6) and Format Indicator (7)*/ - s->eeprom_data[33] = 0x86; - - /*Block Type*/ - s->eeprom_data[34] = 0x02; - - /*Media Code (0:5), EXT (6), Reserved (7)*/ - s->eeprom_data[35] = 0x01; - - /*General Purpose Control*/ - s->eeprom_data[36] = 0xff; - s->eeprom_data[37] = 0xff; - - /*General Purpose Data*/ - s->eeprom_data[38] = 0x00; - s->eeprom_data[39] = 0x00; - } - - s->eeprom_data[126] = tulip_srom_crc(s->eeprom_data) & 0xff; - s->eeprom_data[127] = tulip_srom_crc(s->eeprom_data) >> 8; - - params.nwords = 64; - params.default_content = (uint16_t *) s->eeprom_data; - params.filename = filename; - snprintf(filename, sizeof(filename), "nmc93cxx_eeprom_%s_%d.nvr", info->internal_name, device_get_instance()); - s->eeprom = device_add_parameters(&nmc93cxx_device, ¶ms); - if (!s->eeprom) { - free(s); - return NULL; + if (info->local != 3) { + params.nwords = 64; + params.default_content = (uint16_t *) s->eeprom_data; + params.filename = filename; + snprintf(filename, sizeof(filename), "nmc93cxx_eeprom_%s_%d.nvr", info->internal_name, device_get_instance()); + s->eeprom = device_add_parameters(&nmc93cxx_device, ¶ms); + if (!s->eeprom) { + free(s); + return NULL; + } } tulip_pci_bar[0].addr_regs[0] = 1; @@ -1504,11 +1629,11 @@ nic_init(const device_t *info) tulip_pci_bar[2].addr = 0; mem_mapping_disable(&s->bios_rom.mapping); - eeprom_data = (uint8_t *) &nmc93cxx_eeprom_data(s->eeprom)[0]; + eeprom_data = (info->local == 3) ? s->eeprom_data : (uint8_t *) &nmc93cxx_eeprom_data(s->eeprom)[0]; //pclog("EEPROM Data Format=%02x, Count=%02x, MAC=%02x:%02x:%02x:%02x:%02x:%02x.\n", eeprom_data[0x12], eeprom_data[0x13], eeprom_data[0x14], eeprom_data[0x15], eeprom_data[0x16], eeprom_data[0x17], eeprom_data[0x18], eeprom_data[0x19]); memcpy(s->mii_regs, tulip_mdi_default, sizeof(tulip_mdi_default)); - s->nic = network_attach(s, &eeprom_data[20], tulip_receive, NULL); + s->nic = network_attach(s, &eeprom_data[(info->local == 3) ? 0 : 20], tulip_receive, NULL); pci_add_card(PCI_ADD_NORMAL, tulip_pci_read, tulip_pci_write, s, &s->pci_slot); tulip_reset(s); return s; @@ -1592,3 +1717,17 @@ const device_t dec_tulip_21140_vpc_device = { .force_redraw = NULL, .config = dec_tulip_21140_config }; + +const device_t dec_tulip_21040_device = { + .name = "DEC DE-435 EtherWorks Turbo (DECchip 21040 \"Tulip\")", + .internal_name = "dec_21040_tulip", + .flags = DEVICE_PCI, + .local = 3, + .init = nic_init, + .close = nic_close, + .reset = tulip_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = dec_tulip_21143_config +}; diff --git a/src/network/network.c b/src/network/network.c index 38af502b2..9eb537e3a 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -67,14 +67,9 @@ #include <86box/ui.h> #include <86box/timer.h> #include <86box/network.h> -#include <86box/net_3c501.h> -#include <86box/net_3c503.h> #include <86box/net_ne2000.h> #include <86box/net_pcnet.h> -#include <86box/net_plip.h> #include <86box/net_wd8003.h> -#include <86box/net_tulip.h> -#include <86box/net_rtl8139.h> #ifdef _WIN32 # define WIN32_LEAN_AND_MEAN @@ -117,6 +112,9 @@ static const device_t *net_cards[] = { &threec503_device, &pcnet_am79c960_device, &pcnet_am79c961_device, + &de220p_device, + &ne1000_compat_device, + &ne2000_compat_device, &ne1000_device, &ne2000_device, &pcnet_am79c960_eb_device, @@ -136,6 +134,7 @@ static const device_t *net_cards[] = { &rtl8139c_plus_device, &dec_tulip_21140_device, &dec_tulip_21140_vpc_device, + &dec_tulip_21040_device, &pcnet_am79c960_vlb_device, NULL }; diff --git a/src/nvr_at.c b/src/nvr_at.c index c66799579..4ddec729f 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -686,13 +686,26 @@ nvr_write(uint16_t addr, uint8_t val, void *priv) } } +/* Get the NVR register index (used for APC). */ +uint8_t +nvr_get_index(void *priv, uint8_t addr_id) +{ + nvr_t *nvr = (nvr_t *) priv; + local_t *local = (local_t *) nvr->data; + uint8_t ret; + + ret = local->addr[addr_id]; + + return ret; +} + /* Read from one of the NVR registers. */ static uint8_t nvr_read(uint16_t addr, void *priv) { nvr_t *nvr = (nvr_t *) priv; const local_t *local = (local_t *) nvr->data; - uint8_t ret; + uint8_t ret = 0xff; uint8_t addr_id = (addr & 0x0e) >> 1; uint16_t i; uint16_t checksum = 0x0000; @@ -810,7 +823,8 @@ nvr_read(uint16_t addr, void *priv) break; default: - ret = nvr->regs[local->addr[addr_id]]; + if (!(local->lock[local->addr[addr_id]] & 0x02)) + ret = nvr->regs[local->addr[addr_id]]; break; } else { @@ -931,6 +945,17 @@ nvr_at_index_read_handler(int set, uint16_t base, nvr_t *nvr) } } +void +nvr_at_data_port(int set, nvr_t *nvr) +{ + io_handler(0, 0x71, 1, + nvr_read, NULL, NULL, nvr_write, NULL, NULL, nvr); + + if (set) + io_handler(1, 0x71, 1, + nvr_read, NULL, NULL, nvr_write, NULL, NULL, nvr); +} + void nvr_at_sec_handler(int set, uint16_t base, nvr_t *nvr) { diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index fb96de1ea..4f073cf4a 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -197,8 +197,7 @@ if(WIN32) else() target_sources(plat PRIVATE win_joystick_rawinput.c) endif() - target_sources(ui PRIVATE qt_d3d9renderer.hpp qt_d3d9renderer.cpp) - target_link_libraries(86Box hid d3d9) + target_link_libraries(86Box hid) # CMake 3.22 messed this up for clang/clang++ # See https://gitlab.kitware.com/cmake/cmake/-/issues/22611 diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index 371781b7a..483e6ee53 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -352,6 +352,9 @@ msgstr "Tipus de CPU:" msgid "Speed:" msgstr "Velocitat:" +msgid "Frequency:" +msgstr "Freqüència:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,8 @@ msgstr "Vídeo:" msgid "Voodoo Graphics" msgstr "Gràfics Voodoo" -msgid "IBM 8514/a Graphics" -msgstr "Gràfics IBM 8514/a" +msgid "IBM 8514/A Graphics" +msgstr "Gràfics IBM 8514/A" msgid "XGA Graphics" msgstr "Gràfics XGA" @@ -409,16 +412,16 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Targeta de so 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Targeta de so 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Targeta de so 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Targeta de so 4:" msgid "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "Imatges avançates del sector" msgid "Flux images" msgstr "Imatges de flux" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "No has estat possible inicialitzar SDL, és necessari SDL2.dll" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Esteu segur que voleu restablir la màquina emulada?" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index d86f5b635..84c795092 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -352,6 +352,9 @@ msgstr "Procesor:" msgid "Speed:" msgstr "Rychlost:" +msgid "Frequency:" +msgstr "Frekvence:" + msgid "FPU:" msgstr "Koprocesor:" @@ -385,8 +388,8 @@ msgstr "Grafika:" msgid "Voodoo Graphics" msgstr "Použít grafický akcelerátor Voodoo" -msgid "IBM 8514/a Graphics" -msgstr "Grafika IBM 8514/a" +msgid "IBM 8514/A Graphics" +msgstr "Grafika IBM 8514/A" msgid "XGA Graphics" msgstr "Grafika XGA" @@ -409,16 +412,16 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Zvuková karta 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Zvuková karta 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Zvuková karta 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Zvuková karta 4:" msgid "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "Rozšířené sektorové obrazy" msgid "Flux images" msgstr "Obrazy magnetického toku" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Nastala chyba při inicializaci knihovny SDL, je potřeba SDL2.dll" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Opravdu chcete resetovat emulovaný počítač?" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index 9c985d871..4a4fde3c2 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -352,6 +352,9 @@ msgstr "CPU-Typ:" msgid "Speed:" msgstr "Takt:" +msgid "Frequency:" +msgstr "Frequenz:" + msgid "FPU:" msgstr "FPU-Einheit:" @@ -385,8 +388,8 @@ msgstr "Videokarte:" msgid "Voodoo Graphics" msgstr "Voodoo-Grafik" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/a-Grafik" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A-Grafik" msgid "XGA Graphics" msgstr "XGA-Grafik" @@ -409,16 +412,16 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Soundkarte 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Soundkarte 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Soundkarte 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Soundkarte 4:" msgid "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "Fortgeschrittene Sektorimages" msgid "Flux images" msgstr "Fluximages" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "SDL konnte nicht initialisiert werden, die Datei SDL2.dll wird benötigt" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Sind Sie sich sicher, dass Sie einen Hard-Reset für das emulierte System durchführen wollen?" diff --git a/src/qt/languages/en-GB.po b/src/qt/languages/en-GB.po index 4a6a58db6..031a365c0 100644 --- a/src/qt/languages/en-GB.po +++ b/src/qt/languages/en-GB.po @@ -352,6 +352,9 @@ msgstr "CPU type:" msgid "Speed:" msgstr "Speed:" +msgid "Frequency:" +msgstr "Frequency:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,8 @@ msgstr "Video:" msgid "Voodoo Graphics" msgstr "Voodoo Graphics" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/a Graphics" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A Graphics" msgid "XGA Graphics" msgstr "XGA Graphics" @@ -409,17 +412,17 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card 1:" -msgstr "Sound card 1:" +msgid "Sound card #1:" +msgstr "Sound card #1:" -msgid "Sound card 2:" -msgstr "Sound card 2:" +msgid "Sound card #2:" +msgstr "Sound card #2:" -msgid "Sound card 3:" -msgstr "Sound card 3:" +msgid "Sound card #3:" +msgstr "Sound card #3:" -msgid "Sound card 4:" -msgstr "Sound card 4:" +msgid "Sound card #4:" +msgstr "Sound card #4:" msgid "MIDI Out Device:" msgstr "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "Advanced sector images" msgid "Flux images" msgstr "Flux images" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Unable to initialize SDL, SDL2.dll is required" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Are you sure you want to hard reset the emulated machine?" diff --git a/src/qt/languages/en-US.po b/src/qt/languages/en-US.po index ce7ceb149..06a4b60f1 100644 --- a/src/qt/languages/en-US.po +++ b/src/qt/languages/en-US.po @@ -352,6 +352,9 @@ msgstr "CPU type:" msgid "Speed:" msgstr "Speed:" +msgid "Frequency:" +msgstr "Frequency:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,8 @@ msgstr "Video:" msgid "Voodoo Graphics" msgstr "Voodoo Graphics" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/a Graphics" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A Graphics" msgid "XGA Graphics" msgstr "XGA Graphics" @@ -409,17 +412,17 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card 1:" -msgstr "Sound card 1:" +msgid "Sound card #1:" +msgstr "Sound card #1:" -msgid "Sound card 2:" -msgstr "Sound card 2:" +msgid "Sound card #2:" +msgstr "Sound card #2:" -msgid "Sound card 3:" -msgstr "Sound card 3:" +msgid "Sound card #3:" +msgstr "Sound card #3:" -msgid "Sound card 4:" -msgstr "Sound card 4:" +msgid "Sound card #4:" +msgstr "Sound card #4:" msgid "MIDI Out Device:" msgstr "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "Advanced sector images" msgid "Flux images" msgstr "Flux images" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Unable to initialize SDL, SDL2.dll is required" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Are you sure you want to hard reset the emulated machine?" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index d8d648691..60ac5fb5c 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -352,6 +352,9 @@ msgstr "Tipo de CPU:" msgid "Speed:" msgstr "Velocidad:" +msgid "Frequency:" +msgstr "Frecuencia:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,8 @@ msgstr "Vídeo:" msgid "Voodoo Graphics" msgstr "Voodoo Graphics" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/a Graphics" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A Graphics" msgid "XGA Graphics" msgstr "XGA Graphics" @@ -409,16 +412,16 @@ msgstr "Mando 3..." msgid "Joystick 4..." msgstr "Mando 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Tarjeta de sonido 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Tarjeta de sonido 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Tarjeta de sonido 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Tarjeta de sonido 4:" msgid "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "Imágenes avanzadas de sector" msgid "Flux images" msgstr "Imágenes de fluxo" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Incapaz de inicializar SDL, se requiere SDL2.dll" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "¿Está seguro de que quieres hacer una reinicialización completa de la máquina emulada?" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index 217827f74..50ebffccb 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -352,6 +352,9 @@ msgstr "Suorittimen tyyppi:" msgid "Speed:" msgstr "Nopeus:" +msgid "Frequency:" +msgstr "Taajuus:" + msgid "FPU:" msgstr "Apusuoritin:" @@ -385,8 +388,8 @@ msgstr "Näytönohjain:" msgid "Voodoo Graphics" msgstr "Voodoo-grafiikkasuoritin" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/a-grafiikkasuoritin" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A-grafiikkasuoritin" msgid "XGA Graphics" msgstr "XGA-grafiikkasuoritin" @@ -409,16 +412,16 @@ msgstr "Peliohjain 3..." msgid "Joystick 4..." msgstr "Peliohjain 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Äänikortti 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Äänikortti 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Äänikortti 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Äänikortti 4:" msgid "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "Kehittyneet sektorilevykuvat" msgid "Flux images" msgstr "Flux-levykuvat" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "SDL:n alustus epäonnistui. Tarvitaan SDL2.dll" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Haluatko varmasti käynnistää emuloidun tietokoneen uudelleen?" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index be66e5924..52bccebd2 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -352,6 +352,9 @@ msgstr "Type du processeur:" msgid "Speed:" msgstr "Vitesse:" +msgid "Frequency:" +msgstr "Fréquence:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,8 @@ msgstr "Vidéo:" msgid "Voodoo Graphics" msgstr "Graphique Voodoo" -msgid "IBM 8514/a Graphics" -msgstr "Graphique IBM 8514/a" +msgid "IBM 8514/A Graphics" +msgstr "Graphique IBM 8514/A" msgid "XGA Graphics" msgstr "Graphique XGA" @@ -409,16 +412,16 @@ msgstr "Manette 3..." msgid "Joystick 4..." msgstr "Manette 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Carte son 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Carte son 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Carte son 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Carte son 4:" msgid "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "Images du secteur avancés" msgid "Flux images" msgstr "Images du flux" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Impossible d'initialiser SDL, SDL2.dll est nécessaire" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Etes-vous sûr de vouloir réinitialiser la machine émulée ?" diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index b2aa40d28..19b6a6e85 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -352,6 +352,9 @@ msgstr "Tip procesora:" msgid "Speed:" msgstr "Brzina:" +msgid "Frequency:" +msgstr "Frekvencija:" + msgid "FPU:" msgstr "FPU uređaj:" @@ -385,8 +388,8 @@ msgstr "Video:" msgid "Voodoo Graphics" msgstr "Voodoo grafika" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/a grafika" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A grafika" msgid "XGA Graphics" msgstr "XGA grafika" @@ -409,16 +412,16 @@ msgstr "Palica za igru 3..." msgid "Joystick 4..." msgstr "Palica za igru 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Zvučna kartica 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Zvučna kartica 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Zvučna kartica 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Zvučna kartica 4:" msgid "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "Napredne sektorske slike" msgid "Flux images" msgstr "Flux slike" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Nije moguće inicijalizirati SDL, SDL2.dll je potrebno" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Jeste li sigurni da želite hard resetirati emulirani sistem?" diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index 352a64749..338d2ff5e 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -352,6 +352,9 @@ msgstr "Processzor:" msgid "Speed:" msgstr "Seb.:" +msgid "Frequency:" +msgstr "Frekvencia:" + msgid "FPU:" msgstr "FPU-egység:" @@ -385,8 +388,8 @@ msgstr "Videokártya:" msgid "Voodoo Graphics" msgstr "Voodoo-gyorsítókártya" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/a-gyorsítókártya" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A-gyorsítókártya" msgid "XGA Graphics" msgstr "XGA-gyorsítókártya" @@ -409,16 +412,16 @@ msgstr "Játékvez. 3..." msgid "Joystick 4..." msgstr "Játékvez. 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Hangkártya 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Hangkártya 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Hangkártya 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Hangkártya 4:" msgid "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "Továbbfejlesztett szektor képek" msgid "Flux images" msgstr "Flux képekfájlok" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Az SDL inicializálása nem lehetséges, az SDL2.dll fájl szükséges" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Biztosan szeretné újraindítani az emulált gépet?" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index df71d148b..20c15c656 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -352,6 +352,9 @@ msgstr "Tipo del CPU:" msgid "Speed:" msgstr "Veloc.:" +msgid "Frequency:" +msgstr "Frequenza:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,8 @@ msgstr "Video:" msgid "Voodoo Graphics" msgstr "Grafica Voodoo" -msgid "IBM 8514/a Graphics" -msgstr "Grafica IBM 8514/a" +msgid "IBM 8514/A Graphics" +msgstr "Grafica IBM 8514/A" msgid "XGA Graphics" msgstr "Grafica XGA" @@ -409,16 +412,16 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Scheda audio 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Scheda audio 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Scheda audio 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Scheda audio 4:" msgid "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "Immagini da settori avanzati" msgid "Flux images" msgstr "Immagini flusso" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Impossibile inizializzare SDL, SDL2.dll è necessario" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Sei sicuro di voler riavviare la macchina emulata?" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 7ea47bc1a..d0f206dc9 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -352,6 +352,9 @@ msgstr "CPUタイプ:" msgid "Speed:" msgstr "速度:" +msgid "Frequency:" +msgstr "頻度:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,8 @@ msgstr "ビデオカード:" msgid "Voodoo Graphics" msgstr "Voodooグラフィック" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/aグラフィック" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/Aグラフィック" msgid "XGA Graphics" msgstr "XGAグラフィック" @@ -409,16 +412,16 @@ msgstr "ジョイスティック3..." msgid "Joystick 4..." msgstr "ジョイスティック4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "サウンドカード1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "サウンドカード2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "サウンドカード3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "サウンドカード4:" msgid "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "アドバンスドセクターイメージ" msgid "Flux images" msgstr "Fluxイメージ" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "SDLが初期化できません。SDL2.dllが必要です" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "使用中のマシンをハード リセットしますか?" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index ac4476ca8..f5d1502b0 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -352,6 +352,9 @@ msgstr "CPU 종류:" msgid "Speed:" msgstr "속도:" +msgid "Frequency:" +msgstr "빈도:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,8 @@ msgstr "비디오 카드:" msgid "Voodoo Graphics" msgstr "Voodoo 그래픽" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/a 그래픽" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A 그래픽" msgid "XGA Graphics" msgstr "XGA 그래픽" @@ -409,16 +412,16 @@ msgstr "조이스틱 3..." msgid "Joystick 4..." msgstr "조이스틱 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "사운드 카드 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "사운드 카드 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "사운드 카드 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "사운드 카드 4:" msgid "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "어드밴스드 섹터 이미지" msgid "Flux images" msgstr "플럭스 이미지" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "SDL을 초기화할 수 없습니다. SDL2.dll이 필요합니다" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "실행중인 머신을 재시작하시겠습니까?" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index b24e338f4..eb7a13e4e 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -352,6 +352,9 @@ msgstr "Rodzaj procesora:" msgid "Speed:" msgstr "Szybkość:" +msgid "Frequency:" +msgstr "Częstotliwość:" + msgid "FPU:" msgstr "Jednostka FPU:" @@ -385,8 +388,8 @@ msgstr "Wideo:" msgid "Voodoo Graphics" msgstr "Grafika Voodoo" -msgid "IBM 8514/a Graphics" -msgstr "Grafika IBM 8514/a" +msgid "IBM 8514/A Graphics" +msgstr "Grafika IBM 8514/A" msgid "XGA Graphics" msgstr "Grafika XGA" @@ -409,16 +412,16 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Karta dźwiękowa 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Karta dźwiękowa 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Karta dźwiękowa 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Karta dźwiękowa 4:" msgid "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "Zaawansowane obrazy sektorów" msgid "Flux images" msgstr "Flux images" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Nie można zainicjować SDL, wymagany SDL2.dll" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Jesteś pewien że chcesz wykonać twardy reset emulowanej maszyny?" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index 0db661b4f..148ca716c 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -352,6 +352,9 @@ msgstr "Tipo de CPU:" msgid "Speed:" msgstr "Veloc.:" +msgid "Frequency:" +msgstr "Frequência:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,8 @@ msgstr "Vídeo:" msgid "Voodoo Graphics" msgstr "3DFX Voodoo" -msgid "IBM 8514/a Graphics" -msgstr "Gráficos IBM 8514/a" +msgid "IBM 8514/A Graphics" +msgstr "Gráficos IBM 8514/A" msgid "XGA Graphics" msgstr "Gráficos XGA" @@ -409,16 +412,16 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Placa de som 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Placa de som 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Placa de som 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Placa de som 4:" msgid "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "Imagens de setor avançado" msgid "Flux images" msgstr "Imagens de fluxo" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Não é possível inicializar o SDL, é necessário o SDL2.dll" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Tem certeza de que deseja reiniciar completamente a máquina emulada?" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index 8f080e423..e309d91bf 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -352,6 +352,9 @@ msgstr "Tipo do CPU:" msgid "Speed:" msgstr "Velocidade:" +msgid "Frequency:" +msgstr "Frequência:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,8 @@ msgstr "Vídeo:" msgid "Voodoo Graphics" msgstr "Gráficos Voodoo" -msgid "IBM 8514/a Graphics" -msgstr "Gráficos IBM 8514/a" +msgid "IBM 8514/A Graphics" +msgstr "Gráficos IBM 8514/A" msgid "XGA Graphics" msgstr "Gráficos XGA" @@ -409,16 +412,16 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Placa de som 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Placa de som 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Placa de som 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Placa de som 4:" msgid "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "Imagens avançadas de sector" msgid "Flux images" msgstr "Imagens de fluxo" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Não foi possível inicializar o SDL. O ficheiro SDL2.dll é necessário!" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Tem a certeza de que quer um reinício completo da máquina emulada?" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index b0bcc0e1e..4aa99eb87 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -31,6 +31,9 @@ msgstr "&Скрыть строку состояния" msgid "Hide &toolbar" msgstr "С&крыть панель инструментов" +msgid "Show non-primary monitors" +msgstr "&Показывать неосновные мониторы" + msgid "&Resizeable window" msgstr "&Изменяемый размер окна" @@ -55,8 +58,32 @@ msgstr "Open&GL (3.0)" msgid "&VNC" msgstr "&VNC" +msgid "Renderer options..." +msgstr "Параметры рендеринга..." + +msgid "OpenGL 3.0 renderer options" +msgstr "Параметры рендеринга OpenGL 3.0" + +msgid "Render behavior" +msgstr "Режим рендеринга" + +msgid "Synchronize with video" +msgstr "Синхронизировать с видео" + +msgid "Use target framerate:" +msgstr "Использовать целевую частоту кадров:" + +msgid "VSync" +msgstr "Вертикальная синхронизация" + +msgid "Shaders" +msgstr "Шейдеры" + +msgid "No shader selected" +msgstr "Шейдер не выбран" + msgid "Specify dimensions..." -msgstr "&Указать размеры..." +msgstr "&Указать размеры главного окна..." msgid "F&orce 4:3 display ratio" msgstr "У&становить соотношение сторон 4:3" @@ -127,6 +154,9 @@ msgstr "&Целочисленное масштабирование" msgid "4:&3 Integer scale" msgstr "4:&3 Целочисленное масштабирование" +msgid "Apply fullscreen stretch mode when maximized" +msgstr "Применить полноэкранный режим растяжения при разворачивании окна" + msgid "E&GA/(S)VGA settings" msgstr "Настройки E&GA/(S)VGA" @@ -193,6 +223,9 @@ msgstr "Включить интеграцию &Discord" msgid "Sound &gain..." msgstr "&Усиление звука..." +msgid "Open screenshots folder..." +msgstr "Открыть папку скриншотов..." + msgid "Begin trace\tCtrl+T" msgstr "Начать трассировку\tCtrl+T" @@ -232,6 +265,9 @@ msgstr "&Перемотка в конец" msgid "E&ject" msgstr "И&звлечь" +msgid "Eject %s" +msgstr "Извлечь %s" + msgid "&Image..." msgstr "&Образ..." @@ -241,6 +277,9 @@ msgstr "Э&кспорт в 86F..." msgid "&Mute" msgstr "О&тключить звук" +msgid "&Unmute" +msgstr "В&ключить звук" + msgid "E&mpty" msgstr "П&устой" @@ -352,6 +391,9 @@ msgstr "Тип ЦП:" msgid "Speed:" msgstr "Скорость:" +msgid "Frequency:" +msgstr "Частота:" + msgid "FPU:" msgstr "FPU:" @@ -368,25 +410,28 @@ msgid "Time synchronization" msgstr "Синхронизация времени" msgid "Disabled" -msgstr "Отключить" +msgstr "Отключено" msgid "Enabled (local time)" -msgstr "Включить (местное)" +msgstr "Включено (местное)" msgid "Enabled (UTC)" -msgstr "Включить (UTC)" +msgstr "Включено (UTC)" msgid "Dynamic Recompiler" msgstr "Динамический рекомпилятор" msgid "Video:" -msgstr "Видеокарта:" +msgstr "Видеокарта 1:" + +msgid "Video #2:" +msgstr "Видеокарта 2:" msgid "Voodoo Graphics" msgstr "Ускоритель Voodoo" -msgid "IBM 8514/a Graphics" -msgstr "Ускоритель IBM 8514/a" +msgid "IBM 8514/A Graphics" +msgstr "Ускоритель IBM 8514/A" msgid "XGA Graphics" msgstr "Ускоритель XGA" @@ -409,23 +454,23 @@ msgstr "Джойстик 3..." msgid "Joystick 4..." msgstr "Джойстик 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Звуковая карта 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Звуковая карта 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Звуковая карта 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Звуковая карта 4:" msgid "MIDI Out Device:" -msgstr "MIDI Out устр-во:" +msgstr "MIDI Out устройство:" msgid "MIDI In Device:" -msgstr "MIDI In устр-во:" +msgstr "MIDI In устройство:" msgid "Standalone MPU-401" msgstr "Отдельный MPU-401" @@ -440,7 +485,7 @@ msgid "Nuked (more accurate)" msgstr "Nuked (более точный)" msgid "YMFM (faster)" -msgstr "YMFM (быстрей)" +msgstr "YMFM (быстрее)" msgid "Network type:" msgstr "Тип сети:" @@ -451,6 +496,30 @@ msgstr "Устройство PCap:" msgid "Network adapter:" msgstr "Сетевая карта:" +msgid "Network Card #1" +msgstr "Сетевая карта 1:" + +msgid "Network Card #2" +msgstr "Сетевая карта 2:" + +msgid "Network Card #3" +msgstr "Сетевая карта 3:" + +msgid "Network Card #4" +msgstr "Сетевая карта 4:" + +msgid "Mode" +msgstr "Режим:" + +msgid "Interface" +msgstr "Интерфейс:" + +msgid "Adapter" +msgstr "Адаптер:" + +msgid "VDE Socket" +msgstr "VDE Socket:" + msgid "COM1 Device:" msgstr "Устройство COM1:" @@ -476,16 +545,28 @@ msgid "LPT4 Device:" msgstr "Устройство LPT4:" msgid "Serial port 1" -msgstr "Последов. порт COM1" +msgstr "Последовательный порт COM1" msgid "Serial port 2" -msgstr "Последов. порт COM2" +msgstr "Последовательный порт COM2" msgid "Serial port 3" -msgstr "Последов. порт COM3" +msgstr "Последовательный порт COM3" msgid "Serial port 4" -msgstr "Последов. порт COM4" +msgstr "Последовательный порт COM4" + +msgid "Serial port passthrough 1" +msgstr "Сквозной последовательный порт COM1" + +msgid "Serial port passthrough 2" +msgstr "Сквозной последовательный порт COM2" + +msgid "Serial port passthrough 3" +msgstr "Сквозной последовательный порт COM3" + +msgid "Serial port passthrough 4" +msgstr "Сквозной последовательный порт COM4" msgid "Parallel port 1" msgstr "Параллельный порт LPT1" @@ -538,8 +619,14 @@ msgstr "&Создать..." msgid "&Existing..." msgstr "&Выбрать..." +msgid "Browse..." +msgstr "Выбрать..." + msgid "&Remove" -msgstr "&Убрать" +msgstr "&Удалить" + +msgid "Remove" +msgstr "Удалить" msgid "Bus:" msgstr "Шина:" @@ -554,7 +641,7 @@ msgid "&Specify..." msgstr "&Указать..." msgid "Sectors:" -msgstr "Сектора:" +msgstr "Секторы:" msgid "Heads:" msgstr "Головки:" @@ -602,7 +689,7 @@ msgid "ISA RTC:" msgstr "ISA RTC:" msgid "ISA Memory Expansion" -msgstr "Карта расширения памяти (ISA)" +msgstr "Карта расширения памяти ISA" msgid "Card 1:" msgstr "Карта 1:" @@ -622,6 +709,9 @@ msgstr "Устройство ISABugger" msgid "POST card" msgstr "Карта POST" +msgid "86Box Unit Tester" +msgstr "Модульный Тестер 86Box" + msgid "FONT_SIZE" msgstr "9" @@ -658,6 +748,9 @@ msgstr "86Box не смог найти ни одного подходящего msgid "(empty)" msgstr "(пусто)" +msgid "Clear image history" +msgstr "Очистить историю образов" + msgid "All files" msgstr "Все файлы" @@ -713,7 +806,7 @@ msgid "Floppy & CD-ROM drives" msgstr "Гибкие диски и CD-ROM" msgid "Other removable devices" -msgstr "Другие съёмные устр-ва" +msgstr "Другие съёмные устройства" msgid "Other peripherals" msgstr "Другая периферия" @@ -785,7 +878,7 @@ msgid "Microsoft SideWinder Pad" msgstr "Microsoft SideWinder Pad" msgid "Thrustmaster Flight Control System" -msgstr "Система управления полетом Thrustmaster" +msgstr "Система управления полётом Thrustmaster" msgid "None" msgstr "Нет" @@ -811,9 +904,6 @@ msgstr "Расширенные образы секторов" msgid "Flux images" msgstr "Образы Flux" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Невозможно инициализировать SDL, требуется SDL2.dll" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Вы уверены, что хотите выполнить холодную перезагрузку эмулируемой машины?" @@ -845,7 +935,7 @@ msgid "Do you want to save the settings?" msgstr "Хотите ли вы сохранить настройки?" msgid "This will hard reset the emulated machine." -msgstr "Это приведет к холодной перезагрузке эмулируемой машины." +msgstr "Это приведёт к холодной перезагрузке эмулируемой машины." msgid "Save" msgstr "Сохранить" @@ -854,7 +944,7 @@ msgid "About 86Box" msgstr "О 86Box" msgid "86Box v" -msgstr "86Box v." +msgstr "86Box v" msgid "An emulator of old computers\n\nAuthors: Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." msgstr "Эмулятор старых компьютеров\n\nАвторы: Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nВыпускается под лицензией GNU General Public License версии 2 или более поздней. Дополнительную информацию см. в файле LICENSE." diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index a8f60b861..376723efa 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -352,6 +352,9 @@ msgstr "Procesor:" msgid "Speed:" msgstr "Rýchlosť:" +msgid "Frequency:" +msgstr "Frekvencia:" + msgid "FPU:" msgstr "Koprocesor:" @@ -385,8 +388,8 @@ msgstr "Grafika:" msgid "Voodoo Graphics" msgstr "Použiť grafický akcelerátor Voodoo" -msgid "IBM 8514/a Graphics" -msgstr "Grafika IBM 8514/a" +msgid "IBM 8514/A Graphics" +msgstr "Grafika IBM 8514/A" msgid "XGA Graphics" msgstr "Grafika XGA" @@ -409,16 +412,16 @@ msgstr "Joystick 3..." msgid "Joystick 4..." msgstr "Joystick 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Zvuková karta 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Zvuková karta 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Zvuková karta 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Zvuková karta 4:" msgid "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "Rozšírené sektorové obrazy" msgid "Flux images" msgstr "Obrazy magnetického toku" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Nastala chyba pri inicializácii knižnice SDL, je potreba SDL2.dll" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Naozaj chcete resetovať emulovaný počítač?" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index 98a51d863..cde1011d1 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -352,6 +352,9 @@ msgstr "Vrsta procesorja:" msgid "Speed:" msgstr "Hitrost:" +msgid "Frequency:" +msgstr "Pogostost:" + msgid "FPU:" msgstr "Procesor plavajoče vejice:" @@ -385,8 +388,8 @@ msgstr "Video:" msgid "Voodoo Graphics" msgstr "Voodoo grafika" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/a grafika" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A grafika" msgid "XGA Graphics" msgstr "XGA grafika" @@ -409,16 +412,16 @@ msgstr "Igralna palica 3..." msgid "Joystick 4..." msgstr "Igralna palica 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Zvočna kartica 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Zvočna kartica 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Zvočna kartica 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Zvočna kartica 4:" msgid "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "Napredne sektorske slike" msgid "Flux images" msgstr "Tokovne slike" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Ne morem inicializirati SDL, potrebna je knjižica SDL2.dll" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Ste prepričani, da želite ponovno zagnati emulirani sistem?" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index 0d6875eb8..0989218e5 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -352,6 +352,9 @@ msgstr "CPU türü:" msgid "Speed:" msgstr "Hız:" +msgid "Frequency:" +msgstr "Sıklık:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,8 @@ msgstr "Ekran kartı:" msgid "Voodoo Graphics" msgstr "Voodoo Grafikleri" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/a Grafikleri" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A Grafikleri" msgid "XGA Graphics" msgstr "XGA Grafikleri" @@ -409,16 +412,16 @@ msgstr "Oyun kolu 3..." msgid "Joystick 4..." msgstr "Oyun kolu 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Ses kartı 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Ses kartı 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Ses kartı 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Ses kartı 4:" msgid "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "Gelişmiş sektör imajları" msgid "Flux images" msgstr "Flux images" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "SDL başlatılamadı, SDL2.dll gerekmektedir" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Emüle edilen makineyi yeniden başlatmak istediğinizden emin misiniz?" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index 6f8ecac52..76796a57a 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -352,6 +352,9 @@ msgstr "Тип ЦП:" msgid "Speed:" msgstr "Швидкість:" +msgid "Frequency:" +msgstr "Частота:" + msgid "FPU:" msgstr "FPU:" @@ -385,8 +388,8 @@ msgstr "Відеокарта:" msgid "Voodoo Graphics" msgstr "Прискорювач Voodoo" -msgid "IBM 8514/a Graphics" -msgstr "Прискорювач IBM 8514/a" +msgid "IBM 8514/A Graphics" +msgstr "Прискорювач IBM 8514/A" msgid "XGA Graphics" msgstr "Прискорювач XGA" @@ -409,16 +412,16 @@ msgstr "Джойстик 3..." msgid "Joystick 4..." msgstr "Джойстик 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "Звукова карта 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "Звукова карта 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "Звукова карта 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "Звукова карта 4:" msgid "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "Розширені образи секторів" msgid "Flux images" msgstr "Образи Flux" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "Неможливо ініціалізувати SDL, потрібно SDL2.dll" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "Ви впевнені, що хочете виконати холодне перезавантаження емульованої машини?" @@ -854,7 +854,7 @@ msgid "About 86Box" msgstr "Про 86Box" msgid "86Box v" -msgstr "86Box v." +msgstr "86Box v" msgid "An emulator of old computers\n\nAuthors: Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information." msgstr "Емулятор старих комп'ютерів\n\nАвтори: Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nВипускаєтся під ліцензією GNU General Public License версії 2 або більше пізніше. Додадкову інформацію см. у файлі LICENSE." diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index 3d045b74e..94c468d80 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -352,6 +352,9 @@ msgstr "CPU 类型:" msgid "Speed:" msgstr "速度:" +msgid "Frequency:" +msgstr "频率:" + msgid "FPU:" msgstr "浮点处理器 (FPU):" @@ -385,8 +388,8 @@ msgstr "显卡:" msgid "Voodoo Graphics" msgstr "Voodoo Graphics" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/a Graphics" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A Graphics" msgid "XGA Graphics" msgstr "XGA Graphics" @@ -409,16 +412,16 @@ msgstr "操纵杆 3..." msgid "Joystick 4..." msgstr "操纵杆 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "声卡 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "声卡 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "声卡 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "声卡 4:" msgid "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "高级扇区映像" msgid "Flux images" msgstr "Flux 映像" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "无法初始化 SDL,需要 SDL2.dll" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "确定要硬重置模拟器吗?" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index 2d2ea473e..7836f7ef8 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -352,6 +352,9 @@ msgstr "CPU 類型:" msgid "Speed:" msgstr "速度:" +msgid "Frequency:" +msgstr "頻率:" + msgid "FPU:" msgstr "浮點處理器 (FPU):" @@ -368,7 +371,7 @@ msgid "Time synchronization" msgstr "時間同步" msgid "Disabled" -msgstr "禁用" +msgstr "停用" msgid "Enabled (local time)" msgstr "啟用 (本地時間)" @@ -385,8 +388,8 @@ msgstr "顯示卡:" msgid "Voodoo Graphics" msgstr "Voodoo Graphics" -msgid "IBM 8514/a Graphics" -msgstr "IBM 8514/a Graphics" +msgid "IBM 8514/A Graphics" +msgstr "IBM 8514/A Graphics" msgid "XGA Graphics" msgstr "XGA Graphics" @@ -409,16 +412,16 @@ msgstr "搖桿 3..." msgid "Joystick 4..." msgstr "搖桿 4..." -msgid "Sound card 1:" +msgid "Sound card #1:" msgstr "音效卡 1:" -msgid "Sound card 2:" +msgid "Sound card #2:" msgstr "音效卡 2:" -msgid "Sound card 3:" +msgid "Sound card #3:" msgstr "音效卡 3:" -msgid "Sound card 4:" +msgid "Sound card #4:" msgstr "音效卡 4:" msgid "MIDI Out Device:" @@ -811,9 +814,6 @@ msgstr "進階磁區映像" msgid "Flux images" msgstr "Flux 映像" -msgid "Unable to initialize SDL, SDL2.dll is required" -msgstr "無法初始化 SDL,需要 SDL2.dll" - msgid "Are you sure you want to hard reset the emulated machine?" msgstr "確定要硬重設模擬器嗎?" @@ -917,7 +917,7 @@ msgid "You are loading an unsupported configuration" msgstr "正在載入一個不受支援的設定" msgid "CPU type filtering based on selected machine is disabled for this emulated machine.\n\nThis makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software.\n\nEnabling this setting is not officially supported and any bug reports filed may be closed as invalid." -msgstr "此模擬電腦禁用了基於選定電腦的 CPU 類型過濾。\n\n能夠選中與所選機器本不相容的 CPU,但是可能會遇到與機器 BIOS 或其他軟體不相容的問題。\n\n啟用此設定不受官方支援,並且提交的任何錯誤報告可能會視為無效而關閉。" +msgstr "此模擬電腦停用了基於選定電腦的 CPU 類型過濾。\n\n能夠選中與所選機器本不相容的 CPU,但是可能會遇到與機器 BIOS 或其他軟體不相容的問題。\n\n啟用此設定不受官方支援,並且提交的任何錯誤報告可能會視為無效而關閉。" msgid "Continue" msgstr "繼續" diff --git a/src/qt/qt.c b/src/qt/qt.c index c2a5396da..47f5b9410 100644 --- a/src/qt/qt.c +++ b/src/qt/qt.c @@ -52,10 +52,8 @@ plat_vidapi(char *api) return 3; } else if (!strcasecmp(api, "qt_vulkan")) { return 4; - } else if (!strcasecmp(api, "qt_d3d9")) { - return 5; } else if (!strcasecmp(api, "vnc")) { - return 6; + return 5; } return 0; @@ -83,9 +81,6 @@ plat_vidapi_name(int api) name = "qt_vulkan"; break; case 5: - name = "qt_d3d9"; - break; - case 6: name = "vnc"; break; default: diff --git a/src/qt/qt_d3d9renderer.cpp b/src/qt/qt_d3d9renderer.cpp deleted file mode 100644 index 868f58274..000000000 --- a/src/qt/qt_d3d9renderer.cpp +++ /dev/null @@ -1,200 +0,0 @@ -#include "qt_mainwindow.hpp" -#include "qt_d3d9renderer.hpp" -#include -#include - -extern "C" { -#include <86box/86box.h> -#include <86box/video.h> -} - -D3D9Renderer::D3D9Renderer(QWidget *parent, int monitor_index) - : QWidget { parent } - , RendererCommon() -{ - QPalette pal = palette(); - pal.setColor(QPalette::Window, Qt::black); - setAutoFillBackground(true); - setPalette(pal); - - setAttribute(Qt::WA_NativeWindow); - setAttribute(Qt::WA_PaintOnScreen); - setAttribute(Qt::WA_NoSystemBackground); - setAttribute(Qt::WA_OpaquePaintEvent); - - windowHandle = (HWND) winId(); - surfaceInUse = true; - finalized = true; - - RendererCommon::parentWidget = parent; - - this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - this->m_monitor_index = monitor_index; - - d3d9surface = nullptr; - d3d9dev = nullptr; - d3d9 = nullptr; -} - -D3D9Renderer::~D3D9Renderer() -{ - finalize(); -} - -void -D3D9Renderer::finalize() -{ - if (!finalized) { - while (surfaceInUse) { } - finalized = true; - } - surfaceInUse = true; - if (d3d9surface) { - d3d9surface->Release(); - d3d9surface = nullptr; - } - if (d3d9dev) { - d3d9dev->Release(); - d3d9dev = nullptr; - } - if (d3d9) { - d3d9->Release(); - d3d9 = nullptr; - } -} - -void -D3D9Renderer::hideEvent(QHideEvent *event) -{ - finalize(); -} - -void -D3D9Renderer::showEvent(QShowEvent *event) -{ - if (d3d9) finalize(); - params = {}; - - if (FAILED(Direct3DCreate9Ex(D3D_SDK_VERSION, &d3d9))) { - return error("Failed to create Direct3D 9 context"); - } - - params.Windowed = true; - params.SwapEffect = D3DSWAPEFFECT_FLIPEX; - params.BackBufferWidth = width() * devicePixelRatioF(); - params.BackBufferHeight = height() * devicePixelRatioF(); - params.BackBufferCount = 1; - params.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; - params.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; - params.hDeviceWindow = (HWND) winId(); - - HRESULT result = d3d9->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, windowHandle, D3DCREATE_MULTITHREADED | D3DCREATE_HARDWARE_VERTEXPROCESSING, ¶ms, nullptr, &d3d9dev); - if (FAILED(result)) - result = d3d9->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, windowHandle, D3DCREATE_MULTITHREADED | D3DCREATE_SOFTWARE_VERTEXPROCESSING, ¶ms, nullptr, &d3d9dev); - if (FAILED(result)) { - return error("Failed to create Direct3D 9 device"); - } - - result = d3d9dev->CreateOffscreenPlainSurface(2048, 2048, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &d3d9surface, nullptr); - if (FAILED(result)) - result = d3d9dev->CreateOffscreenPlainSurface(1024, 1024, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &d3d9surface, nullptr); - if (FAILED(result)) { - return error("Failed to create Direct3D 9 surface"); - } - if (!alreadyInitialized) { - emit initialized(); - alreadyInitialized = true; - } - surfaceInUse = false; - finalized = false; -} - -void -D3D9Renderer::paintEvent(QPaintEvent *event) -{ - IDirect3DSurface9 *backbuffer = nullptr; - RECT srcRect; - RECT dstRect; - HRESULT result = d3d9dev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); - - if (FAILED(result)) { - return; - } - - srcRect.top = source.top(); - srcRect.bottom = source.bottom(); - srcRect.left = source.left(); - srcRect.right = source.right(); - dstRect.top = destination.top() * devicePixelRatioF(); - dstRect.bottom = destination.bottom() * devicePixelRatioF(); - dstRect.left = destination.left() * devicePixelRatioF(); - dstRect.right = destination.right() * devicePixelRatioF(); - d3d9dev->BeginScene(); - d3d9dev->Clear(0, nullptr, D3DCLEAR_TARGET, 0xFF000000, 0, 0); - while (surfaceInUse) { } - surfaceInUse = true; - d3d9dev->StretchRect(d3d9surface, &srcRect, backbuffer, &dstRect, video_filter_method == 0 ? D3DTEXF_POINT : D3DTEXF_LINEAR); - result = d3d9dev->EndScene(); - surfaceInUse = false; - if (SUCCEEDED(result)) { - if (FAILED(d3d9dev->PresentEx(nullptr, nullptr, 0, nullptr, 0))) { - finalize(); - showEvent(nullptr); - } - } -} - -bool -D3D9Renderer::event(QEvent *event) -{ - bool res = false; - if (!eventDelegate(event, res)) - return QWidget::event(event); - return res; -} - -void -D3D9Renderer::resizeEvent(QResizeEvent *event) -{ - onResize(event->size().width() * devicePixelRatioF(), event->size().height() * devicePixelRatioF()); - - params.BackBufferWidth = event->size().width() * devicePixelRatioF(); - params.BackBufferHeight = event->size().height() * devicePixelRatioF(); - if (d3d9dev) - d3d9dev->Reset(¶ms); - QWidget::resizeEvent(event); -} - -void -D3D9Renderer::blit(int x, int y, int w, int h) -{ - if (blitDummied || (x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (monitors[m_monitor_index].target_buffer == NULL) || surfaceInUse) { - video_blit_complete_monitor(m_monitor_index); - return; - } - surfaceInUse = true; - auto origSource = source; - source.setRect(x, y, w, h); - RECT srcRect; - D3DLOCKED_RECT lockRect; - srcRect.top = source.top(); - srcRect.bottom = source.bottom(); - srcRect.left = source.left(); - srcRect.right = source.right(); - - if (monitors[m_monitor_index].mon_screenshots) { - video_screenshot_monitor((uint32_t *) &(monitors[m_monitor_index].target_buffer->line[y][x]), 0, 0, 2048, m_monitor_index); - } - if (SUCCEEDED(d3d9surface->LockRect(&lockRect, &srcRect, 0))) { - for (int y1 = 0; y1 < h; y1++) { - video_copy(((uint8_t *) lockRect.pBits) + (y1 * lockRect.Pitch), &(monitors[m_monitor_index].target_buffer->line[y + y1][x]), w * 4); - } - video_blit_complete_monitor(m_monitor_index); - d3d9surface->UnlockRect(); - } else - video_blit_complete_monitor(m_monitor_index); - if (origSource != source) - onResize(this->width() * devicePixelRatioF(), this->height() * devicePixelRatioF()); - surfaceInUse = false; - QTimer::singleShot(0, this, [this] { this->update(); }); -} diff --git a/src/qt/qt_d3d9renderer.hpp b/src/qt/qt_d3d9renderer.hpp deleted file mode 100644 index 37c27443b..000000000 --- a/src/qt/qt_d3d9renderer.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef D3D9RENDERER_HPP -#define D3D9RENDERER_HPP - -#include -#include "qt_renderercommon.hpp" - -#include -#include -#include - -class D3D9Renderer : public QWidget, public RendererCommon { - Q_OBJECT -public: - explicit D3D9Renderer(QWidget *parent = nullptr, int monitor_index = 0); - ~D3D9Renderer(); - bool hasBlitFunc() override { return true; } - void blit(int x, int y, int w, int h) override; - void finalize() override; - -protected: - void showEvent(QShowEvent *event) override; - void hideEvent(QHideEvent *event) override; - void resizeEvent(QResizeEvent *event) override; - void paintEvent(QPaintEvent *event) override; - bool event(QEvent *event) override; - QPaintEngine *paintEngine() const override { return nullptr; } - -signals: - void initialized(); - void error(QString); - -private: - HWND windowHandle = 0; - D3DPRESENT_PARAMETERS params {}; - IDirect3D9Ex *d3d9 = nullptr; - IDirect3DDevice9Ex *d3d9dev = nullptr; - IDirect3DSurface9 *d3d9surface = nullptr; - - std::atomic surfaceInUse { false }; - std::atomic finalized { false }; - bool alreadyInitialized = false; - int m_monitor_index = 0; -}; - -#endif // D3D9RENDERER_HPP diff --git a/src/qt/qt_hardwarerenderer.cpp b/src/qt/qt_hardwarerenderer.cpp index 47f0de718..ee2ec07df 100644 --- a/src/qt/qt_hardwarerenderer.cpp +++ b/src/qt/qt_hardwarerenderer.cpp @@ -136,22 +136,6 @@ HardwareRenderer::initializeGL() m_context->swapBuffers(this); } -void -HardwareRenderer::paintOverGL() -{ - /* Context switching is needed to make use of QPainter to draw status bar icons in fullscreen. - Especially since it seems to be impossible to use QPainter on externally-created OpenGL contexts. */ - if (video_fullscreen && status_icons_fullscreen) { - m_context->makeCurrent(nullptr); - makeCurrent(); - QPainter painter(this); - drawStatusBarIcons(&painter); - painter.end(); - doneCurrent(); - m_context->makeCurrent(this); - } -} - void HardwareRenderer::paintGL() { diff --git a/src/qt/qt_hardwarerenderer.hpp b/src/qt/qt_hardwarerenderer.hpp index 1918cda18..f7861d2bd 100644 --- a/src/qt/qt_hardwarerenderer.hpp +++ b/src/qt/qt_hardwarerenderer.hpp @@ -53,7 +53,7 @@ public: { onResize(size().width(), size().height()); } - void paintOverGL() override; + std::vector> getBuffers() override; HardwareRenderer(QWidget *parent = nullptr, RenderType rtype = RenderType::OpenGL) : QOpenGLWindow(QOpenGLWindow::NoPartialUpdate, parent->windowHandle()) diff --git a/src/qt/qt_joystickconfiguration.cpp b/src/qt/qt_joystickconfiguration.cpp index c363cd544..e03d57e09 100644 --- a/src/qt/qt_joystickconfiguration.cpp +++ b/src/qt/qt_joystickconfiguration.cpp @@ -118,19 +118,12 @@ JoystickConfiguration::on_comboBoxDevice_currentIndexChanged(int index) Models::AddEntry(model, QString("%1 (Y axis)").arg(plat_joystick_state[joystick].pov[d].name), 0); } - for (int d = 0; d < plat_joystick_state[joystick].nr_sliders; d++) { - Models::AddEntry(model, plat_joystick_state[joystick].slider[d].name, 0); - } - int nr_axes = plat_joystick_state[joystick].nr_axes; - int nr_povs = plat_joystick_state[joystick].nr_povs; int mapping = joystick_state[joystick_nr].axis_mapping[c]; if (mapping & POV_X) cbox->setCurrentIndex(nr_axes + (mapping & 3) * 2); else if (mapping & POV_Y) cbox->setCurrentIndex(nr_axes + (mapping & 3) * 2 + 1); - else if (mapping & SLIDER) - cbox->setCurrentIndex(nr_axes + nr_povs * 2 + (mapping & 3)); else cbox->setCurrentIndex(mapping); diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 4d02e2601..cafd4fd8e 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -342,7 +342,7 @@ main(int argc, char *argv[]) /* Set the PAUSE mode depending on the renderer. */ #ifdef USE_VNC - if (vnc_enabled && vid_api != 6) + if (vnc_enabled && vid_api != 5) plat_pause(1); else #endif diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index e0252dd7a..f24ab0788 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -157,8 +157,6 @@ keyb_filter(BMessage *message, BHandler **target, BMessageFilter *filter) static BMessageFilter *filter; #endif -std::atomic blitDummied { false }; - extern void qt_mouse_capture(int); extern "C" void qt_blit(int x, int y, int w, int h, int monitor_index); @@ -342,7 +340,6 @@ MainWindow::MainWindow(QWidget *parent) ui->actionUpdate_status_bar_icons->setChecked(update_icons); ui->actionEnable_Discord_integration->setChecked(enable_discord); ui->actionApply_fullscreen_stretch_mode_when_maximized->setChecked(video_fullscreen_scale_maximized); - ui->actionShow_status_icons_in_fullscreen->setChecked(status_icons_fullscreen); #ifndef DISCORD ui->actionEnable_Discord_integration->setVisible(false); @@ -369,14 +366,9 @@ MainWindow::MainWindow(QWidget *parent) ui->actionVulkan->setVisible(false); ui->actionOpenGL_3_0_Core->setVisible(false); } -#if !defined Q_OS_WINDOWS - ui->actionDirect3D_9->setVisible(false); - if (vid_api == 5) - vid_api = 0; -#endif #ifndef USE_VNC - if (vid_api == 6) + if (vid_api == 5) vid_api = 0; ui->actionVNC->setVisible(false); #endif @@ -410,14 +402,13 @@ MainWindow::MainWindow(QWidget *parent) actGroup->addAction(ui->actionHardware_Renderer_OpenGL_ES); actGroup->addAction(ui->actionOpenGL_3_0_Core); actGroup->addAction(ui->actionVulkan); - actGroup->addAction(ui->actionDirect3D_9); actGroup->addAction(ui->actionVNC); actGroup->setExclusive(true); connect(actGroup, &QActionGroup::triggered, [this](QAction *action) { vid_api = action->property("vid_api").toInt(); #ifdef USE_VNC - if (vnc_enabled && vid_api != 6) { + if (vnc_enabled && vid_api != 5) { startblit(); vnc_enabled = 0; vnc_close(); @@ -442,11 +433,8 @@ MainWindow::MainWindow(QWidget *parent) case 4: newVidApi = RendererStack::Renderer::Vulkan; break; - case 5: - newVidApi = RendererStack::Renderer::Direct3D9; - break; #ifdef USE_VNC - case 6: + case 5: { newVidApi = RendererStack::Renderer::Software; startblit(); @@ -612,7 +600,7 @@ MainWindow::MainWindow(QWidget *parent) video_setblit(qt_blit); if (start_in_fullscreen) { - connect(ui->stackedWidget, &RendererStack::blit, this, [this] () { + connect(ui->stackedWidget, &RendererStack::blitToRenderer, this, [this] () { if (start_in_fullscreen) { QTimer::singleShot(100, ui->actionFullscreen, &QAction::trigger); start_in_fullscreen = 0; @@ -808,6 +796,14 @@ MainWindow::initRendererMonitorSlot(int monitor_index) } secondaryRenderer->switchRenderer((RendererStack::Renderer) vid_api); secondaryRenderer->setMouseTracking(true); + + if (monitor_settings[monitor_index].mon_window_maximized) { + if (renderers[monitor_index]) + renderers[monitor_index]->onResize(renderers[monitor_index]->width(), + renderers[monitor_index]->height()); + + device_force_redraw(); + } } } } @@ -1148,8 +1144,6 @@ MainWindow::on_actionFullscreen_triggered() { if (video_fullscreen > 0) { showNormal(); - if (vid_api == 5) - QTimer::singleShot(0, this, [this]() { ui->stackedWidget->switchRenderer(RendererStack::Renderer::Direct3D9); }); ui->menubar->show(); if (!hide_status_bar) ui->statusbar->show(); @@ -1185,8 +1179,6 @@ MainWindow::on_actionFullscreen_triggered() ui->toolBar->hide(); ui->stackedWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); showFullScreen(); - if (vid_api == 5) - QTimer::singleShot(0, this, [this]() { ui->stackedWidget->switchRenderer(RendererStack::Renderer::Direct3D9); }); } ui->stackedWidget->onResize(width(), height()); } @@ -1308,7 +1300,7 @@ void MainWindow::blitToWidget(int x, int y, int w, int h, int monitor_index) { if (monitor_index >= 1) { - if (!blitDummied && renderers[monitor_index] && renderers[monitor_index]->isVisible()) + if (renderers[monitor_index] && renderers[monitor_index]->isVisible()) renderers[monitor_index]->blit(x, y, w, h); else video_blit_complete_monitor(monitor_index); @@ -1379,12 +1371,12 @@ MainWindow::on_actionResizable_window_triggered(bool checked) { if (checked) { vid_resize = 1; - setWindowFlag(Qt::WindowMaximizeButtonHint); + setWindowFlag(Qt::WindowMaximizeButtonHint, true); setWindowFlag(Qt::MSWindowsFixedSizeDialogHint, false); setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); for (int i = 1; i < MONITORS_NUM; i++) { if (monitors[i].target_buffer) { - renderers[i]->setWindowFlag(Qt::WindowMaximizeButtonHint); + renderers[i]->setWindowFlag(Qt::WindowMaximizeButtonHint, true); renderers[i]->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); } } @@ -1968,8 +1960,6 @@ MainWindow::on_actionShow_non_primary_monitors_triggered() { show_second_monitors = (int) ui->actionShow_non_primary_monitors->isChecked(); - blitDummied = true; - if (show_second_monitors) { for (int monitor_index = 1; monitor_index < MONITORS_NUM; monitor_index++) { auto &secondaryRenderer = renderers[monitor_index]; @@ -1999,8 +1989,6 @@ MainWindow::on_actionShow_non_primary_monitors_triggered() } } } - - blitDummied = false; } void @@ -2043,11 +2031,3 @@ void MainWindow::on_actionACPI_Shutdown_triggered() { acpi_pwrbut_pressed = 1; } - -void MainWindow::on_actionShow_status_icons_in_fullscreen_triggered() -{ - status_icons_fullscreen = !status_icons_fullscreen; - ui->actionShow_status_icons_in_fullscreen->setChecked(status_icons_fullscreen); - config_save(); -} - diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 553f9602c..950d145c1 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -12,8 +12,6 @@ class MediaMenu; class RendererStack; -extern std::atomic blitDummied; - namespace Ui { class MainWindow; } @@ -144,7 +142,6 @@ private slots: void on_actionCursor_Puck_triggered(); void on_actionACPI_Shutdown_triggered(); - void on_actionShow_status_icons_in_fullscreen_triggered(); private slots: void on_actionShow_non_primary_monitors_triggered(); diff --git a/src/qt/qt_mainwindow.ui b/src/qt/qt_mainwindow.ui index d682815bb..08d8bbf63 100644 --- a/src/qt/qt_mainwindow.ui +++ b/src/qt/qt_mainwindow.ui @@ -117,7 +117,6 @@ - @@ -180,7 +179,6 @@ - @@ -773,10 +771,10 @@ :/menuicons/win/icons/acpi_shutdown.ico:/menuicons/win/icons/acpi_shutdown.ico - ACPI Shutdown + ACPI shutdown - ACPI Shutdown + ACPI shutdown true @@ -831,17 +829,6 @@ MCA devices... - - - true - - - Direct3D 9 - - - 5 - - true @@ -858,7 +845,7 @@ VNC - 6 + 5 @@ -882,14 +869,6 @@ Cursor/Puck - - - true - - - Show status icons in fullscreen - - true diff --git a/src/qt/qt_mediamenu.cpp b/src/qt/qt_mediamenu.cpp index 26169b0d0..541e31190 100644 --- a/src/qt/qt_mediamenu.cpp +++ b/src/qt/qt_mediamenu.cpp @@ -456,6 +456,13 @@ MediaMenu::cdromMount(int i, const QString &filename) cdrom[i].ops = nullptr; memset(cdrom[i].image_path, 0, sizeof(cdrom[i].image_path)); +#ifdef _WIN32 + if ((fn.data() != NULL) && (strlen(fn.data()) >= 1) && (fn.data()[strlen(fn.data()) - 1] == '/')) + fn.data()[strlen(fn.data()) - 1] = '\\'; +#else + if ((fn.data() != NULL) && (strlen(fn.data()) >= 1) && (fn.data()[strlen(fn.data()) - 1] == '\\')) + fn.data()[strlen(fn.data()) - 1] = '/'; +#endif cdrom_image_open(&(cdrom[i]), fn.data()); /* Signal media change to the emulated machine. */ if (cdrom[i].insert) diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 6890bd407..356334bac 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -602,7 +602,6 @@ ProgSettings::reloadStrings() translatedstrings[IDS_2094] = QCoreApplication::translate("", "Failed to set up PCap").toStdWString(); translatedstrings[IDS_2095] = QCoreApplication::translate("", "No PCap devices found").toStdWString(); translatedstrings[IDS_2096] = QCoreApplication::translate("", "Invalid PCap device").toStdWString(); - translatedstrings[IDS_2112] = QCoreApplication::translate("", "Unable to initialize SDL, libsdl2 is required").toStdWString(); translatedstrings[IDS_2130] = QCoreApplication::translate("", "Make sure libpcap is installed and that you are on a libpcap-compatible network connection.").toStdWString(); translatedstrings[IDS_2115] = QCoreApplication::translate("", "Unable to initialize Ghostscript").toStdWString(); translatedstrings[IDS_2063] = QCoreApplication::translate("", "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine.").toStdWString(); diff --git a/src/qt/qt_renderercommon.cpp b/src/qt/qt_renderercommon.cpp index 05c35e09b..178134c9d 100644 --- a/src/qt/qt_renderercommon.cpp +++ b/src/qt/qt_renderercommon.cpp @@ -17,15 +17,11 @@ #include "qt_renderercommon.hpp" #include "qt_mainwindow.hpp" -#include "qt_machinestatus.hpp" #include #include #include #include -#include -#include -#include #include @@ -33,8 +29,6 @@ extern "C" { #include <86box/86box.h> #include <86box/plat.h> #include <86box/video.h> - -int status_icons_fullscreen = 0; } RendererCommon::RendererCommon() = default; @@ -137,52 +131,6 @@ RendererCommon::onResize(int width, int height) monitors[r_monitor_index].mon_res_y = (double) destination.height(); } -void RendererCommon::drawStatusBarIcons(QPainter* painter) -{ - uint32_t x = 0; - auto prevcompositionMode = painter->compositionMode(); - painter->setCompositionMode(QPainter::CompositionMode::CompositionMode_SourceOver); - for (int i = 0; i < main_window->statusBar()->children().count(); i++) { - QLabel* label = qobject_cast(main_window->statusBar()->children()[i]); - if (label) { -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - const QPixmap pixmap = label->pixmap(); -#elif QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) - const QPixmap pixmap = label->pixmap(Qt::ReturnByValue); -#else - const QPixmap pixmap = (label->pixmap() ? *label->pixmap() : QPixmap()); -#endif - if (!pixmap.isNull()) { - painter->setBrush(QColor::fromRgbF(0, 0, 0, 1.)); - painter->fillRect(x, painter->device()->height() - pixmap.height() - 5, - pixmap.width(), pixmap.height() + 5, QColor::fromRgbF(0, 0, 0, .5)); - painter->drawPixmap(x + main_window->statusBar()->layout()->spacing() / 2, - painter->device()->height() - pixmap.height() - 3, pixmap); - x += pixmap.width(); - if (i <= main_window->statusBar()->children().count() - 3) { - painter->fillRect(x, painter->device()->height() - pixmap.height() - 5, - main_window->statusBar()->layout()->spacing(), pixmap.height() + 5, - QColor::fromRgbF(0, 0, 0, .5)); - x += main_window->statusBar()->layout()->spacing(); - } else - painter->fillRect(x, painter->device()->height() - pixmap.height() - 4, 4, - pixmap.height() + 4, QColor::fromRgbF(0, 0, 0, .5)); - } - } - } - if (main_window->status->getMessage().isEmpty() == false) { - auto curStatusMsg = main_window->status->getMessage(); - auto textSize = painter->fontMetrics().size(Qt::TextSingleLine, QChar(' ') + curStatusMsg + QChar(' ')); - painter->setPen(QColor(0, 0, 0, 127)); - painter->fillRect(painter->device()->width() - textSize.width(), painter->device()->height() - textSize.height(), - textSize.width(), textSize.height(), QColor(0, 0, 0, 127)); - painter->setPen(QColor(255, 255, 255, 255)); - painter->drawText(QRectF(painter->device()->width() - textSize.width(), painter->device()->height() - textSize.height(), - textSize.width(), textSize.height()), Qt::TextSingleLine, QChar(' ') + curStatusMsg + QChar(' ')); - } - painter->setCompositionMode(prevcompositionMode); -} - bool RendererCommon::eventDelegate(QEvent *event, bool &result) { diff --git a/src/qt/qt_renderercommon.hpp b/src/qt/qt_renderercommon.hpp index 897240d27..af72474c7 100644 --- a/src/qt/qt_renderercommon.hpp +++ b/src/qt/qt_renderercommon.hpp @@ -35,9 +35,6 @@ public: /* Reloads options of renderer */ virtual void reloadOptions() { } - virtual bool hasBlitFunc() { return false; } - virtual void blit(int x, int y, int w, int h) { } - int r_monitor_index = 0; protected: diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index e5ed77ba7..0f86e8ee6 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -25,9 +25,6 @@ #include "qt_openglrenderer.hpp" #include "qt_softwarerenderer.hpp" #include "qt_vulkanwindowrenderer.hpp" -#ifdef Q_OS_WIN -# include "qt_d3d9renderer.hpp" -#endif #include "qt_mainwindow.hpp" #include "qt_util.hpp" @@ -279,40 +276,14 @@ RendererStack::switchRenderer(Renderer renderer) { startblit(); if (current) { - if ((current_vid_api == Renderer::Direct3D9 && renderer != Renderer::Direct3D9) - || (current_vid_api != Renderer::Direct3D9 && renderer == Renderer::Direct3D9)) { - rendererWindow->finalize(); - if (rendererWindow->hasBlitFunc()) { - while (directBlitting) { } - connect(this, &RendererStack::blit, this, &RendererStack::blitDummy, Qt::DirectConnection); - disconnect(this, &RendererStack::blit, this, &RendererStack::blitRenderer); - } else { - connect(this, &RendererStack::blit, this, &RendererStack::blitDummy, Qt::DirectConnection); - disconnect(this, &RendererStack::blit, this, &RendererStack::blitCommon); - } + rendererWindow->finalize(); + removeWidget(current.get()); + disconnect(this, &RendererStack::blitToRenderer, nullptr, nullptr); - removeWidget(current.get()); - disconnect(this, &RendererStack::blitToRenderer, nullptr, nullptr); + /* Create new renderer only after previous is destroyed! */ + connect(current.get(), &QObject::destroyed, [this, renderer](QObject *) { createRenderer(renderer); }); - /* Create new renderer only after previous is destroyed! */ - connect(current.get(), &QObject::destroyed, [this, renderer](QObject *) { - createRenderer(renderer); - disconnect(this, &RendererStack::blit, this, &RendererStack::blitDummy); - blitDummied = false; - QTimer::singleShot(1000, this, []() { blitDummied = false; }); - }); - - rendererWindow->hasBlitFunc() ? current.reset() : current.release()->deleteLater(); - } else { - rendererWindow->finalize(); - removeWidget(current.get()); - disconnect(this, &RendererStack::blitToRenderer, nullptr, nullptr); - - /* Create new renderer only after previous is destroyed! */ - connect(current.get(), &QObject::destroyed, [this, renderer](QObject *) { createRenderer(renderer); }); - - current.release()->deleteLater(); - } + current.release()->deleteLater(); } else { createRenderer(renderer); } @@ -321,7 +292,6 @@ RendererStack::switchRenderer(Renderer renderer) void RendererStack::createRenderer(Renderer renderer) { - current_vid_api = renderer; switch (renderer) { default: case Renderer::Software: @@ -374,27 +344,6 @@ RendererStack::createRenderer(Renderer renderer) current.reset(this->createWindowContainer(hw, this)); break; } -#ifdef Q_OS_WIN - case Renderer::Direct3D9: - { - this->createWinId(); - auto hw = new D3D9Renderer(this, m_monitor_index); - rendererWindow = hw; - connect(hw, &D3D9Renderer::error, this, [this](QString str) { - auto msgBox = new QMessageBox(QMessageBox::Critical, "86Box", QString("Failed to initialize D3D9 renderer. Falling back to software rendering.\n\n") + str, QMessageBox::Ok); - msgBox->setAttribute(Qt::WA_DeleteOnClose); - msgBox->show(); - imagebufs = {}; - QTimer::singleShot(0, this, [this]() { switchRenderer(Renderer::Software); }); - }); - connect(hw, &D3D9Renderer::initialized, this, [this]() { - endblit(); - emit rendererChanged(); - }); - current.reset(hw); - break; - } -#endif #if QT_CONFIG(vulkan) case Renderer::Vulkan: { @@ -444,44 +393,18 @@ RendererStack::createRenderer(Renderer renderer) currentBuf = 0; - if (rendererWindow->hasBlitFunc()) { - connect(this, &RendererStack::blit, this, &RendererStack::blitRenderer, Qt::DirectConnection); - } else { - connect(this, &RendererStack::blit, this, &RendererStack::blitCommon, Qt::DirectConnection); - } - - if (renderer != Renderer::OpenGL3 && renderer != Renderer::Vulkan && renderer != Renderer::Direct3D9) { + if (renderer != Renderer::OpenGL3 && renderer != Renderer::Vulkan) { imagebufs = rendererWindow->getBuffers(); endblit(); emit rendererChanged(); } } -void -RendererStack::blitDummy(int x, int y, int w, int h) -{ - video_blit_complete_monitor(m_monitor_index); - blitDummied = true; -} - -void -RendererStack::blitRenderer(int x, int y, int w, int h) -{ - if (blitDummied) { - blitDummied = false; - video_blit_complete_monitor(m_monitor_index); - return; - } - directBlitting = true; - rendererWindow->blit(x, y, w, h); - directBlitting = false; -} - // called from blitter thread void -RendererStack::blitCommon(int x, int y, int w, int h) +RendererStack::blit(int x, int y, int w, int h) { - if (blitDummied || (x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (monitors[m_monitor_index].target_buffer == NULL) || imagebufs.empty() || std::get(imagebufs[currentBuf])->test_and_set()) { + if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (monitors[m_monitor_index].target_buffer == NULL) || imagebufs.empty() || std::get(imagebufs[currentBuf])->test_and_set()) { video_blit_complete_monitor(m_monitor_index); return; } diff --git a/src/qt/qt_rendererstack.hpp b/src/qt/qt_rendererstack.hpp index c9d90869b..5a08b351c 100644 --- a/src/qt/qt_rendererstack.hpp +++ b/src/qt/qt_rendererstack.hpp @@ -59,7 +59,6 @@ public: OpenGLES, OpenGL3, Vulkan, - Direct3D9, None = -1 }; void switchRenderer(Renderer renderer); @@ -81,13 +80,10 @@ public: signals: void blitToRenderer(int buf_idx, int x, int y, int w, int h); - void blit(int x, int y, int w, int h); void rendererChanged(); public slots: - void blitCommon(int x, int y, int w, int h); - void blitRenderer(int x, int y, int w, int h); - void blitDummy(int x, int y, int w, int h); + void blit(int x, int y, int w, int h); private: void createRenderer(Renderer renderer); @@ -107,13 +103,10 @@ private: int isMouseDown = 0; int m_monitor_index = 0; - Renderer current_vid_api = Renderer::None; - std::vector> imagebufs; RendererCommon *rendererWindow { nullptr }; std::unique_ptr current; - std::atomic directBlitting { false }; }; #endif // QT_RENDERERCONTAINER_HPP diff --git a/src/qt/qt_settingsdisplay.ui b/src/qt/qt_settingsdisplay.ui index dfda43c40..5dd76287f 100644 --- a/src/qt/qt_settingsdisplay.ui +++ b/src/qt/qt_settingsdisplay.ui @@ -42,7 +42,7 @@ - XGA + XGA Graphics @@ -95,7 +95,7 @@ - 8514/A + IBM 8514/A Graphics diff --git a/src/qt/qt_settingsinput.cpp b/src/qt/qt_settingsinput.cpp index 34d111e10..05e44c2c0 100644 --- a/src/qt/qt_settingsinput.cpp +++ b/src/qt/qt_settingsinput.cpp @@ -137,22 +137,16 @@ get_axis(JoystickConfiguration &jc, int axis, int joystick_nr) { int axis_sel = jc.selectedAxis(axis); int nr_axes = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_axes; - int nr_povs = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_povs; if (axis_sel < nr_axes) { return axis_sel; } axis_sel -= nr_axes; - if (axis_sel < nr_povs * 2) { - if (axis_sel & 1) - return POV_Y | (axis_sel >> 1); - else - return POV_X | (axis_sel >> 1); - } - axis_sel -= nr_povs; - - return SLIDER | (axis_sel >> 1); + if (axis_sel & 1) + return POV_Y | (axis_sel >> 1); + else + return POV_X | (axis_sel >> 1); } static int diff --git a/src/qt/qt_settingsmachine.ui b/src/qt/qt_settingsmachine.ui index 22ecc15df..54bc06f5c 100644 --- a/src/qt/qt_settingsmachine.ui +++ b/src/qt/qt_settingsmachine.ui @@ -100,7 +100,7 @@ - PIT Mode: + PIT mode: @@ -158,7 +158,7 @@ - Speed: + Frequency: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter diff --git a/src/qt/qt_softwarerenderer.cpp b/src/qt/qt_softwarerenderer.cpp index ab9ed932d..a8c0229d3 100644 --- a/src/qt/qt_softwarerenderer.cpp +++ b/src/qt/qt_softwarerenderer.cpp @@ -24,7 +24,6 @@ extern "C" { #include <86box/86box.h> -#include <86box/plat.h> #include <86box/video.h> } @@ -114,7 +113,6 @@ SoftwareRenderer::onPaint(QPaintDevice *device) #endif painter.setCompositionMode(QPainter::CompositionMode_Plus); painter.drawImage(destination, *images[cur_image], source); - if (video_fullscreen && status_icons_fullscreen) drawStatusBarIcons(&painter); } std::vector> diff --git a/src/qt/sdl_joystick.cpp b/src/qt/sdl_joystick.cpp index cdbf102b8..4437bb696 100644 --- a/src/qt/sdl_joystick.cpp +++ b/src/qt/sdl_joystick.cpp @@ -36,19 +36,19 @@ joystick_init() int d; strncpy(plat_joystick_state[c].name, SDL_JoystickNameForIndex(c), 64); - plat_joystick_state[c].nr_axes = SDL_JoystickNumAxes(sdl_joy[c]); - plat_joystick_state[c].nr_buttons = SDL_JoystickNumButtons(sdl_joy[c]); - plat_joystick_state[c].nr_povs = SDL_JoystickNumHats(sdl_joy[c]); + plat_joystick_state[c].nr_axes = std::min(SDL_JoystickNumAxes(sdl_joy[c]), MAX_JOY_AXES); + plat_joystick_state[c].nr_buttons = std::min(SDL_JoystickNumButtons(sdl_joy[c]), MAX_JOY_BUTTONS); + plat_joystick_state[c].nr_povs = std::min(SDL_JoystickNumHats(sdl_joy[c]), MAX_JOY_POVS); - for (d = 0; d < std::min(plat_joystick_state[c].nr_axes, 8); d++) { + for (d = 0; d < plat_joystick_state[c].nr_axes; d++) { snprintf(plat_joystick_state[c].axis[d].name, sizeof(plat_joystick_state[c].axis[d].name), "Axis %i", d); plat_joystick_state[c].axis[d].id = d; } - for (d = 0; d < std::min(plat_joystick_state[c].nr_buttons, 8); d++) { + for (d = 0; d < plat_joystick_state[c].nr_buttons; d++) { snprintf(plat_joystick_state[c].button[d].name, sizeof(plat_joystick_state[c].button[d].name), "Button %i", d); plat_joystick_state[c].button[d].id = d; } - for (d = 0; d < std::min(plat_joystick_state[c].nr_povs, 4); d++) { + for (d = 0; d < plat_joystick_state[c].nr_povs; d++) { snprintf(plat_joystick_state[c].pov[d].name, sizeof(plat_joystick_state[c].pov[d].name), "POV %i", d); plat_joystick_state[c].pov[d].id = d; } @@ -116,17 +116,13 @@ joystick_process() for (c = 0; c < joysticks_present; c++) { int b; - plat_joystick_state[c].a[0] = SDL_JoystickGetAxis(sdl_joy[c], 0); - plat_joystick_state[c].a[1] = SDL_JoystickGetAxis(sdl_joy[c], 1); - plat_joystick_state[c].a[2] = SDL_JoystickGetAxis(sdl_joy[c], 2); - plat_joystick_state[c].a[3] = SDL_JoystickGetAxis(sdl_joy[c], 3); - plat_joystick_state[c].a[4] = SDL_JoystickGetAxis(sdl_joy[c], 4); - plat_joystick_state[c].a[5] = SDL_JoystickGetAxis(sdl_joy[c], 5); + for (b = 0; b < plat_joystick_state[c].nr_axes; b++) + plat_joystick_state[c].a[b] = SDL_JoystickGetAxis(sdl_joy[c], b); - for (b = 0; b < 16; b++) + for (b = 0; b < plat_joystick_state[c].nr_buttons; b++) plat_joystick_state[c].b[b] = SDL_JoystickGetButton(sdl_joy[c], b); - for (b = 0; b < 4; b++) + for (b = 0; b < plat_joystick_state[c].nr_povs; b++) plat_joystick_state[c].p[b] = SDL_JoystickGetHat(sdl_joy[c], b); // pclog("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", c, joystick_state[c].x, joystick_state[c].y, joystick_state[c].b[0], joystick_state[c].b[1], joysticks_present); } diff --git a/src/qt/win_joystick_rawinput.c b/src/qt/win_joystick_rawinput.c index 7ee0e8227..bb05c3f5c 100644 --- a/src/qt/win_joystick_rawinput.c +++ b/src/qt/win_joystick_rawinput.c @@ -35,6 +35,29 @@ #include <86box/gameport.h> #include <86box/win.h> +/* These are defined in hidusage.h in the Windows SDK, but not in mingw-w64. */ +#ifndef HID_USAGE_SIMULATION_AILERON +# define HID_USAGE_SIMULATION_AILERON ((USAGE) 0xb0) +#endif +#ifndef HID_USAGE_SIMULATION_ELEVATOR +# define HID_USAGE_SIMULATION_ELEVATOR ((USAGE) 0xb8) +#endif +#ifndef HID_USAGE_SIMULATION_ACCELLERATOR +# define HID_USAGE_SIMULATION_ACCELLERATOR ((USAGE) 0xc4) +#endif +#ifndef HID_USAGE_SIMULATION_BRAKE +# define HID_USAGE_SIMULATION_BRAKE ((USAGE) 0xc5) +#endif +#ifndef HID_USAGE_SIMULATION_CLUTCH +# define HID_USAGE_SIMULATION_CLUTCH ((USAGE) 0xc6) +#endif +#ifndef HID_USAGE_SIMULATION_SHIFTER +# define HID_USAGE_SIMULATION_SHIFTER ((USAGE) 0xc7) +#endif +#ifndef HID_USAGE_SIMULATION_STEERING +# define HID_USAGE_SIMULATION_STEERING ((USAGE) 0xc8) +#endif + #ifdef ENABLE_JOYSTICK_LOG int joystick_do_log = ENABLE_JOYSTICK_LOG; @@ -65,14 +88,14 @@ typedef struct { USHORT bitsize; LONG max; LONG min; - } axis[8]; + } axis[MAX_JOY_AXES]; struct raw_pov_t { USAGE usage; USHORT link; LONG max; LONG min; - } pov[4]; + } pov[MAX_JOY_POVS]; } raw_joystick_t; plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; @@ -85,7 +108,7 @@ raw_joystick_t raw_joystick_state[MAX_PLAT_JOYSTICKS]; void joystick_add_button(raw_joystick_t *rawjoy, plat_joystick_t *joy, USAGE usage) { - if (joy->nr_buttons >= 32) + if (joy->nr_buttons >= MAX_JOY_BUTTONS) return; if (usage < 1 || usage > 128) return; @@ -98,7 +121,7 @@ joystick_add_button(raw_joystick_t *rawjoy, plat_joystick_t *joy, USAGE usage) void joystick_add_axis(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS prop) { - if (joy->nr_axes >= 8) + if (joy->nr_axes >= MAX_JOY_AXES) return; switch (prop->Range.UsageMin) { @@ -120,6 +143,42 @@ joystick_add_axis(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS case HID_USAGE_GENERIC_RZ: sprintf(joy->axis[joy->nr_axes].name, "RZ"); break; + case HID_USAGE_GENERIC_SLIDER: + sprintf(joy->axis[joy->nr_axes].name, "Slider"); + break; + case HID_USAGE_GENERIC_DIAL: + sprintf(joy->axis[joy->nr_axes].name, "Dial"); + break; + case HID_USAGE_GENERIC_WHEEL: + sprintf(joy->axis[joy->nr_axes].name, "Wheel"); + break; + case HID_USAGE_SIMULATION_AILERON: + sprintf(joy->axis[joy->nr_axes].name, "Aileron"); + break; + case HID_USAGE_SIMULATION_ELEVATOR: + sprintf(joy->axis[joy->nr_axes].name, "Elevator"); + break; + case HID_USAGE_SIMULATION_RUDDER: + sprintf(joy->axis[joy->nr_axes].name, "Rudder"); + break; + case HID_USAGE_SIMULATION_THROTTLE: + sprintf(joy->axis[joy->nr_axes].name, "Throttle"); + break; + case HID_USAGE_SIMULATION_ACCELLERATOR: + sprintf(joy->axis[joy->nr_axes].name, "Accelerator"); + break; + case HID_USAGE_SIMULATION_BRAKE: + sprintf(joy->axis[joy->nr_axes].name, "Brake"); + break; + case HID_USAGE_SIMULATION_CLUTCH: + sprintf(joy->axis[joy->nr_axes].name, "Clutch"); + break; + case HID_USAGE_SIMULATION_SHIFTER: + sprintf(joy->axis[joy->nr_axes].name, "Shifter"); + break; + case HID_USAGE_SIMULATION_STEERING: + sprintf(joy->axis[joy->nr_axes].name, "Steering"); + break; default: return; } @@ -147,7 +206,7 @@ joystick_add_axis(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS void joystick_add_pov(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS prop) { - if (joy->nr_povs >= 4) + if (joy->nr_povs >= MAX_JOY_POVS) return; sprintf(joy->pov[joy->nr_povs].name, "POV %d", joy->nr_povs + 1); @@ -367,10 +426,10 @@ win_joystick_handle(PRAWINPUT raw) /* Read axes */ for (int a = 0; a < plat_joystick_state[j].nr_axes; a++) { - struct raw_axis_t *axis = &raw_joystick_state[j].axis[a]; - ULONG uvalue = 0; - LONG value = 0; - LONG center = (axis->max - axis->min + 1) / 2; + const struct raw_axis_t *axis = &raw_joystick_state[j].axis[a]; + ULONG uvalue = 0; + LONG value = 0; + LONG center = (axis->max - axis->min + 1) / 2; r = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, axis->link, axis->usage, &uvalue, raw_joystick_state[j].data, (PCHAR) raw->data.hid.bRawData, raw->data.hid.dwSizeHid); @@ -395,14 +454,16 @@ win_joystick_handle(PRAWINPUT raw) } plat_joystick_state[j].a[a] = value; - // joystick_log("%s %-06d ", plat_joystick_state[j].axis[a].name, plat_joystick_state[j].a[a]); +#if 0 + joystick_log("%s %-06d ", plat_joystick_state[j].axis[a].name, plat_joystick_state[j].a[a]); +#endif } /* read povs */ for (int p = 0; p < plat_joystick_state[j].nr_povs; p++) { - struct raw_pov_t *pov = &raw_joystick_state[j].pov[p]; - ULONG uvalue = 0; - LONG value = -1; + const struct raw_pov_t *pov = &raw_joystick_state[j].pov[p]; + ULONG uvalue = 0; + LONG value = -1; r = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, pov->link, pov->usage, &uvalue, raw_joystick_state[j].data, (PCHAR) raw->data.hid.bRawData, raw->data.hid.dwSizeHid); @@ -415,9 +476,13 @@ win_joystick_handle(PRAWINPUT raw) plat_joystick_state[j].p[p] = value; - // joystick_log("%s %-3d ", plat_joystick_state[j].pov[p].name, plat_joystick_state[j].p[p]); +#if 0 + joystick_log("%s %-3d ", plat_joystick_state[j].pov[p].name, plat_joystick_state[j].p[p]); +#endif } - // joystick_log("\n"); +#if 0 + joystick_log("\n"); +#endif } static int diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 65417ebe3..a6420fb01 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -1864,7 +1864,9 @@ begin: cdrom_audio_pause_resume(dev->drv, 0x00); dev->drv->audio_op = 0x01; scsi_cdrom_command_complete(dev); - break; + if ((dev->packet_status == PHASE_COMPLETE) || (dev->packet_status == PHASE_ERROR)) + scsi_cdrom_buf_free(dev); + return; } fallthrough; case GPCMD_SET_SPEED: @@ -3613,6 +3615,14 @@ atapi_out: dev->sony_vendor = 1; len = (cdb[7] << 8) | cdb[8]; + if (!len) { + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_log("CD-ROM %i: PlayBack Control Sony All done - callback set\n", dev->id); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * CDROM_TIME; + scsi_cdrom_set_callback(dev); + break; + } scsi_cdrom_buf_alloc(dev, 65536); scsi_cdrom_set_buf_len(dev, BufLen, &len); diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index f271df3ec..e9ebe8504 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -207,12 +207,6 @@ 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, scsi_device_t *dev); - -static void -ncr_dma_initiator_receive(ncr5380_t *ncr_dev, ncr_t *ncr, scsi_device_t *dev); - static void ncr_callback(void *priv); @@ -256,7 +250,7 @@ static void ncr_reset(ncr5380_t *ncr_dev, ncr_t *ncr) { memset(ncr, 0x00, sizeof(ncr_t)); - ncr_log("NCR reset\n"); + ncr_log("NCR Reset\n"); timer_stop(&ncr_dev->timer); @@ -266,27 +260,6 @@ ncr_reset(ncr5380_t *ncr_dev, ncr_t *ncr) ncr_irq(ncr_dev, ncr, 0); } -static void -ncr_timer_on(ncr5380_t *ncr_dev, ncr_t *ncr, int callback) -{ - double p = ncr_dev->period; - - if (ncr->data_wait & 2) - ncr->data_wait &= ~2; - - if (callback) { - if (ncr_dev->type == 3) - p *= 512.0; - else - p *= 144.0; - } - - p += 1.0; - - ncr_log("P = %lf, command = %02x, callback = %i, period = %lf, t128 pos = %i\n", p, ncr->command[0], callback, ncr_dev->period, ncr_dev->t128.host_pos); - timer_on_auto(&ncr_dev->timer, p); -} - static uint32_t get_bus_host(ncr_t *ncr) { @@ -477,13 +450,8 @@ ncr_bus_update(void *priv, int bus) /*If the SCSI phase is Data In or Data Out, allocate the SCSI buffer based on the transfer length of the command*/ if (dev->buffer_length && (dev->phase == SCSI_PHASE_DATA_IN || dev->phase == SCSI_PHASE_DATA_OUT)) { p = scsi_device_get_callback(dev); - if (p <= 0.0) { - ncr_dev->period = 0.2; - } else { - ncr_dev->period = p / ((double) dev->buffer_length); - } - ncr->data_wait |= 2; - ncr_log("SCSI ID %i: command 0x%02x for p = %lf, update = %lf, len = %i\n", ncr->target_id, ncr->command[0], p, ncr_dev->period, dev->buffer_length); + ncr_dev->period = (p > 0.0) ? p : (((double) dev->buffer_length) * 0.2); + ncr_log("SCSI ID %i: command 0x%02x for p = %lf, update = %lf, len = %i, dmamode = %x\n", ncr->target_id, ncr->command[0], scsi_device_get_callback(dev), ncr_dev->period, dev->buffer_length, ncr->dma_mode); } } ncr->new_phase = dev->phase; @@ -502,14 +470,15 @@ ncr_bus_update(void *priv, int bus) } else { ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; - if (ncr->data_wait & 2) - ncr->data_wait &= ~2; if (ncr->dma_mode == DMA_IDLE) { /*If a data in command that is not read 6/10 has been issued*/ ncr->data_wait |= 1; ncr_log("DMA mode idle in\n"); timer_on_auto(&ncr_dev->timer, ncr_dev->period); - } else + } else { + ncr_log("DMA mode IN.\n"); ncr->clear_req = 3; + } + ncr->cur_bus &= ~BUS_REQ; ncr->new_phase = SCSI_PHASE_DATA_IN; } @@ -532,9 +501,9 @@ ncr_bus_update(void *priv, int bus) ncr->data_wait |= 1; ncr_log("DMA mode idle out\n"); timer_on_auto(&ncr_dev->timer, ncr_dev->period); - } else { + } else ncr->clear_req = 3; - } + ncr->cur_bus &= ~BUS_REQ; ncr_log("CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); } @@ -594,7 +563,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv) { ncr5380_t *ncr_dev = (ncr5380_t *) priv; ncr_t *ncr = &ncr_dev->ncr; - const scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; + scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; int bus_host = 0; ncr_log("NCR5380 write(%04x,%02x)\n", port & 7, val); @@ -627,7 +596,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv) /*Don't stop the timer until it finishes the transfer*/ if (ncr_dev->t128.block_loaded && (ncr->mode & MODE_DMA)) { ncr_log("Continuing DMA mode\n"); - ncr_timer_on(ncr_dev, ncr, 0); + timer_on_auto(&ncr_dev->timer, ncr_dev->period + 1.0); } /*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/ @@ -638,13 +607,6 @@ ncr_write(uint16_t port, uint8_t val, void *priv) ncr->dma_mode = DMA_IDLE; } } else { - /*Don't stop the timer until it finishes the transfer*/ - if (ncr_dev->block_count_loaded && (ncr->mode & MODE_DMA) && - !timer_is_on(&ncr_dev->timer)) { - ncr_log("Continuing DMA mode\n"); - ncr_timer_on(ncr_dev, ncr, 0); - } - /*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/ if (!ncr_dev->block_count_loaded && !(ncr->mode & MODE_DMA)) { ncr_log("No DMA mode\n"); @@ -669,22 +631,16 @@ ncr_write(uint16_t port, uint8_t val, void *priv) /*a Write 6/10 has occurred, start the timer when the block count is loaded*/ ncr->dma_mode = DMA_SEND; if (ncr_dev->type == 3) { - if (dev->buffer_length > 0) { + if ((ncr->mode & MODE_DMA) && !timer_is_on(&ncr_dev->timer) && (dev->buffer_length > 0)) { memset(ncr_dev->t128.buffer, 0, MIN(512, dev->buffer_length)); - - ncr_log("DMA send timer start, enabled? = %i\n", timer_is_on(&ncr_dev->timer)); - ncr_dev->t128.block_count = dev->buffer_length >> 9; - ncr_dev->t128.block_loaded = 1; - - ncr_dev->t128.host_pos = 0; ncr_dev->t128.status |= 0x04; - } - } else { - if ((ncr->mode & MODE_DMA) && !timer_is_on(&ncr_dev->timer)) { - memset(ncr_dev->buffer, 0, MIN(128, dev->buffer_length)); + ncr_dev->t128.host_pos = 0; + ncr_dev->t128.block_count = dev->buffer_length >> 9; - ncr_log("DMA send timer on\n"); - ncr_timer_on(ncr_dev, ncr, 0); + if (dev->buffer_length < 512) + ncr_dev->t128.block_count = 1; + + ncr_dev->t128.block_loaded = 1; } } break; @@ -694,29 +650,18 @@ ncr_write(uint16_t port, uint8_t val, void *priv) /*a Read 6/10 has occurred, start the timer when the block count is loaded*/ ncr->dma_mode = DMA_INITIATOR_RECEIVE; if (ncr_dev->type == 3) { - ncr_log("DMA receive timer start, enabled? = %i, cdb[0] = %02x, buflen = %i\n", - timer_is_on(&ncr_dev->timer), ncr->command[0], dev->buffer_length); - if (dev->buffer_length > 0) { + if ((ncr->mode & MODE_DMA) && !timer_is_on(&ncr_dev->timer) && (dev->buffer_length > 0)) { memset(ncr_dev->t128.buffer, 0, MIN(512, dev->buffer_length)); - + ncr_dev->t128.status |= 0x04; + ncr_dev->t128.host_pos = MIN(512, dev->buffer_length); ncr_dev->t128.block_count = dev->buffer_length >> 9; if (dev->buffer_length < 512) ncr_dev->t128.block_count = 1; ncr_dev->t128.block_loaded = 1; - - ncr_dev->t128.host_pos = MIN(512, dev->buffer_length); - ncr_dev->t128.status |= 0x04; timer_on_auto(&ncr_dev->timer, 0.02); } - } else { - if ((ncr->mode & MODE_DMA) && !timer_is_on(&ncr_dev->timer)) { - memset(ncr_dev->buffer, 0, MIN(128, dev->buffer_length)); - - ncr_log("DMA receive timer start\n"); - ncr_timer_on(ncr_dev, ncr, 0); - } } break; @@ -725,10 +670,8 @@ ncr_write(uint16_t port, uint8_t val, void *priv) break; } - if (ncr->dma_mode == DMA_IDLE || ncr_dev->type == 0 || ncr_dev->type >= 3) { - bus_host = get_bus_host(ncr); - ncr_bus_update(priv, bus_host); - } + bus_host = get_bus_host(ncr); + ncr_bus_update(priv, bus_host); } static uint8_t @@ -853,7 +796,7 @@ memio_read(uint32_t addr, void *priv) { ncr5380_t *ncr_dev = (ncr5380_t *) priv; ncr_t *ncr = &ncr_dev->ncr; - const scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; + scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; uint8_t ret = 0xff; addr &= 0x3fff; @@ -881,10 +824,12 @@ memio_read(uint32_t addr, void *priv) break; case 0x3900: - if (ncr_dev->buffer_host_pos >= MIN(128, dev->buffer_length) || !(ncr_dev->status_ctrl & CTRL_DATA_DIR)) { + if (ncr_dev->buffer_host_pos >= MIN(128, dev->buffer_length) || (!(ncr_dev->status_ctrl & CTRL_DATA_DIR))) { ret = 0xff; + ncr_log("No Read.\n"); } else { ret = ncr_dev->buffer[ncr_dev->buffer_host_pos++]; + ncr_log("Read host pos = %i, ret = %02x\n", ncr_dev->buffer_host_pos, ret); if (ncr_dev->buffer_host_pos == MIN(128, dev->buffer_length)) { ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; @@ -914,11 +859,9 @@ memio_read(uint32_t addr, void *priv) break; case 0x3982: /* switch register read */ - ret = 0xff; - break; - - case 0x3983: - ret = 0xff; + ret = 0xf8; + ret |= (ncr_dev->irq & 0x07); + ncr_log("Switches read=%02x.\n", ret); break; default: @@ -944,7 +887,7 @@ memio_write(uint32_t addr, uint8_t val, void *priv) { ncr5380_t *ncr_dev = (ncr5380_t *) priv; ncr_t *ncr = &ncr_dev->ncr; - const scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; + scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; addr &= 0x3fff; @@ -988,13 +931,10 @@ memio_write(uint32_t addr, uint8_t val, void *priv) break; case 0x3981: /* block counter register */ - ncr_log("Write block counter register: val=%d, dma mode = %i, period = %lf\n", val, ncr->dma_mode, ncr_dev->period); + ncr_log("Write block counter register: val=%d, dma mode=%x, period=%lf\n", val, ncr->dma_mode, ncr_dev->period); ncr_dev->block_count = val; ncr_dev->block_count_loaded = 1; - 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 = MIN(128, dev->buffer_length); ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; @@ -1002,6 +942,11 @@ memio_write(uint32_t addr, uint8_t val, void *priv) ncr_dev->buffer_host_pos = 0; ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; } + if ((ncr->mode & MODE_DMA) && !timer_is_on(&ncr_dev->timer) && (dev->buffer_length > 0)) { + memset(ncr_dev->buffer, 0, MIN(128, dev->buffer_length)); + ncr_log("DMA timer on\n"); + timer_on_auto(&ncr_dev->timer, ncr_dev->period); + } break; default: @@ -1117,191 +1062,43 @@ t130b_out(uint16_t port, uint8_t val, void *priv) } } -static void -ncr_dma_send(ncr5380_t *ncr_dev, ncr_t *ncr, scsi_device_t *dev) -{ - int bus; - 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 (uint8_t c = 0; c < 10; c++) { - ncr_bus_read(ncr_dev); - if (ncr->cur_bus & BUS_REQ) - break; - } - - /* Data ready. */ - if (ncr_dev->type == 3) - data = ncr_dev->t128.buffer[ncr_dev->t128.pos]; - else - data = ncr_dev->buffer[ncr_dev->buffer_pos]; - bus = get_bus_host(ncr) & ~BUS_DATAMASK; - bus |= BUS_SETDATA(data); - - ncr_bus_update(ncr_dev, bus | BUS_ACK); - ncr_bus_update(ncr_dev, bus & ~BUS_ACK); - - if (ncr_dev->type == 3) { - ncr_dev->t128.pos++; - ncr_log("Buffer pos for writing = %d, data = %02x\n", ncr_dev->t128.pos, data); - - if (ncr_dev->t128.pos == MIN(512, dev->buffer_length)) { - ncr_dev->t128.pos = 0; - ncr_dev->t128.host_pos = 0; - ncr_dev->t128.status &= ~0x02; - ncr_dev->t128.block_count = (ncr_dev->t128.block_count - 1) & 0xff; - ncr_log("Remaining blocks to be written=%d\n", ncr_dev->t128.block_count); - if (!ncr_dev->t128.block_count) { - ncr_dev->t128.block_loaded = 0; - ncr_log("IO End of write transfer\n"); - ncr->tcr |= TCR_LAST_BYTE_SENT; - ncr->isr |= STATUS_END_OF_DMA; - timer_stop(&ncr_dev->timer); - if (ncr->mode & MODE_ENA_EOP_INT) { - ncr_log("NCR write irq\n"); - ncr_irq(ncr_dev, ncr, 1); - } - } - return; - } - } else { - ncr_dev->buffer_pos++; - ncr_log("Buffer pos for writing = %d\n", ncr_dev->buffer_pos); - - if (ncr_dev->buffer_pos == MIN(128, dev->buffer_length)) { - ncr_dev->buffer_pos = 0; - ncr_dev->buffer_host_pos = 0; - ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; - ncr_dev->ncr_busy = 0; - ncr_dev->block_count = (ncr_dev->block_count - 1) & 0xff; - ncr_log("Remaining blocks to be written=%d\n", ncr_dev->block_count); - if (!ncr_dev->block_count) { - ncr_dev->block_count_loaded = 0; - ncr_log("IO End of write transfer\n"); - ncr->tcr |= TCR_LAST_BYTE_SENT; - ncr->isr |= STATUS_END_OF_DMA; - timer_stop(&ncr_dev->timer); - if (ncr->mode & MODE_ENA_EOP_INT) { - ncr_log("NCR write irq\n"); - ncr_irq(ncr_dev, ncr, 1); - } - } - return; - } - } - ncr_dma_send(ncr_dev, ncr, dev); -} - -static void -ncr_dma_initiator_receive(ncr5380_t *ncr_dev, ncr_t *ncr, scsi_device_t *dev) -{ - int bus; - 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 (uint8_t c = 0; c < 10; c++) { - ncr_bus_read(ncr_dev); - if (ncr->cur_bus & BUS_REQ) - break; - } - - /* Data ready. */ - ncr_bus_read(ncr_dev); - temp = BUS_GETDATA(ncr->cur_bus); - - bus = get_bus_host(ncr); - - ncr_bus_update(ncr_dev, bus | BUS_ACK); - ncr_bus_update(ncr_dev, bus & ~BUS_ACK); - - if (ncr_dev->type == 3) { - ncr_dev->t128.buffer[ncr_dev->t128.pos++] = temp; - ncr_log("Buffer pos for reading = %d, temp = %02x\n", ncr_dev->t128.pos, temp); - - if (ncr_dev->t128.pos == MIN(512, dev->buffer_length)) { - ncr_dev->t128.pos = 0; - ncr_dev->t128.host_pos = 0; - ncr_dev->t128.status &= ~0x02; - ncr_dev->t128.block_count = (ncr_dev->t128.block_count - 1) & 0xff; - ncr_log("Remaining blocks to be read=%d, status=%02x, len=%i, cdb[0] = %02x\n", ncr_dev->t128.block_count, ncr_dev->t128.status, dev->buffer_length, ncr->command[0]); - if (!ncr_dev->t128.block_count) { - ncr_dev->t128.block_loaded = 0; - ncr_log("IO End of read transfer\n"); - ncr->isr |= STATUS_END_OF_DMA; - timer_stop(&ncr_dev->timer); - if (ncr->mode & MODE_ENA_EOP_INT) { - ncr_log("NCR read irq\n"); - ncr_irq(ncr_dev, ncr, 1); - } - } - return; - } - } else { - ncr_dev->buffer[ncr_dev->buffer_pos++] = temp; - ncr_log("Buffer pos for reading = %d\n", ncr_dev->buffer_pos); - - if (ncr_dev->buffer_pos == MIN(128, dev->buffer_length)) { - ncr_dev->buffer_pos = 0; - ncr_dev->buffer_host_pos = 0; - ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; - ncr_dev->block_count = (ncr_dev->block_count - 1) & 0xff; - ncr_log("Remaining blocks to be read=%d\n", ncr_dev->block_count); - if (!ncr_dev->block_count) { - ncr_dev->block_count_loaded = 0; - ncr_log("IO End of read transfer\n"); - ncr->isr |= STATUS_END_OF_DMA; - timer_stop(&ncr_dev->timer); - if (ncr->mode & MODE_ENA_EOP_INT) { - ncr_log("NCR read irq\n"); - ncr_irq(ncr_dev, ncr, 1); - } - } - return; - } - } - ncr_dma_initiator_receive(ncr_dev, ncr, dev); -} - static void ncr_callback(void *priv) { ncr5380_t *ncr_dev = (ncr5380_t *) priv; ncr_t *ncr = &ncr_dev->ncr; scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id]; + int bus; + int bytes_tx = 0; + int limit = 100; + uint8_t temp; - if (ncr_dev->type == 3) { - ncr_log("DMA Callback, load = %i\n", ncr_dev->t128.block_loaded); - if (ncr->dma_mode != DMA_IDLE && (ncr->mode & MODE_DMA) && ncr_dev->t128.block_loaded) { - ncr_log("Timer on! Host POS = %i, status = %02x, DMA mode = %i, Period = %lf\n", ncr_dev->t128.host_pos, ncr_dev->t128.status, ncr->dma_mode, scsi_device_get_callback(dev)); - if (ncr_dev->t128.host_pos == MIN(512, dev->buffer_length) && ncr_dev->t128.block_count) { - ncr_dev->t128.status |= 0x04; - } - ncr_timer_on(ncr_dev, ncr, 0); - } + if (ncr_dev->type != 3) { + if (ncr->dma_mode != DMA_IDLE) + timer_on_auto(&ncr_dev->timer, 1.0); } else { - 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) { - ncr_timer_on(ncr_dev, ncr, 0); + if ((ncr->dma_mode != DMA_IDLE) && (ncr->mode & MODE_DMA) && ncr_dev->t128.block_loaded) { + if ((ncr_dev->t128.host_pos == MIN(512, dev->buffer_length)) && ncr_dev->t128.block_count) + ncr_dev->t128.status |= 0x04; + + timer_on_auto(&ncr_dev->timer, ncr_dev->period / 55.0); } } if (ncr->data_wait & 1) { ncr->clear_req = 3; ncr->data_wait &= ~1; - if (ncr->dma_mode == DMA_IDLE) { - return; + if (ncr_dev->type == 3) { + if (ncr->dma_mode == DMA_IDLE) + return; } } + if (ncr_dev->type != 3) { + if (ncr->dma_mode == DMA_IDLE) + return; + } + switch (ncr->dma_mode) { case DMA_SEND: if (ncr_dev->type != 3) { @@ -1317,9 +1114,52 @@ ncr_callback(void *priv) if (!ncr_dev->block_count_loaded) break; + + while (bytes_tx < limit) { + for (uint8_t c = 0; c < 10; c++) { + ncr_bus_read(ncr_dev); + if (ncr->cur_bus & BUS_REQ) + break; + } + + /* Data ready. */ + temp = ncr_dev->buffer[ncr_dev->buffer_pos]; + + bus = get_bus_host(ncr) & ~BUS_DATAMASK; + bus |= BUS_SETDATA(temp); + + ncr_bus_update(ncr_dev, bus | BUS_ACK); + ncr_bus_update(ncr_dev, bus & ~BUS_ACK); + + ncr_dev->buffer_pos++; + bytes_tx++; + ncr_log("Buffer pos for writing = %d\n", ncr_dev->buffer_pos); + + if (ncr_dev->buffer_pos == MIN(128, dev->buffer_length)) { + bytes_tx = 0; + ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + ncr_dev->buffer_pos = 0; + ncr_dev->buffer_host_pos = 0; + ncr_dev->ncr_busy = 0; + ncr_dev->block_count = (ncr_dev->block_count - 1) & 0xff; + ncr_log("Remaining blocks to be written=%d\n", ncr_dev->block_count); + if (!ncr_dev->block_count) { + ncr_dev->block_count_loaded = 0; + ncr_log("IO End of write transfer\n"); + ncr->tcr |= TCR_LAST_BYTE_SENT; + ncr->isr |= STATUS_END_OF_DMA; + timer_stop(&ncr_dev->timer); + if (ncr->mode & MODE_ENA_EOP_INT) { + ncr_log("NCR write irq\n"); + ncr_irq(ncr_dev, ncr, 1); + } + } + break; + } + } } else { if (!(ncr_dev->t128.status & 0x04)) { - ncr_log("Write status busy\n"); + ncr_log("Write status busy, block count = %i, host pos = %i\n", ncr_dev->t128.block_count, ncr_dev->t128.host_pos); break; } @@ -1330,8 +1170,48 @@ ncr_callback(void *priv) if (ncr_dev->t128.host_pos < MIN(512, dev->buffer_length)) break; + +write_again: + for (uint8_t c = 0; c < 10; c++) { + ncr_bus_read(ncr_dev); + if (ncr->cur_bus & BUS_REQ) + break; + } + + /* Data ready. */ + temp = ncr_dev->t128.buffer[ncr_dev->t128.pos]; + + bus = get_bus_host(ncr) & ~BUS_DATAMASK; + bus |= BUS_SETDATA(temp); + + ncr_bus_update(ncr_dev, bus | BUS_ACK); + ncr_bus_update(ncr_dev, bus & ~BUS_ACK); + + ncr_dev->t128.pos++; + ncr_log("Buffer pos for writing = %d\n", ncr_dev->t128.pos); + + if (ncr_dev->t128.pos == MIN(512, dev->buffer_length)) { + ncr_dev->t128.pos = 0; + ncr_dev->t128.host_pos = 0; + ncr_dev->t128.status &= ~0x02; + ncr_dev->ncr_busy = 0; + ncr_dev->t128.block_count = (ncr_dev->t128.block_count - 1) & 0xff; + ncr_log("Remaining blocks to be written=%d\n", ncr_dev->t128.block_count); + if (!ncr_dev->t128.block_count) { + ncr_dev->t128.block_loaded = 0; + ncr_log("IO End of write transfer\n"); + ncr->tcr |= TCR_LAST_BYTE_SENT; + ncr->isr |= STATUS_END_OF_DMA; + timer_stop(&ncr_dev->timer); + if (ncr->mode & MODE_ENA_EOP_INT) { + ncr_log("NCR write irq\n"); + ncr_irq(ncr_dev, ncr, 1); + } + } + break; + } else + goto write_again; } - ncr_dma_send(ncr_dev, ncr, dev); break; case DMA_INITIATOR_RECEIVE: @@ -1348,6 +1228,47 @@ ncr_callback(void *priv) if (!ncr_dev->block_count_loaded) break; + + while (bytes_tx < limit) { + for (uint8_t c = 0; c < 10; c++) { + ncr_bus_read(ncr_dev); + if (ncr->cur_bus & BUS_REQ) + break; + } + + /* Data ready. */ + ncr_bus_read(ncr_dev); + temp = BUS_GETDATA(ncr->cur_bus); + + bus = get_bus_host(ncr); + + ncr_bus_update(ncr_dev, bus | BUS_ACK); + ncr_bus_update(ncr_dev, bus & ~BUS_ACK); + + ncr_dev->buffer[ncr_dev->buffer_pos++] = temp; + ncr_log("Buffer pos for reading = %d\n", ncr_dev->buffer_pos); + bytes_tx++; + + if (ncr_dev->buffer_pos == MIN(128, dev->buffer_length)) { + bytes_tx = 0; + ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + ncr_dev->buffer_pos = 0; + ncr_dev->buffer_host_pos = 0; + ncr_dev->block_count = (ncr_dev->block_count - 1) & 0xff; + ncr_log("Remaining blocks to be read=%d\n", ncr_dev->block_count); + if (!ncr_dev->block_count) { + ncr_dev->block_count_loaded = 0; + ncr_log("IO End of read transfer\n"); + ncr->isr |= STATUS_END_OF_DMA; + timer_stop(&ncr_dev->timer); + if (ncr->mode & MODE_ENA_EOP_INT) { + ncr_log("NCR read irq\n"); + ncr_irq(ncr_dev, ncr, 1); + } + } + break; + } + } } else { if (!(ncr_dev->t128.status & 0x04)) { ncr_log("Read status busy, block count = %i, host pos = %i\n", ncr_dev->t128.block_count, ncr_dev->t128.host_pos); @@ -1361,8 +1282,46 @@ ncr_callback(void *priv) if (ncr_dev->t128.host_pos < MIN(512, dev->buffer_length)) break; + +read_again: + for (uint8_t c = 0; c < 10; c++) { + ncr_bus_read(ncr_dev); + if (ncr->cur_bus & BUS_REQ) + break; + } + + /* Data ready. */ + ncr_bus_read(ncr_dev); + temp = BUS_GETDATA(ncr->cur_bus); + + bus = get_bus_host(ncr); + + ncr_bus_update(ncr_dev, bus | BUS_ACK); + ncr_bus_update(ncr_dev, bus & ~BUS_ACK); + + ncr_dev->t128.buffer[ncr_dev->t128.pos++] = temp; + ncr_log("Buffer pos for reading=%d, temp=%02x, len=%d.\n", ncr_dev->t128.pos, temp, dev->buffer_length); + + if (ncr_dev->t128.pos == MIN(512, dev->buffer_length)) { + ncr_dev->t128.pos = 0; + ncr_dev->t128.host_pos = 0; + ncr_dev->t128.status &= ~0x02; + ncr_dev->t128.block_count = (ncr_dev->t128.block_count - 1) & 0xff; + ncr_log("Remaining blocks to be read=%d, status=%02x, len=%i, cdb[0] = %02x\n", ncr_dev->t128.block_count, ncr_dev->t128.status, dev->buffer_length, ncr->command[0]); + if (!ncr_dev->t128.block_count) { + ncr_dev->t128.block_loaded = 0; + ncr_log("IO End of read transfer\n"); + ncr->isr |= STATUS_END_OF_DMA; + timer_stop(&ncr_dev->timer); + if (ncr->mode & MODE_ENA_EOP_INT) { + ncr_log("NCR read irq\n"); + ncr_irq(ncr_dev, ncr, 1); + } + } + break; + } else + goto read_again; } - ncr_dma_initiator_receive(ncr_dev, ncr, dev); break; default: @@ -1375,7 +1334,8 @@ ncr_callback(void *priv) ncr_log("Updating DMA\n"); ncr->mode &= ~MODE_DMA; ncr->dma_mode = DMA_IDLE; - timer_on_auto(&ncr_dev->timer, 10.0); + if (ncr_dev->type == 3) + timer_on_auto(&ncr_dev->timer, 10.0); } } @@ -1392,12 +1352,12 @@ t128_read(uint32_t addr, void *priv) ret = ncr_dev->bios_rom.rom[addr & 0x1fff]; else if ((addr >= 0x1800) && (addr < 0x1880)) ret = ncr_dev->t128.ext_ram[addr & 0x7f]; - else if ((addr >= 0x1c00) && (addr < 0x1c20)) + else if ((addr >= 0x1c00) && (addr < 0x1c20)) { ret = ncr_dev->t128.ctrl; - else if ((addr >= 0x1c20) && (addr < 0x1c40)) { + ncr_log("T128 ctrl read=%02x, dma=%02x\n", ret, ncr->mode & MODE_DMA); + } else if ((addr >= 0x1c20) && (addr < 0x1c40)) { ret = ncr_dev->t128.status; - ncr_log("T128 status read = %02x, cur bus = %02x, req = %02x, dma = %02x\n", - ret, ncr->cur_bus, ncr->cur_bus & BUS_REQ, ncr->mode & MODE_DMA); + ncr_log("T128 status read=%02x, dma=%02x\n", ret, ncr->mode & MODE_DMA); } else if ((addr >= 0x1d00) && (addr < 0x1e00)) ret = ncr_read((addr - 0x1d00) >> 5, ncr_dev); else if (addr >= 0x1e00 && addr < 0x2000) { @@ -1414,7 +1374,7 @@ t128_read(uint32_t addr, void *priv) ncr_dev->t128.status &= ~0x04; ncr_log("Transfer busy read, status = %02x, period = %lf\n", ncr_dev->t128.status, ncr_dev->period); - if (ncr_dev->period == 0.2 || ncr_dev->period == 0.02) + if ((ncr_dev->period == 0.2) || (ncr_dev->period == 0.02)) timer_on_auto(&ncr_dev->timer, 40.2); } else if ((ncr_dev->t128.host_pos < MIN(512, dev->buffer_length)) && (scsi_device_get_callback(dev) > 100.0)) @@ -1436,12 +1396,11 @@ t128_write(uint32_t addr, uint8_t val, void *priv) if ((addr >= 0x1800) && (addr < 0x1880)) ncr_dev->t128.ext_ram[addr & 0x7f] = val; else if ((addr >= 0x1c00) && (addr < 0x1c20)) { - if ((val & 0x02) && !(ncr_dev->t128.ctrl & 0x02)) { + if ((val & 0x02) && !(ncr_dev->t128.ctrl & 0x02)) ncr_dev->t128.status |= 0x02; - ncr_log("Timer fired\n"); - } + ncr_dev->t128.ctrl = val; - ncr_log("T128 ctrl write = %02x\n", val); + ncr_log("T128 ctrl write=%02x\n", val); } else if ((addr >= 0x1d00) && (addr < 0x1e00)) ncr_write((addr - 0x1d00) >> 5, val, ncr_dev); else if ((addr >= 0x1e00) && (addr < 0x2000)) { @@ -1455,11 +1414,11 @@ t128_write(uint32_t addr, uint8_t val, void *priv) if (ncr_dev->t128.host_pos == MIN(512, dev->buffer_length)) { ncr_dev->t128.status &= ~0x04; + ncr_dev->ncr_busy = 1; ncr_log("Transfer busy write, status = %02x\n", ncr_dev->t128.status); timer_on_auto(&ncr_dev->timer, 0.02); } - } else - ncr_log("Write PDMA addr = %i, val = %02x\n", addr & 0x1ff, val); + } } } @@ -1645,14 +1604,12 @@ ncr_init(const device_t *info) sprintf(&temp[strlen(temp)], " IRQ=%d", ncr_dev->irq); ncr_log("%s\n", temp); - ncr_reset(ncr_dev, &ncr_dev->ncr); if ((ncr_dev->type < 3) || (ncr_dev->type == 4)) { - ncr_dev->status_ctrl = STATUS_BUFFER_NOT_READY; - ncr_dev->buffer_host_pos = 128; + ncr_dev->status_ctrl = STATUS_BUFFER_NOT_READY; + ncr_dev->buffer_host_pos = 128; } else { - ncr_dev->t128.status = 0x04; - ncr_dev->t128.host_pos = 512; - + ncr_dev->t128.status = 0x04; + ncr_dev->t128.host_pos = 512; if (!ncr_dev->t128.bios_enabled) ncr_dev->t128.status |= 0x80; } diff --git a/src/sio/CMakeLists.txt b/src/sio/CMakeLists.txt index d19ca7066..f2ed78445 100644 --- a/src/sio/CMakeLists.txt +++ b/src/sio/CMakeLists.txt @@ -20,7 +20,8 @@ add_library(sio OBJECT sio_acc3221.c sio_ali5123.c sio_f82c710.c sio_82091aa.c sio_it8702.c sio_pc87306.c sio_pc87307.c sio_pc87309.c sio_pc87310.c sio_pc87311.c sio_pc87332.c sio_prime3b.c sio_prime3c.c - sio_w83627hf.c sio_w83787f.c sio_w83877f.c sio_w83977f.c sio_um8669f.c + sio_w83627hf.c sio_w83787f.c sio_w83877f.c sio_w83977f.c + sio_um8663f.c sio_um8669f.c sio_vt82c686.c) if(SIO_DETECT) diff --git a/src/sio/sio_fdc37c669.c b/src/sio/sio_fdc37c669.c index cb678427c..0cd686991 100644 --- a/src/sio/sio_fdc37c669.c +++ b/src/sio/sio_fdc37c669.c @@ -305,7 +305,7 @@ fdc37c669_reset(void *priv) dev->regs[0x21] = 0x3c; dev->regs[0x22] = 0x3d; - if (dev->id == 1) { + if (dev->id != 1) { fdc_reset(dev->fdc); fdc37c669_fdc_handler(dev); } diff --git a/src/sio/sio_fdc37c6xx.c b/src/sio/sio_fdc37c6xx.c index 23fcd2fb3..c1fb2c1a5 100644 --- a/src/sio/sio_fdc37c6xx.c +++ b/src/sio/sio_fdc37c6xx.c @@ -394,6 +394,20 @@ const device_t fdc37c661_ide_device = { .config = NULL }; +const device_t fdc37c661_ide_sec_device = { + .name = "SMC FDC37C661 Super I/O (With Secondary IDE)", + .internal_name = "fdc37c661_ide_sec", + .flags = 0, + .local = 0x261, + .init = fdc37c6xx_init, + .close = fdc37c6xx_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t fdc37c663_device = { .name = "SMC FDC37C663 Super I/O", .internal_name = "fdc37c663", @@ -464,6 +478,20 @@ const device_t fdc37c665_ide_pri_device = { .config = NULL }; +const device_t fdc37c665_ide_sec_device = { + .name = "SMC FDC37C665 Super I/O (With Secondary IDE)", + .internal_name = "fdc37c665_ide_sec", + .flags = 0, + .local = 0x265, + .init = fdc37c6xx_init, + .close = fdc37c6xx_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t fdc37c666_device = { .name = "SMC FDC37C666 Super I/O", .internal_name = "fdc37c666", diff --git a/src/sio/sio_it86x1f.c b/src/sio/sio_it86x1f.c index 74e79bbed..ece59501f 100644 --- a/src/sio/sio_it86x1f.c +++ b/src/sio/sio_it86x1f.c @@ -414,8 +414,10 @@ it86x1f_pnp_write_vendor_reg(uint8_t ld, uint8_t reg, uint8_t val, void *priv) case 0x23: val &= (1 << dev->gpio_ldn) - 1; dev->global_regs[reg & 0x0f] = val; +#ifdef ENABLE_IT86X1F_LOG if (val) - pclog("IT86x1F: Warning: ISAPnP mode enabled.\n"); + it86x1f_log("IT86x1F: Warning: ISAPnP mode enabled.\n"); +#endif break; case 0x24: diff --git a/src/sio/sio_um8663f.c b/src/sio/sio_um8663f.c new file mode 100644 index 000000000..7391b029f --- /dev/null +++ b/src/sio/sio_um8663f.c @@ -0,0 +1,366 @@ +/* + * 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 UMF8663F Super I/O chip. + * + * Authors: Miran Grca, + * + * Copyright 2024 Miran Grca. + */ +#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/lpt.h> +#include <86box/serial.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/gameport.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/sio.h> +#include <86box/random.h> +#include <86box/plat_unused.h> + +#ifdef ENABLE_UM8663F_LOG +int um8663f_do_log = ENABLE_UM8663F_LOG; + +static void +um8663f_log(const char *fmt, ...) +{ + va_list ap; + + if (um8663f_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define um8663f_log(fmt, ...) +#endif + +typedef struct um8663f_t { + uint8_t max_reg; + uint8_t ide; + uint8_t locked; + uint8_t cur_reg; + uint8_t regs[5]; + + fdc_t *fdc; + serial_t *uart[2]; +} um8663f_t; + +static void +um8663f_fdc_handler(um8663f_t *dev) +{ + fdc_remove(dev->fdc); + if (dev->regs[0] & 0x01) + fdc_set_base(dev->fdc, (dev->regs[1] & 0x01) ? FDC_PRIMARY_ADDR : FDC_SECONDARY_ADDR); +} + +static void +um8663f_uart_handler(um8663f_t *dev, int port) +{ + uint8_t shift = (port + 1); + + serial_remove(dev->uart[port]); + if (dev->regs[0] & (2 << port)) { + switch ((dev->regs[1] >> shift) & 0x01) { + case 0x00: + if (port == 1) + serial_setup(dev->uart[port], COM4_ADDR, COM4_IRQ); + else + serial_setup(dev->uart[port], COM3_ADDR, COM1_IRQ); + break; + case 0x01: + if (port == 1) + serial_setup(dev->uart[port], COM2_ADDR, COM2_IRQ); + else + serial_setup(dev->uart[port], COM1_ADDR, COM1_IRQ); + break; + + default: + break; + } + } +} + +static void +um8663f_lpt_handler(um8663f_t *dev) +{ + lpt1_remove(); + if (dev->regs[0] & 0x08) { + switch ((dev->regs[1] >> 3) & 0x01) { + case 0x01: + lpt1_init(LPT1_ADDR); + lpt1_irq(7); + break; + case 0x00: + lpt1_init(LPT2_ADDR); + lpt1_irq(5); + break; + + default: + break; + } + } +} + +static void +um8663f_ide_handler(um8663f_t *dev) +{ + int board = dev->ide - 1; + + if (dev->ide > 0) { + ide_handlers(board, 0); + ide_set_base(board, (dev->regs[1] & 0x10) ? 0x01f0 : 0x0170); + ide_set_side(board, (dev->regs[1] & 0x10) ? 0x03f6 : 0x0376); + if (dev->regs[0] & 0x10) + ide_handlers(board, 1); + } +} + +static void +um8663f_write(uint16_t port, uint8_t val, void *priv) +{ + um8663f_t *dev = (um8663f_t *) priv; + uint8_t valxor; + + um8663f_log("UM8663F: write(%04X, %02X)\n", port, val); + + if (dev->locked) { + if ((port == 0x108) && (val == 0xaa)) + dev->locked = 0; + } else { + if (port == 0x108) { + if (val == 0x55) + dev->locked = 1; + else + dev->cur_reg = val; + } else if ((dev->cur_reg >= 0xc0) && (dev->cur_reg <= dev->max_reg)) { + valxor = (dev->regs[dev->cur_reg - 0xc0] ^ val); + dev->regs[dev->cur_reg - 0xc0] = val; + switch (dev->cur_reg - 0xc0) { + /* Port enable register. */ + case 0x00: + if (valxor & 0x10) + um8663f_ide_handler(dev); + if (valxor & 0x08) + um8663f_lpt_handler(dev); + if (valxor & 0x04) + um8663f_uart_handler(dev, 1); + if (valxor & 0x02) + um8663f_uart_handler(dev, 0); + if (valxor & 0x01) + um8663f_fdc_handler(dev); + break; + /* + Port configuration register: + - Bits 7, 6: + - 0, 0 = LPT 1 is none; + - 0, 1 = LPT 1 is EPP; + - 1, 0 = LPT 1 is SPP; + - 1, 1 = LPT 1 is ECP; + - Bit 4 = 0 = IDE is secondary, 1 = IDE is primary; + - Bit 3 = 0 = LPT 1 is 278h, 1 = LPT 1 is 378h; + - Bit 2 = 0 = UART 2 is COM4, 1 = UART 2 is COM2; + - Bit 1 = 0 = UART 1 is COM3, 1 = UART 2 is COM1; + - Bit 0 = 0 = FDC is 370h, 1 = UART 2 is 3f0h. + */ + case 0x01: + if (valxor & 0x10) + um8663f_ide_handler(dev); + if (valxor & 0x08) + um8663f_lpt_handler(dev); + if (valxor & 0x04) + um8663f_uart_handler(dev, 1); + if (valxor & 0x02) + um8663f_uart_handler(dev, 0); + if (valxor & 0x01) + um8663f_fdc_handler(dev); + break; + } + } + } +} + +static uint8_t +um8663f_read(uint16_t port, void *priv) +{ + const um8663f_t *dev = (um8663f_t *) priv; + uint8_t ret = 0xff; + + if (!dev->locked) { + if (port == 0x108) + ret = dev->cur_reg; /* ??? */ + else if ((dev->cur_reg >= 0xc0) && (dev->cur_reg <= dev->max_reg)) { + ret = dev->regs[dev->cur_reg - 0xc0]; + if (dev->cur_reg == 0xc0) + ret = (ret & 0x1f) | ((random_generate() & 0x07) << 5); + } + } + + um8663f_log("UM8663F: read(%04X) = %02X\n", port, ret); + + return ret; +} + +static void +um8663f_reset(void *priv) +{ + um8663f_t *dev = (um8663f_t *) priv; + + serial_remove(dev->uart[0]); + serial_setup(dev->uart[0], COM1_ADDR, COM1_IRQ); + + serial_remove(dev->uart[1]); + serial_setup(dev->uart[1], COM2_ADDR, COM2_IRQ); + + lpt1_remove(); + lpt1_init(LPT1_ADDR); + + fdc_reset(dev->fdc); + fdc_remove(dev->fdc); + + memset(dev->regs, 0x00, sizeof(dev->regs)); + + dev->regs[0x00] = (dev->ide > 0) ? 0x1f : 0x0f; + dev->regs[0x01] = (dev->ide == 2) ? 0x0f : 0x1f; + + um8663f_fdc_handler(dev); + um8663f_uart_handler(dev, 0); + um8663f_uart_handler(dev, 1); + um8663f_lpt_handler(dev); + um8663f_ide_handler(dev); + + dev->locked = 1; +} + +static void +um8663f_close(void *priv) +{ + um8663f_t *dev = (um8663f_t *) priv; + + free(dev); +} + +static void * +um8663f_init(UNUSED(const device_t *info)) +{ + um8663f_t *dev = (um8663f_t *) calloc(1, sizeof(um8663f_t)); + + dev->fdc = device_add(&fdc_at_smc_device); + + dev->uart[0] = device_add_inst(&ns16550_device, 1); + dev->uart[1] = device_add_inst(&ns16550_device, 2); + + dev->ide = info->local & 0xff; + if (dev->ide < IDE_BUS_MAX) + device_add(&ide_isa_device); + + dev->max_reg = info->local >> 8; + + io_sethandler(0x0108, 0x0002, um8663f_read, NULL, NULL, um8663f_write, NULL, NULL, dev); + + um8663f_reset(dev); + + return dev; +} + +const device_t um8663af_device = { + .name = "UMC UM8663AF Super I/O", + .internal_name = "um8663af", + .flags = 0, + .local = 0xc300, + .init = um8663f_init, + .close = um8663f_close, + .reset = um8663f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t um8663af_ide_device = { + .name = "UMC UM8663AF Super I/O (With IDE)", + .internal_name = "um8663af_ide", + .flags = 0, + .local = 0xc301, + .init = um8663f_init, + .close = um8663f_close, + .reset = um8663f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t um8663af_ide_sec_device = { + .name = "UMC UM8663AF Super I/O (With Secondary IDE)", + .internal_name = "um8663af_ide_sec", + .flags = 0, + .local = 0xc302, + .init = um8663f_init, + .close = um8663f_close, + .reset = um8663f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t um8663bf_device = { + .name = "UMC UM8663BF Super I/O", + .internal_name = "um8663bf", + .flags = 0, + .local = 0xc400, + .init = um8663f_init, + .close = um8663f_close, + .reset = um8663f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t um8663bf_ide_device = { + .name = "UMC UM8663BF Super I/O (With IDE)", + .internal_name = "um8663bf_ide", + .flags = 0, + .local = 0xc401, + .init = um8663f_init, + .close = um8663f_close, + .reset = um8663f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t um8663bf_ide_sec_device = { + .name = "UMC UM8663BF Super I/O (With Secondary IDE)", + .internal_name = "um8663bf_ide_sec", + .flags = 0, + .local = 0xc402, + .init = um8663f_init, + .close = um8663f_close, + .reset = um8663f_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/sio/sio_w83787f.c b/src/sio/sio_w83787f.c index 33cfc6311..2e4b82059 100644 --- a/src/sio/sio_w83787f.c +++ b/src/sio/sio_w83787f.c @@ -215,8 +215,9 @@ static void w83787f_fdc_handler(w83787f_t *dev) { fdc_remove(dev->fdc); - if (!(dev->regs[0] & 0x20) && !(dev->regs[6] & 0x08)) + if (!(dev->regs[0] & 0x20)) fdc_set_base(dev->fdc, (dev->regs[0] & 0x10) ? FDC_PRIMARY_ADDR : FDC_SECONDARY_ADDR); + fdc_set_power_down(dev->fdc, !!(dev->regs[6] & 0x08)); } static void @@ -258,10 +259,10 @@ w83787f_write(uint16_t port, uint8_t val, void *priv) return; } else { if (dev->locked) { - if (dev->rw_locked) + if (dev->rw_locked && (dev->cur_reg <= 0x0b)) return; if (dev->cur_reg == 6) - val &= 0xF3; + val &= 0xFB; valxor = val ^ dev->regs[dev->cur_reg]; dev->regs[dev->cur_reg] = val; } else @@ -363,7 +364,7 @@ w83787f_read(uint16_t port, void *priv) else if (port == 0x252) { if (dev->cur_reg == 7) ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2)); - else if (!dev->rw_locked) + else if (!dev->rw_locked || (dev->cur_reg > 0x0b)) ret = dev->regs[dev->cur_reg]; } } @@ -406,6 +407,7 @@ w83787f_reset(w83787f_t *dev) dev->regs[0x00] = 0xd0; fdc_reset(dev->fdc); + w83787f_fdc_handler(dev); dev->regs[0x01] = 0x2C; dev->regs[0x03] = 0x70; diff --git a/src/sio/sio_w83877f.c b/src/sio/sio_w83877f.c index 8cbb82876..c9a437630 100644 --- a/src/sio/sio_w83877f.c +++ b/src/sio/sio_w83877f.c @@ -78,12 +78,12 @@ w83877f_remap(w83877f_t *dev) { uint8_t hefras = HEFRAS; - io_removehandler(0x250, 0x0002, + io_removehandler(0x250, 0x0003, w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev); io_removehandler(FDC_PRIMARY_ADDR, 0x0002, w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev); dev->base_address = (hefras ? FDC_PRIMARY_ADDR : 0x250); - io_sethandler(dev->base_address, 0x0002, + io_sethandler(dev->base_address, hefras ? 0x0002 : 0x0003, w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev); dev->key_times = hefras + 1; dev->key = (hefras ? 0x86 : 0x88) | HEFERE; @@ -155,8 +155,9 @@ static void w83877f_fdc_handler(w83877f_t *dev) { fdc_remove(dev->fdc); - if (!(dev->regs[6] & 0x08) && (dev->regs[0x20] & 0xc0)) - fdc_set_base(dev->fdc, FDC_PRIMARY_ADDR); + if (dev->regs[0x20] & 0xc0) + fdc_set_base(dev->fdc, make_port(dev, 0x20)); + fdc_set_power_down(dev->fdc, !!(dev->regs[6] & 0x08)); } static void @@ -252,7 +253,7 @@ w83877f_write(uint16_t port, uint8_t val, void *priv) if (dev->cur_reg == 0x29) return; if (dev->cur_reg == 6) - val &= 0xF3; + val &= 0xFB; valxor = val ^ dev->regs[dev->cur_reg]; dev->regs[dev->cur_reg] = val; } else diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index bf4cf61be..d4ff1eb0f 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -18,7 +18,7 @@ add_library(snd OBJECT sound.c snd_opl.c snd_opl_nuked.c snd_opl_ymfm.cpp snd_re snd_lpt_dss.c snd_ps1.c snd_adlib.c snd_adlibgold.c snd_ad1848.c snd_audiopci.c snd_azt2316a.c snd_cms.c snd_cmi8x38.c snd_cs423x.c snd_gus.c snd_sb.c snd_sb_dsp.c snd_emu8k.c snd_mpu401.c snd_sn76489.c snd_ssi2001.c snd_wss.c snd_ym7128.c - snd_optimc.c midi_opl4.c midi_opl4_yrw801.c) + snd_optimc.c) if(OPENAL) if(VCPKG_TOOLCHAIN) @@ -125,5 +125,10 @@ if(GUSMAX) target_compile_definitions(snd PRIVATE USE_GUSMAX) endif() +if(OPL4ML) + target_compile_definitions(snd PRIVATE USE_OPL4ML) + target_sources(snd PRIVATE midi_opl4.c midi_opl4_yrw801.c) +endif() + add_subdirectory(resid-fp) target_link_libraries(86Box resid-fp) diff --git a/src/sound/midi.c b/src/sound/midi.c index c5dbd666f..bb107acbf 100644 --- a/src/sound/midi.c +++ b/src/sound/midi.c @@ -100,7 +100,9 @@ static const MIDI_OUT_DEVICE devices[] = { #ifdef USE_RTMIDI { &rtmidi_output_device }, #endif +#if defined(DEV_BRANCH) && defined(USE_OPL4ML) { &opl4_midi_device }, +#endif { NULL } // clang-format on }; diff --git a/src/unix/unix.c b/src/unix/unix.c index 4f21ddd53..6c21bfa45 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -63,7 +63,6 @@ extern wchar_t sdl_win_title[512]; plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; joystick_t joystick_state[MAX_JOYSTICKS]; int joysticks_present; -int status_icons_fullscreen = 0; /* unused. */ SDL_mutex *blitmtx; SDL_threadID eventthread; static int exit_event = 0; @@ -263,8 +262,6 @@ plat_get_string(int i) return L"No PCap devices found"; case IDS_2096: return L"Invalid PCap device"; - case IDS_2112: - return L"Unable to initialize SDL, libsdl2 is required"; case IDS_2133: return L"libgs is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files."; case IDS_2130: diff --git a/src/unix/unix_cdrom.c b/src/unix/unix_cdrom.c index 424f1a9a3..61813a754 100644 --- a/src/unix/unix_cdrom.c +++ b/src/unix/unix_cdrom.c @@ -145,6 +145,8 @@ cdrom_mount(uint8_t id, char *fn) cdrom[id].ops->exit(&(cdrom[id])); cdrom[id].ops = NULL; memset(cdrom[id].image_path, 0, sizeof(cdrom[id].image_path)); + if ((fn != NULL) && (strlen(fn) >= 1) && (fn[strlen(fn) - 1] == '\\')) + fn[strlen(fn) - 1] = '/'; cdrom_image_open(&(cdrom[id]), fn); /* Signal media change to the emulated machine. */ if (cdrom[id].insert) diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index 638837757..8fbd62e35 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -19,7 +19,7 @@ add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.c vid_sigma.c vid_wy700.c vid_ega.c vid_ega_render.c vid_svga.c vid_8514a.c vid_svga_render.c vid_ddc.c vid_vga.c vid_ati_eeprom.c vid_ati18800.c vid_ati28800.c vid_ati_mach8.c vid_ati_mach64.c vid_ati68875_ramdac.c - vid_ati68860_ramdac.c vid_bt48x_ramdac.c + vid_ati68860_ramdac.c vid_bt48x_ramdac.c vid_chips_69000.c vid_av9194.c vid_icd2061.c vid_ics2494.c vid_ics2595.c vid_cl54xx.c vid_et3000.c vid_et4000.c vid_sc1148x_ramdac.c vid_sc1502x_ramdac.c vid_et4000w32.c vid_stg_ramdac.c vid_ht216.c vid_oak_oti.c vid_paradise.c diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 864a88978..ff1470164 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -13,7 +13,7 @@ * * Authors: TheCollector1995. * - * Copyright 2022-2023 TheCollector1995. + * Copyright 2022-2024 TheCollector1995. */ #include #include @@ -38,8 +38,14 @@ #include <86box/vid_xga.h> #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> +#include <86box/vid_ati_eeprom.h> +#include <86box/vid_ati_mach8.h> #include "cpu.h" +#ifdef ATI_8514_ULTRA +#define BIOS_MACH8_ROM_PATH "roms/video/mach8/11301113140.BIN" +#endif + static void ibm8514_accel_outb(uint16_t port, uint8_t val, void *priv); static void ibm8514_accel_outw(uint16_t port, uint16_t val, void *priv); static uint8_t ibm8514_accel_inb(uint16_t port, void *priv); @@ -63,6 +69,27 @@ ibm8514_log(const char *fmt, ...) # define ibm8514_log(fmt, ...) #endif +#define WRITE8(addr, var, val) \ + switch ((addr) & 1) { \ + case 0: \ + var = (var & 0xff00) | (val); \ + break; \ + case 1: \ + var = (var & 0x00ff) | ((val) << 8); \ + break; \ + } + +#define READ8(addr, var) \ + switch ((addr) & 1) { \ + case 0: \ + temp = (var) & 0xff; \ + break; \ + case 1: \ + temp = ((var) >> 8) & 0xff; \ + break; \ + } + + #define READ_PIXTRANS_WORD(cx, n) \ if ((cmd <= 1) || (cmd == 5)) { \ temp = dev->vram[((dev->accel.cy * dev->pitch) + (cx) + (n)) & dev->vram_mask]; \ @@ -453,16 +480,15 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) switch (port) { case 0x82e8: case 0xc2e8: - if (len == 1) { + if (len == 1) dev->accel.cur_y = (dev->accel.cur_y & 0x700) | val; - } else + else dev->accel.cur_y = val & 0x7ff; break; case 0x82e9: case 0xc2e9: - if (len == 1) { + if (len == 1) dev->accel.cur_y = (dev->accel.cur_y & 0xff) | ((val & 0x07) << 8); - } break; case 0x86e8: @@ -474,9 +500,8 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) break; case 0x86e9: case 0xc6e9: - if (len == 1) { + if (len == 1) dev->accel.cur_x = (dev->accel.cur_x & 0xff) | ((val & 0x07) << 8); - } break; case 0x8ae8: @@ -742,16 +767,19 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) else { dev->accel.multifunc_cntl = val; dev->accel.multifunc[dev->accel.multifunc_cntl >> 12] = dev->accel.multifunc_cntl & 0xfff; - if ((dev->accel.multifunc_cntl >> 12) == 1) { + if ((dev->accel.multifunc_cntl >> 12) == 1) dev->accel.clip_top = val & 0x7ff; - if (val & 0x400) - dev->accel.clip_top |= ~0x3ff; - } - if ((dev->accel.multifunc_cntl >> 12) == 2) { + + if ((dev->accel.multifunc_cntl >> 12) == 2) dev->accel.clip_left = val & 0x7ff; - if (val & 0x400) - dev->accel.clip_left |= ~0x3ff; - } + + if ((dev->accel.multifunc_cntl >> 12) == 3) + dev->accel.multifunc[3] = val & 0x7ff; + + if ((dev->accel.multifunc_cntl >> 12) == 4) + dev->accel.multifunc[4] = val & 0x7ff; + + ibm8514_log("CLIPBOTTOM=%d, CLIPRIGHT=%d, bpp=%d, pitch=%d.\n", dev->accel.multifunc[3], dev->accel.multifunc[4], dev->accel_bpp, dev->pitch); if (port == 0xfee8) dev->accel.cmd_back = 1; else @@ -763,6 +791,12 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) if (len == 1) { dev->accel.multifunc_cntl = (dev->accel.multifunc_cntl & 0xff) | (val << 8); dev->accel.multifunc[dev->accel.multifunc_cntl >> 12] = dev->accel.multifunc_cntl & 0xfff; + if ((dev->accel.multifunc_cntl >> 12) == 1) + dev->accel.clip_top = dev->accel.multifunc_cntl & 0x7ff; + + if ((dev->accel.multifunc_cntl >> 12) == 2) + dev->accel.clip_left = dev->accel.multifunc_cntl & 0x7ff; + if (port == 0xfee9) dev->accel.cmd_back = 1; else @@ -855,151 +889,126 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint8_t old = 0; - if (port & 0x8000) { + if (port & 0x8000) ibm8514_accel_out_fifo(svga, port, val, len); - } else { + else { switch (port) { case 0x2e8: - if (len == 1) - dev->htotal = (dev->htotal & 0xff00) | val; - else { - dev->htotal = val; - svga_recalctimings(svga); - } - break; case 0x2e9: - if (len != 1) { - dev->htotal = (dev->htotal & 0xff) | (val << 8); - ibm8514_log("IBM 8514/A: H_TOTAL write 02E8 = %d\n", dev->htotal + 1); - svga_recalctimings(svga); - } + WRITE8(port, dev->htotal, val); break; case 0x6e8: - dev->hdisp = val; - ibm8514_log("IBM 8514/A: H_DISP write 06E8 = %d\n", dev->hdisp + 1); - svga_recalctimings(svga); + case 0x6e9: + if (!(port & 1)) { + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04))) { + dev->hdisped = val; + dev->hdisp = (dev->hdisped + 1) << 3; + } + } + ibm8514_log("IBM 8514/A: H_DISP write 06E8 = %d, advfunc=%x.\n", dev->hdisp, dev->accel.advfunc_cntl & 4); break; case 0xae8: + case 0xae9: + if (!(port & 1)) { + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04))) { + dev->hsync_start = val; + dev->hblankstart = (dev->hsync_start & 0x07); + } + } ibm8514_log("IBM 8514/A: H_SYNC_STRT write 0AE8 = %d\n", val + 1); - svga_recalctimings(svga); break; case 0xee8: + case 0xee9: + if (!(port & 1)) { + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04))) { + dev->hsync_width = val; + dev->hblank_end_val = (dev->hblankstart + (dev->hsync_width & 0x1f) - 1) & 0x3f; + } + } ibm8514_log("IBM 8514/A: H_SYNC_WID write 0EE8 = %d\n", val + 1); - svga_recalctimings(svga); break; case 0x12e8: - if (len == 1) - dev->vtotal = (dev->vtotal & 0x1f00) | val; - else { - dev->vtotal = val & 0x1fff; - svga_recalctimings(svga); - } - break; case 0x12e9: - if (len == 1) { - dev->vtotal = (dev->vtotal & 0xff) | ((val & 0x1f) << 8); - ibm8514_log("IBM 8514/A: V_TOTAL write 12E8 = %d\n", dev->vtotal); - svga_recalctimings(svga); + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04))) { + WRITE8(port, dev->v_total_reg, val); + dev->v_total_reg &= 0x1fff; + dev->vtotal = dev->v_total_reg; + dev->vtotal++; } break; case 0x16e8: - if (len == 1) - dev->vdisp = (dev->vdisp & 0x1f00) | val; - else { - dev->vdisp = val & 0x1fff; - svga_recalctimings(svga); - } - break; case 0x16e9: - if (len == 1) { - dev->vdisp = (dev->vdisp & 0xff) | ((val & 0x1f) << 8); - ibm8514_log("IBM 8514/A: V_DISP write 16E8 = %d\n", dev->vdisp); - svga_recalctimings(svga); + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04))) { + WRITE8(port, dev->v_disp, val); + dev->v_disp &= 0x1fff; + dev->vdisp = dev->v_disp; + dev->vdisp >>= 1; + dev->vdisp++; } + ibm8514_log("IBM 8514/A: V_DISP write 16E8 = %d\n", dev->vdisp); break; case 0x1ae8: - if (len == 1) - dev->vsyncstart = (dev->vsyncstart & 0x1f00) | val; - else { - dev->vsyncstart = val & 0x1fff; - svga_recalctimings(svga); - } - break; case 0x1ae9: - if (len == 1) { - dev->vsyncstart = (dev->vsyncstart & 0xff) | ((val & 0x1f) << 8); - ibm8514_log("IBM 8514/A: V_SYNC_STRT write 1AE8 = %d\n", dev->vsyncstart); - svga_recalctimings(svga); + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04))) { + WRITE8(port, dev->v_sync_start, val); + dev->v_sync_start &= 0x1fff; + dev->vsyncstart = dev->v_sync_start; + dev->vsyncstart++; } break; case 0x1ee8: - dev->vsyncwidth = val; + case 0x1ee9: ibm8514_log("IBM 8514/A: V_SYNC_WID write 1EE8 = %02x\n", val); - svga_recalctimings(svga); break; case 0x22e8: dev->disp_cntl = val & 0x7e; dev->interlace = !!(val & 0x10); - ibm8514_log("IBM 8514/A: DISP_CNTL write 22E8 = %02x, SCANMODULOS = %d\n", dev->disp_cntl, dev->scanmodulos); - svga_recalctimings(svga); + ibm8514_log("IBM 8514/A: DISP_CNTL write 22E8 = %02x, interlace = %d\n", dev->disp_cntl, dev->interlace); break; case 0x42e8: old = dev->subsys_stat; - if ((val & 0xff) & 1) + if (val & 1) dev->subsys_stat &= ~1; - if ((val & 0xff) & 2) + if (val & 2) dev->subsys_stat &= ~2; - if ((val & 0xff) & 4) + if (val & 4) dev->subsys_stat &= ~4; - if ((val & 0xff) & 8) + if (val & 8) dev->subsys_stat &= ~8; - if (len != 1) { - old = dev->subsys_cntl; - dev->subsys_cntl = (val >> 8); - if ((old ^ dev->subsys_cntl) & 1) - dev->subsys_stat |= 1; - if ((old ^ dev->subsys_cntl) & 2) - dev->subsys_stat |= 2; - if ((old ^ dev->subsys_cntl) & 4) - dev->subsys_stat |= 4; - if ((old ^ dev->subsys_cntl) & 8) - dev->subsys_stat |= 8; - } break; case 0x42e9: - if (len == 1) { - old = dev->subsys_cntl; - dev->subsys_cntl = val; - if ((old ^ val) & 1) - dev->subsys_stat |= 1; - if ((old ^ val) & 2) - dev->subsys_stat |= 2; - if ((old ^ val) & 4) - dev->subsys_stat |= 4; - if ((old ^ val) & 8) - dev->subsys_stat |= 8; - } + old = dev->subsys_cntl; + dev->subsys_cntl = val; + if ((old ^ val) & 1) + dev->subsys_stat |= 1; + if ((old ^ val) & 2) + dev->subsys_stat |= 2; + if ((old ^ val) & 4) + dev->subsys_stat |= 4; + if ((old ^ val) & 8) + dev->subsys_stat |= 8; break; case 0x4ae8: - if (!val) - break; - dev->accel.advfunc_cntl = val & 0x0f; - dev->on[0] = val & 0x01; - vga_on = !dev->on[0]; - ibm8514_log("IBM 8514/A: VGA ON = %i, val = %02x\n", vga_on, val); + case 0x4ae9: + WRITE8(port, dev->accel.advfunc_cntl, val); + dev->on[port & 1] = dev->accel.advfunc_cntl & 0x01; + vga_on = !dev->on[port & 1]; + dev->vendor_mode[port & 1] = 0; + ibm8514_log("IBM 8514/A: (0x%04x): ON=%d, shadow crt=%x.\n", port, dev->on[port & 1], dev->accel.advfunc_cntl & 4); svga_recalctimings(svga); break; + default: break; } @@ -1036,16 +1045,16 @@ ibm8514_accel_in(uint16_t port, svga_t *svga, int len) vpos = dev->vc & 0x7ff; if (vblankend > dev->v_total) { vblankend -= dev->v_total; - if (vpos >= svga->vblankstart || vpos <= vblankend) + if ((vpos >= svga->vblankstart) || (vpos <= vblankend)) temp |= 2; } else { - if (vpos >= svga->vblankstart && vpos <= vblankend) + if ((vpos >= svga->vblankstart) && (vpos <= vblankend)) temp |= 2; } break; case 0x6e8: - temp = dev->hdisp; + temp = dev->hdisped; break; case 0x22e8: @@ -1091,22 +1100,19 @@ ibm8514_accel_in(uint16_t port, svga_t *svga, int len) case 0x82e8: case 0xc2e8: - if (len != 1) { + if (len != 1) temp = dev->accel.cur_y; - } break; case 0x86e8: case 0xc6e8: - if (len != 1) { + if (len != 1) temp = dev->accel.cur_x; - } break; case 0x92e8: - if (len != 1) { + if (len != 1) temp = dev->test; - } break; case 0x9ae8: @@ -1200,12 +1206,6 @@ ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t ibm8514_accel_start(count, cpu_input, mix_dat, cpu_dat, svga, len); } -#define CLAMP(x) \ - do { \ - if ((x) & ~0xff) \ - x = ((x) < 0) ? 0 : 0xff; \ - } while (0) - void ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, UNUSED(int len)) { @@ -3831,7 +3831,24 @@ bitblt: } } -#undef CLAMP +void +ibm8514_render_blank(svga_t *svga) +{ + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + if ((dev->displine + svga->y_add) < 0) + return; + + if (dev->firstline_draw == 2000) + dev->firstline_draw = dev->displine; + dev->lastline_draw = dev->displine; + + uint32_t *line_ptr = &svga->monitor->target_buffer->line[dev->displine + svga->y_add][svga->x_add]; + uint32_t line_width = (uint32_t)(dev->h_disp) * sizeof(uint32_t); + + if (dev->h_disp > 0) + memset(line_ptr, 0, line_width); +} void ibm8514_render_8bpp(svga_t *svga) @@ -3840,9 +3857,8 @@ ibm8514_render_8bpp(svga_t *svga) uint32_t *p; uint32_t dat; - if ((dev->displine + svga->y_add) < 0) { + if ((dev->displine + svga->y_add) < 0) return; - } if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) { p = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; @@ -4109,148 +4125,153 @@ ibm8514_render_overscan_right(ibm8514_t *dev, svga_t *svga) } void -ibm8514_poll(void *priv, svga_t *svga) +ibm8514_poll(void *priv) { - ibm8514_t *dev = (ibm8514_t *) priv; + svga_t *svga = (svga_t *)priv; + ibm8514_t *dev = (ibm8514_t *)svga->dev8514; uint32_t x; int wx; int wy; - if (!dev->linepos) { - if ((dev->displine == dev->hwcursor_latch.y) && dev->hwcursor_latch.ena) { - dev->hwcursor_on = dev->hwcursor_latch.cur_ysize - dev->hwcursor_latch.yoff; - dev->hwcursor_oddeven = 0; - } - - if ((dev->displine == (dev->hwcursor_latch.y + 1)) && dev->hwcursor_latch.ena && dev->interlace) { - dev->hwcursor_on = dev->hwcursor_latch.cur_ysize - (dev->hwcursor_latch.yoff + 1); - dev->hwcursor_oddeven = 1; - } - - timer_advance_u64(&svga->timer, svga->dispofftime); - svga->cgastat |= 1; - dev->linepos = 1; - - if (dev->dispon) { - dev->hdisp_on = 1; - - dev->ma &= dev->vram_mask; - - if (dev->firstline == 2000) { - dev->firstline = dev->displine; - video_wait_for_buffer_monitor(svga->monitor_index); + ibm8514_log("IBM 8514/A poll.\n"); + if (dev->on[0] || dev->on[1]) { + ibm8514_log("ON!\n"); + if (!dev->linepos) { + if ((dev->displine == dev->hwcursor_latch.y) && dev->hwcursor_latch.ena) { + dev->hwcursor_on = dev->hwcursor_latch.cur_ysize - dev->hwcursor_latch.yoff; + dev->hwcursor_oddeven = 0; } - if (dev->hwcursor_on) - dev->changedvram[dev->ma >> 12] = dev->changedvram[(dev->ma >> 12) + 1] = dev->interlace ? 3 : 2; + if ((dev->displine == (dev->hwcursor_latch.y + 1)) && dev->hwcursor_latch.ena && dev->interlace) { + dev->hwcursor_on = dev->hwcursor_latch.cur_ysize - (dev->hwcursor_latch.yoff + 1); + dev->hwcursor_oddeven = 1; + } - svga->render8514(svga); + timer_advance_u64(&svga->timer8514, dev->dispofftime); + svga->cgastat |= 1; + dev->linepos = 1; - svga->x_add = (overscan_x >> 1); - ibm8514_render_overscan_left(dev, svga); - ibm8514_render_overscan_right(dev, svga); - svga->x_add = (overscan_x >> 1); + if (dev->dispon) { + dev->hdisp_on = 1; - if (dev->hwcursor_on) { - if (svga->hwcursor_draw) - svga->hwcursor_draw(svga, dev->displine + svga->y_add); - dev->hwcursor_on--; - if (dev->hwcursor_on && dev->interlace) + dev->ma &= dev->vram_mask; + + if (dev->firstline == 2000) { + dev->firstline = dev->displine; + video_wait_for_buffer_monitor(svga->monitor_index); + } + + if (dev->hwcursor_on) + dev->changedvram[dev->ma >> 12] = dev->changedvram[(dev->ma >> 12) + 1] = dev->interlace ? 3 : 2; + + svga->render8514(svga); + + svga->x_add = (overscan_x >> 1); + ibm8514_render_overscan_left(dev, svga); + ibm8514_render_overscan_right(dev, svga); + svga->x_add = (overscan_x >> 1); + + if (dev->hwcursor_on) { + if (svga->hwcursor_draw) + svga->hwcursor_draw(svga, dev->displine + svga->y_add); dev->hwcursor_on--; + if (dev->hwcursor_on && dev->interlace) + dev->hwcursor_on--; + } + + if (dev->lastline < dev->displine) + dev->lastline = dev->displine; } - if (dev->lastline < dev->displine) - dev->lastline = dev->displine; - } - - dev->displine++; - if (dev->interlace) dev->displine++; - if ((svga->cgastat & 8) && ((dev->displine & 0x0f) == (svga->crtc[0x11] & 0x0f)) && svga->vslines) - svga->cgastat &= ~8; - svga->vslines++; - if (dev->displine > 1500) - dev->displine = 0; - } else { - timer_advance_u64(&svga->timer, svga->dispontime); - if (dev->dispon) - svga->cgastat &= ~1; - dev->hdisp_on = 0; + if (dev->interlace) + dev->displine++; + if ((svga->cgastat & 8) && ((dev->displine & 0x0f) == (svga->crtc[0x11] & 0x0f)) && svga->vslines) + svga->cgastat &= ~8; + svga->vslines++; + if (dev->displine > 1500) + dev->displine = 0; + } else { + timer_advance_u64(&svga->timer8514, dev->dispontime); + if (dev->dispon) + svga->cgastat &= ~1; + dev->hdisp_on = 0; - dev->linepos = 0; - if (dev->dispon) { - if (dev->sc == dev->rowcount) { - dev->sc = 0; - dev->maback += (dev->rowoffset << 3); - if (dev->interlace) + dev->linepos = 0; + if (dev->dispon) { + if (dev->sc == dev->rowcount) { + dev->sc = 0; dev->maback += (dev->rowoffset << 3); - dev->maback &= dev->vram_mask; - dev->ma = dev->maback; - } else { - dev->sc++; - dev->sc &= 0x1f; - dev->ma = dev->maback; - } - } + if (dev->interlace) + dev->maback += (dev->rowoffset << 3); - dev->vc++; - dev->vc &= 0x7ff; - - if (dev->vc == dev->dispend) { - dev->dispon = 0; - - for (x = 0; x < ((dev->vram_mask + 1) >> 12); x++) { - if (dev->changedvram[x]) - dev->changedvram[x]--; + dev->maback &= dev->vram_mask; + dev->ma = dev->maback; + } else { + dev->sc++; + dev->sc &= 0x1f; + dev->ma = dev->maback; + } } - if (svga->fullchange) - svga->fullchange--; - } - if (dev->vc == dev->v_syncstart) { - dev->dispon = 0; - svga->cgastat |= 8; - x = dev->h_disp; + dev->vc++; + dev->vc &= 0x7ff; - if (dev->interlace && !dev->oddeven) - dev->lastline++; - if (dev->interlace && dev->oddeven) - dev->firstline--; + if (dev->vc == dev->dispend) { + dev->dispon = 0; - wx = x; + for (x = 0; x < ((dev->vram_mask + 1) >> 12); x++) { + if (dev->changedvram[x]) + dev->changedvram[x]--; + } - wy = dev->lastline - dev->firstline; - svga_doblit(wx, wy, svga); + if (svga->fullchange) + svga->fullchange--; + } + if (dev->vc == dev->v_syncstart) { + dev->dispon = 0; + svga->cgastat |= 8; + x = dev->h_disp; - dev->firstline = 2000; - dev->lastline = 0; + if (dev->interlace && !dev->oddeven) + dev->lastline++; + if (dev->interlace && dev->oddeven) + dev->firstline--; - dev->firstline_draw = 2000; - dev->lastline_draw = 0; + wx = x; + wy = dev->lastline - dev->firstline; + svga_doblit(wx, wy, svga); - dev->oddeven ^= 1; + dev->firstline = 2000; + dev->lastline = 0; - svga->monitor->mon_changeframecount = dev->interlace ? 3 : 2; - svga->vslines = 0; + dev->firstline_draw = 2000; + dev->lastline_draw = 0; - if (dev->interlace && dev->oddeven) - dev->ma = dev->maback = (dev->rowoffset << 1); - else - dev->ma = dev->maback = 0; + dev->oddeven ^= 1; - dev->ma = (dev->ma << 2); - dev->maback = (dev->maback << 2); - } - if (dev->vc == dev->v_total) { - dev->vc = 0; - dev->sc = 0; - dev->dispon = 1; - dev->displine = (dev->interlace && dev->oddeven) ? 1 : 0; + svga->monitor->mon_changeframecount = dev->interlace ? 3 : 2; + svga->vslines = 0; - svga->x_add = (overscan_x >> 1); + if (dev->interlace && dev->oddeven) + dev->ma = dev->maback = (dev->rowoffset << 1); + else + dev->ma = dev->maback = 0; - dev->hwcursor_on = 0; - dev->hwcursor_latch = dev->hwcursor; + dev->ma = (dev->ma << 2); + dev->maback = (dev->maback << 2); + } + if (dev->vc == dev->v_total) { + dev->vc = 0; + dev->sc = 0; + dev->dispon = 1; + dev->displine = (dev->interlace && dev->oddeven) ? 1 : 0; + + svga->x_add = (overscan_x >> 1); + + dev->hwcursor_on = 0; + dev->hwcursor_latch = dev->hwcursor; + } } } } @@ -4260,48 +4281,41 @@ ibm8514_recalctimings(svga_t *svga) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (dev->on[0]) { - dev->h_disp = (dev->hdisp + 1) << 3; - dev->pitch = (dev->accel.advfunc_cntl & 4) ? 1024 : 640; - dev->h_total = (dev->htotal + 1); - dev->v_total = (dev->vtotal + 1); - dev->v_syncstart = (dev->vsyncstart + 1); - dev->rowcount = !!(dev->disp_cntl & 0x08); - dev->dispend = ((dev->vdisp >> 1) + 1); - if (dev->dispend == 766) - dev->dispend += 2; + svga->render8514 = ibm8514_render_blank; +#ifdef ATI_8514_ULTRA + if (dev->extensions) { + if (svga->ext8514 != NULL) + ati8514_recalctimings(svga); + } else +#endif + { + if (dev->on[0] || dev->on[1]) { + dev->h_disp = dev->hdisp; + dev->h_total = dev->htotal + 1; + dev->h_blankstart = dev->hblankstart; + dev->h_blank_end_val = dev->hblank_end_val; + dev->v_total = dev->vtotal; + dev->v_syncstart = dev->vsyncstart; + dev->dispend = dev->vdisp; + dev->rowcount = !!(dev->disp_cntl & 0x08); - if (dev->dispend == 598) - dev->dispend += 2; + if (dev->dispend == 766) + dev->dispend += 2; - if (dev->accel.advfunc_cntl & 4) { - if (dev->h_disp == 8) { - dev->h_disp = 1024; - dev->dispend = 768; - dev->v_total = 1536; - dev->v_syncstart = 1536; - } - - if (dev->dispend == 598) - dev->dispend = 600; - - if (dev->interlace) { - dev->dispend >>= 1; - dev->v_syncstart >>= 2; - dev->v_total >>= 2; + if (dev->accel.advfunc_cntl & 4) { + dev->pitch = 1024; + if (!dev->h_disp) { + dev->h_disp = 1024; + dev->dispend = 768; + } + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 44900000.0; } else { - dev->v_syncstart >>= 1; - dev->v_total >>= 1; - } - - dev->rowoffset = 0x80; - - ibm8514_log("1024x768 clock mode, hdisp = %d, htotal = %d, vtotal = %d, vsyncstart = %d, interlace = %02x\n", dev->h_disp, dev->h_total, dev->v_total, dev->v_syncstart, dev->interlace); - svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; - } else { - if (dev->h_disp == 1024) { - dev->h_disp = 640; - dev->dispend = 480; + dev->pitch = 640; + if (!dev->h_disp) { + dev->h_disp = 640; + dev->dispend = 480; + } + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 25175000.0; } if (dev->interlace) { @@ -4314,11 +4328,10 @@ ibm8514_recalctimings(svga_t *svga) } dev->rowoffset = 0x80; - - svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + svga->map8 = dev->pallook; + svga->render8514 = ibm8514_render_8bpp; + ibm8514_log("BPP=%d, Pitch = %d, rowoffset = %d, crtc13 = %02x, highres bit = %02x, has_vga? = %d.\n", dev->bpp, dev->pitch, dev->rowoffset, svga->crtc[0x13], dev->accel.advfunc_cntl & 4, !ibm8514_standalone_enabled); } - svga->render8514 = ibm8514_render_8bpp; - ibm8514_log("BPP=%d, Pitch = %d, rowoffset = %d, crtc13 = %02x, mode = %d, highres bit = %02x, has_vga? = %d.\n", dev->bpp, dev->pitch, dev->rowoffset, svga->crtc[0x13], dev->ibm_mode, dev->accel.advfunc_cntl & 4, !ibm8514_standalone_enabled); } ibm8514_log("8514 enabled, hdisp=%d, vtotal=%d, htotal=%d, dispend=%d, rowoffset=%d, split=%d, vsyncstart=%d, split=%08x\n", dev->hdisp, dev->vtotal, dev->htotal, dev->dispend, dev->rowoffset, dev->split, dev->vsyncstart, dev->split); } @@ -4355,6 +4368,19 @@ ibm8514_mca_feedb(void *priv) return dev->pos_regs[2] & 1; } +static void +ibm8514_mca_reset(void *priv) +{ + svga_t *svga = (svga_t *) priv; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + ibm8514_log("MCA reset.\n"); + dev->on[0] = 0; + dev->on[1] = 0; + vga_on = 1; + ibm8514_mca_write(0x102, 0, svga); +} + static void * ibm8514_init(const device_t *info) { @@ -4365,6 +4391,7 @@ ibm8514_init(const device_t *info) ibm8514_t *dev = (ibm8514_t *) calloc(1, sizeof(ibm8514_t)); svga->dev8514 = dev; + svga->ext8514 = NULL; dev->vram_size = 1024 << 10; dev->vram = calloc(dev->vram_size, 1); @@ -4376,13 +4403,58 @@ ibm8514_init(const device_t *info) dev->type = info->flags; dev->bpp = 0; +#ifdef ATI_8514_ULTRA + dev->extensions = device_get_config_int("extensions"); + + switch (dev->extensions) { + case 1: + if (rom_present(BIOS_MACH8_ROM_PATH)) { + mach = (mach_t *) calloc(1, sizeof(mach_t)); + svga->ext8514 = mach; + ati8514_init(svga, svga->ext8514, svga->dev8514); + + if (dev->type & DEVICE_MCA) { + rom_init(&dev->bios_rom, + BIOS_MACH8_ROM_PATH, + 0xc6800, 0x1000, 0x0fff, + 0x0800, MEM_MAPPING_EXTERNAL); + mem_mapping_disable(&dev->bios_rom.mapping); + dev->pos_regs[0] = 0x88; + dev->pos_regs[1] = 0x80; + mca_add(ati8514_mca_read, ati8514_mca_write, ibm8514_mca_feedb, ibm8514_mca_reset, svga); + ati_eeprom_load(&mach->eeprom, "ati8514_mca.nvr", 0); + } else { + rom_init(&dev->bios_rom, + BIOS_MACH8_ROM_PATH, + 0xd0000, 0x1000, 0x0fff, + 0x0800, MEM_MAPPING_EXTERNAL); + ati_eeprom_load(&mach->eeprom, "ati8514.nvr", 0); + } + break; + } + fallthrough; + + default: + ibm8514_io_set(svga); + + if (dev->type & DEVICE_MCA) { + dev->pos_regs[0] = 0x7f; + dev->pos_regs[1] = 0xef; + mca_add(ibm8514_mca_read, ibm8514_mca_write, ibm8514_mca_feedb, ibm8514_mca_reset, svga); + } + break; + } +#else ibm8514_io_set(svga); if (dev->type & DEVICE_MCA) { dev->pos_regs[0] = 0x7f; dev->pos_regs[1] = 0xef; - mca_add(ibm8514_mca_read, ibm8514_mca_write, ibm8514_mca_feedb, NULL, svga); + mca_add(ibm8514_mca_read, ibm8514_mca_write, ibm8514_mca_feedb, ibm8514_mca_reset, svga); } +#endif + + timer_add(&svga->timer8514, ibm8514_poll, svga, 1); return svga; } @@ -4393,6 +4465,13 @@ ibm8514_close(void *priv) svga_t *svga = (svga_t *) priv; ibm8514_t *dev = (ibm8514_t *) svga->dev8514; +#ifdef ATI_8514_ULTRA + mach_t *mach = (mach_t *) svga->ext8514; + + if (mach) + free(mach); +#endif + if (dev) { free(dev->vram); free(dev->changedvram); @@ -4417,6 +4496,34 @@ ibm8514_force_redraw(void *priv) svga->fullchange = changeframecount; } +#ifdef ATI_8514_ULTRA +// clang-format off +static const device_config_t ext8514_config[] = { + { + .name = "extensions", + .description = "Vendor", + .type = CONFIG_SELECTION, + .default_int = 0, + .selection = { + { + .description = "IBM", + .value = 0 + }, + { + .description = "ATI", + .value = 1 + }, + { + .description = "" + } + } + }, + { + .type = CONFIG_END + } +}; +#endif + // clang-format off const device_t gen8514_isa_device = { .name = "Generic 8514/A clone (ISA)", diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index 1f2b69e25..368312fcb 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -408,7 +408,7 @@ ati28800_recalctimings(svga_t *svga) int clock_sel; if (ati28800->regs[0xad] & 0x08) - svga->hblankstart = ((ati28800->regs[0x0d] >> 2) << 8) + svga->crtc[2] + 1; + svga->hblankstart = ((ati28800->regs[0x0d] >> 2) << 8) + svga->crtc[2]; clock_sel = ((svga->miscout >> 2) & 3) | ((ati28800->regs[0xbe] & 0x10) >> 1) | ((ati28800->regs[0xb9] & 2) << 1); @@ -429,8 +429,7 @@ ati28800_recalctimings(svga_t *svga) svga->hdisp <<= 1; svga->htotal <<= 1; svga->rowoffset <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; svga->gdcreg[5] &= ~0x40; } @@ -446,8 +445,7 @@ ati28800_recalctimings(svga_t *svga) if ((ati28800->regs[0xb6] & 0x18) == 8) { svga->hdisp <<= 1; svga->htotal <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; svga->ati_4color = 1; } else svga->ati_4color = 0; @@ -494,8 +492,7 @@ ati28800_recalctimings(svga_t *svga) else { svga->render = svga_render_15bpp_highres; svga->hdisp >>= 1; - svga->hblankstart = ((svga->hblankstart - 1) >> 1) + 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; svga->rowoffset <<= 1; svga->ma_latch <<= 1; } diff --git a/src/video/vid_ati68860_ramdac.c b/src/video/vid_ati68860_ramdac.c index 7cdd18019..ac2a0f7cb 100644 --- a/src/video/vid_ati68860_ramdac.c +++ b/src/video/vid_ati68860_ramdac.c @@ -44,6 +44,7 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/mem.h> +#include <86box/rom.h> #include <86box/timer.h> #include <86box/video.h> #include <86box/vid_8514a.h> @@ -129,7 +130,8 @@ ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga) ramdac->render = svga_render_4bpp_highres; break; case 0x83: - ramdac->render = svga_render_8bpp_highres; + /*FIXME*/ + ramdac->render = svga_render_8bpp_clone_highres; break; case 0xa0: case 0xb0: @@ -154,7 +156,8 @@ ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga) ramdac->render = svga_render_RGBA8888_highres; break; default: - ramdac->render = svga_render_8bpp_highres; + /*FIXME*/ + ramdac->render = svga_render_8bpp_clone_highres; break; } break; @@ -234,7 +237,8 @@ ati68860_ramdac_init(UNUSED(const device_t *info)) ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) malloc(sizeof(ati68860_ramdac_t)); memset(ramdac, 0, sizeof(ati68860_ramdac_t)); - ramdac->render = svga_render_8bpp_highres; + /*FIXME*/ + ramdac->render = svga_render_8bpp_clone_highres; return ramdac; } diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index cdd906067..9aa396383 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -516,7 +516,7 @@ mach64_recalctimings(svga_t *svga) svga->htotal = (mach64->crtc_h_total_disp & 255) + 1; svga->hdisp_time = svga->hdisp = ((mach64->crtc_h_total_disp >> 16) & 255) + 1; svga->hblankstart = (mach64->crtc_h_sync_strt_wid & 255) + - ((mach64->crtc_h_sync_strt_wid >> 8) & 7) + 1; + ((mach64->crtc_h_sync_strt_wid >> 8) & 7); svga->hblank_end_val = (svga->hblankstart + ((mach64->crtc_h_sync_strt_wid >> 16) & 31) - 1) & 63; svga->vsyncstart = (mach64->crtc_v_sync_strt_wid & 2047) + 1; diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index b19f1e3d6..3888e9c26 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -13,7 +13,7 @@ * * Authors: TheCollector1995. * - * Copyright 2022-2023 TheCollector1995. + * Copyright 2022-2024 TheCollector1995. */ #include #include @@ -40,154 +40,14 @@ #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> #include <86box/vid_ati_eeprom.h> +#include <86box/vid_ati_mach8.h> -#define BIOS_MACH8_ROM_PATH "roms/video/mach8/BIOS.BIN" +#define BIOS_MACH8_VGA_ROM_PATH "roms/video/mach8/BIOS.BIN" #define BIOS_MACH32_ISA_ROM_PATH "roms/video/mach32/ATi Mach32 Graphics Pro ISA.BIN" #define BIOS_MACH32_VLB_ROM_PATH "roms/video/mach32/MACH32VLB.VBI" #define BIOS_MACH32_MCA_ROM_PATH "roms/video/mach32/MACH32MCA_Olivetti.BIN" #define BIOS_MACH32_PCI_ROM_PATH "roms/video/mach32/intelopt_00000.rom" -typedef struct mach_t { - ati_eeprom_t eeprom; - svga_t svga; - - rom_t bios_rom; - rom_t bios_rom2; - mem_mapping_t mmio_linear_mapping; - - int mca_bus; - int pci_bus; - int vlb_bus; - int has_bios; - - uint8_t regs[256]; - uint8_t pci_regs[256]; - uint8_t int_line; - uint8_t pci_slot; - uint8_t irq_state; - - int index; - int ramdac_type; - int old_mode; - - uint32_t memory; - - uint16_t config1; - uint16_t config2; - - uint8_t pos_regs[8]; - uint8_t pci_cntl_reg; - uint8_t cursor_col_0; - uint8_t cursor_col_1; - uint8_t ext_cur_col_0_r; - uint8_t ext_cur_col_1_r; - uint8_t ext_cur_col_0_g; - uint8_t ext_cur_col_1_g; - uint16_t cursor_col_0_rg; - uint16_t cursor_col_1_rg; - uint16_t cursor_col_b; - uint16_t cursor_offset_lo; - uint16_t cursor_offset_lo_reg; - uint16_t cursor_offset_hi; - uint16_t cursor_offset_hi_reg; - uint16_t cursor_vh_offset; - uint16_t cursor_x; - uint16_t cursor_y; - uint16_t misc; - uint16_t memory_aperture; - uint16_t local_cntl; - uint32_t linear_base; - uint8_t ap_size; - uint8_t bank_w; - uint8_t bank_r; - uint16_t shadow_set; - int ext_on[2]; - - struct { - uint8_t line_idx; - int16_t line_array[6]; - uint8_t patt_idx; - uint8_t patt_len; - uint8_t pix_trans[2]; - uint8_t eeprom_control; - uint16_t dest_x_end; - uint16_t dest_x_start; - uint16_t dest_y_end; - uint16_t src_x_end; - uint16_t src_x_start; - uint16_t src_x; - uint16_t src_y; - int16_t bres_count; - uint16_t clock_sel; - uint16_t crt_pitch; - uint16_t ge_pitch; - uint16_t dest_cmp_fn; - uint16_t dp_config; - uint16_t ext_ge_config; - uint16_t ge_offset_lo; - uint16_t ge_offset_hi; - uint16_t linedraw_opt; - uint16_t max_waitstates; - uint8_t patt_data_idx; - uint8_t patt_data[0x18]; - uint16_t scan_to_x; - uint16_t scratch0; - uint16_t scratch1; - uint16_t test; - uint16_t pattern; - uint16_t test2; - uint16_t test3; - uint16_t test4; - int src_y_dir; - int cmd_type; - int block_write_mono_pattern_enable; - int mono_pattern_enable; - int16_t cx_end_line; - int16_t cy_end_line; - int16_t cx; - int16_t cx_end; - int16_t cy_end; - int16_t dx; - int16_t dx_end; - int16_t dy; - int16_t dy_end; - int16_t dx_start; - int16_t dy_start; - int16_t cy; - int16_t sx_start; - int16_t sx_end; - int16_t sx; - int16_t x_count; - int16_t xx_count; - int16_t xxx_count; - int16_t sy; - int16_t y_count; - int16_t err; - int16_t width; - int16_t src_width; - int16_t height; - int16_t bleft, bright, btop, bbottom; - int poly_src; - int temp_cnt; - int stepx; - int stepy; - int src_stepx; - uint8_t color_pattern[16]; - uint8_t color_pattern_full[32]; - uint16_t color_pattern_word[8]; - int mono_pattern[8][8]; - uint32_t ge_offset; - uint32_t crt_offset; - uint32_t patt_len_reg; - int poly_fill; - uint16_t dst_clr_cmp_mask; - int clip_overrun; - int color_pattern_idx; - } accel; - - atomic_int force_busy; -} mach_t; - static video_timings_t timing_gfxultra_isa = { .type = VIDEO_ISA, .write_b = 3, .write_w = 3, .write_l = 6, .read_b = 5, .read_w = 5, .read_l = 10 }; static video_timings_t timing_mach32_vlb = { .type = VIDEO_BUS, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 20, .read_w = 20, .read_l = 21 }; static video_timings_t timing_mach32_mca = { .type = VIDEO_MCA, .write_b = 4, .write_w = 5, .write_l = 10, .read_b = 5, .read_w = 5, .read_l = 10 }; @@ -199,7 +59,17 @@ static uint8_t mach_accel_inb(uint16_t port, void *priv); static uint16_t mach_accel_inw(uint16_t port, void *priv); static uint8_t mach_in(uint16_t addr, void *priv); -static void mach32_updatemapping(mach_t *mach); +#ifdef ATI_8514_ULTRA +static void ati8514_accel_outb(uint16_t port, uint8_t val, void *priv); +static void ati8514_accel_outw(uint16_t port, uint16_t val, void *priv); +static void ati8514_accel_outl(uint16_t port, uint32_t val, void *priv); +static uint8_t ati8514_accel_inb(uint16_t port, void *priv); +static uint16_t ati8514_accel_inw(uint16_t port, void *priv); +static uint32_t ati8514_accel_inl(uint16_t port, void *priv); +#endif + + +static void mach32_updatemapping(mach_t *mach, svga_t *svga); #ifdef ENABLE_MACH_LOG int mach_do_log = ENABLE_MACH_LOG; @@ -253,9 +123,9 @@ mach_log(const char *fmt, ...) #define READ_PIXTRANS_WORD(cx, n) \ if ((cmd == 0) || (cmd == 1) || (cmd == 5) || (mach->accel.cmd_type == -1)) { \ - if (dev->bpp) { \ + if (dev->bpp) \ temp = vram_w[((dev->accel.cy * dev->pitch) + (cx) + (n)) & (dev->vram_mask >> 1)]; \ - } else { \ + else { \ temp = dev->vram[((dev->accel.cy * dev->pitch) + (cx) + (n)) & dev->vram_mask]; \ temp |= (dev->vram[((dev->accel.cy * dev->pitch) + (cx) + (n + 1)) & dev->vram_mask] << 8); \ } \ @@ -462,10 +332,8 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } if ((dev->accel_bpp == 8) || (dev->accel_bpp == 15) || (dev->accel_bpp == 16) || (dev->accel_bpp == 24)) { - if (dev->accel_bpp == 24) - mach_log("24BPP: CMDType=%d, cwh(%d,%d,%d,%d), dpconfig=%04x\n", cmd_type, clip_l, clip_r, clip_t, clip_b, mach->accel.dp_config); - else - mach_log("RdMask=%04x, Clipping: l=%d, r=%d, t=%d, b=%d, LineDrawOpt=%04x, BPP=%d, CMDType = %d, offs=%08x, DPCONFIG = %04x, cnt = %d, input = %d, mono_src = %d, frgdsel = %d, d(%d,%d), dstxend = %d, pitch = %d, extcrt = %d, rw = %x, monpattern = %x.\n", rd_mask, clip_l, clip_r, clip_t, clip_b, mach->accel.linedraw_opt, dev->accel_bpp, cmd_type, mach->accel.ge_offset, mach->accel.dp_config, count, cpu_input, mono_src, frgd_sel, dev->accel.cur_x, dev->accel.cur_y, mach->accel.dest_x_end, dev->ext_pitch, dev->ext_crt_pitch, mach->accel.dp_config & 1, mach->accel.mono_pattern_enable); + if (cpu_input && (cmd_type == 2)) + mach_log("RdMask=%04x, DPCONFIG=%04x, Clipping: l=%d, r=%d, t=%d, b=%d, LineDrawOpt=%04x, BPP=%d, CMDType = %d, offs=%08x, cnt = %d, input = %d, mono_src = %d, frgdsel = %d, d(%d,%d), dstxend = %d, pitch = %d, extcrt = %d, rw = %x, monpattern = %x.\n", rd_mask, mach->accel.dp_config, clip_l, clip_r, clip_t, clip_b, mach->accel.linedraw_opt, dev->accel_bpp, cmd_type, mach->accel.ge_offset, count, cpu_input, mono_src, frgd_sel, dev->accel.cur_x, dev->accel.cur_y, mach->accel.dest_x_end, dev->ext_pitch, dev->ext_crt_pitch, mach->accel.dp_config & 1, mach->accel.mono_pattern_enable); } switch (cmd_type) { @@ -948,10 +816,16 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (dev->accel.cur_y >= 0x600) dev->accel.dy |= ~0x5ff; + if (mach->accel.dp_config == 0x5211) { + if (mach->accel.dest_x_end == 1024) { + goto skip_dx; + } + } /*Destination Width*/ if (mach->accel.dest_x_start != dev->accel.dx) mach->accel.dest_x_start = dev->accel.dx; +skip_dx: mach->accel.dx_start = mach->accel.dest_x_start; if (mach->accel.dest_x_start >= 0x600) mach->accel.dx_start |= ~0x5ff; @@ -1336,7 +1210,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } dev->accel.sx++; - if (dev->accel.sx >= mach->accel.width) { + if ((dev->accel.sx >= mach->accel.width) || (dev->accel.dx >= 0x600)) { dev->accel.sx = 0; if (mach->accel.stepx == -1) dev->accel.dx += mach->accel.width; @@ -2156,10 +2030,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach_pixel_read(mach)) src_dat = cpu_dat; else { - READ(dev->accel.src + (dev->accel.cx), src_dat); - if (mono_src == 3) { + READ(dev->accel.src + dev->accel.cx, src_dat); + if (mono_src == 3) src_dat = (src_dat & rd_mask) == rd_mask; - } } break; case 5: @@ -2179,7 +2052,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 break; } - READ(dev->accel.dest + (dev->accel.dx), dest_dat); + READ(dev->accel.dest + dev->accel.dx, dest_dat); switch (compare_mode) { case 1: @@ -2299,7 +2172,7 @@ mach_accel_out_pixtrans(mach_t *mach, ibm8514_t *dev, uint16_t val) case 0x000: /*8-bit size*/ if (mono_src == 2) { if ((frgd_sel != 2) && (bkgd_sel != 2)) { - if ((mach->accel.dp_config & 0x1000) && ((dev->local & 0xff) >= 0x02)) + if (mach->accel.dp_config & 0x1000) val = (val >> 8) | (val << 8); mach_accel_start(mach->accel.cmd_type, 1, 8, val | (val << 16), 0, mach, dev); } else @@ -2313,12 +2186,10 @@ mach_accel_out_pixtrans(mach_t *mach, ibm8514_t *dev, uint16_t val) if (mach->accel.dp_config & 0x1000) val = (val >> 8) | (val << 8); mach_accel_start(mach->accel.cmd_type, 1, 16, val | (val << 16), 0, mach, dev); - } else { + } else mach_accel_start(mach->accel.cmd_type, 1, 2, -1, val | (val << 16), mach, dev); - } - } else { + } else mach_accel_start(mach->accel.cmd_type, 1, 2, -1, val | (val << 16), mach, dev); - } break; default: @@ -2398,7 +2269,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) break; case 0xbd: if ((old ^ val) & 4) { - mach32_updatemapping(mach); + mach32_updatemapping(mach, svga); } break; case 0xb3: @@ -2508,6 +2379,9 @@ mach_in(uint16_t addr, void *priv) break; case 0x1cf: switch (mach->index) { + case 0xa0: + temp = mach->regs[0xa0] | 0x10; + break; case 0xa8: temp = (svga->vc >> 8) & 3; break; @@ -2516,11 +2390,10 @@ mach_in(uint16_t addr, void *priv) break; case 0xb0: temp = mach->regs[0xb0] | 0x80; + temp &= ~0x18; if ((dev->local & 0xff) >= 0x02) { /*Mach32 VGA 1MB memory*/ temp |= 0x08; - temp &= ~0x10; } else { /*ATI 28800 VGA 512kB memory*/ - temp &= ~0x08; temp |= 0x10; } break; @@ -2587,15 +2460,95 @@ mach_in(uint16_t addr, void *priv) return temp; } + +#ifdef ATI_8514_ULTRA +static void +ati8514_out(uint16_t addr, uint8_t val, void *priv) +{ + mach_log("ADDON OUT addr=%03x, val=%02x.\n", addr, val); + svga_out(addr, val, priv); +} + +static uint8_t +ati8514_in(uint16_t addr, void *priv) +{ + uint8_t temp = 0xff; + + temp = svga_in(addr, priv); + + mach_log("ADDON IN addr=%03x, temp=%02x.\n", addr, temp); + return temp; +} + +void +ati8514_recalctimings(svga_t *svga) +{ + const mach_t *mach = (mach_t *) svga->ext8514; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + mach_log("ON0=%d, ON1=%d, vgahdisp=%d.\n", dev->on[0], dev->on[1], svga->hdisp); + if (dev->on[0] || dev->on[1]) { + dev->h_disp = dev->hdisp; + dev->h_total = dev->htotal + 1; + dev->h_blankstart = dev->hblankstart; + dev->h_blank_end_val = dev->hblank_end_val; + dev->v_total = dev->vtotal; + dev->v_syncstart = dev->vsyncstart; + dev->rowcount = !!(dev->disp_cntl & 0x08); + dev->dispend = dev->vdisp; + + if (dev->dispend == 766) + dev->dispend += 2; + + if (dev->dispend == 598) + dev->dispend += 2; + + if (dev->accel.advfunc_cntl & 4) { + if (dev->h_disp != 800) { + dev->h_disp = 1024; + dev->dispend = 768; + } + svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; + } else { + svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + } + + if (dev->interlace) { + dev->dispend >>= 1; + dev->v_syncstart >>= 2; + dev->v_total >>= 2; + } else { + dev->v_syncstart >>= 1; + dev->v_total >>= 1; + } + + dev->pitch = dev->ext_pitch; + dev->rowoffset = dev->ext_crt_pitch; + mach_log("cntl=%d, hv(%d,%d), pitch=%d, rowoffset=%d, advfunc_cntl=%x, shadow=%x.\n", dev->accel.advfunc_cntl & 4, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, dev->accel.advfunc_cntl & 4, mach->shadow_set & 3); + svga->map8 = dev->pallook; + svga->render8514 = ibm8514_render_8bpp; + } else { + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + if (svga->seqregs[1] & 8) { /*40 column*/ + svga->render = svga_render_text_40; + } else { + svga->render = svga_render_text_80; + } + } + } +} +#endif + static void mach_recalctimings(svga_t *svga) { - const mach_t *mach = (mach_t *) svga->priv; + mach_t *mach = (mach_t *) svga->priv; ibm8514_t *dev = (ibm8514_t *) svga->dev8514; int clock_sel; if (mach->regs[0xad] & 0x08) - svga->hblankstart = ((mach->regs[0x0d] >> 2) << 8) + svga->crtc[2] + 1; + svga->hblankstart = ((mach->regs[0x0d] >> 2) << 8) + svga->crtc[2]; + clock_sel = ((svga->miscout >> 2) & 3) | ((mach->regs[0xbe] & 0x10) >> 1) | ((mach->regs[0xb9] & 2) << 1); if ((dev->local & 0xff) >= 0x02) { @@ -2615,8 +2568,7 @@ mach_recalctimings(svga_t *svga) if ((mach->regs[0xb6] & 0x18) >= 0x10) { svga->hdisp <<= 1; svga->htotal <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; svga->rowoffset <<= 1; svga->gdcreg[5] &= ~0x40; } @@ -2634,52 +2586,45 @@ mach_recalctimings(svga_t *svga) if ((mach->regs[0xb6] & 0x18) == 8) { svga->hdisp <<= 1; svga->htotal <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; svga->ati_4color = 1; } else svga->ati_4color = 0; } + svga->render8514 = ibm8514_render_blank; mach_log("ON[0]=%d, ON[1]=%d, exton[0]=%d, exton[1]=%d, vendormode0=%d, vendormode1=%d.\n", dev->on[0], dev->on[1], mach->ext_on[0], mach->ext_on[1], dev->vendor_mode[0], dev->vendor_mode[1]); if (dev->on[0] || dev->on[1]) { mach_log("8514/A ON.\n"); + dev->h_disp = dev->hdisp; + dev->h_total = dev->htotal + 1; + dev->h_blankstart = dev->hblankstart; + dev->h_blank_end_val = dev->hblank_end_val; + dev->v_total = dev->vtotal; + dev->v_syncstart = dev->vsyncstart; + dev->dispend = dev->vdisp; + dev->rowcount = !!(dev->disp_cntl & 0x08); + + if (dev->dispend == 766) + dev->dispend += 2; + + if (dev->dispend == 598) + dev->dispend += 2; + + if (dev->dispend == 478) + dev->dispend += 2; + if ((dev->local & 0xff) >= 0x02) { - dev->h_disp = (dev->hdisp + 1) << 3; - dev->h_total = (dev->htotal + 1); - dev->v_total = (dev->vtotal + 1); - dev->v_syncstart = (dev->vsyncstart + 1); - dev->dispend = ((dev->vdisp >> 1) + 1); - dev->rowcount = !!(dev->disp_cntl & 0x08); - - if (dev->dispend == 766) - dev->dispend += 2; - - if (dev->dispend == 598) - dev->dispend += 2; - - if (dev->accel.advfunc_cntl & 4) { - if (mach->shadow_set & 2) { - if ((dev->h_disp == 8) && !dev->bpp) { - dev->h_disp = 1024; - dev->dispend = 768; - dev->v_total = 1536; - dev->v_syncstart = 1536; - } - mach_log("Shadow set 2.\n"); - svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; - } else - svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + if ((dev->accel.advfunc_cntl ^ dev->modechange) & 0x04) { + if ((mach->shadow_set ^ mach->compat_mode) & 0x03) + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + else + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 44900000.0; } else { - if ((dev->h_disp == 1024) && !dev->bpp) { - dev->h_disp = 640; - dev->dispend = 480; - } - if (mach->shadow_set & 1) { - mach_log("Shadow set 1.\n"); - svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; - } else - svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + if ((mach->shadow_set ^ mach->compat_mode) & 0x03) + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + else + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 25175000.0; } if (dev->interlace) { @@ -2690,6 +2635,7 @@ mach_recalctimings(svga_t *svga) dev->v_syncstart >>= 1; dev->v_total >>= 1; } + dev->pitch = dev->ext_pitch; dev->rowoffset = dev->ext_crt_pitch; if ((mach->accel.ext_ge_config & 0x800) || (!(mach->accel.ext_ge_config & 0x8000) && !(mach->accel.ext_ge_config & 0x800))) { @@ -2706,7 +2652,7 @@ mach_recalctimings(svga_t *svga) } else dev->accel_bpp = 8; - mach_log("hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, bpp=%d.\n", dev->h_disp, dev->dispend, dev->pitch, dev->ext_crt_pitch, mach->accel.ext_ge_config & 0xcec0, dev->accel_bpp); + mach_log("hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, bpp=%d, shadow=%x, vgahdisp=%d.\n", dev->h_disp, dev->dispend, dev->pitch, dev->ext_crt_pitch, mach->accel.ext_ge_config & 0xcec0, dev->accel_bpp, mach->shadow_set & 3, svga->hdisp); switch (dev->accel_bpp) { case 8: svga->render8514 = ibm8514_render_8bpp; @@ -2738,53 +2684,38 @@ mach_recalctimings(svga_t *svga) } switch (mach->regs[0xb8] & 0xc0) { case 0x40: - svga->clock *= 2; + svga->clock8514 *= 2; break; case 0x80: - svga->clock *= 3; + svga->clock8514 *= 3; break; case 0xc0: - svga->clock *= 4; + svga->clock8514 *= 4; break; default: break; } } else { - dev->h_disp = (dev->hdisp + 1) << 3; - dev->h_total = (dev->htotal + 1); - dev->v_total = (dev->vtotal + 1); - dev->v_syncstart = (dev->vsyncstart + 1); - dev->rowcount = !!(dev->disp_cntl & 0x08); - dev->dispend = ((dev->vdisp >> 1) + 1); - - if (dev->dispend == 766) - dev->dispend += 2; - - if (dev->dispend == 598) - dev->dispend += 2; - - if (dev->accel.advfunc_cntl & 4) { - if (mach->shadow_set & 2) { - if (dev->h_disp == 8) { - dev->h_disp = 1024; - dev->dispend = 768; - dev->v_total = 1536; - dev->v_syncstart = 1536; - } - svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; - } else - svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + if ((dev->accel.advfunc_cntl ^ dev->modechange) & 0x04) { + if ((mach->shadow_set ^ mach->compat_mode) & 0x03) + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + else + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 44900000.0; } else { - if (dev->h_disp == 1024) { - dev->h_disp = 640; - dev->dispend = 480; + if ((mach->shadow_set ^ mach->compat_mode) & 0x03) + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + else + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + + if (((mach->shadow_set & 0x03) != 0x02) || !(dev->accel.advfunc_cntl & 0x04)) { /*Shadow set of 2 and bit 2 of port 0x4ae8 mean 1024x768+*/ + if (!(mach->accel.clock_sel & 0x01)) { + dev->h_disp = 640; + dev->dispend = 480; + } } - if (mach->shadow_set & 1) { - svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; - } else - svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); } + if (dev->interlace) { dev->dispend >>= 1; dev->v_syncstart >>= 2; @@ -2793,13 +2724,14 @@ mach_recalctimings(svga_t *svga) dev->v_syncstart >>= 1; dev->v_total >>= 1; } + dev->pitch = dev->ext_pitch; dev->rowoffset = dev->ext_crt_pitch; - mach_log("cntl=%d, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x.\n", dev->accel.advfunc_cntl & 4, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, mach->accel.ext_ge_config & 0xcec0); + mach_log("cntl=%d, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, shadow=%x interlace=%d.\n", dev->accel.advfunc_cntl & 4, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, mach->accel.ext_ge_config & 0xcec0, mach->shadow_set & 3, dev->interlace); svga->map8 = dev->pallook; svga->render8514 = ibm8514_render_8bpp; if (mach->regs[0xb8] & 0x40) - svga->clock *= 2; + svga->clock8514 *= 2; } } @@ -2862,24 +2794,23 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x82e8: case 0xc2e8: case 0xf6ee: - if (len == 1) { + if (len == 1) dev->accel.cur_y = (dev->accel.cur_y & 0x700) | val; - } else + else dev->accel.cur_y = val & 0x7ff; break; case 0x82e9: case 0xc2e9: case 0xf6ef: - if (len == 1) { + if (len == 1) dev->accel.cur_y = (dev->accel.cur_y & 0xff) | ((val & 0x07) << 8); - } break; case 0x86e8: case 0xc6e8: - if (len == 1) { + if (len == 1) dev->accel.cur_x = (dev->accel.cur_x & 0x700) | val; - } else + else dev->accel.cur_x = val & 0x7ff; break; case 0x86e9: @@ -3284,24 +3215,22 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u else { dev->accel.multifunc_cntl = val; dev->accel.multifunc[dev->accel.multifunc_cntl >> 12] = dev->accel.multifunc_cntl & 0xfff; - if ((dev->accel.multifunc_cntl >> 12) == 1) { + if ((dev->accel.multifunc_cntl >> 12) == 1) dev->accel.clip_top = val & 0x7ff; - } - if ((dev->accel.multifunc_cntl >> 12) == 2) { + + if ((dev->accel.multifunc_cntl >> 12) == 2) dev->accel.clip_left = val & 0x7ff; - } - if ((dev->accel.multifunc_cntl >> 12) == 3) { + + if ((dev->accel.multifunc_cntl >> 12) == 3) dev->accel.multifunc[3] = val & 0x7ff; - } - if ((dev->accel.multifunc_cntl >> 12) == 4) { + + if ((dev->accel.multifunc_cntl >> 12) == 4) dev->accel.multifunc[4] = val & 0x7ff; - } + mach_log("CLIPBOTTOM=%d, CLIPRIGHT=%d, bpp=%d, pitch=%d.\n", dev->accel.multifunc[3], dev->accel.multifunc[4], dev->accel_bpp, dev->pitch); if ((dev->accel.multifunc_cntl >> 12) == 5) { - if (dev->local < 2) + if ((dev->local & 0xff) < 0x02) dev->ext_crt_pitch = 128; - - svga_recalctimings(svga); } if (port == 0xfee8) dev->accel.cmd_back = 1; @@ -3314,17 +3243,15 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u if (len == 1) { dev->accel.multifunc_cntl = (dev->accel.multifunc_cntl & 0xff) | (val << 8); dev->accel.multifunc[dev->accel.multifunc_cntl >> 12] = dev->accel.multifunc_cntl & 0xfff; - if ((dev->accel.multifunc_cntl >> 12) == 1) { + if ((dev->accel.multifunc_cntl >> 12) == 1) dev->accel.clip_top = dev->accel.multifunc_cntl & 0x7ff; - } - if ((dev->accel.multifunc_cntl >> 12) == 2) { - dev->accel.clip_left = dev->accel.multifunc_cntl & 0x7ff; - } - if ((dev->accel.multifunc_cntl >> 12) == 5) { - if (dev->local < 2) - dev->ext_crt_pitch = 128; - svga_recalctimings(svga); + if ((dev->accel.multifunc_cntl >> 12) == 2) + dev->accel.clip_left = dev->accel.multifunc_cntl & 0x7ff; + + if ((dev->accel.multifunc_cntl >> 12) == 5) { + if ((dev->local & 0xff) < 0x02) + dev->ext_crt_pitch = 128; } if (port == 0xfee9) dev->accel.cmd_back = 1; @@ -3680,80 +3607,95 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u } static void -mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) +mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8514_t *dev) { - svga_t *svga = &mach->svga; - ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint8_t old = 0; - mach_log("[%04X:%08X]: Port NORMAL OUT=%04x, val=%04x.\n", CS, cpu_state.pc, port, val); + if (port != 0x7aee && port != 0x7aef && port != 0x42e8 && port != 0x42e9 && port != 0x46e8 && port != 0x46e9) + mach_log("[%04X:%08X]: Port CALL OUT=%04x, val=%02x.\n", CS, cpu_state.pc, port, val); switch (port) { case 0x2e8: case 0x2e9: WRITE8(port, dev->htotal, val); - svga_recalctimings(svga); break; + case 0x6e8: case 0x6e9: if (!(port & 1)) { - if ((dev->vendor_mode[0] || dev->vendor_mode[1]) && ((mach->shadow_set & 3) == 0)) - dev->hdisp = val; - else if (!dev->on[0] || !dev->on[1]) - dev->hdisp = val; - - mach_log("ATI 8514/A: H_DISP write 06E8 = %d\n", dev->hdisp + 1); + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04)) || (mach->accel.clock_sel & 0x01)) { + dev->hdisped = val; + dev->hdisp = (dev->hdisped + 1) << 3; + } } - svga_recalctimings(svga); + mach_log("[%04X:%08X]: ATI 8514/A: H_DISP write 06E8 = %d, actual val=%d, set lock=%x, shadow set=%x, advfunc=%x, dispcntl=%02x.\n", CS, cpu_state.pc, dev->hdisp, ((val + 1) << 3), mach->shadow_cntl, mach->shadow_set, dev->accel.advfunc_cntl & 4, dev->disp_cntl & 0x60); break; case 0xae8: + case 0xae9: + if (!(port & 1)) { + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04)) || (mach->accel.clock_sel & 0x01)) { + dev->hsync_start = val; + dev->hblankstart = (dev->hsync_start & 0x07); + } + } mach_log("ATI 8514/A: H_SYNC_STRT write 0AE8 = %d\n", val + 1); - svga_recalctimings(svga); break; case 0xee8: + case 0xee9: + if (!(port & 1)) { + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04)) || (mach->accel.clock_sel & 0x01)) { + dev->hsync_width = val; + dev->hblank_end_val = (dev->hblankstart + (dev->hsync_width & 0x1f) - 1) & 0x3f; + } + } mach_log("ATI 8514/A: H_SYNC_WID write 0EE8 = %d\n", val + 1); - svga_recalctimings(svga); break; case 0x12e8: case 0x12e9: - WRITE8(port, dev->vtotal, val); - dev->vtotal &= 0x1fff; - svga_recalctimings(svga); + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04)) || (mach->accel.clock_sel & 0x01)) { + WRITE8(port, dev->v_total_reg, val); + dev->v_total_reg &= 0x1fff; + dev->vtotal = dev->v_total_reg; + dev->vtotal++; + } break; case 0x16e8: case 0x16e9: - if ((dev->vendor_mode[0] || dev->vendor_mode[1]) && ((mach->shadow_set & 3) == 0)) { - WRITE8(port, dev->vdisp, val); - } else if (!dev->on[0] || !dev->on[1]) { - WRITE8(port, dev->vdisp, val); + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04)) || (mach->accel.clock_sel & 0x01)) { + WRITE8(port, dev->v_disp, val); + dev->v_disp &= 0x1fff; + dev->vdisp = dev->v_disp; + dev->vdisp >>= 1; + dev->vdisp++; } - dev->vdisp &= 0x1fff; - mach_log("ATI 8514/A: V_DISP write 16E8 = %d\n", (dev->vdisp >> 1) + 1); - svga_recalctimings(svga); + dev->modechange = dev->accel.advfunc_cntl & 0x04; + mach->compat_mode = mach->shadow_set & 0x03; + mach_log("ATI 8514/A: V_DISP write 16E8 = %d\n", dev->vdisp); break; case 0x1ae8: case 0x1ae9: - WRITE8(port, dev->vsyncstart, val); - dev->vsyncstart &= 0x1fff; - svga_recalctimings(svga); + if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04)) || (mach->accel.clock_sel & 0x01)) { + WRITE8(port, dev->v_sync_start, val); + dev->v_sync_start &= 0x1fff; + dev->vsyncstart = dev->v_sync_start; + dev->vsyncstart++; + } break; case 0x1ee8: case 0x1ee9: mach_log("ATI 8514/A: V_SYNC_WID write 1EE8 = %02x\n", val); - svga_recalctimings(svga); break; case 0x22e8: - dev->disp_cntl = val & 0x7e; + dev->disp_cntl = val; dev->interlace = !!(val & 0x10); - svga_recalctimings(svga); - mach_log("ATI 8514/A: DISP_CNTL write 22E8 = %02x, SCANMODULOS = %d\n", dev->disp_cntl, dev->scanmodulos); + mach_log("ATI 8514/A: DISP_CNTL write 22E8 = %02x, interlace = %d\n", dev->disp_cntl, dev->interlace); break; case 0x42e8: @@ -3782,16 +3724,16 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0x4ae8: case 0x4ae9: - if (dev->local < 2) + WRITE8(port, dev->accel.advfunc_cntl, val); + dev->on[port & 1] = dev->accel.advfunc_cntl & 0x01; + if ((dev->local & 0xff) < 0x02) dev->ext_crt_pitch = 128; - WRITE8(port, dev->accel.advfunc_cntl, val); - dev->on[port & 1] = (dev->accel.advfunc_cntl & 0x01); - mach_log("ATI 8514/A: (0x%04x): ON=%d.\n", port, dev->on[port & 1]); vga_on = !dev->on[port & 1]; mach->ext_on[port & 1] = dev->on[port & 1]; - mach32_updatemapping(mach); + mach32_updatemapping(mach, svga); dev->vendor_mode[port & 1] = 0; + mach_log("ATI 8514/A: (0x%04x): ON=%d, shadow crt=%x.\n", port, dev->on[port & 1], dev->accel.advfunc_cntl & 4); svga_recalctimings(svga); break; @@ -3853,7 +3795,7 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0x22ee: if (mach->pci_bus) { mach->pci_cntl_reg = val; - mach32_updatemapping(mach); + mach32_updatemapping(mach, svga); } break; @@ -3876,7 +3818,7 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0x32ee: case 0x32ef: WRITE8(port, mach->local_cntl, val); - mach32_updatemapping(mach); + mach32_updatemapping(mach, svga); break; case 0x36ee: @@ -3902,12 +3844,14 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0x42ee: case 0x42ef: + mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); WRITE8(port, mach->accel.test2, val); break; case 0x46ee: case 0x46ef: - WRITE8(port, mach->accel.test3, val); + mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); + WRITE8(port, mach->shadow_cntl, val); break; case 0x4aee: @@ -3935,10 +3879,10 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0x5aee: case 0x5aef: - WRITE8(port, mach->shadow_set, val); - mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); - if (mach->shadow_set & 3) - svga_recalctimings(svga); + if (!(mach->shadow_cntl & 0x3f)) { + WRITE8(port, mach->shadow_set, val); + mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); + } break; case 0x5eee: @@ -3948,7 +3892,7 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) if (!mach->pci_bus) mach->linear_base = (mach->memory_aperture & 0xff00) << 12; - mach32_updatemapping(mach); + mach32_updatemapping(mach, svga); break; case 0x62ee: @@ -3980,7 +3924,7 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) case 0x76ef: WRITE8(port, mach->accel.ge_pitch, val); dev->ext_pitch = ((mach->accel.ge_pitch & 0xff) << 3); - mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); + mach_log("ATI 8514/A: (0x%04x) val = %04x, extpitch = %d.\n", port, val, dev->ext_pitch); svga_recalctimings(svga); break; @@ -4012,16 +3956,19 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) } svga_set_ramdac_type(svga, !!(mach->accel.ext_ge_config & 0x4000)); dev->vendor_mode[port & 1] = 1; - mach32_updatemapping(mach); + mach32_updatemapping(mach, svga); + mach_log("ATI 8514/A: (0x%04x) val = %02x.\n", port, val); + svga_recalctimings(svga); + } else { + if (mach->accel.ext_ge_config & 0x8080) + ati_eeprom_write(&mach->eeprom, mach->accel.ext_ge_config & 0x4040, mach->accel.ext_ge_config & 0x2020, mach->accel.ext_ge_config & 0x1010); } - mach_log("ATI 8514/A: (0x%04x) val = %02x.\n", port, val); - svga_recalctimings(svga); break; case 0x7eee: case 0x7eef: WRITE8(port, mach->accel.eeprom_control, val); - ati_eeprom_write(&mach->eeprom, mach->accel.eeprom_control & 4, mach->accel.eeprom_control & 2, mach->accel.eeprom_control & 1); + ati_eeprom_write(&mach->eeprom, mach->accel.eeprom_control & 8, mach->accel.eeprom_control & 2, mach->accel.eeprom_control & 1); mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); break; @@ -4030,6 +3977,16 @@ mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) } } +static void +mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) +{ + svga_t *svga = &mach->svga; + + mach_log("[%04X:%08X]: Port NORMAL OUT=%04x, val=%04x.\n", CS, cpu_state.pc, port, val); + + mach_accel_out_call(port, val, mach, svga, (ibm8514_t *) svga->dev8514); +} + static uint16_t mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, int len) { @@ -4043,28 +4000,24 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in switch (port) { case 0x82e8: case 0xc2e8: - if (len != 1) { + if (len != 1) temp = dev->accel.cur_y; - } break; case 0x86e8: case 0xc6e8: - if (len != 1) { + if (len != 1) temp = dev->accel.cur_x; - } break; case 0x92e8: - if (len != 1) { + if (len != 1) temp = dev->test; - } break; case 0x96e8: - if (len != 1) { + if (len != 1) temp = dev->accel.maj_axis_pcnt; - } break; case 0x9ae8: @@ -4287,9 +4240,9 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in break; case 0x96ee: - if (len == 1) { + if (len == 1) temp = dev->accel.maj_axis_pcnt & 0xff; - } else { + else { temp = dev->accel.maj_axis_pcnt; if ((mach->accel.test == 0x1555) || (mach->accel.test == 0x0aaa)) temp = mach->accel.test; @@ -4303,9 +4256,8 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0xa2ee: if (len == 1) temp = mach->accel.linedraw_opt & 0xff; - else { + else temp = mach->accel.linedraw_opt; - } break; case 0xa2ef: if (len == 1) @@ -4314,17 +4266,23 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0xb2ee: if (len == 1) - temp = dev->hdisp; + temp = dev->hdisped; else { - temp = dev->hdisp & 0xff; + temp = dev->hdisped & 0xff; temp |= (dev->htotal << 8); - mach_log("HDISP read=%d, HTOTAL read=%d.\n", temp & 0xff, temp >> 8); } break; case 0xb2ef: - if (len == 1) { + if (len == 1) temp = dev->htotal; - } + break; + + case 0xb6ee: + temp = dev->hsync_start; + break; + + case 0xbaee: + temp = dev->hsync_width; break; case 0xc2ee: @@ -4342,26 +4300,26 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0xc6ee: if (len == 1) - temp = dev->vdisp & 0xff; + temp = dev->v_disp & 0xff; else { - temp = dev->vdisp; + temp = dev->v_disp; mach_log("VDISP read=%d.\n", temp); } break; case 0xc6ef: if (len == 1) - temp = dev->vdisp >> 8; + temp = dev->v_disp >> 8; break; case 0xcaee: if (len == 1) - temp = dev->vsyncstart & 0xff; + temp = dev->v_sync_start & 0xff; else - temp = dev->vsyncstart; + temp = dev->v_sync_start; break; case 0xcaef: if (len == 1) - temp = dev->vsyncstart >> 8; + temp = dev->v_sync_start >> 8; break; case 0xceee: @@ -4428,15 +4386,14 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in } mach_log("[%04X:%08X]: Port FIFO IN=%04x, temp=%04x, len=%d.\n", CS, cpu_state.pc, port, temp, len); + return temp; } static uint8_t -mach_accel_in(uint16_t port, mach_t *mach) +mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) { - svga_t *svga = &mach->svga; - ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - uint8_t temp = 0; + uint8_t temp = 0; uint16_t vpos = 0; uint16_t vblankend = svga->vblankstart + svga->crtc[0x16]; @@ -4448,13 +4405,13 @@ mach_accel_in(uint16_t port, mach_t *mach) if ((vpos >= svga->vblankstart) || (vpos <= vblankend)) temp |= 2; } else { - if ((vpos >= svga->vblankstart) && (vpos <= vblankend)) + if ((vpos >= svga->vblankstart) && (vpos <= vblankend)) temp |= 2; } break; case 0x6e8: - temp = dev->hdisp; + temp = dev->hdisped; break; case 0x22e8: @@ -4476,26 +4433,25 @@ mach_accel_in(uint16_t port, mach_t *mach) case 0x42e8: case 0x42e9: vpos = dev->vc & 0x7ff; - if (!(dev->subsys_stat & 1)) { - if (vblankend > dev->v_total) { - vblankend -= dev->v_total; - if ((vpos >= svga->vblankstart) || (vpos <= vblankend)) - dev->subsys_stat |= 1; - } else { - if ((vpos >= svga->vblankstart) && (vpos <= vblankend)) - dev->subsys_stat |= 1; - } + if (vblankend > dev->v_total) { + vblankend -= dev->v_total; + if ((vpos >= svga->vblankstart) || (vpos <= vblankend)) + dev->subsys_stat |= 1; + } else { + if ((vpos >= svga->vblankstart) && (vpos <= vblankend)) + dev->subsys_stat |= 1; } - if (port & 1) { + if (port & 1) temp = 0x80; - } else { + else { temp = dev->subsys_stat | 0x80; - if (mach->accel.ext_ge_config & 0x08) { + if (mach->accel.ext_ge_config & 0x08) temp |= ((mach->accel.ext_ge_config & 0x07) << 4); - } else + else temp |= 0x20; } + mach_log("Subsystem Status=%04x, 4ae8 shadow set=%02x.\n", temp, dev->accel.advfunc_cntl & 4); break; /*ATI Mach8/32 specific registers*/ @@ -4510,9 +4466,8 @@ mach_accel_in(uint16_t port, mach_t *mach) break; case 0x22ee: - if (mach->pci_bus) { + if (mach->pci_bus) temp = mach->pci_cntl_reg; - } break; case 0x32ee: @@ -4525,10 +4480,8 @@ mach_accel_in(uint16_t port, mach_t *mach) READ8(port, mach->misc); if (!(port & 1)) { + temp &= ~0x0c; switch (mach->memory) { - case 512: - temp &= ~0x0c; - break; case 1024: temp |= 0x04; break; @@ -4540,6 +4493,8 @@ mach_accel_in(uint16_t port, mach_t *mach) break; default: + if ((dev->local & 0xff) < 0x02) + temp |= 0x04; break; } } @@ -4552,7 +4507,7 @@ mach_accel_in(uint16_t port, mach_t *mach) case 0x46ee: case 0x46ef: - READ8(port, mach->accel.test3); + READ8(port, mach->shadow_cntl); break; case 0x4aee: @@ -4563,6 +4518,23 @@ mach_accel_in(uint16_t port, mach_t *mach) case 0x52ee: case 0x52ef: READ8(port, mach->accel.scratch0); +#ifdef ATI_8514_ULTRA + if (mach->mca_bus) { + if (!(port & 1)) { + if (svga->ext8514 != NULL) + temp = dev->pos_regs[4]; + } else { + if (svga->ext8514 != NULL) + temp = dev->pos_regs[5]; + } + } else { + if (!(port & 1)) { + if (svga->ext8514 != NULL) { + temp = 0x20 | 0x80; + } + } + } +#endif break; case 0x56ee: @@ -4620,10 +4592,65 @@ mach_accel_in(uint16_t port, mach_t *mach) default: break; } - mach_log("[%04X:%08X]: Port NORMAL IN=%04x, temp=%04x.\n", CS, cpu_state.pc, port, temp); + if (port != 0x62ee && port != 0x62ef && port != 0x42e8 && port != 0x42e9) + mach_log("[%04X:%08X]: Port NORMAL IN=%04x, temp=%04x.\n", CS, cpu_state.pc, port, temp); + return temp; } +#ifdef ATI_8514_ULTRA +static void +ati8514_accel_out(uint16_t port, uint8_t val, svga_t *svga) +{ + mach_log("[%04X:%08X]: Port NORMAL OUT=%04x, val=%04x.\n", CS, cpu_state.pc, port, val); + + mach_accel_out_call(port, val, (mach_t *)svga->ext8514, svga, (ibm8514_t *) svga->dev8514); +} + +static void +ati8514_accel_outb(uint16_t port, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *)priv; + mach_t *mach = (mach_t *)svga->ext8514; + + if (port & 0x8000) + mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val, 1); + else + ati8514_accel_out(port, val, svga); +} + +static void +ati8514_accel_outw(uint16_t port, uint16_t val, void *priv) +{ + svga_t *svga = (svga_t *)priv; + mach_t *mach = (mach_t *)svga->ext8514; + + if (port & 0x8000) + mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val, 2); + else { + ati8514_accel_out(port, val, svga); + ati8514_accel_out(port + 1, (val >> 8), svga); + } +} + +static void +ati8514_accel_outl(uint16_t port, uint32_t val, void *priv) +{ + svga_t *svga = (svga_t *)priv; + mach_t *mach = (mach_t *)svga->ext8514; + + if (port & 0x8000) { + mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val & 0xffff, 2); + mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port + 2, val >> 16, 2); + } else { + ati8514_accel_out(port, val, svga); + ati8514_accel_out(port + 1, (val >> 8), svga); + ati8514_accel_out(port + 2, (val >> 16), svga); + ati8514_accel_out(port + 3, (val >> 24), svga); + } +} +#endif + static void mach_accel_outb(uint16_t port, uint8_t val, void *priv) { @@ -4666,6 +4693,72 @@ mach_accel_outl(uint16_t port, uint32_t val, void *priv) mach_accel_out(port + 3, (val >> 24), mach); } } + +#ifdef ATI_8514_ULTRA +static uint8_t +ati8514_accel_in(uint16_t port, svga_t *svga) +{ + return mach_accel_in_call(port, (mach_t *) svga->ext8514, svga, (ibm8514_t *) svga->dev8514); +} + +static uint8_t +ati8514_accel_inb(uint16_t port, void *priv) +{ + svga_t *svga = (svga_t *)priv; + mach_t *mach = (mach_t *)svga->ext8514; + uint8_t temp; + + if (port & 0x8000) + temp = mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, 1); + else + temp = ati8514_accel_in(port, svga); + + return temp; +} + +static uint16_t +ati8514_accel_inw(uint16_t port, void *priv) +{ + svga_t *svga = (svga_t *)priv; + mach_t *mach = (mach_t *)svga->ext8514; + uint16_t temp; + + if (port & 0x8000) + temp = mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, 2); + else { + temp = ati8514_accel_in(port, svga); + temp |= (ati8514_accel_in(port + 1, svga) << 8); + } + return temp; +} + +static uint32_t +ati8514_accel_inl(uint16_t port, void *priv) +{ + svga_t *svga = (svga_t *)priv; + mach_t *mach = (mach_t *)svga->ext8514; + uint32_t temp; + + if (port & 0x8000) { + temp = mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, 2); + temp = (mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port + 2, 2) << 16); + } else { + temp = ati8514_accel_in(port, svga); + temp |= (ati8514_accel_in(port + 1, svga) << 8); + temp |= (ati8514_accel_in(port + 2, svga) << 16); + temp |= (ati8514_accel_in(port + 3, svga) << 24); + } + return temp; +} +#endif + +static uint8_t +mach_accel_in(uint16_t port, mach_t *mach) +{ + svga_t *svga = &mach->svga; + return mach_accel_in_call(port, mach, svga, (ibm8514_t *) svga->dev8514); +} + static uint8_t mach_accel_inb(uint16_t port, void *priv) { @@ -5212,9 +5305,8 @@ mach32_ap_readl(uint32_t addr, void *priv) } static void -mach32_updatemapping(mach_t *mach) +mach32_updatemapping(mach_t *mach, svga_t *svga) { - svga_t *svga = &mach->svga; ibm8514_t *dev = (ibm8514_t *) svga->dev8514; if (mach->pci_bus && (!(mach->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM))) { @@ -5349,119 +5441,120 @@ mach32_hwcursor_draw(svga_t *svga, int displine) dev->hwcursor_latch.addr += 16; } -#if 0 +#ifdef ATI_8514_ULTRA static void -mach_io_remove(mach_t *mach) +ati8514_io_set(svga_t *svga) { - io_removehandler(0x2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x12e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x16e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x1ae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x1ee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x22e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x26e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x2ee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x42e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x4ae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x52e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x56e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x5ae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x5ee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x82e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x86e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x8ae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x8ee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x92e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x96e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x9ae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x9ee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xa2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xa6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xaae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xaee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xb2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xb6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xbae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xbee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xe2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x2e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x6e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x12e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x16e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x1ae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x1ee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x22e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x26e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x2ee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x42e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x4ae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x52e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x56e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x5ae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x5ee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x82e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x86e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x8ae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x8ee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x92e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x96e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x9ae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x9ee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xa2e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xa6e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xaae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xaee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xb2e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xb6e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xbae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xbee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xe2e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); - io_removehandler(0xc2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xc6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xcae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xcee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xd2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xd6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xdae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xdee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xe6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xeae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xeee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xf2e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xf6e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xfae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xfee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xc2e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xc6e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xcae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xcee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xd2e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xd6e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xdae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xdee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xe6e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xeae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xeee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xf2e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xf6e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xfae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xfee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); - io_removehandler(0x02ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x06ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x0aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x0eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x12ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x16ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x1aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x1eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x22ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x26ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x2aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x2eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x32ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x36ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x3aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x3eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x42ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x46ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x4aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x52ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x56ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x5aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x5eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x62ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x66ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x6aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x6eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x72ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x76ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x7aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x7eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x82ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x8eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x92ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x96ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0x9aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xa2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xa6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xaaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xaeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xb2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xb6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xbaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xbeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xc2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xc6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xcaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xceee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xd2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xd6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xdaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xdeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xe2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xe6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xeeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xf2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xfaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_removehandler(0xfeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x02ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x06ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x0aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x0eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x12ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x16ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x1aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x1eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x22ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x26ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x2aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x2eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x32ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x36ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x3aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x3eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x42ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x46ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x4aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x52ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x56ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x5aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x5eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x62ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x66ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x6aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x6eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x72ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x76ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x7aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x7eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x82ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x86ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x8eee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x92ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x96ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x9aee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xa2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xa6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xaaee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xaeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xb2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xb6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xbaee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xbeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xc2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xc6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xcaee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xceee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xd2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xd6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xdaee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xdeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xe2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xe6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xeeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xf2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xf6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0xfeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); } #endif @@ -5577,7 +5670,6 @@ mach_io_set(mach_t *mach) io_sethandler(0xeeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0xf2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0xf6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); - io_sethandler(0xfaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0xfeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); } @@ -5633,6 +5725,34 @@ mach_mca_reset(void *priv) mach_mca_write(0x102, 0, mach); } +#ifdef ATI_8514_ULTRA +uint8_t +ati8514_mca_read(int port, void *priv) +{ + const svga_t *svga = (svga_t *) priv; + const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + return (dev->pos_regs[port & 7]); +} + +void +ati8514_mca_write(int port, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + if (port < 0x102) + return; + + dev->pos_regs[port & 7] = val; + mach_log("[%04X]: MCA write port = %x, val = %02x, biosaddr = %05x.\n", CS, port & 7, dev->pos_regs[port & 7], (((dev->pos_regs[3] & 0x3e) << 0x0c) >> 1) + 0xc0000); + mem_mapping_disable(&dev->bios_rom.mapping); + + if (dev->pos_regs[2] & 0x01) + mem_mapping_enable(&dev->bios_rom.mapping); +} +#endif + static uint8_t mach32_pci_read(UNUSED(int func), int addr, void *priv) { @@ -5728,19 +5848,19 @@ mach32_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) io_sethandler(0x02ea, 4, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); io_sethandler(0x03c0, 32, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); } else { - io_removehandler(0x03c0, 32, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); io_removehandler(0x02ea, 4, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); + io_removehandler(0x03c0, 32, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); } - mach32_updatemapping(mach); + mach32_updatemapping(mach, &mach->svga); break; case 0x12: mach->linear_base = (mach->linear_base & 0xff000000) | ((val & 0xc0) << 16); - mach32_updatemapping(mach); + mach32_updatemapping(mach, &mach->svga); break; case 0x13: mach->linear_base = (mach->linear_base & 0xc00000) | (val << 24); - mach32_updatemapping(mach); + mach32_updatemapping(mach, &mach->svga); break; case 0x30: @@ -5818,12 +5938,11 @@ mach8_init(const device_t *info) 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); } - } else { + } else rom_init(&mach->bios_rom, - BIOS_MACH8_ROM_PATH, + BIOS_MACH8_VGA_ROM_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - } if ((dev->local & 0xff) >= 0x02) { svga_init(info, svga, mach, mach->memory << 10, /*default: 2MB for Mach32*/ @@ -5884,7 +6003,7 @@ mach8_init(const device_t *info) dev->changedvram = calloc(dev->vram_size >> 12, 1); dev->vram_mask = dev->vram_size - 1; video_inform(VIDEO_FLAG_TYPE_8514, &timing_gfxultra_isa); - mach->config1 = 0x02 | 0x20 | 0x80; + mach->config1 = 0x01 | 0x02 | 0x20 | 0x08 | 0x80; mach->config2 = 0x02; svga->clock_gen = device_add(&ati18810_device); } @@ -5911,6 +6030,7 @@ mach8_init(const device_t *info) mach->cursor_col_1 = 0xff; mach->ext_cur_col_1_r = 0xff; mach->ext_cur_col_1_g = 0xff; + io_sethandler(0xfaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); if (mach->vlb_bus) ati_eeprom_load(&mach->eeprom, "mach32_vlb.nvr", 1); else if (mach->mca_bus) { @@ -5927,23 +6047,54 @@ mach8_init(const device_t *info) pci_add_card(PCI_ADD_NORMAL, mach32_pci_read, mach32_pci_write, mach, &mach->pci_slot); } else pci_add_card(PCI_ADD_VIDEO, mach32_pci_read, mach32_pci_write, mach, &mach->pci_slot); + mach->pci_regs[PCI_REG_COMMAND] = 0x83; mach->pci_regs[0x30] = 0x00; mach->pci_regs[0x32] = 0x0c; mach->pci_regs[0x33] = 0x00; } else ati_eeprom_load(&mach->eeprom, "mach32.nvr", 1); - } else { + } else ati_eeprom_load_mach8(&mach->eeprom, "mach8.nvr"); - } + + timer_add(&svga->timer8514, ibm8514_poll, svga, 1); return mach; } -static int -mach8_available(void) +#ifdef ATI_8514_ULTRA +void +ati8514_init(svga_t *svga, void *ext8514, void *dev8514) { - return rom_present(BIOS_MACH8_ROM_PATH); + mach_t *mach = (mach_t *)ext8514; + ibm8514_t *dev = (ibm8514_t *)dev8514; + + dev->on[0] = 0; + dev->on[1] = 0; + dev->ext_pitch = 1024; + dev->ext_crt_pitch = 0x80; + dev->accel_bpp = 8; + dev->rowoffset = 0x80; + dev->hdisp = 1024; + dev->vdisp = 768; + + io_sethandler(0x02ea, 4, ati8514_in, NULL, NULL, ati8514_out, NULL, NULL, svga); + ati8514_io_set(svga); + mach->mca_bus = !!(dev->type & DEVICE_MCA); + + if (mach->mca_bus) + mach->config1 = 0x02 | 0x04 | 0x08 | 0x20 | 0x80; + else + mach->config1 = 0x02 | 0x08 | 0x20 | 0x80; + + mach->config2 = 0x01 | 0x02; +} +#endif + +static int +mach8_vga_available(void) +{ + return rom_present(BIOS_MACH8_VGA_ROM_PATH); } static int @@ -6093,15 +6244,15 @@ static const device_config_t mach32_pci_config[] = { } }; -const device_t mach8_isa_device = { - .name = "ATI Mach8 (ISA)", - .internal_name = "mach8_isa", +const device_t mach8_vga_isa_device = { + .name = "ATI Mach8 (ATI Graphics Ultra) (ISA)", + .internal_name = "mach8_vga_isa", .flags = DEVICE_ISA, .local = 1, .init = mach8_init, .close = mach_close, .reset = NULL, - { .available = mach8_available }, + { .available = mach8_vga_available }, .speed_changed = mach_speed_changed, .force_redraw = mach_force_redraw, .config = NULL diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index 2ba4323f3..2ea07c346 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -891,7 +891,7 @@ const device_config_t cga_config[] = { // clang-format on const device_t cga_device = { - .name = "CGA", + .name = "IBM CGA", .internal_name = "cga", .flags = DEVICE_ISA, .local = 0, diff --git a/src/video/vid_chips_69000.c b/src/video/vid_chips_69000.c new file mode 100644 index 000000000..d91ab1a8b --- /dev/null +++ b/src/video/vid_chips_69000.c @@ -0,0 +1,2551 @@ +/* + * 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. + * + * C&T 69000 emulation. + * + * + * + * Authors: Cacodemon345 + * + * Copyright 2023-2024 Cacodemon345 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/device.h> +#include <86box/timer.h> +#include <86box/video.h> +#include <86box/vid_svga.h> +#include <86box/vid_svga_render.h> +#include <86box/pci.h> +#include <86box/thread.h> +#include <86box/i2c.h> +#include <86box/vid_ddc.h> +#include <86box/plat_unused.h> +#include <86box/bswap.h> +#include + +#pragma pack(push, 1) +typedef struct chips_69000_bitblt_t +{ + /* BR00 - Source and Destination Span Register. */ + uint16_t source_span; + uint16_t destination_span; + + /* BR01 - Pattern/Source Expansion Background Color & Transparency Key Register. */ + uint32_t pattern_source_key_bg; + + /* BR02 - Pattern/Source Expansion Foreground Color Register. */ + uint32_t pattern_source_key_fg; + + /* BR03 - Monochrome Source Control Register. */ + uint8_t monochrome_source_left_clip; + uint8_t monochrome_source_right_clip; + uint8_t monochrome_source_initial_discard; + uint8_t monochrome_source_alignment : 3; + uint8_t monochrome_source_expansion_color_reg_select : 1; + uint8_t dummy_8 : 4; + + /* BR04 - BitBLT Control Register. */ + uint32_t bitblt_control; + + /* BR05 - Pattern Address Register. */ + uint32_t pat_addr; + + /* BR06 - Source Address Register. */ + uint32_t source_addr; + + /* BR07 - Destination Address Register. */ + uint32_t destination_addr; + + /* BR08 - Destination Width & Height Register. */ + uint16_t destination_width; + uint16_t destination_height; + + /* BR09 - Source Expansion Background Color & Transparency Key Register. */ + uint32_t source_key_bg; + + /* BR0A - Source Expansion Foreground Color Register. */ + uint32_t source_key_fg; +} chips_69000_bitblt_t; +#pragma pack(pop) + +typedef struct chips_69000_t { + svga_t svga; + uint8_t pci_conf_status; + uint8_t slot, irq_state; + uint8_t pci_line_interrupt; + uint8_t pci_rom_enable; + uint8_t read_write_bank; + bool engine_active; + bool quit; + thread_t *accel_thread; + event_t *fifo_event, *fifo_data_event; + pc_timer_t decrement_timer; + uint16_t rom_addr; + mem_mapping_t linear_mapping; + uint8_t on_board; + + rgb_t cursor_palette[8]; + uint32_t cursor_pallook[8]; + + uint8_t mm_regs[256], mm_index; + uint8_t flat_panel_regs[256], flat_panel_index; + uint8_t ext_regs[256], ext_index; + + union { + uint32_t mem_regs[4]; + uint16_t mem_regs_w[4 * 2]; + uint8_t mem_regs_b[4 * 4]; + }; + union { + uint32_t bitblt_regs[11]; + uint16_t bitblt_regs_w[11 * 2]; + uint8_t bitblt_regs_b[11 * 4]; + struct chips_69000_bitblt_t bitblt; + }; + + struct + { + struct chips_69000_bitblt_t bitblt; + + uint32_t actual_source_height; + uint32_t actual_destination_height; + + uint32_t actual_destination_width; + + uint32_t count_x, count_y; + int x, y; + int x_dir, y_dir; + + uint8_t bytes_per_pixel; + + /* Byte counter for BitBLT port writes. */ + uint8_t bytes_written; + uint8_t bytes_skip; + uint32_t mono_bytes_pitch; + uint8_t mono_bits_skip_left; + uint32_t bytes_counter; + uint32_t bytes_in_line_written; + uint8_t bytes_port[256]; + } bitblt_running; + + union { + uint16_t subsys_vid; + uint8_t subsys_vid_b[2]; + }; + + union { + uint16_t subsys_pid; + uint8_t subsys_pid_b[2]; + }; + + rom_t bios_rom; + + void* i2c_ddc, *ddc; + + uint8_t st01; +} chips_69000_t; + +/* TODO: Probe timings on real hardware. */ +static video_timings_t timing_chips = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 10, .read_w = 10, .read_l = 10 }; + +uint8_t chips_69000_readb_linear(uint32_t addr, void *p); +uint16_t chips_69000_readw_linear(uint32_t addr, void *p); +uint32_t chips_69000_readl_linear(uint32_t addr, void *p); +void chips_69000_writeb_linear(uint32_t addr, uint8_t val, void *p); +void chips_69000_writew_linear(uint32_t addr, uint16_t val, void *p); +void chips_69000_writel_linear(uint32_t addr, uint32_t val, void *p); + +/* Multimedia handling. */ +uint8_t +chips_69000_read_multimedia(chips_69000_t* chips) +{ + switch (chips->mm_index) { + case 0: + /* Report no playback/capture capability. */ + return 0; + default: + return chips->mm_regs[chips->mm_index]; + } + return chips->mm_regs[chips->mm_index]; +} + +/* Multimedia (write) handling. */ +void +chips_69000_write_multimedia(chips_69000_t* chips, uint8_t val) +{ + switch (chips->mm_index) { + case 0: + return; + default: + chips->mm_regs[chips->mm_index] = val; + break; + } + chips->mm_regs[chips->mm_index] = val; +} + +/* Flat panel handling. */ +uint8_t +chips_69000_read_flat_panel(chips_69000_t* chips) +{ + switch (chips->flat_panel_index) { + case 0: + return 1; + default: + return chips->flat_panel_regs[chips->flat_panel_index]; + } + return chips->flat_panel_regs[chips->flat_panel_index]; +} + +/* Flat panel (write) handling. */ +void +chips_69000_write_flat_panel(chips_69000_t* chips, uint8_t val) +{ + switch (chips->flat_panel_index) { + case 0: + return; + case 1: + case 0x20 ... 0x33: + case 0x35: + case 0x36: + chips->flat_panel_regs[chips->flat_panel_index] = val; + svga_recalctimings(&chips->svga); + return; + default: + chips->flat_panel_regs[chips->flat_panel_index] = val; + break; + } + chips->flat_panel_regs[chips->flat_panel_index] = val; +} + +void +chips_69000_interrupt(chips_69000_t* chips) +{ + pci_irq(chips->slot, PCI_INTA, 0, !!((chips->mem_regs[0] & chips->mem_regs[1]) & 0x80004040), &chips->irq_state); +} + +void +chips_69000_bitblt_interrupt(chips_69000_t* chips) +{ + chips->engine_active = 0; + chips->mem_regs[1] |= 1 << 31; + + chips_69000_interrupt(chips); +} + +void +chips_69000_do_rop_8bpp(uint8_t *dst, uint8_t src, uint8_t rop) +{ + switch (rop) { + case 0x00: + *dst = 0; + break; + case 0x11: + *dst = ~(*dst) & ~src; + break; + case 0x22: + *dst &= ~src; + break; + case 0x33: + *dst = ~src; + break; + case 0x44: + *dst = src & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x66: + *dst ^= src; + break; + case 0x77: + *dst = ~src | ~(*dst); + break; + case 0x88: + *dst &= src; + break; + case 0x99: + *dst ^= ~src; + break; + case 0xAA: + break; /* No-op. */ + case 0xBB: + *dst |= ~src; + break; + case 0xCC: + *dst = src; + break; + case 0xDD: + *dst = src | ~(*dst); + break; + case 0xEE: + *dst |= src; + break; + case 0xFF: + *dst = 0xFF; + break; + } +} + +void +chips_69000_do_rop_16bpp(uint16_t *dst, uint16_t src, uint8_t rop) +{ + switch (rop) { + case 0x00: + *dst = 0; + break; + case 0x11: + *dst = ~(*dst) & ~src; + break; + case 0x22: + *dst &= ~src; + break; + case 0x33: + *dst = ~src; + break; + case 0x44: + *dst = src & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x66: + *dst ^= src; + break; + case 0x77: + *dst = ~src | ~(*dst); + break; + case 0x88: + *dst &= src; + break; + case 0x99: + *dst ^= ~src; + break; + case 0xAA: + break; /* No-op. */ + case 0xBB: + *dst |= ~src; + break; + case 0xCC: + *dst = src; + break; + case 0xDD: + *dst = src | ~(*dst); + break; + case 0xEE: + *dst |= src; + break; + case 0xFF: + *dst = 0xFFFF; + break; + } +} + +void +chips_69000_do_rop_24bpp(uint32_t *dst, uint32_t src, uint8_t rop) +{ + switch (rop) { + case 0x00: + *dst = 0; + break; + case 0x11: + *dst = ~(*dst) & ~src; + break; + case 0x22: + *dst &= ~src; + break; + case 0x33: + *dst = ~src; + break; + case 0x44: + *dst = src & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x66: + *dst ^= src; + break; + case 0x77: + *dst = ~src | ~(*dst); + break; + case 0x88: + *dst &= src; + break; + case 0x99: + *dst ^= ~src; + break; + case 0xAA: + break; /* No-op. */ + case 0xBB: + *dst |= ~src; + break; + case 0xCC: + *dst = src; + break; + case 0xDD: + *dst = src | ~(*dst); + break; + case 0xEE: + *dst |= src; + break; + case 0xFF: + *dst = 0xFFFFFF; + break; + } +} + +void +chips_69000_do_rop_8bpp_patterned(uint8_t *dst, uint8_t pattern, uint8_t src, uint8_t rop) +{ + if ((rop & 0xF) == ((rop >> 4) & 0xF)) { + return chips_69000_do_rop_8bpp(dst, src, rop); + } + + switch (rop) { + case 0x00: + *dst = 0; + break; + case 0x05: + *dst = ~(*dst) & ~pattern; + break; + case 0x0A: + *dst &= ~pattern; + break; + case 0x0F: + *dst = ~pattern; + break; + case 0x1A: + *dst = pattern ^ (*dst | (pattern & src)); + break; + case 0x2A: + *dst = *dst & (~(src & pattern)); + break; + case 0x3A: + *dst = src ^ (pattern | (*dst ^ src)); + break; + case 0x4A: + *dst = *dst ^ (pattern & (src | *dst)); + break; + case 0x50: + *dst = pattern & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x5A: + *dst ^= pattern; + break; + case 0x5F: + *dst = ~pattern | ~(*dst); + break; + case 0x6A: + *dst = *dst ^ (pattern & src); + break; + case 0x7A: + *dst = *dst ^ (pattern & (src | (~*dst))); + break; + case 0x8A: + *dst = *dst & (src | (~pattern)); + break; + case 0x9A: + *dst = *dst ^ (pattern & (~src)); + break; + case 0xB8: + *dst = (((pattern ^ *dst) & src) ^ pattern); + break; + case 0xA0: + *dst &= pattern; + break; + case 0xA5: + *dst ^= ~pattern; + break; + case 0xAA: + break; /* No-op. */ + case 0xAC: + *dst = src ^ (pattern & (*dst ^ src)); + break; + case 0xAF: + *dst |= ~pattern; + break; + case 0xBA: + *dst |= (pattern & ~src); + break; + case 0xCA: + *dst ^= (pattern & (src ^ *dst)); + break; + case 0xE2: + *dst ^= (src & (pattern ^ *dst)); + break; + case 0xDA: + *dst ^= pattern & (~(src & *dst)); + break; + case 0xEA: + *dst |= pattern & src; + break; + case 0xF0: + *dst = pattern; + break; + case 0xF5: + *dst = pattern | ~(*dst); + break; + case 0xFA: + *dst |= pattern; + break; + case 0xFF: + *dst = 0xFF; + break; + default: + pclog("Unknown ROP 0x%X\n", rop); + break; + } +} + +void +chips_69000_do_rop_16bpp_patterned(uint16_t *dst, uint16_t pattern, uint16_t src, uint8_t rop) +{ + if ((rop & 0xF) == ((rop >> 4) & 0xF)) { + return chips_69000_do_rop_16bpp(dst, src, rop); + } + + switch (rop) { + default: + pclog("Unknown ROP 0x%X\n", rop); + break; + case 0x00: + *dst = 0; + break; + case 0x05: + *dst = ~(*dst) & ~pattern; + break; + case 0x0A: + *dst &= ~pattern; + break; + case 0x0F: + *dst = ~pattern; + break; + case 0x1A: + *dst = pattern ^ (*dst | (pattern & src)); + break; + case 0x2A: + *dst = *dst & (~(src & pattern)); + break; + case 0x3A: + *dst = src ^ (pattern | (*dst ^ src)); + break; + case 0x4A: + *dst = *dst ^ (pattern & (src | *dst)); + break; + case 0x50: + *dst = pattern & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x5A: + *dst ^= pattern; + break; + case 0x5F: + *dst = ~pattern | ~(*dst); + break; + case 0x6A: + *dst = *dst ^ (pattern & src); + break; + case 0x7A: + *dst = *dst ^ (pattern & (src | (~*dst))); + break; + case 0x8A: + *dst = *dst & (src | (~pattern)); + break; + case 0x9A: + *dst = *dst ^ (pattern & (~src)); + break; + case 0xB8: + *dst = (((pattern ^ *dst) & src) ^ pattern); + break; + case 0xA0: + *dst &= pattern; + break; + case 0xA5: + *dst ^= ~pattern; + break; + case 0xAA: + break; /* No-op. */ + case 0xAC: + *dst = src ^ (pattern & (*dst ^ src)); + break; + case 0xAF: + *dst |= ~pattern; + break; + case 0xBA: + *dst |= (pattern & ~src); + break; + case 0xCA: + *dst ^= (pattern & (src ^ *dst)); + break; + case 0xE2: + *dst ^= (src & (pattern ^ *dst)); + break; + case 0xDA: + *dst ^= pattern & (~(src & *dst)); + break; + case 0xEA: + *dst |= pattern & src; + break; + case 0xF0: + *dst = pattern; + break; + case 0xF5: + *dst = pattern | ~(*dst); + break; + case 0xFA: + *dst |= pattern; + break; + case 0xFF: + *dst = 0xFF; + break; + } +} + +void +chips_69000_do_rop_24bpp_patterned(uint32_t *dst, uint32_t pattern, uint32_t src, uint8_t rop) +{ + uint32_t orig_dst = *dst & 0xFF000000; + + if ((rop & 0xF) == ((rop >> 4) & 0xF)) { + return chips_69000_do_rop_24bpp(dst, src, rop); + } + + switch (rop) { + default: + pclog("Unknown ROP 0x%X\n", rop); + break; + case 0x00: + *dst = 0; + break; + case 0x05: + *dst = ~(*dst) & ~pattern; + break; + case 0x0A: + *dst &= ~pattern; + break; + case 0x0F: + *dst = ~pattern; + break; + case 0x1A: + *dst = pattern ^ (*dst | (pattern & src)); + break; + case 0x2A: + *dst = *dst & (~(src & pattern)); + break; + case 0x3A: + *dst = src ^ (pattern | (*dst ^ src)); + break; + case 0x4A: + *dst = *dst ^ (pattern & (src | *dst)); + break; + case 0x50: + *dst = pattern & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x5A: + *dst ^= pattern; + break; + case 0x5F: + *dst = ~pattern | ~(*dst); + break; + case 0x6A: + *dst = *dst ^ (pattern & src); + break; + case 0x7A: + *dst = *dst ^ (pattern & (src | (~*dst))); + break; + case 0x8A: + *dst = *dst & (src | (~pattern)); + break; + case 0x9A: + *dst = *dst ^ (pattern & (~src)); + break; + case 0xB8: + *dst = (((pattern ^ *dst) & src) ^ pattern); + break; + case 0xA0: + *dst &= pattern; + break; + case 0xA5: + *dst ^= ~pattern; + break; + case 0xAA: + break; /* No-op. */ + case 0xAC: + *dst = src ^ (pattern & (*dst ^ src)); + break; + case 0xAF: + *dst |= ~pattern; + break; + case 0xBA: + *dst |= (pattern & ~src); + break; + case 0xCA: + *dst ^= (pattern & (src ^ *dst)); + break; + case 0xDA: + *dst ^= pattern & (~(src & *dst)); + break; + case 0xE2: + *dst ^= (src & (pattern ^ *dst)); + break; + case 0xEA: + *dst |= pattern & src; + break; + case 0xF0: + *dst = pattern; + break; + case 0xF5: + *dst = pattern | ~(*dst); + break; + case 0xFA: + *dst |= pattern; + break; + case 0xFF: + *dst = 0xFF; + break; + } + *dst &= 0xFFFFFF; + *dst |= orig_dst; +} + +void +chips_69000_recalctimings(svga_t *svga) +{ + chips_69000_t *chips = (chips_69000_t *) svga->priv; + + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->priv); + + if (chips->ext_regs[0x81] & 0x10) { + svga->htotal -= 5; + } + + if (((chips->ext_regs[0x61] & 0x8) && !(chips->ext_regs[0x61] & 0x4)) + || ((chips->ext_regs[0x61] & 0x2) && !(chips->ext_regs[0x61] & 0x1))) { + svga->dpms = 1; + } else + svga->dpms = 0; + + if (chips->ext_regs[0x09] & 0x1) { + svga->vtotal -= 2; + svga->vtotal &= 0xFF; + svga->vtotal |= (svga->crtc[0x30] & 0xF) << 8; + svga->vtotal += 2; + + svga->dispend--; + svga->dispend &= 0xFF; + svga->dispend |= (svga->crtc[0x31] & 0xF) << 8; + svga->dispend++; + + svga->vsyncstart--; + svga->vsyncstart &= 0xFF; + svga->vsyncstart |= (svga->crtc[0x32] & 0xF) << 8; + svga->vsyncstart++; + + svga->vblankstart--; + svga->vblankstart &= 0xFF; + svga->vblankstart |= (svga->crtc[0x33] & 0xF) << 8; + svga->vblankstart++; + + if (!(chips->ext_regs[0x81] & 0x10)) + svga->htotal -= 5; + + svga->htotal |= (svga->crtc[0x38] & 0x1) << 8; + + if (!(chips->ext_regs[0x81] & 0x10)) + svga->htotal += 5; + + svga->hblank_end_val = ((svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00)) | (svga->crtc[0x3c] & 0b11000000); + svga->hblank_end_mask = 0xff; + + svga->ma_latch |= (svga->crtc[0x40] & 0xF) << 16; + svga->rowoffset |= (svga->crtc[0x41] & 0xF) << 8; + + svga->interlace = !!(svga->crtc[0x70] & 0x80); + + if (svga->hdisp == 1280 && svga->dispend == 1024) { + svga->interlace = 0; + } + + switch (chips->ext_regs[0x81] & 0xF) { + default: + svga->bpp = 8; + break; + case 0b0010: + svga->bpp = 8; + svga->render = svga_render_8bpp_highres; + break; + + case 0b0100: + svga->bpp = 15; + svga->render = svga_render_15bpp_highres; + break; + case 0b0101: + svga->bpp = 16; + svga->render = svga_render_16bpp_highres; + break; + case 0b0110: + svga->bpp = 24; + svga->render = svga_render_24bpp_highres; + break; + case 0b0111: + svga->bpp = 32; + svga->render = svga_render_32bpp_highres; + break; + } +#if 1 + if (chips->flat_panel_regs[0x01] & 0x2) { + /* TODO: Fix horizontal parameter calculations. */ + if (svga->hdisp > (((chips->flat_panel_regs[0x20] | ((chips->flat_panel_regs[0x25] & 0xF) << 8)) + 1) << 3)) { + svga->hdisp = ((chips->flat_panel_regs[0x20] | ((chips->flat_panel_regs[0x25] & 0xF) << 8)) + 1) << 3; + //svga->htotal = ((chips->flat_panel_regs[0x23] | ((chips->flat_panel_regs[0x26] & 0xF) << 8)) + 5) << 3; + //svga->hblank_end_val = svga->htotal - 1; + svga->hoverride = 1; + } else + svga->hoverride = 0; + + if (svga->dispend > (((chips->flat_panel_regs[0x30] | ((chips->flat_panel_regs[0x35] & 0xF) << 8)) + 1))) { + svga->dispend = svga->vsyncstart = svga->vblankstart = ((chips->flat_panel_regs[0x30] | ((chips->flat_panel_regs[0x35] & 0xF) << 8)) + 1); + } + //svga->hdisp = ((chips->flat_panel_regs[0x20] | ((chips->flat_panel_regs[0x25] & 0xF) << 8)) + 1) << 3; + //svga->htotal = ((chips->flat_panel_regs[0x23] | ((chips->flat_panel_regs[0x26] & 0xF) << 8)) + 5) << 3; + //svga->hblank_end_val = svga->htotal - 1; + //svga->dispend = svga->vsyncstart = svga->vblankstart = ((chips->flat_panel_regs[0x30] | ((chips->flat_panel_regs[0x35] & 0xF) << 8)) + 1); + //svga->vsyncstart = ((chips->flat_panel_regs[0x31] | ((chips->flat_panel_regs[0x35] & 0xF0) << 4)) + 1); + //svga->vtotal = ((chips->flat_panel_regs[0x33] | ((chips->flat_panel_regs[0x36] & 0xF) << 8)) + 2); + svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((chips->flat_panel_regs[0x03] >> 2) & 3, svga->priv); + } else { + svga->hoverride = 0; + } +#endif + } else { + svga->bpp = 8; + svga->hoverride = 0; + } +} + +void +chips_69000_decrement_timer(void* p) +{ + chips_69000_t *chips = (chips_69000_t*)p; + + chips->ext_regs[0xD2]--; + timer_on_auto(&chips->decrement_timer, 1000000. / 2000.); +} + +void +chips_69000_recalc_banking(chips_69000_t *chips) +{ + svga_t* svga = &chips->svga; + chips->svga.read_bank = chips->svga.write_bank = 0; + + svga->chain2_write = !(svga->seqregs[0x4] & 4); + svga->chain4 = (svga->seqregs[0x4] & 8) || (chips->ext_regs[0xA] & 0x4); + svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && ((svga->chain4 && (svga->packed_chain4 || svga->force_old_addr)) || svga->fb_only) && !(svga->adv_flags & FLAG_ADDR_BY8); + + if (chips->ext_regs[0xA] & 1) { + chips->svga.read_bank = chips->svga.write_bank = 0x10000 * (chips->ext_regs[0xE] & 0x7f); + } + + /*if (chips->ext_regs[0x40] & 2) { + svga->decode_mask = (1 << 18) - 1; + } else { + svga->decode_mask = (1 << 21) - 1; + }*/ +} + +void +chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) +{ + uint32_t pattern_fg = chips->bitblt_running.bitblt.pattern_source_key_fg; + uint32_t pattern_bg = chips->bitblt_running.bitblt.pattern_source_key_bg; + uint8_t pattern_data = 0; + uint32_t pattern_pixel = 0; + uint32_t dest_pixel = 0; + uint32_t dest_addr = chips->bitblt_running.bitblt.destination_addr + (chips->bitblt_running.y * chips->bitblt_running.bitblt.destination_span) + (chips->bitblt_running.x * chips->bitblt_running.bytes_per_pixel); + uint8_t vert_pat_alignment = (chips->bitblt_running.bitblt.bitblt_control >> 20) & 7; + uint8_t orig_dest_addr_bit = chips->bitblt_running.bitblt.destination_addr & 1; + + switch (chips->bitblt_running.bytes_per_pixel) { + case 1: /* 8 bits-per-pixel. */ + { + dest_pixel = chips_69000_readb_linear(dest_addr, chips); + break; + } + case 2: /* 16 bits-per-pixel. */ + { + dest_pixel = chips_69000_readb_linear(dest_addr, chips); + dest_pixel |= chips_69000_readb_linear(dest_addr + 1, chips) << 8; + break; + } + case 3: /* 24 bits-per-pixel. */ + { + dest_pixel = chips_69000_readb_linear(dest_addr, chips); + dest_pixel |= chips_69000_readb_linear(dest_addr + 1, chips) << 8; + dest_pixel |= chips_69000_readb_linear(dest_addr + 2, chips) << 16; + break; + } + } + + if (chips->bitblt_running.bytes_per_pixel == 2) { + chips->bitblt_running.bitblt.destination_addr >>= 1; + } + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 18)) { + uint8_t is_true = 0; + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 19)) + pattern_data = 0; + else + pattern_data = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + ((vert_pat_alignment + (chips->bitblt_running.y & 7)) & 7), chips); + + is_true = !!(pattern_data & (1 << (7 - ((chips->bitblt_running.bitblt.destination_addr + chips->bitblt_running.x) & 7)))); + + if (!is_true && (chips->bitblt_running.bitblt.bitblt_control & (1 << 17))) { + if (chips->bitblt_running.bytes_per_pixel == 2) { + chips->bitblt_running.bitblt.destination_addr <<= 1; + chips->bitblt_running.bitblt.destination_addr |= orig_dest_addr_bit; + } + return; + } + + pattern_pixel = is_true ? pattern_fg : pattern_bg; + + pattern_pixel &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; + } else { + if (chips->bitblt_running.bytes_per_pixel == 1) { + pattern_pixel = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7) + + (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7), chips); + } + if (chips->bitblt_running.bytes_per_pixel == 2) { + pattern_pixel = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + (2 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (2 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)), chips); + + pattern_pixel |= chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + (2 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (2 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)) + 1, chips) << 8; + } + if (chips->bitblt_running.bytes_per_pixel == 3) { + pattern_pixel = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + (4 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (3 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)), chips); + + pattern_pixel |= chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + (4 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (3 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)) + 1, chips) << 8; + + pattern_pixel |= chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + (4 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (3 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)) + 2, chips) << 16; + } + } + if (chips->bitblt_running.bytes_per_pixel == 2) { + chips->bitblt_running.bitblt.destination_addr <<= 1; + chips->bitblt_running.bitblt.destination_addr |= orig_dest_addr_bit; + } + + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 14)) { + switch ((chips->bitblt_running.bitblt.bitblt_control >> 15) & 3) { + case 1: + case 3: + { + uint32_t color_key = (chips->bitblt_running.bitblt.monochrome_source_expansion_color_reg_select) + ? chips->bitblt_running.bitblt.source_key_bg + : chips->bitblt_running.bitblt.pattern_source_key_bg; + color_key &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; + + if (!!(color_key == dest_pixel) == !!(chips->bitblt_running.bitblt.bitblt_control & (1 << 16))) { + return; + } + + break; + } + } + } + + switch (chips->bitblt_running.bytes_per_pixel) { + case 1: /* 8 bits-per-pixel. */ + { + chips_69000_do_rop_8bpp_patterned((uint8_t*)&dest_pixel, pattern_pixel, pixel, chips->bitblt_running.bitblt.bitblt_control & 0xFF); + break; + } + case 2: /* 16 bits-per-pixel. */ + { + chips_69000_do_rop_16bpp_patterned((uint16_t*)&dest_pixel, pattern_pixel, pixel, chips->bitblt_running.bitblt.bitblt_control & 0xFF); + break; + } + case 3: /* 24 bits-per-pixel. */ + { + chips_69000_do_rop_24bpp_patterned((uint32_t*)&dest_pixel, pattern_pixel, pixel, chips->bitblt_running.bitblt.bitblt_control & 0xFF); + break; + } + } + + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 14)) { + switch ((chips->bitblt_running.bitblt.bitblt_control >> 15) & 3) { + case 0: + case 2: + { + uint32_t color_key = (chips->bitblt_running.bitblt.monochrome_source_expansion_color_reg_select) + ? chips->bitblt_running.bitblt.source_key_bg + : chips->bitblt_running.bitblt.pattern_source_key_bg; + color_key &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; + dest_pixel &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; + + if (!!(color_key == dest_pixel) == !!(chips->bitblt_running.bitblt.bitblt_control & (1 << 16))) { + return; + } + + break; + } + } + } + + switch (chips->bitblt_running.bytes_per_pixel) { + case 1: /* 8 bits-per-pixel. */ + { + chips_69000_writeb_linear(dest_addr, dest_pixel & 0xFF, chips); + break; + } + case 2: /* 16 bits-per-pixel. */ + { + chips_69000_writeb_linear(dest_addr, dest_pixel & 0xFF, chips); + chips_69000_writeb_linear(dest_addr + 1, (dest_pixel >> 8) & 0xFF, chips); + break; + } + case 3: /* 24 bits-per-pixel. */ + { + chips_69000_writeb_linear(dest_addr, dest_pixel & 0xFF, chips); + chips_69000_writeb_linear(dest_addr + 1, (dest_pixel >> 8) & 0xFF, chips); + chips_69000_writeb_linear(dest_addr + 2, (dest_pixel >> 16) & 0xFF, chips); + break; + } + } +} + +void +chips_69000_process_mono_bit(chips_69000_t* chips, uint8_t val) +{ + uint32_t pixel = 0x0; + uint8_t is_true = !!val; + uint32_t source_fg = chips->bitblt_running.bitblt.pattern_source_key_fg; + uint32_t source_bg = chips->bitblt_running.bitblt.pattern_source_key_bg; + + if (!chips->engine_active) + return; + + if (chips->bitblt_running.bitblt.monochrome_source_expansion_color_reg_select) { + source_fg = chips->bitblt_running.bitblt.source_key_fg; + source_bg = chips->bitblt_running.bitblt.source_key_bg; + } + + if (chips->bitblt_running.bitblt.monochrome_source_initial_discard) { + chips->bitblt_running.bitblt.monochrome_source_initial_discard--; + return; + } + + if (chips->bitblt_running.mono_bits_skip_left) { + chips->bitblt_running.mono_bits_skip_left--; + return; + } + + if (!is_true && (chips->bitblt_running.bitblt.bitblt_control & (1 << 13))) { + goto advance; + } + pixel = is_true ? source_fg : source_bg; + pixel &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; + + chips_69000_process_pixel(chips, pixel); + +advance: + chips->bitblt_running.x += chips->bitblt_running.x_dir; + chips->bitblt_running.count_x += 1; + if (chips->bitblt_running.count_x >= chips->bitblt_running.actual_destination_width) { + chips->bitblt_running.count_y += 1; + chips->bitblt_running.y += chips->bitblt_running.y_dir * 1; + chips->bitblt_running.count_x = 0; + chips->bitblt_running.x = 0; + chips->bitblt_running.mono_bits_skip_left = chips->bitblt_running.bitblt.monochrome_source_left_clip; + if (chips->bitblt_running.count_y >= (chips->bitblt_running.actual_destination_height)) + chips_69000_bitblt_interrupt(chips); + } +} + +void chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data); + +void +chips_69000_setup_bitblt(chips_69000_t* chips) +{ + chips->engine_active = 1; + + memset(&chips->bitblt_running, 0, sizeof(chips->bitblt_running)); + chips->bitblt_running.bitblt = chips->bitblt; + chips->bitblt_running.actual_source_height = chips->bitblt.destination_height; + chips->bitblt_running.actual_destination_height = chips->bitblt.destination_height; + chips->bitblt_running.count_x = chips->bitblt_running.count_y = 0; + chips->bitblt_running.bytes_written = 0; + chips->bitblt_running.bytes_counter = 0; + chips->bitblt_running.bytes_in_line_written = 0; + chips->bitblt_running.bytes_skip = 0; + chips->bitblt_running.mono_bytes_pitch = 0; + chips->bitblt_running.mono_bits_skip_left = 0; + int orig_cycles = cycles; + + if (chips->bitblt.bitblt_control & (1 << 23)) { + chips->bitblt_running.bytes_per_pixel = 1 + ((chips->bitblt.bitblt_control >> 24) & 3); + } else { + chips->bitblt_running.bytes_per_pixel = 1 + ((chips->ext_regs[0x20] >> 4) & 3); + } + + chips->bitblt_running.actual_destination_width = chips->bitblt_running.bitblt.destination_width / chips->bitblt_running.bytes_per_pixel; + + chips->bitblt_running.x = 0; + chips->bitblt_running.y = 0; + + switch ((chips->bitblt_running.bitblt.bitblt_control >> 8) & 3) { + case 0: + chips->bitblt_running.x_dir = 1; + chips->bitblt_running.y_dir = 1; + break; + case 1: + chips->bitblt_running.x_dir = -1; + chips->bitblt_running.y_dir = 1; + if (!(chips->bitblt_running.bitblt.bitblt_control & (1 << 10))) + chips->bitblt_running.bitblt.source_addr -= (chips->bitblt_running.bytes_per_pixel - 1); + chips->bitblt_running.bitblt.destination_addr -= (chips->bitblt_running.bytes_per_pixel - 1); + break; + case 2: + chips->bitblt_running.x_dir = 1; + chips->bitblt_running.y_dir = -1; + break; + case 3: + chips->bitblt_running.x_dir = -1; + chips->bitblt_running.y_dir = -1; + if (!(chips->bitblt_running.bitblt.bitblt_control & (1 << 10))) + chips->bitblt_running.bitblt.source_addr -= (chips->bitblt_running.bytes_per_pixel - 1); + chips->bitblt_running.bitblt.destination_addr -= (chips->bitblt_running.bytes_per_pixel - 1); + break; + } + + /* Drawing is pointless if monochrome pattern is enabled, monochrome write-masking is enabled and solid pattern is enabled. */ + if ((chips->bitblt_running.bitblt.bitblt_control & (1 << 17)) + && (chips->bitblt_running.bitblt.bitblt_control & (1 << 18)) + && (chips->bitblt_running.bitblt.bitblt_control & (1 << 19))) { + chips_69000_bitblt_interrupt(chips); + return; + } + +#if 0 + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { + pclog("C&T: Monochrome blit (monochrome_source_alignment = %d, " + "monochrome left clip = %d, " + "monochrome right clip = %d, " + "monochrome initial discard = %d, " + "destination_width = %d, destination_height = %d)\n", chips->bitblt_running.bitblt.monochrome_source_alignment, + chips->bitblt_running.bitblt.monochrome_source_left_clip, + chips->bitblt_running.bitblt.monochrome_source_right_clip, + chips->bitblt_running.bitblt.monochrome_source_initial_discard, + chips->bitblt_running.bitblt.destination_width, + chips->bitblt_running.bitblt.destination_height); + } +#endif + + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 10)) { + chips->bitblt_running.bitblt.source_addr &= 7; + if (!(chips->bitblt_running.bitblt.bitblt_control & (1 << 12))) { + /* Yes, the NT 4.0 and Linux drivers will send this many amount of bytes to the video adapter on quadword-boundary-crossing image blits. + This weird calculation is intended and deliberate. + */ + if ((chips->bitblt_running.bitblt.source_addr + (chips->bitblt_running.bitblt.destination_width)) > ((chips->bitblt_running.bitblt.destination_width + 7) & ~7)) + chips->bitblt_running.bytes_skip = 8 + (((chips->bitblt_running.bitblt.destination_width + 7) & ~7) - chips->bitblt_running.bitblt.destination_width); + } else { + chips->bitblt_running.mono_bits_skip_left = chips->bitblt_running.bitblt.monochrome_source_left_clip; + + if (chips->bitblt_running.bitblt.monochrome_source_alignment == 5) + chips->bitblt_running.bitblt.monochrome_source_alignment = 0; + + if (chips->bitblt_running.bitblt.monochrome_source_alignment == 0) { + chips->bitblt_running.mono_bytes_pitch = ((chips->bitblt_running.actual_destination_width + chips->bitblt_running.bitblt.monochrome_source_left_clip + 63) & ~63) / 8; + } + } + + return; + } + + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { + uint32_t source_addr = chips->bitblt_running.bitblt.source_addr; + + while (chips->engine_active) { + switch (chips->bitblt_running.bitblt.monochrome_source_alignment) { + case 0: /* Source-span aligned. */ + { + /* Note: This value means quadword-alignment when BitBLT port is the source. */ + /* TODO: This is handled purely on a best case basis. */ + uint32_t orig_count_y = chips->bitblt_running.count_y; + uint32_t orig_source_addr = chips->bitblt_running.bitblt.source_addr; + while (orig_count_y == chips->bitblt_running.count_y) { + int i = 0; + uint8_t data = chips_69000_readb_linear(orig_source_addr, chips); + orig_source_addr++; + for (i = 0; i < 8; i++) { + chips_69000_process_mono_bit(chips, !!(data & (1 << (7 - i)))); + if (orig_count_y != chips->bitblt_running.count_y) { + break; + } + } + if ((source_addr + chips->bitblt_running.bitblt.source_span) == orig_source_addr) + break; + } + + source_addr = chips->bitblt_running.bitblt.source_addr + chips->bitblt_running.bitblt.source_span; + chips->bitblt_running.bitblt.source_addr = source_addr; + break; + } + case 1: /* Bit-aligned */ + case 2: /* Byte-aligned */ + { + uint32_t data = chips_69000_readb_linear(source_addr, chips); + chips_69000_bitblt_write(chips, data & 0xFF); + source_addr += 1; + break; + } + case 3: /* Word-aligned*/ + { + uint32_t data = chips_69000_readw_linear(source_addr, chips); + chips_69000_bitblt_write(chips, data & 0xFF); + chips_69000_bitblt_write(chips, (data >> 8) & 0xFF); + source_addr += 2; + break; + } + case 4: /* Doubleword-aligned*/ + { + uint32_t data = chips_69000_readl_linear(source_addr, chips); + chips_69000_bitblt_write(chips, data & 0xFF); + chips_69000_bitblt_write(chips, (data >> 8) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 16) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 24) & 0xFF); + source_addr += 4; + break; + } + case 5: /* Quadword-aligned*/ + { + uint64_t data = (uint64_t)chips_69000_readl_linear(source_addr, chips) | ((uint64_t)chips_69000_readl_linear(source_addr + 4, chips) << 32ull); + chips_69000_bitblt_write(chips, data & 0xFF); + chips_69000_bitblt_write(chips, (data >> 8) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 16) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 24) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 32ull) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 40ull) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 48ull) & 0xFF); + chips_69000_bitblt_write(chips, (data >> 56ull) & 0xFF); + source_addr += 8; + break; + } + } + } + return; + } + + do { + do { + uint32_t pixel = 0; + uint32_t source_addr = chips->bitblt_running.bitblt.source_addr + (chips->bitblt_running.y * chips->bitblt.source_span) + (chips->bitblt_running.x * chips->bitblt_running.bytes_per_pixel); + + switch (chips->bitblt_running.bytes_per_pixel) { + case 1: /* 8 bits-per-pixel. */ + { + pixel = chips_69000_readb_linear(source_addr, chips); + break; + } + case 2: /* 16 bits-per-pixel. */ + { + pixel = chips_69000_readb_linear(source_addr, chips); + pixel |= chips_69000_readb_linear(source_addr + 1, chips) << 8; + break; + } + case 3: /* 24 bits-per-pixel. */ + { + pixel = chips_69000_readb_linear(source_addr, chips); + pixel |= chips_69000_readb_linear(source_addr + 1, chips) << 8; + pixel |= chips_69000_readb_linear(source_addr + 2, chips) << 16; + break; + } + } + + chips_69000_process_pixel(chips, pixel); + + chips->bitblt_running.x += chips->bitblt_running.x_dir; + } while ((++chips->bitblt_running.count_x) < chips->bitblt_running.actual_destination_width); + + chips->bitblt_running.y += chips->bitblt_running.y_dir; + chips->bitblt_running.count_x = 0; + chips->bitblt_running.x = 0; + } while ((++chips->bitblt_running.count_y) < chips->bitblt_running.actual_destination_height); + cycles = orig_cycles; + chips_69000_bitblt_interrupt(chips); +} + +void +chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { + + if (!chips->engine_active) { + return; + } + + if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { + int orig_cycles = cycles; + chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; + if (chips->bitblt_running.bitblt.monochrome_source_alignment == 1) { + uint8_t val = chips->bitblt_running.bytes_port[0]; + int i = 0; + chips->bitblt_running.bytes_written = 0; + for (i = 0; i < 8; i++) { + chips_69000_process_mono_bit(chips, !!(val & (1 << (7 - i)))); + } + } else if (chips->bitblt_running.bitblt.monochrome_source_alignment == 0 && chips->bitblt_running.mono_bytes_pitch && chips->bitblt_running.mono_bytes_pitch == chips->bitblt_running.bytes_written) { + int orig_count_y = chips->bitblt_running.count_y; + int i = 0, j = 0; + chips->bitblt_running.bytes_written = 0; + + for (j = 0; j < chips->bitblt_running.mono_bytes_pitch; j++) { + for (i = 0; i < 8; i++) { + chips_69000_process_mono_bit(chips, !!(chips->bitblt_running.bytes_port[j] & (1 << (7 - i)))); + if (orig_count_y != chips->bitblt_running.count_y) { + cycles = orig_cycles; + return; + } + } + } + } + else if ((chips->bitblt_running.bitblt.monochrome_source_alignment == 0 && !chips->bitblt_running.mono_bytes_pitch) + || chips->bitblt_running.bitblt.monochrome_source_alignment == 2) { + int orig_count_y = chips->bitblt_running.count_y; + int i = 0; + uint8_t val = chips->bitblt_running.bytes_port[0]; + chips->bitblt_running.bytes_written = 0; + + for (i = 0; i < 8; i++) { + chips_69000_process_mono_bit(chips, !!(val & (1 << (7 - i)))); + if (orig_count_y != chips->bitblt_running.count_y && chips->bitblt_running.bitblt.monochrome_source_alignment != 1) { + cycles = orig_cycles; + return; + } + } + } else if (chips->bitblt_running.bitblt.monochrome_source_alignment == 3 + && chips->bitblt_running.bytes_written == 2) { + int orig_count_y = chips->bitblt_running.count_y; + int i = 0; + uint16_t val = (chips->bitblt_running.bytes_port[1]) | (chips->bitblt_running.bytes_port[0] << 8); + chips->bitblt_running.bytes_written = 0; + + for (i = 0; i < 16; i++) { + chips_69000_process_mono_bit(chips, !!(val & (1 << (15 - i)))); + if (orig_count_y != chips->bitblt_running.count_y) { + cycles = orig_cycles; + return; + } + } + } else if (chips->bitblt_running.bitblt.monochrome_source_alignment == 4 + && chips->bitblt_running.bytes_written == 4) { + int orig_count_y = chips->bitblt_running.count_y; + int i = 0; + uint32_t val = chips->bitblt_running.bytes_port[3] | (chips->bitblt_running.bytes_port[2] << 8) | (chips->bitblt_running.bytes_port[1] << 16) | (chips->bitblt_running.bytes_port[0] << 24); + chips->bitblt_running.bytes_written = 0; + + for (i = 0; i < 32; i++) { + chips_69000_process_mono_bit(chips, !!(val & (1 << (31 - i)))); + if (orig_count_y != chips->bitblt_running.count_y) { + cycles = orig_cycles; + return; + } + } + } else if (chips->bitblt_running.bitblt.monochrome_source_alignment == 5 && chips->bitblt_running.bytes_written == 8) { + int orig_count_y = chips->bitblt_running.count_y; + int i = 0; + uint64_t val = 0; + + val |= chips->bitblt_running.bytes_port[7]; + val |= chips->bitblt_running.bytes_port[6] << 8; + val |= chips->bitblt_running.bytes_port[5] << 16; + val |= chips->bitblt_running.bytes_port[4] << 24; + val |= (uint64_t)chips->bitblt_running.bytes_port[3] << 32ULL; + val |= (uint64_t)chips->bitblt_running.bytes_port[2] << 40ULL; + val |= (uint64_t)chips->bitblt_running.bytes_port[1] << 48ULL; + val |= (uint64_t)chips->bitblt_running.bytes_port[0] << 56ULL; + + chips->bitblt_running.bytes_written = 0; + + for (i = 0; i < 64; i++) { + chips_69000_process_mono_bit(chips, !!(val & (1 << (63 - i)))); + if (orig_count_y != chips->bitblt_running.count_y) { + cycles = orig_cycles; + return; + } + } + } + cycles = orig_cycles; + return; + } + + chips->bitblt_running.bytes_counter++; + if (chips->bitblt_running.bytes_counter <= (chips->bitblt_running.bitblt.source_addr)) { + return; + } + chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; + if (chips->bitblt_running.bytes_written == chips->bitblt_running.bytes_per_pixel) { + int orig_cycles = cycles; + uint32_t source_pixel = chips->bitblt_running.bytes_port[0]; + chips->bitblt_running.bytes_written = 0; + if (chips->bitblt_running.bytes_per_pixel >= 2) + source_pixel |= (chips->bitblt_running.bytes_port[1] << 8); + if (chips->bitblt_running.bytes_per_pixel >= 3) + source_pixel |= (chips->bitblt_running.bytes_port[2] << 16); + + chips->bitblt_running.bytes_in_line_written += chips->bitblt_running.bytes_per_pixel; + + chips_69000_process_pixel(chips, source_pixel); + cycles = orig_cycles; + chips->bitblt_running.x += chips->bitblt_running.x_dir; + + if (chips->bitblt_running.bytes_in_line_written >= chips->bitblt_running.bitblt.destination_width) { + if (chips->bitblt_running.bytes_skip) { + chips->bitblt_running.bitblt.source_addr = chips->bitblt_running.bytes_skip; + } + else if (chips->bitblt_running.bitblt.destination_width & 7) + chips->bitblt_running.bitblt.source_addr = 8 - ((chips->bitblt_running.bitblt.destination_width) & 7); + else + chips->bitblt_running.bitblt.source_addr = 0; + + chips->bitblt_running.y += chips->bitblt_running.y_dir; + chips->bitblt_running.count_y++; + chips->bitblt_running.bytes_counter = 0; + chips->bitblt_running.bytes_in_line_written = 0; + + chips->bitblt_running.count_x = 0; + chips->bitblt_running.x = 0; + + if (chips->bitblt_running.count_y >= chips->bitblt_running.actual_destination_height) { + chips_69000_bitblt_interrupt(chips); + return; + } + } + } +} + +uint8_t +chips_69000_read_ext_reg(chips_69000_t* chips) +{ + uint8_t index = chips->ext_index; + uint8_t val = chips->ext_regs[index]; + switch (index) { + case 0x00: + val = 0x2C; + break; + case 0x01: + val = 0x10; + break; + case 0x02: + val = 0xC0; + break; + case 0x03: + val = 0x00; + break; + case 0x04: + val = 0x62; + break; + case 0x05: + val = 0x00; + break; + case 0x06: + val = chips->linear_mapping.base >> 24; + break; + case 0x08: + val = 0x02; + break; + case 0x0A: + val = chips->ext_regs[index] & 0x37; + break; + case 0x20: + val &= ~1; + val |= !!chips->engine_active; + /* TODO: Handle BitBLT reset, if required. */ + break; + case 0x63: + { + val = chips->ext_regs[index]; + if (!(chips->ext_regs[0x62] & 0x8)) + val = (val & ~8) | (i2c_gpio_get_scl(chips->i2c_ddc) << 3); + + if (!(chips->ext_regs[0x62] & 0x4)) + val = (val & ~4) | (i2c_gpio_get_sda(chips->i2c_ddc) << 2); + + break; + } + case 0x70: + val = 0x3; + break; + case 0x71: + val = 0b01101000; + break; + case 0xD0: + val |= 1; + break; + } + return val; +} + +void +chips_69000_write_ext_reg(chips_69000_t* chips, uint8_t val) +{ + switch (chips->ext_index) { + case 0xA: + chips->ext_regs[chips->ext_index] = val & 0x37; + chips_69000_recalc_banking(chips); + break; + case 0xB: + chips->ext_regs[chips->ext_index] = val & 0xD; + break; + case 0xE: + chips->ext_regs[chips->ext_index] = val & 0x7f; + chips_69000_recalc_banking(chips); + break; + case 0x9: + chips->ext_regs[chips->ext_index] = val & 0x3; + svga_recalctimings(&chips->svga); + break; + case 0x40: + chips->ext_regs[chips->ext_index] = val & 0x3; + chips_69000_recalc_banking(chips); + svga_recalctimings(&chips->svga); + break; + case 0x60: + chips->ext_regs[chips->ext_index] = val & 0x43; + break; + case 0x20: + chips->ext_regs[chips->ext_index] = val & 0x3f; + break; + case 0x61: + chips->ext_regs[chips->ext_index] = val & 0x7f; + svga_recalctimings(&chips->svga); + break; + case 0x62: + chips->ext_regs[chips->ext_index] = val & 0x9C; + break; + case 0x63: + { + uint8_t scl = 0, sda = 0; + if (chips->ext_regs[0x62] & 0x8) + scl = !!(val & 8); + else + scl = i2c_gpio_get_scl(chips->i2c_ddc); + + if (chips->ext_regs[0x62] & 0x4) + sda = !!(val & 4); + else + scl = i2c_gpio_get_sda(chips->i2c_ddc); + + i2c_gpio_set(chips->i2c_ddc, scl, sda); + + chips->ext_regs[chips->ext_index] = val & 0x9F; + break; + } + case 0x67: + chips->ext_regs[chips->ext_index] = val & 0x2; + break; + case 0x80: + chips->ext_regs[chips->ext_index] = val & 0xBF; + svga_set_ramdac_type(&chips->svga, (val & 0x80) ? RAMDAC_8BIT : RAMDAC_6BIT); + break; + case 0x81: + chips->ext_regs[chips->ext_index] = val & 0x1f; + svga_recalctimings(&chips->svga); + break; + case 0x82: + chips->ext_regs[chips->ext_index] = val & 0xf; + chips->svga.lut_map = !!(val & 0x8); + break; + case 0xA0: + chips->ext_regs[chips->ext_index] = val; + chips->svga.hwcursor.ena = ((val & 7) == 0b101) || ((val & 7) == 0b1); + chips->svga.hwcursor.cur_xsize = chips->svga.hwcursor.cur_ysize = ((val & 7) == 0b1) ? 32 : 64; + break; + case 0xA2: + chips->ext_regs[chips->ext_index] = val; + chips->svga.hwcursor.addr = (val << 8) | ((chips->ext_regs[0xA3] & 0x3F) << 16); + break; + case 0xA3: + chips->ext_regs[chips->ext_index] = val; + chips->svga.hwcursor.addr = ((chips->ext_regs[0xA2]) << 8) | ((val & 0x3F) << 16); + break; + case 0xA4: + chips->ext_regs[chips->ext_index] = val; + chips->svga.hwcursor.x = val | (chips->ext_regs[0xA5] & 7) << 8; + if (chips->ext_regs[0xA5] & 0x80) + chips->svga.hwcursor.x = -chips->svga.hwcursor.x; + break; + case 0xA5: + chips->ext_regs[chips->ext_index] = val; + chips->svga.hwcursor.x = chips->ext_regs[0xA4] | (val & 7) << 8; + if (chips->ext_regs[0xA5] & 0x80) + chips->svga.hwcursor.x = -chips->svga.hwcursor.x; + break; + case 0xA6: + chips->ext_regs[chips->ext_index] = val; + chips->svga.hwcursor.y = val | (chips->ext_regs[0xA7] & 7) << 8; + if (chips->ext_regs[0xA7] & 0x80) { + chips->svga.hwcursor.y = -chips->svga.hwcursor.y; + } + break; + case 0xA7: + chips->ext_regs[chips->ext_index] = val; + chips->svga.hwcursor.y = chips->ext_regs[0xA6] | (val & 7) << 8; + if (chips->ext_regs[0xA7] & 0x80) { + chips->svga.hwcursor.y = -chips->svga.hwcursor.y; + } + break; + case 0xC8: + case 0xC9: + case 0xCB: + chips->ext_regs[chips->ext_index] = val; + svga_recalctimings(&chips->svga); + break; + case 0xD2: + break; + default: + chips->ext_regs[chips->ext_index] = val; + break; + } +} + +void +chips_69000_out(uint16_t addr, uint8_t val, void *p) +{ + chips_69000_t *chips = (chips_69000_t *) p; + svga_t *svga = &chips->svga; + uint8_t old, index; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x3c0: + if (!(chips->ext_regs[0x09] & 0x02)) + break; + svga->attraddr = val & 31; + if ((val & 0x20) != svga->attr_palette_enable) { + svga->fullchange = 3; + svga->attr_palette_enable = val & 0x20; + svga_recalctimings(svga); + } + return; + case 0x3c1: + if ((chips->ext_regs[0x09] & 0x02)) + { + svga->attrff = 1; + svga_out(addr, val, svga); + svga->attrff = 0; + return; + } + break; + case 0x3c9: + if (!(chips->ext_regs[0x80] & 0x01)) + break; + if (svga->adv_flags & FLAG_RAMDAC_SHIFT) + val <<= 2; + svga->fullchange = svga->monitor->mon_changeframecount; + switch (svga->dac_pos) { + case 0: + svga->dac_r = val; + svga->dac_pos++; + break; + case 1: + svga->dac_g = val; + svga->dac_pos++; + break; + case 2: + index = svga->dac_addr & 7; + chips->cursor_palette[index].r = svga->dac_r; + chips->cursor_palette[index].g = svga->dac_g; + chips->cursor_palette[index].b = val; + if (svga->ramdac_type == RAMDAC_8BIT) + chips->cursor_pallook[index] = makecol32(chips->cursor_palette[index].r, chips->cursor_palette[index].g, chips->cursor_palette[index].b); + else + chips->cursor_pallook[index] = makecol32(video_6to8[chips->cursor_palette[index].r & 0x3f], video_6to8[chips->cursor_palette[index].g & 0x3f], video_6to8[chips->cursor_palette[index].b & 0x3f]); + svga->dac_pos = 0; + svga->dac_addr = (svga->dac_addr + 1) & 255; + break; + } + return; + case 0x3c5: + svga_out(addr, val, svga); + chips_69000_recalc_banking(chips); + return; + case 0x3D0: + chips->flat_panel_index = val; + return; + case 0x3D1: + return chips_69000_write_flat_panel(chips, val); + case 0x3D2: + chips->mm_index = val; + return; + case 0x3D3: + return chips_69000_write_multimedia(chips, val); + case 0x3D4: + svga->crtcreg = val & 0xff; + return; + case 0x3D5: + if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + old = svga->crtc[svga->crtcreg]; + svga->crtc[svga->crtcreg] = val; + if (old != val) { + if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { + if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { + svga->fullchange = 3; + svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + } else { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + } + break; + case 0x3B6: + case 0x3D6: + chips->ext_index = val; + return; + case 0x3B7: + case 0x3D7: + return chips_69000_write_ext_reg(chips, val); + + } + svga_out(addr, val, svga); +} + +uint8_t +chips_69000_in(uint16_t addr, void *p) +{ + chips_69000_t *chips = (chips_69000_t *) p; + svga_t *svga = &chips->svga; + uint8_t temp = 0, index; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x3C5: + return svga->seqregs[svga->seqaddr]; + case 0x3c9: + if (!(chips->ext_regs[0x80] & 0x01)) { + temp = svga_in(addr, svga); + break; + } + index = (svga->dac_addr - 1) & 7; + switch (svga->dac_pos) { + case 0: + svga->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + temp = chips->cursor_palette[index].r; + else + temp = chips->cursor_palette[index].r & 0x3f; + break; + case 1: + svga->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + temp = chips->cursor_palette[index].g; + else + temp = chips->cursor_palette[index].g & 0x3f; + break; + case 2: + svga->dac_pos = 0; + svga->dac_addr = (svga->dac_addr + 1) & 255; + if (svga->ramdac_type == RAMDAC_8BIT) + temp = chips->cursor_palette[index].b; + else + temp = chips->cursor_palette[index].b & 0x3f; + break; + } + if (svga->adv_flags & FLAG_RAMDAC_SHIFT) + temp >>= 2; + break; + case 0x3D0: + return chips->flat_panel_index; + case 0x3D1: + return chips_69000_read_flat_panel(chips); + case 0x3D2: + return chips->mm_index; + case 0x3D3: + return chips_69000_read_multimedia(chips); + case 0x3D4: + temp = svga->crtcreg; + break; + case 0x3D5: + if (svga->crtcreg & 0x20) + temp = 0xff; + else + temp = svga->crtc[svga->crtcreg]; + break; + case 0x3B6: + case 0x3D6: + temp = chips->ext_index; + break; + case 0x3B7: + case 0x3D7: + temp = chips_69000_read_ext_reg(chips); + break; + default: + temp = svga_in(addr, svga); + break; + } + return temp; +} + +static uint8_t +chips_69000_pci_read(int func, int addr, void *p) +{ + chips_69000_t *chips = (chips_69000_t *) p; + + { + switch (addr) { + case 0x00: + return 0x2C; + case 0x01: + return 0x10; + case 0x02: + return 0xC0; + case 0x03: + return 0x00; + case 0x04: + return (chips->pci_conf_status & 0b11100011) | 0x80; + case 0x06: + return 0x80; + case 0x07: + return 0x02; + case 0x08: + case 0x09: + case 0x0a: + return 0x00; + case 0x0b: + return 0x03; + case 0x13: + return chips->linear_mapping.base >> 24; + case 0x30: + return chips->pci_rom_enable & 0x1; + case 0x31: + return 0x0; + case 0x32: + return chips->rom_addr & 0xFF; + case 0x33: + return (chips->rom_addr & 0xFF00) >> 8; + case 0x3c: + return chips->pci_line_interrupt; + case 0x3d: + return 0x01; + case 0x2C: + case 0x2D: + case 0x6C: + case 0x6D: + return (chips->subsys_vid >> ((addr & 1) * 8)) & 0xFF; + case 0x2E: + case 0x2F: + case 0x6E: + case 0x6F: + return (chips->subsys_pid >> ((addr & 1) * 8)) & 0xFF; + default: + return 0x00; + } + } +} + +static void +chips_69000_pci_write(int func, int addr, uint8_t val, void *p) +{ + chips_69000_t *chips = (chips_69000_t *) p; + + { + switch (addr) { + case 0x04: + { + chips->pci_conf_status = val; + io_removehandler(0x03c0, 0x0020, chips_69000_in, NULL, NULL, chips_69000_out, NULL, NULL, chips); + mem_mapping_disable(&chips->linear_mapping); + mem_mapping_disable(&chips->svga.mapping); + if (chips->pci_conf_status & PCI_COMMAND_IO) { + io_sethandler(0x03c0, 0x0020, chips_69000_in, NULL, NULL, chips_69000_out, NULL, NULL, chips); + } + if (chips->pci_conf_status & PCI_COMMAND_MEM) { + mem_mapping_enable(&chips->svga.mapping); + if (chips->linear_mapping.base) + mem_mapping_enable(&chips->linear_mapping); + } + break; + } + case 0x13: + { + if (!chips->linear_mapping.enable) { + chips->linear_mapping.base = val << 24; + break; + } + mem_mapping_set_addr(&chips->linear_mapping, val << 24, (1 << 24)); + break; + } + case 0x3c: + chips->pci_line_interrupt = val; + break; + case 0x30: + if (chips->on_board) break; + chips->pci_rom_enable = val & 0x1; + mem_mapping_disable(&chips->bios_rom.mapping); + if (chips->pci_rom_enable & 1) { + mem_mapping_set_addr(&chips->bios_rom.mapping, chips->rom_addr << 16, 0x10000); + } + break; + case 0x32: + if (chips->on_board) break; + chips->rom_addr &= ~0xFF; + chips->rom_addr |= val & 0xFC; + if (chips->pci_rom_enable & 1) { + mem_mapping_set_addr(&chips->bios_rom.mapping, chips->rom_addr << 16, 0x10000); + } + break; + case 0x33: + if (chips->on_board) break; + chips->rom_addr &= ~0xFF00; + chips->rom_addr |= (val << 8); + if (chips->pci_rom_enable & 1) { + mem_mapping_set_addr(&chips->bios_rom.mapping, chips->rom_addr << 16, 0x10000); + } + break; + case 0x6C: + case 0x6D: + chips->subsys_vid_b[addr & 1] = val; + break; + case 0x6E: + case 0x6F: + chips->subsys_pid_b[addr & 1] = val; + break; + } + } +} + +uint8_t +chips_69000_readb_mmio(uint32_t addr, chips_69000_t* chips) +{ + addr &= 0xFFF; + switch (addr & 0xFFF) { + case 0x00 ... 0x2B: + if (addr == 0x13) { + return (chips->bitblt_regs_b[addr & 0xFF] & 0x7F) | (chips->engine_active ? 0x80 : 0x00); + } + return chips->bitblt_regs_b[addr & 0xFF]; + case 0x3b: + return (chips->engine_active ? 0x80 : 0x00); + case 0x38: + return 0x7F; + case 0x600 ... 0x60F: + return chips->mem_regs_b[addr & 0xF]; + case 0x768: + return chips_69000_in(0x3b4, chips); + case 0x769: + return chips_69000_in(0x3b5, chips); + case 0x774: + return chips_69000_in(0x3ba, chips); + case 0x780: + return chips_69000_in(0x3c0, chips); + case 0x781: + return chips_69000_in(0x3c1, chips); + case 0x784: + return chips_69000_in(0x3c2, chips); + case 0x788: + return chips_69000_in(0x3c4, chips); + case 0x789: + return chips_69000_in(0x3c5, chips); + case 0x78C: + return chips_69000_in(0x3c6, chips); + case 0x78D: + return chips_69000_in(0x3c7, chips); + case 0x790: + return chips_69000_in(0x3c8, chips); + case 0x791: + return chips_69000_in(0x3c9, chips); + case 0x794: + return chips_69000_in(0x3ca, chips); + case 0x798: + return chips_69000_in(0x3cc, chips); + case 0x79C: + return chips_69000_in(0x3ce, chips); + case 0x79D: + return chips_69000_in(0x3cf, chips); + case 0x7A0: + return chips_69000_in(0x3d0, chips); + case 0x7A1: + return chips_69000_in(0x3d1, chips); + case 0x7A4: + return chips_69000_in(0x3d2, chips); + case 0x7A5: + return chips_69000_in(0x3d3, chips); + case 0x7A8: + return chips_69000_in(0x3d4, chips); + case 0x7A9: + return chips_69000_in(0x3d5, chips); + case 0x7AC: + return chips_69000_in(0x3d6, chips); + case 0x7AD: + return chips_69000_in(0x3d7, chips); + case 0x7B4: + return chips_69000_in(0x3da, chips); + } + return 0x00; +} + +uint16_t +chips_69000_readw_mmio(uint32_t addr, chips_69000_t* chips) +{ + addr &= 0xFFF; + switch (addr & 0xFFF) { + default: + return chips_69000_readb_mmio(addr, chips) | (chips_69000_readb_mmio(addr + 1, chips) << 8); + } + return 0xFFFF; +} + +uint32_t +chips_69000_readl_mmio(uint32_t addr, chips_69000_t* chips) +{ + addr &= 0xFFF; + switch (addr & 0xFFF) { + default: + return chips_69000_readw_mmio(addr, chips) | (chips_69000_readw_mmio(addr + 2, chips) << 16); + } + return 0xFFFFFFFF; +} + +void +chips_69000_writeb_mmio(uint32_t addr, uint8_t val, chips_69000_t* chips) +{ + //pclog("C&T Write 0x%X, val = 0x%02X\n", addr, val); + if (addr & 0x10000) { + chips_69000_bitblt_write(chips, val); + return; + } + addr &= 0xFFF; + switch (addr & 0xFFF) { + case 0x00 ... 0x2B: + if (addr <= 0x3) { + //pclog("[%04X:%08X] C&T Write span 0x%X, val = 0x%02X\n", CS, cpu_state.pc, addr, val); + } + chips->bitblt_regs_b[addr & 0xFF] = val; + if ((addr & 0xFFF) == 0x023 && chips->bitblt_regs[0x8] != 0) { + chips_69000_setup_bitblt(chips); + } + break; + default: + pclog("C&T Write (unknown) 0x%X, val = 0x%02X\n", addr, val); + break; + case 0x600 ... 0x60F: + switch (addr & 0xFFF) + { + case 0x600 ... 0x603: + { + chips->mem_regs_b[addr & 0xF] = val; + chips->mem_regs[(addr >> 2) & 0x3] &= 0x80004040; + if (addr == 0x605 || addr == 0x607) + chips_69000_interrupt(chips); + break; + } + + case 0x604 ... 0x607: + { + chips->mem_regs_b[addr & 0xF] &= ~val; + chips->mem_regs[(addr >> 2) & 0x3] &= 0x80004040; + if (addr == 0x605 || addr == 0x607) + chips_69000_interrupt(chips); + break; + } + + case 0x60c ... 0x60f: + { + chips->mem_regs_b[addr & 0xF] = val; + break; + } + + } + chips->mem_regs_b[addr & 0xF] = val; + break; + case 0x768: + chips_69000_out(0x3b4, val, chips); break; + case 0x769: + chips_69000_out(0x3b5, val, chips); break; + case 0x774: + chips_69000_out(0x3ba, val, chips); break; + case 0x780: + chips_69000_out(0x3c0, val, chips); break; + case 0x781: + chips_69000_out(0x3c1, val, chips); break; + case 0x784: + chips_69000_out(0x3c2, val, chips); break; + case 0x788: + chips_69000_out(0x3c4, val, chips); break; + case 0x789: + chips_69000_out(0x3c5, val, chips); break; + case 0x78C: + chips_69000_out(0x3c6, val, chips); break; + case 0x78D: + chips_69000_out(0x3c7, val, chips); break; + case 0x790: + chips_69000_out(0x3c8, val, chips); break; + case 0x791: + chips_69000_out(0x3c9, val, chips); break; + case 0x794: + chips_69000_out(0x3ca, val, chips); break; + case 0x798: + chips_69000_out(0x3cc, val, chips); break; + case 0x79C: + chips_69000_out(0x3ce, val, chips); break; + case 0x79D: + chips_69000_out(0x3cf, val, chips); break; + case 0x7A0: + chips_69000_out(0x3d0, val, chips); break; + case 0x7A1: + chips_69000_out(0x3d1, val, chips); break; + case 0x7A4: + chips_69000_out(0x3d2, val, chips); break; + case 0x7A5: + chips_69000_out(0x3d3, val, chips); break; + case 0x7A8: + chips_69000_out(0x3d4, val, chips); break; + case 0x7A9: + chips_69000_out(0x3d5, val, chips); break; + case 0x7AC: + chips_69000_out(0x3d6, val, chips); break; + case 0x7AD: + chips_69000_out(0x3d7, val, chips); break; + case 0x7B4: + chips_69000_out(0x3da, val, chips); break; + } +} + +void +chips_69000_writew_mmio(uint32_t addr, uint16_t val, chips_69000_t* chips) +{ + if (addr & 0x10000) { + if ((chips->bitblt_running.bitblt.bitblt_control & (1 << 12))) { + //pclog("BitBLT mono 0x%04X\n", val); + } + chips_69000_bitblt_write(chips, val & 0xFF); + chips_69000_bitblt_write(chips, (val >> 8) & 0xFF); + return; + } + addr &= 0xFFF; + switch (addr & 0xFFF) { + default: + chips_69000_writeb_mmio(addr, val, chips); + chips_69000_writeb_mmio(addr + 1, val >> 8, chips); + break; + } +} + +void +chips_69000_writel_mmio(uint32_t addr, uint32_t val, chips_69000_t* chips) +{ + if (addr & 0x10000) { + if ((chips->bitblt_running.bitblt.bitblt_control & (1 << 12))) { + //pclog("BitBLT mono 0x%08X\n", val); + } + chips_69000_bitblt_write(chips, val & 0xFF); + chips_69000_bitblt_write(chips, (val >> 8) & 0xFF); + chips_69000_bitblt_write(chips, (val >> 16) & 0xFF); + chips_69000_bitblt_write(chips, (val >> 24) & 0xFF); + return; + } + addr &= 0xFFF; + switch (addr & 0xFFF) { + default: + chips_69000_writew_mmio(addr, val, chips); + chips_69000_writew_mmio(addr + 2, val >> 16, chips); + break; + } +} + +uint8_t +chips_69000_readb_linear(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t *) p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; + + if (addr & 0x400000) + return chips_69000_readb_mmio(addr, chips); + + return svga_readb_linear(addr & 0x1FFFFF, p); +} + +uint16_t +chips_69000_readw_linear(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t *) p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; + + if (addr & 0x800000) { + if (addr & 0x400000) + return bswap16(chips_69000_readw_mmio(addr, chips)); + + return bswap16(svga_readw_linear(addr & 0x1FFFFF, p)); + } + + if (addr & 0x400000) + return chips_69000_readw_mmio(addr, chips); + + return svga_readw_linear(addr & 0x1FFFFF, p); +} + +uint32_t +chips_69000_readl_linear(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t *) p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; + + if (addr & 0x800000) { + if (addr & 0x400000) + return bswap32(chips_69000_readl_mmio(addr, chips)); + + return bswap32(svga_readl_linear(addr & 0x1FFFFF, p)); + } + + if (addr & 0x400000) + return chips_69000_readl_mmio(addr, chips); + + return svga_readl_linear(addr & 0x1FFFFF, p); +} + +void +chips_69000_writeb_linear(uint32_t addr, uint8_t val, void *p) +{ + svga_t *svga = (svga_t *) p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; + + if (addr & 0x400000) + return chips_69000_writeb_mmio(addr, val, chips); + + svga_writeb_linear(addr & 0x1FFFFF, val, p); +} + +void +chips_69000_writew_linear(uint32_t addr, uint16_t val, void *p) +{ + svga_t *svga = (svga_t *) p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; + + if (addr & 0x800000) + val = bswap16(val); + + if (addr & 0x400000) + return chips_69000_writew_mmio(addr, val, chips); + + svga_writew_linear(addr & 0x1FFFFF, val, p); +} + +void +chips_69000_writel_linear(uint32_t addr, uint32_t val, void *p) +{ + svga_t *svga = (svga_t *) p; + chips_69000_t *chips = (chips_69000_t *) svga->priv; + + if (addr & 0x800000) + val = bswap32(val); + + if (addr & 0x400000) + return chips_69000_writel_mmio(addr, val, chips); + + svga_writel_linear(addr & 0x1FFFFF, val, p); +} + +void +chips_69000_vblank_start(svga_t *svga) +{ + chips_69000_t *chips = (chips_69000_t *) svga->priv; + chips->mem_regs[1] |= 1 << 14; + chips->svga.crtc[0x40] &= ~0x80; + + chips_69000_interrupt(chips); +} + +static void +chips_69000_hwcursor_draw_64x64(svga_t *svga, int displine) +{ + chips_69000_t *chips = (chips_69000_t *) svga->priv; + uint64_t dat[2]; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + + if (svga->interlace && svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; + + dat[1] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr])); + dat[0] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr + 8])); + svga->hwcursor_latch.addr += 16; + + for (uint8_t x = 0; x < 64; x++) { + if (!(dat[1] & (1ULL << 63))) + svga->monitor->target_buffer->line[displine][(offset + svga->x_add) & 2047] = (dat[0] & (1ULL << 63)) ? svga_lookup_lut_ram(svga, chips->cursor_pallook[5]) : svga_lookup_lut_ram(svga, chips->cursor_pallook[4]); + else if (dat[0] & (1ULL << 63)) + svga->monitor->target_buffer->line[displine][(offset + svga->x_add) & 2047] ^= 0xffffff; + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } + + if (svga->interlace && !svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; +} + +static void +chips_69000_hwcursor_draw(svga_t *svga, int displine) +{ + chips_69000_t *chips = (chips_69000_t *) svga->priv; + uint64_t dat[2]; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + + if ((chips->ext_regs[0xa0] & 7) == 0b101) + return chips_69000_hwcursor_draw_64x64(svga, displine); + + if (svga->interlace) { + dat[1] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr])); + dat[0] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr + 8])); + svga->hwcursor_latch.addr += 16; + if (svga->hwcursor_oddeven) { + dat[1] <<= 32ULL; + dat[0] <<= 32ULL; + } + for (uint8_t x = 0; x < 32; x++) { + if (!(dat[1] & (1ULL << 63))) + svga->monitor->target_buffer->line[displine & 2047][(offset + svga->x_add) & 2047] = (dat[0] & (1ULL << 63)) ? svga_lookup_lut_ram(svga, chips->cursor_pallook[5]) : svga_lookup_lut_ram(svga, chips->cursor_pallook[4]); + else if (dat[0] & (1ULL << 63)) + svga->monitor->target_buffer->line[displine & 2047][(offset + svga->x_add) & 2047] ^= 0xffffff; + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } + return; + } + + if ((svga->hwcursor_on & 1)) { + dat[1] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr - 16])); + dat[0] = bswap64(*(uint64_t *) (&svga->vram[(svga->hwcursor_latch.addr - 16) + 8])); + dat[1] <<= 32ULL; + dat[0] <<= 32ULL; + } + else { + dat[1] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr])); + dat[0] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr + 8])); + svga->hwcursor_latch.addr += 16; + } + + for (uint8_t x = 0; x < 32; x++) { + if (!(dat[1] & (1ULL << 63))) + svga->monitor->target_buffer->line[displine & 2047][(offset + svga->x_add) & 2047] = (dat[0] & (1ULL << 63)) ? svga_lookup_lut_ram(svga, chips->cursor_pallook[5]) : svga_lookup_lut_ram(svga, chips->cursor_pallook[4]); + else if (dat[0] & (1ULL << 63)) + svga->monitor->target_buffer->line[displine & 2047][(offset + svga->x_add) & 2047] ^= 0xffffff; + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } +} + +static float +chips_69000_getclock(int clock, void *priv) +{ + const chips_69000_t *chips = (chips_69000_t *) priv; + + if (clock == 0) + return 25175000.0; + if (clock == 1) + return 28322000.0; + + int m = chips->ext_regs[0xc8]; + int n = chips->ext_regs[0xc9]; + int pl = ((chips->ext_regs[0xcb] >> 4) & 7); + + float fvco = 14318181.0 * ((float)(m + 2) / (float)(n + 2)); + if (chips->ext_regs[0xcb] & 4) + fvco *= 4.0; + float fo = fvco / (float)(1 << pl); + + return fo; +} + +uint32_t +chips_69000_conv_16to32(svga_t* svga, uint16_t color, uint8_t bpp) +{ + uint32_t ret = 0x00000000; + + if (svga->lut_map) { + if (bpp == 15) { + uint8_t b = getcolr(svga->pallook[(color & 0x1f) << 3]); + uint8_t g = getcolg(svga->pallook[(color & 0x3e0) >> 2]); + uint8_t r = getcolb(svga->pallook[(color & 0x7c00) >> 7]); + ret = (video_15to32[color] & 0xFF000000) | makecol(r, g, b); + } else { + uint8_t b = getcolr(svga->pallook[(color & 0x1f) << 3]); + uint8_t g = getcolg(svga->pallook[(color & 0x7e0) >> 3]); + uint8_t r = getcolb(svga->pallook[(color & 0xf800) >> 8]); + ret = (video_16to32[color] & 0xFF000000) | makecol(r, g, b); + } + } else + ret = (bpp == 15) ? video_15to32[color] : video_16to32[color]; + + return ret; +} + +static int +chips_69000_line_compare(svga_t* svga) +{ + const chips_69000_t *chips = (chips_69000_t *) svga->priv; + if (chips->ext_regs[0x81] & 0xF) { + return 0; + } + + return 1; +} + +static void * +chips_69000_init(const device_t *info) +{ + chips_69000_t *chips = calloc(1, sizeof(chips_69000_t)); + + /* Appears to have an odd VBIOS size. */ + if (!info->local) { + rom_init(&chips->bios_rom, "roms/video/chips/69000.ROM", 0xc0000, 0x10000, 0xffff, 0x0000, MEM_MAPPING_EXTERNAL); + mem_mapping_disable(&chips->bios_rom.mapping); + } + + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_chips); + + svga_init(info, &chips->svga, chips, 1 << 21, /*2048kb*/ + chips_69000_recalctimings, + chips_69000_in, chips_69000_out, + NULL, + NULL); + + io_sethandler(0x03c0, 0x0020, chips_69000_in, NULL, NULL, chips_69000_out, NULL, NULL, chips); + + pci_add_card(PCI_ADD_VIDEO, chips_69000_pci_read, chips_69000_pci_write, chips, &chips->slot); + + chips->svga.bpp = 8; + chips->svga.miscout = 1; + chips->svga.recalctimings_ex = chips_69000_recalctimings; + chips->svga.vblank_start = chips_69000_vblank_start; + chips->svga.hwcursor_draw = chips_69000_hwcursor_draw; + chips->svga.getclock = chips_69000_getclock; + chips->svga.conv_16to32 = chips_69000_conv_16to32; + chips->svga.line_compare = chips_69000_line_compare; + + mem_mapping_add(&chips->linear_mapping, 0, 0, chips_69000_readb_linear, chips_69000_readw_linear, chips_69000_readl_linear, chips_69000_writeb_linear, chips_69000_writew_linear, chips_69000_writel_linear, NULL, MEM_MAPPING_EXTERNAL, chips); + + chips->quit = 0; + chips->engine_active = 0; + chips->on_board = !!(info->local); + + chips->svga.packed_chain4 = 1; + + timer_add(&chips->decrement_timer, chips_69000_decrement_timer, chips, 0); + timer_on_auto(&chips->decrement_timer, 1000000. / 2000.); + + chips->i2c_ddc = i2c_gpio_init("c&t_69000_mga"); + chips->ddc = ddc_init(i2c_gpio_get_bus(chips->i2c_ddc)); + + chips->flat_panel_regs[0x01] = 1; + + return chips; +} + +static int +chips_69000_available(void) +{ + return rom_present("roms/video/chips/69000.ROM"); +} + +void +chips_69000_close(void *p) +{ + chips_69000_t *chips = (chips_69000_t *) p; + + chips->quit = 1; +// thread_set_event(chips->fifo_event); + // thread_wait(chips->accel_thread); + ddc_close(chips->ddc); + i2c_gpio_close(chips->i2c_ddc); + svga_close(&chips->svga); + + free(chips); +} + +void +chips_69000_speed_changed(void *p) +{ + chips_69000_t *chips = (chips_69000_t *) p; + + svga_recalctimings(&chips->svga); +} + +void +chips_69000_force_redraw(void *p) +{ + chips_69000_t *chips = (chips_69000_t *) p; + + chips->svga.fullchange = changeframecount; +} + +const device_t chips_69000_device = { + .name = "Chips & Technologies B69000", + .internal_name = "c&t_69000", + .flags = DEVICE_PCI, + .local = 0, + .init = chips_69000_init, + .close = chips_69000_close, + .reset = NULL, + { .available = chips_69000_available }, + .speed_changed = chips_69000_speed_changed, + .force_redraw = chips_69000_force_redraw, + .config = NULL +}; + +const device_t chips_69000_onboard_device = { + .name = "Chips & Technologies B69000 (onboard)", + .internal_name = "c&t_69000_onboard", + .flags = DEVICE_PCI, + .local = 1, + .init = chips_69000_init, + .close = chips_69000_close, + .reset = NULL, + { .available = chips_69000_available }, + .speed_changed = chips_69000_speed_changed, + .force_redraw = chips_69000_force_redraw, + .config = NULL +}; diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 168912e9d..bf27a700a 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -809,13 +809,14 @@ gd54xx_out(uint16_t addr, uint8_t val, void *priv) svga->hwcursor.addr = ((gd54xx->vram_size - 0x4000) + ((val & 0x3f) * 256)); break; case 0x07: - svga->packed_chain4 = svga->seqregs[7] & 1; + svga->packed_chain4 = svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA; if (gd54xx_is_5422(svga)) gd543x_recalc_mapping(gd54xx); else svga->seqregs[svga->seqaddr] &= 0x0f; if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429) - svga->set_reset_disabled = svga->seqregs[7] & 1; + svga->set_reset_disabled = svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA; + gd54xx_set_svga_fast(gd54xx); svga_recalctimings(svga); break; @@ -1641,8 +1642,6 @@ gd54xx_recalc_banking(gd54xx_t *gd54xx) } else svga->extra_banks[1] = svga->extra_banks[0] + 0x8000; } - - svga->write_bank = svga->read_bank = svga->extra_banks[0]; } static void @@ -1661,7 +1660,7 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx) gd54xx->mmio_vram_overlap = 0; - if (!gd54xx_is_5422(svga) || !(svga->seqregs[7] & 0xf0) || !(svga->seqregs[0x07] & 0x01)) { + if (!gd54xx_is_5422(svga) || !(svga->seqregs[0x07] & 0xf0) || !(svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA)) { mem_mapping_disable(&gd54xx->linear_mapping); mem_mapping_disable(&gd54xx->aperture2_mapping); switch (svga->gdcreg[6] & 0x0c) { @@ -1687,7 +1686,7 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx) break; } - if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x07] & 0x01) && (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429)) { + if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA) && (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429)) { if (gd54xx->mmio_vram_overlap) { mem_mapping_disable(&svga->mapping); mem_mapping_set_addr(&gd54xx->mmio_mapping, 0xb8000, 0x08000); @@ -1698,10 +1697,10 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx) } else { if ((svga->crtc[0x27] <= CIRRUS_ID_CLGD5429) || (!gd54xx->pci && !gd54xx->vlb)) { if (svga->gdcreg[0x0b] & CIRRUS_BANKING_GRANULARITY_16K) { - base = (svga->seqregs[7] & 0xf0) << 16; + base = (svga->seqregs[0x07] & 0xf0) << 16; size = 1 * 1024 * 1024; } else { - base = (svga->seqregs[7] & 0xe0) << 16; + base = (svga->seqregs[0x07] & 0xe0) << 16; size = 2 * 1024 * 1024; } } else if (gd54xx->pci) { @@ -1751,7 +1750,7 @@ gd54xx_recalctimings(svga_t *svga) uint8_t rdmask; uint8_t linedbl = svga->dispend * 9 / 10 >= svga->hdisp; - svga->hblankstart = svga->crtc[2] + 1; + svga->hblankstart = svga->crtc[2]; if (svga->crtc[0x1b] & ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5424) ? 0xa0 : 0x20)) { /* Special blanking mode: the blank start and end become components of the window generator, @@ -1761,17 +1760,16 @@ gd54xx_recalctimings(svga_t *svga) svga->hblank_end_val = (svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00) | (((svga->crtc[0x1a] >> 4) & 3) << 6); + svga->hblank_end_mask = 0x000000ff; + if (svga->crtc[0x1b] & 0x20) { - svga->hblankstart = svga->crtc[1] + ((svga->crtc[3] >> 5) & 3) + 1; - svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3); + svga->hblankstart = svga->crtc[1]/* + ((svga->crtc[3] >> 5) & 3) + 1*/; + svga->hblank_end_val = svga->htotal - 1 /* + ((svga->crtc[3] >> 5) & 3)*/; /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ if (!svga->scrblank && svga->attr_palette_enable) svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; - /* No overscan in this mode. */ - svga->hblank_overscan = 0; - svga->monitor->mon_overscan_y = 0; svga->monitor->mon_overscan_x = 0; @@ -1789,15 +1787,14 @@ gd54xx_recalctimings(svga_t *svga) } svga->map8 = svga->pallook; - if (svga->seqregs[7] & CIRRUS_SR7_BPP_SVGA) { + if (svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA) { if (linedbl) svga->render = svga_render_8bpp_lowres; else { svga->render = svga_render_8bpp_highres; if ((svga->dispend == 512) && !svga->interlace && gd54xx_is_5434(svga)) { svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; } } } else if (svga->gdcreg[5] & 0x40) @@ -1839,7 +1836,7 @@ gd54xx_recalctimings(svga_t *svga) break; case 5: - if (gd54xx_is_5434(svga) && (svga->seqregs[7] & CIRRUS_SR7_BPP_32)) { + if (gd54xx_is_5434(svga) && (svga->seqregs[0x07] & CIRRUS_SR7_BPP_32)) { svga->bpp = 32; if (linedbl) svga->render = svga_render_32bpp_lowres; @@ -1876,7 +1873,7 @@ gd54xx_recalctimings(svga_t *svga) break; case 0xf: - switch (svga->seqregs[7] & CIRRUS_SR7_BPP_MASK) { + switch (svga->seqregs[0x07] & CIRRUS_SR7_BPP_MASK) { case CIRRUS_SR7_BPP_32: if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430) { svga->bpp = 32; @@ -1956,7 +1953,7 @@ gd54xx_recalctimings(svga_t *svga) uint8_t m = gd54xx->vclk_d[clocksel] & 0x01 ? 2 : 1; float freq = (14318184.0F * ((float) n / ((float) d * m))); if (gd54xx_is_5422(svga)) { - switch (svga->seqregs[7] & (gd54xx_is_5434(svga) ? 0xe : 6)) { + switch (svga->seqregs[0x07] & (gd54xx_is_5434(svga) ? 0xe : 6)) { case 2: freq /= 2.0F; break; @@ -1978,11 +1975,16 @@ gd54xx_recalctimings(svga_t *svga) svga->htotal += ((svga->crtc[0x1c] >> 3) & 0x07); if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - if (svga->seqregs[1] & 8) { + if (svga->seqregs[1] & 8) svga->render = svga_render_text_40; - } else + else svga->render = svga_render_text_80; } + + if (!(svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA)) { + svga->extra_banks[0] = 0; + svga->extra_banks[1] = 0x8000; + } } static void @@ -2005,11 +2007,11 @@ gd54xx_hwcursor_draw(svga_t *svga, int displine) svga->hwcursor_latch.addr += pitch; for (int x = 0; x < svga->hwcursor.cur_xsize; x += 8) { - dat[0] = svga->vram[svga->hwcursor_latch.addr & svga->vram_display_mask]; + dat[0] = svga->vram[svga->hwcursor_latch.addr & gd54xx->vram_mask]; if (svga->hwcursor.cur_xsize == 64) - dat[1] = svga->vram[(svga->hwcursor_latch.addr + 0x08) & svga->vram_display_mask]; + dat[1] = svga->vram[(svga->hwcursor_latch.addr + 0x08) & gd54xx->vram_mask]; else - dat[1] = svga->vram[(svga->hwcursor_latch.addr + 0x80) & svga->vram_display_mask]; + dat[1] = svga->vram[(svga->hwcursor_latch.addr + 0x80) & gd54xx->vram_mask]; for (uint8_t xx = 0; xx < 8; xx++) { b0 = (dat[0] >> (7 - xx)) & 1; b1 = (dat[1] >> (7 - xx)) & 1; @@ -2193,13 +2195,8 @@ gd54xx_write(uint32_t addr, uint8_t val, void *priv) return; } - if ((svga->seqregs[0x07] & 0x01) == 0) { - svga_write(addr, val, svga); - return; - } - + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; - svga_write_linear(addr, val, svga); } @@ -2215,11 +2212,7 @@ gd54xx_writew(uint32_t addr, uint16_t val, void *priv) return; } - if ((svga->seqregs[0x07] & 0x01) == 0) { - svga_writew(addr, val, svga); - return; - } - + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; if (svga->writemode < 4) @@ -2244,11 +2237,7 @@ gd54xx_writel(uint32_t addr, uint32_t val, void *priv) return; } - if ((svga->seqregs[0x07] & 0x01) == 0) { - svga_writel(addr, val, svga); - return; - } - + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; if (svga->writemode < 4) @@ -2346,7 +2335,7 @@ gd54xx_readb_linear(uint32_t addr, void *priv) uint8_t ap = gd54xx_get_aperture(addr); addr &= 0x003fffff; /* 4 MB mask */ - if ((svga->seqregs[0x07] & 0x01) == 0) + if (!(svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA)) return svga_read_linear(addr, svga); if ((addr >= (svga->vram_max - 256)) && (addr < svga->vram_max)) { @@ -2389,7 +2378,7 @@ gd54xx_readw_linear(uint32_t addr, void *priv) addr &= 0x003fffff; /* 4 MB mask */ - if ((svga->seqregs[0x07] & 0x01) == 0) + if (!(svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA)) return svga_readw_linear(addr, svga); if ((addr >= (svga->vram_max - 256)) && (addr < svga->vram_max)) { @@ -2439,7 +2428,7 @@ gd54xx_readl_linear(uint32_t addr, void *priv) addr &= 0x003fffff; /* 4 MB mask */ - if ((svga->seqregs[0x07] & 0x01) == 0) + if (!(svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA)) return svga_readl_linear(addr, svga); if ((addr >= (svga->vram_max - 256)) && (addr < svga->vram_max)) { @@ -2579,7 +2568,7 @@ gd54xx_writeb_linear(uint32_t addr, uint8_t val, void *priv) uint8_t ap = gd54xx_get_aperture(addr); - if ((svga->seqregs[0x07] & 0x01) == 0) { + if (!(svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA)) { svga_write_linear(addr, val, svga); return; } @@ -2626,7 +2615,7 @@ gd54xx_writew_linear(uint32_t addr, uint16_t val, void *priv) uint32_t old_addr = addr; uint8_t ap = gd54xx_get_aperture(addr); - if ((svga->seqregs[0x07] & 0x01) == 0) { + if (!(svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA)) { svga_writew_linear(addr, val, svga); return; } @@ -2693,7 +2682,7 @@ gd54xx_writel_linear(uint32_t addr, uint32_t val, void *priv) uint32_t old_addr = addr; uint8_t ap = gd54xx_get_aperture(addr); - if ((svga->seqregs[0x07] & 0x01) == 0) { + if (!(svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA)) { svga_writel_linear(addr, val, svga); return; } @@ -2770,12 +2759,10 @@ gd54xx_read(uint32_t addr, void *priv) gd54xx_t *gd54xx = (gd54xx_t *) priv; svga_t *svga = &gd54xx->svga; - if ((svga->seqregs[0x07] & 0x01) == 0) - return svga_read(addr, svga); - if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) return gd54xx_mem_sys_dest_read(gd54xx, 0); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; return svga_read_linear(addr, svga); } @@ -2787,15 +2774,13 @@ gd54xx_readw(uint32_t addr, void *priv) svga_t *svga = &gd54xx->svga; uint16_t ret; - if ((svga->seqregs[0x07] & 0x01) == 0) - return svga_readw(addr, svga); - if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { ret = gd54xx_read(addr, priv); ret |= gd54xx_read(addr + 1, priv) << 8; return ret; } + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; return svga_readw_linear(addr, svga); } @@ -2807,9 +2792,6 @@ gd54xx_readl(uint32_t addr, void *priv) svga_t *svga = &gd54xx->svga; uint32_t ret; - if ((svga->seqregs[0x07] & 0x01) == 0) - return svga_readl(addr, svga); - if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) { ret = gd54xx_read(addr, priv); ret |= gd54xx_read(addr + 1, priv) << 8; @@ -2818,6 +2800,7 @@ gd54xx_readl(uint32_t addr, void *priv) return ret; } + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; return svga_readl_linear(addr, svga); } @@ -3445,7 +3428,7 @@ gd54xx_pattern_copy(gd54xx_t *gd54xx) if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) pattern_pitch = 1; - dsta = gd54xx->blt.dst_addr & svga->vram_mask; + dsta = gd54xx->blt.dst_addr & gd54xx->vram_mask; /* The vertical offset is in the three low-order bits of the Source Address register. */ pattern_y = gd54xx->blt.src_addr & 0x07; @@ -3459,7 +3442,7 @@ gd54xx_pattern_copy(gd54xx_t *gd54xx) */ /* The boundary has to be equal to the size of the pattern. */ - srca = (gd54xx->blt.src_addr & ~0x07) & svga->vram_mask; + srca = (gd54xx->blt.src_addr & ~0x07) & gd54xx->vram_mask; for (uint16_t y = 0; y <= gd54xx->blt.height; y++) { /* Go to the correct pattern line. */ @@ -3470,16 +3453,16 @@ gd54xx_pattern_copy(gd54xx_t *gd54xx) if (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_SOLIDFILL) bitmask = 1; else - bitmask = svga->vram[srca2 & svga->vram_mask] & (0x80 >> pixel); + bitmask = svga->vram[srca2 & gd54xx->vram_mask] & (0x80 >> pixel); } for (int xx = 0; xx < gd54xx->blt.pixel_width; xx++) { if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) src = gd54xx_color_expand(gd54xx, bitmask, xx); else { - src = svga->vram[(srca2 + (x % (gd54xx->blt.pixel_width << 3)) + xx) & svga->vram_mask]; + src = svga->vram[(srca2 + (x % (gd54xx->blt.pixel_width << 3)) + xx) & gd54xx->vram_mask]; bitmask = gd54xx_transparent_comp(gd54xx, xx, src); } - dst = &(svga->vram[(dsta + x + xx) & svga->vram_mask]); + dst = &(svga->vram[(dsta + x + xx) & gd54xx->vram_mask]); target = *dst; gd54xx_rop(gd54xx, &target, &target, &src); if (gd54xx->blt.pixel_width == 3) @@ -3488,7 +3471,7 @@ gd54xx_pattern_copy(gd54xx_t *gd54xx) gd54xx_blit(gd54xx, bitmask, dst, target, (x < gd54xx->blt.pattern_x)); } pixel = (pixel + 1) & 7; - svga->changedvram[((dsta + x) & svga->vram_mask) >> 12] = changeframecount; + svga->changedvram[((dsta + x) & gd54xx->vram_mask) >> 12] = changeframecount; } pattern_y = (pattern_y + 1) & 7; dsta += gd54xx->blt.dst_pitch; @@ -3549,7 +3532,7 @@ gd54xx_mem_sys_src(gd54xx_t *gd54xx, uint32_t cpu_dat, uint32_t count) bitmask = gd54xx_transparent_comp(gd54xx, gd54xx->blt.xx_count, exp); } - dst = &(svga->vram[gd54xx->blt.dst_addr_backup & svga->vram_mask]); + dst = &(svga->vram[gd54xx->blt.dst_addr_backup & gd54xx->vram_mask]); target = *dst; gd54xx_rop(gd54xx, &target, &target, &exp); if ((gd54xx->blt.pixel_width == 3) && (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND)) @@ -3562,7 +3545,7 @@ gd54xx_mem_sys_src(gd54xx_t *gd54xx, uint32_t cpu_dat, uint32_t count) if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) gd54xx->blt.xx_count = (gd54xx->blt.xx_count + 1) % gd54xx->blt.pixel_width; - svga->changedvram[(gd54xx->blt.dst_addr_backup & svga->vram_mask) >> 12] = changeframecount; + svga->changedvram[(gd54xx->blt.dst_addr_backup & gd54xx->vram_mask) >> 12] = changeframecount; if (!gd54xx->blt.xx_count) { /* 1 mask bit = 1 blitted pixel */ @@ -3619,18 +3602,18 @@ gd54xx_normal_blit(uint32_t count, gd54xx_t *gd54xx, svga_t *svga) mask = 0; if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) { - mask = svga->vram[src_addr & svga->vram_mask] & (0x80 >> (gd54xx->blt.x_count / gd54xx->blt.pixel_width)); + mask = svga->vram[src_addr & gd54xx->vram_mask] & (0x80 >> (gd54xx->blt.x_count / gd54xx->blt.pixel_width)); shift = (gd54xx->blt.x_count % gd54xx->blt.pixel_width); src = gd54xx_color_expand(gd54xx, mask, shift); } else { - src = svga->vram[src_addr & svga->vram_mask]; + src = svga->vram[src_addr & gd54xx->vram_mask]; src_addr += gd54xx->blt.dir; mask = 1; } count--; - dst = svga->vram[dst_addr & svga->vram_mask]; - svga->changedvram[(dst_addr & svga->vram_mask) >> 12] = changeframecount; + dst = svga->vram[dst_addr & gd54xx->vram_mask]; + svga->changedvram[(dst_addr & gd54xx->vram_mask) >> 12] = changeframecount; gd54xx_rop(gd54xx, &dst, &dst, (const uint8_t *) &src); @@ -3642,7 +3625,7 @@ gd54xx_normal_blit(uint32_t count, gd54xx_t *gd54xx, svga_t *svga) mask = 0; if (((gd54xx->blt.width - width) >= gd54xx->blt.pattern_x) && !((gd54xx->blt.mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) && !mask)) { - svga->vram[dst_addr & svga->vram_mask] = dst; + svga->vram[dst_addr & gd54xx->vram_mask] = dst; } dst_addr += gd54xx->blt.dir; @@ -3666,10 +3649,10 @@ gd54xx_normal_blit(uint32_t count, gd54xx_t *gd54xx, svga_t *svga) } else src_addr = gd54xx->blt.src_addr_backup = gd54xx->blt.src_addr_backup + (gd54xx->blt.src_pitch * gd54xx->blt.dir); - dst_addr &= svga->vram_mask; - gd54xx->blt.dst_addr_backup &= svga->vram_mask; - src_addr &= svga->vram_mask; - gd54xx->blt.src_addr_backup &= svga->vram_mask; + dst_addr &= gd54xx->vram_mask; + gd54xx->blt.dst_addr_backup &= gd54xx->vram_mask; + src_addr &= gd54xx->vram_mask; + gd54xx->blt.src_addr_backup &= gd54xx->vram_mask; gd54xx->blt.x_count = 0; @@ -3710,7 +3693,7 @@ gd54xx_mem_sys_dest(uint32_t count, gd54xx_t *gd54xx, svga_t *svga) gd54xx->blt.msd_buf_pos = 0; while (gd54xx->blt.msd_buf_pos < 32) { - gd54xx->blt.msd_buf[gd54xx->blt.msd_buf_pos & 0x1f] = svga->vram[gd54xx->blt.src_addr_backup & svga->vram_mask]; + gd54xx->blt.msd_buf[gd54xx->blt.msd_buf_pos & 0x1f] = svga->vram[gd54xx->blt.src_addr_backup & gd54xx->vram_mask]; gd54xx->blt.src_addr_backup += gd54xx->blt.dir; gd54xx->blt.msd_buf_pos++; @@ -4149,7 +4132,11 @@ gd54xx_init(const device_t *info) break; case CIRRUS_ID_CLGD5436: - romfn = BIOS_GD5436_PATH; + if (info->local & 0x200) { + romfn = NULL; + gd54xx->has_bios = 0; + } else + romfn = BIOS_GD5436_PATH; break; case CIRRUS_ID_CLGD5430: @@ -4981,6 +4968,20 @@ const device_t gd5428_onboard_device = { .config = gd5428_onboard_config }; +const device_t gd5428_vlb_onboard_device = { + .name = "Cirrus Logic GD5428 (VLB) (On-Board)", + .internal_name = "cl_gd5428_vlb_onboard", + .flags = DEVICE_VLB, + .local = CIRRUS_ID_CLGD5428, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = NULL }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5428_onboard_config +}; + const device_t gd5429_isa_device = { .name = "Cirrus Logic GD5429 (ISA)", .internal_name = "cl_gd5429_isa", @@ -5151,6 +5152,20 @@ const device_t gd5434_pci_device = { .config = gd5434_config }; +const device_t gd5436_onboard_pci_device = { + .name = "Cirrus Logic GD5436 (PCI) (On-Board)", + .internal_name = "cl_gd5436_onboard_pci", + .flags = DEVICE_PCI, + .local = CIRRUS_ID_CLGD5436 | 0x200, + .init = gd54xx_init, + .close = gd54xx_close, + .reset = gd54xx_reset, + { .available = NULL }, + .speed_changed = gd54xx_speed_changed, + .force_redraw = gd54xx_force_redraw, + .config = gd5434_config +}; + const device_t gd5436_pci_device = { .name = "Cirrus Logic GD5436 (PCI)", .internal_name = "cl_gd5436_pci", diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 670d88e61..8f995117c 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -295,22 +295,22 @@ ega_in(uint16_t addr, void *priv) break; case 0x3c0: - if (ega_type) + if (ega_type == 1) ret = ega->attraddr | ega->attr_palette_enable; break; case 0x3c1: - if (ega_type) + if (ega_type == 1) ret = ega->attrregs[ega->attraddr]; break; case 0x3c2: ret = (egaswitches & (8 >> egaswitchread)) ? 0x10 : 0x00; break; case 0x3c4: - if (ega_type) + if (ega_type == 1) ret = ega->seqaddr; break; case 0x3c5: - if (ega_type) + if (ega_type == 1) ret = ega->seqregs[ega->seqaddr & 0xf]; break; case 0x3c6: @@ -318,24 +318,24 @@ ega_in(uint16_t addr, void *priv) ret = ega->ctl_mode; break; case 0x3c8: - if (ega_type) + if (ega_type == 1) ret = 2; break; case 0x3cc: - if (ega_type) + if (ega_type == 1) ret = ega->miscout; break; case 0x3ce: - if (ega_type) + if (ega_type == 1) ret = ega->gdcaddr; break; case 0x3cf: - if (ega_type) + if (ega_type == 1) ret = ega->gdcreg[ega->gdcaddr & 0xf]; break; case 0x3d0: case 0x3d4: - if (ega_type) + if (ega_type == 1) ret = ega->crtcreg; break; case 0x3d1: @@ -349,14 +349,21 @@ ega_in(uint16_t addr, void *priv) break; case 0x10: - case 0x11: - /* TODO: Return light pen address once implemented. */ - if (ega_type) + if (ega_type == 1) ret = ega->crtc[ega->crtcreg]; + else + ret = ega->light_pen >> 8; + break; + + case 0x11: + if (ega_type == 1) + ret = ega->crtc[ega->crtcreg]; + else + ret = ega->light_pen & 0xff; break; default: - if (ega_type) + if (ega_type == 1) ret = ega->crtc[ega->crtcreg]; break; } @@ -557,7 +564,7 @@ ega_recalctimings(ega_t *ega) overscan_x <<= 1; ega->y_add = (overscan_y >> 1); - ega->x_add = (overscan_x >> 1); + ega->x_add = (overscan_x >> 1) - ega->scrollcache; if (ega->vres) ega->y_add >>= 1; @@ -804,10 +811,6 @@ ega_poll(void *priv) ega->cca = ega->ma; ega->maback <<= 2; ega->sc = 0; - if (ega->attrregs[0x10] & 0x20) { - ega->scrollcache = 0; - ega->x_add = (overscan_x >> 1); - } } if (ega->vc == ega->dispend) { ega->dispon = 0; @@ -1619,7 +1622,7 @@ static const device_config_t ega_config[] = { }; const device_t ega_device = { - .name = "EGA", + .name = "IBM EGA", .internal_name = "ega", .flags = DEVICE_ISA, .local = EGA_IBM, diff --git a/src/video/vid_ega_render.c b/src/video/vid_ega_render.c index 98905e0c8..0cb1216ad 100644 --- a/src/video/vid_ega_render.c +++ b/src/video/vid_ega_render.c @@ -199,6 +199,7 @@ ega_render_graphics(ega_t *ega) const bool attrblink = ((ega->attrregs[0x10] & 8) != 0); const bool blinked = ega->blink & 0x10; const bool crtcreset = ((ega->crtc[0x17] & 0x80) == 0); + const bool seq9dot = ((ega->seqregs[1] & 1) == 0); const bool seqoddeven = ((ega->seqregs[1] & 4) != 0); const uint8_t blinkmask = (attrblink && blinked ? 0x8 : 0x0); uint32_t *p = &buffer32->line[ega->displine + ega->y_add][ega->x_add]; @@ -206,6 +207,15 @@ ega_render_graphics(ega_t *ega) const int dotwidth = 1 << dwshift; const int charwidth = dotwidth * 8; int secondcclk = 0; + + /* Compensate for 8dot scroll */ + if (!seq9dot) { + for (int x = 0; x < dotwidth; x++) { + p[x] = ega->overscan_color; + } + p += dotwidth; + } + for (int x = 0; x <= (ega->hdisp + ega->scrollcache); x += charwidth) { uint32_t addr = ega->remap_func(ega, ega->ma) & ega->vrammask; diff --git a/src/video/vid_et3000.c b/src/video/vid_et3000.c index 4f7dbae3e..97da08822 100644 --- a/src/video/vid_et3000.c +++ b/src/video/vid_et3000.c @@ -14,11 +14,13 @@ * * Copyright 2016-2018 Miran Grca. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/io.h> #include <86box/mca.h> @@ -40,7 +42,12 @@ typedef struct { rom_t bios_rom; + uint8_t pel_wd; uint8_t banking; + uint8_t reg_3d8; + uint8_t reg_3bf; + uint8_t tries; + uint8_t ext_enable; } et3000_t; static video_timings_t timing_et3000_isa = { VIDEO_ISA, 3, 3, 6, 5, 5, 10 }; @@ -48,30 +55,130 @@ static video_timings_t timing_et3000_isa = { VIDEO_ISA, 3, 3, 6, 5, 5, 10 }; static uint8_t et3000_in(uint16_t addr, void *priv); static void et3000_out(uint16_t addr, uint8_t val, void *priv); +#ifdef ENABLE_ET3000_LOG +int svga_do_log = ENABLE_ET3000_LOG; + +static void +et3000_log(const char *fmt, ...) +{ + va_list ap; + + if (et3000_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define et3000_log(fmt, ...) +#endif + static uint8_t et3000_in(uint16_t addr, void *priv) { et3000_t *dev = (et3000_t *) priv; svga_t *svga = &dev->svga; + uint8_t ret = 0xff; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + if ((addr >= 0x03b0) && (addr < 0x03bc) && (svga->miscout & 1)) + return 0xff; + + if ((addr >= 0x03d0) && (addr < 0x03dc) && !(svga->miscout & 1)) + return 0xff; switch (addr) { - case 0x3cd: /*Banking*/ - return dev->banking; - - case 0x3d4: - return svga->crtcreg; - - case 0x3d5: - return svga->crtc[svga->crtcreg]; - default: + ret = svga_in(addr, svga); + +#ifdef ENABLE_ET3000_LOG + if (addr != 0x03da) + et3000_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret); +#endif + break; + + case 0x3c1: + /* It appears the extended attribute registers are **NOT** + protected by key on the ET3000AX, as the BIOS attempts to + write to attribute register 16h without the key. */ + ret = svga_in(addr, svga); + et3000_log("[%04X:%08X] [R] %04X: %02X = %02X (%i)\n", CS, cpu_state.pc, + addr, svga->attraddr, ret, dev->ext_enable); + break; + + case 0x3c5: + if ((svga->seqaddr >= 6) && !dev->ext_enable) + ret = 0xff; + else + ret = svga_in(addr, svga); + et3000_log("[%04X:%08X] [R] %04X: %02X = %02X (%i)\n", CS, cpu_state.pc, + addr, svga->seqaddr, ret, dev->ext_enable); + break; + + case 0x3cf: + if ((svga->gdcaddr >= 0x0d) && !dev->ext_enable) + ret = 0xff; + else + ret = svga_in(addr, svga); + et3000_log("[%04X:%08X] [R] %04X: %02X = %02X (%i)\n", CS, cpu_state.pc, + addr, svga->gdcaddr & 15, ret, dev->ext_enable); + break; + + case 0x3cb: /*PEL Address/Data Wd*/ + ret = dev->pel_wd; + et3000_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret); + break; + + case 0x3cd: /*Banking*/ + ret = dev->banking; + et3000_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret); + break; + + case 0x3b4: + case 0x3d4: + ret = svga->crtcreg; + et3000_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret); + break; + + case 0x3b5: + case 0x3d5: + if ((svga->crtcreg >= 0x18) && (svga->crtcreg < 0x23) && !dev->ext_enable) + ret = 0xff; + else if (svga->crtcreg > 0x25) + ret = 0xff; + else + ret = svga->crtc[svga->crtcreg]; + et3000_log("[%04X:%08X] [R] %04X: %02X = %02X\n", CS, cpu_state.pc, + addr, svga->crtcreg, ret); + break; + + case 0x3b8: + case 0x3d8: + ret = dev->reg_3d8; + et3000_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret); + break; + + case 0x3ba: + case 0x3da: + svga->attrff = 0; + + if (svga->cgastat & 0x01) + svga->cgastat &= ~0x30; + else + svga->cgastat ^= 0x30; + + ret = svga->cgastat; + + if ((svga->fcr & 0x08) && svga->dispon) + ret |= 0x08; + break; + + case 0x3bf: + ret = dev->reg_3bf; + et3000_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret); break; } - return svga_in(addr, svga); + return ret; } static void @@ -80,47 +187,119 @@ et3000_out(uint16_t addr, uint8_t val, void *priv) et3000_t *dev = (et3000_t *) priv; svga_t *svga = &dev->svga; uint8_t old; + uint8_t index; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + et3000_log("[%04X:%08X] [W] %04X = %02X\n", CS, cpu_state.pc, addr, val); + + if ((addr >= 0x03b0) && (addr < 0x03bc) && (svga->miscout & 1)) + return; + + if ((addr >= 0x03d0) && (addr < 0x03dc) && !(svga->miscout & 1)) + return; switch (addr) { case 0x3c0: - case 0x3c1: + /* It appears the extended attribute registers are **NOT** + protected by key on the ET3000AX, as the BIOS attempts to + write to attribute register 16h without the key. */ + if (svga->attrff && (svga->attraddr == 0x11) && (svga->attrregs[0x16] & 0x01)) + val = (val & 0xf0) | (svga->attrregs[0x11] & 0x0f); +#ifdef ENABLE_ET3000_LOG + if (svga->attrff && (svga->attraddr > 0x14)) + et3000_log("3C1: %02X = %02X\n", svga->attraddr, val); +#endif if (svga->attrff && (svga->attraddr == 0x16)) { svga->attrregs[0x16] = val; svga->chain4 &= ~0x10; if (svga->gdcreg[5] & 0x40) svga->chain4 |= (svga->attrregs[0x16] & 0x10); svga_recalctimings(svga); + return; } break; + case 0x3c1: + return; + case 0x3c2: + svga->miscout = val; + svga->vidclock = val & 4; + svga_recalctimings(svga); + return; + + case 0x3c4: + svga->seqaddr = val & 0x07; + return; case 0x3c5: + if ((svga->seqaddr >= 6) && !dev->ext_enable) + return; + if (svga->seqaddr == 4) { svga->seqregs[4] = val; svga->chain2_write = !(val & 4); svga->chain4 = (svga->chain4 & ~8) | (val & 8); - svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4 && !(svga->adv_flags & FLAG_ADDR_BY8); + et3000_log("CHAIN2 = %i, CHAIN4 = %i\n", svga->chain2_write, svga->chain4); + svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && + !svga->gdcreg[1]) && svga->chain4 && + !(svga->adv_flags & FLAG_ADDR_BY8); return; } +#ifdef ENABLE_ET3000_LOG + else if (svga->seqaddr > 4) + et3000_log("3C5: %02X = %02X\n", svga->seqaddr, val); +#endif break; - case 0x3cf: - if ((svga->gdcaddr & 15) == 5) { - svga->chain4 &= ~0x10; - if (val & 0x40) - svga->chain4 |= (svga->attrregs[0x16] & 0x10); + case 0x3c9: + if (svga->adv_flags & FLAG_RAMDAC_SHIFT) + val <<= 2; + svga->fullchange = svga->monitor->mon_changeframecount; + switch (svga->dac_pos) { + case 0: + if (!(svga->attrregs[0x16] & 0x02) && !(svga->attrregs[0x17] & 0x80)) + svga->dac_r = val; + svga->dac_pos++; + break; + case 1: + if (!(svga->attrregs[0x16] & 0x02) && !(svga->attrregs[0x17] & 0x80)) + svga->dac_g = val; + svga->dac_pos++; + break; + case 2: + index = svga->dac_addr & 255; + if (!(svga->attrregs[0x16] & 0x02) && !(svga->attrregs[0x17] & 0x80)) { + svga->dac_b = val; + svga->vgapal[index].r = svga->dac_r; + svga->vgapal[index].g = svga->dac_g; + svga->vgapal[index].b = svga->dac_b; + if (svga->ramdac_type == RAMDAC_8BIT) + svga->pallook[index] = makecol32(svga->vgapal[index].r, svga->vgapal[index].g, + svga->vgapal[index].b); + else + svga->pallook[index] = makecol32(video_6to8[svga->vgapal[index].r & 0x3f], + video_6to8[svga->vgapal[index].g & 0x3f], + video_6to8[svga->vgapal[index].b & 0x3f]); + } + svga->dac_pos = 0; + svga->dac_addr = (svga->dac_addr + 1) & 255; + break; + + default: + break; } + return; + + case 0x3cb: /*PEL Address/Data Wd*/ + et3000_log("3CB = %02X\n", val); + dev->pel_wd = val; break; case 0x3cd: /*Banking*/ - dev->banking = val; + et3000_log("3CD = %02X\n", val); if (!(svga->crtc[0x23] & 0x80) && !(svga->gdcreg[6] & 0x08)) { switch ((val >> 6) & 3) { case 0: /*128K segments*/ - svga->write_bank = (val & 7) << 17; + svga->write_bank = ((val >> 0) & 7) << 17; svga->read_bank = ((val >> 3) & 7) << 17; break; case 1: /*64K segments*/ @@ -132,13 +311,68 @@ et3000_out(uint16_t addr, uint8_t val, void *priv) break; } } + dev->banking = val; return; + case 0x3ce: + svga->gdcaddr = val & 0x0f; + return; + case 0x3cf: + if ((svga->gdcaddr >= 0x0d) && !dev->ext_enable) + return; + + if ((svga->gdcaddr & 15) == 5) { + svga->chain4 &= ~0x10; + if (val & 0x40) + svga->chain4 |= (svga->attrregs[0x16] & 0x10); + } else if ((svga->gdcaddr & 15) == 6) { + if (!(svga->crtc[0x23] & 0x80) && !(val & 0x08)) { + switch ((dev->banking >> 6) & 3) { + case 0: /*128K segments*/ + svga->write_bank = ((dev->banking >> 0) & 7) << 17; + svga->read_bank = ((dev->banking >> 3) & 7) << 17; + break; + case 1: /*64K segments*/ + svga->write_bank = (dev->banking & 7) << 16; + svga->read_bank = ((dev->banking >> 3) & 7) << 16; + break; + + default: + break; + } + } else + svga->write_bank = svga->read_bank = 0; + + old = svga->gdcreg[6]; + svga_out(addr, val, svga); + if ((old & 0xc) != 0 && (val & 0xc) == 0) { + /* Override mask - ET3000 supports linear 128k at A0000. */ + svga->banked_mask = 0x1ffff; + } + return; + } +#ifdef ENABLE_ET3000_LOG + else if ((svga->gdcaddr & 15) > 8) + et3000_log("3CF: %02X = %02X\n", (svga->gdcaddr & 15), val); +#endif + break; + + case 0x3b4: case 0x3d4: svga->crtcreg = val & 0x3f; return; + case 0x3b5: case 0x3d5: + if ((svga->crtcreg >= 0x18) && (svga->crtcreg < 0x23) && !dev->ext_enable) + return; + else if (svga->crtcreg > 0x25) + return; + + /* Unlike the ET4000AX, which protects all bits of the + overflow high register (0x35 there, 0x25 here) except for + bits 4 and 7, if bit 7 of CRTC 11h is set, the ET3000AX + does not to that. */ if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) return; if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) @@ -146,6 +380,11 @@ et3000_out(uint16_t addr, uint8_t val, void *priv) old = svga->crtc[svga->crtcreg]; svga->crtc[svga->crtcreg] = val; +#ifdef ENABLE_ET3000_LOG + if (svga->crtcreg > 0x18) + et3000_log("3D5: %02X = %02X\n", svga->crtcreg, val); +#endif + if (old != val) { if (svga->crtcreg < 0x0e || svga->crtcreg > 0x10) { svga->fullchange = changeframecount; @@ -154,6 +393,27 @@ et3000_out(uint16_t addr, uint8_t val, void *priv) } break; + case 0x3b8: + case 0x3d8: + et3000_log("%04X = %02X\n", addr, val); + dev->reg_3d8 = val; + if ((val == 0xa0) && (dev->tries == 1)) { + dev->ext_enable = 1; + dev->tries = 0; + } else if (val == 0x29) + dev->tries = 1; + return; + + case 0x3bf: + et3000_log("%04X = %02X\n", addr, val); + dev->reg_3bf = val; + if ((val == 0x01) && (dev->tries == 1)) { + dev->ext_enable = 0; + dev->tries = 0; + } else if (val == 0x03) + dev->tries = 1; + return; + default: break; } @@ -199,10 +459,8 @@ et3000_recalctimings(svga_t *svga) } } -#if 0 - pclog("HDISP = %i, HTOTAL = %i, ROWOFFSET = %i, INTERLACE = %i\n", - svga->hdisp, svga->htotal, svga->rowoffset, svga->interlace); -#endif + et3000_log("HDISP = %i, HTOTAL = %i, ROWOFFSET = %i, INTERLACE = %i\n", + svga->hdisp, svga->htotal, svga->rowoffset, svga->interlace); switch (((svga->miscout >> 2) & 3) | ((svga->crtc[0x24] << 1) & 4)) { case 0: @@ -238,7 +496,7 @@ et3000_init(const device_t *info) svga_init(info, &dev->svga, dev, device_get_config_int("memory") << 10, et3000_recalctimings, et3000_in, et3000_out, NULL, NULL); - io_sethandler(0x03c0, 32, + io_sethandler(0x03b0, 48, et3000_in, NULL, NULL, et3000_out, NULL, NULL, dev); break; diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index cb44e9383..ae6b7ae82 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -244,11 +244,61 @@ et4000_out(uint16_t addr, uint8_t val, void *priv) et4000_t *dev = (et4000_t *) priv; svga_t *svga = &dev->svga; uint8_t old; + uint8_t pal4to16[16] = { 0, 7, 0x38, 0x3f, 0, 3, 4, 0x3f, 0, 2, 4, 0x3e, 0, 3, 5, 0x3f }; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; switch (addr) { + case 0x3c0: + case 0x3c1: + if (!svga->attrff) { + svga->attraddr = val & 0x1f; + if ((val & 0x20) != svga->attr_palette_enable) { + svga->fullchange = 3; + svga->attr_palette_enable = val & 0x20; + svga_recalctimings(svga); + } + } else { + if ((svga->attraddr == 0x13) && (svga->attrregs[0x13] != val)) + svga->fullchange = svga->monitor->mon_changeframecount; + old = svga->attrregs[svga->attraddr & 0x1f]; + svga->attrregs[svga->attraddr & 0x1f] = val; + if (svga->attraddr < 0x10) + svga->fullchange = svga->monitor->mon_changeframecount; + + if ((svga->attraddr == 0x10) || (svga->attraddr == 0x14) || (svga->attraddr < 0x10)) { + for (int c = 0; c < 0x10; c++) { + if (svga->attrregs[0x10] & 0x80) + svga->egapal[c] = (svga->attrregs[c] & 0xf) | ((svga->attrregs[0x14] & 0xf) << 4); + else if (svga->ati_4color) + svga->egapal[c] = pal4to16[(c & 0x03) | ((val >> 2) & 0xc)]; + else + svga->egapal[c] = (svga->attrregs[c] & 0x3f) | ((svga->attrregs[0x14] & 0xc) << 4); + } + svga->fullchange = svga->monitor->mon_changeframecount; + } + /* Recalculate timings on change of attribute register 0x11 + (overscan border color) too. */ + if (svga->attraddr == 0x10) { + svga->chain4 &= ~0x02; + if ((val & 0x40) && (svga->attrregs[0x10] & 0x40)) + svga->chain4 |= (svga->seqregs[0x0e] & 0x02); + if (old != val) + svga_recalctimings(svga); + } else if (svga->attraddr == 0x11) { + svga->overscan_color = svga->pallook[svga->attrregs[0x11]]; + if (old != val) + svga_recalctimings(svga); + } else if (svga->attraddr == 0x12) { + if ((val & 0xf) != svga->plane_mask) + svga->fullchange = svga->monitor->mon_changeframecount; + svga->plane_mask = val & 0xf; + } + } + svga->attrff ^= 1; + return; + case 0x3c5: if (svga->seqaddr == 4) { svga->seqregs[4] = val; @@ -260,7 +310,7 @@ et4000_out(uint16_t addr, uint8_t val, void *priv) } else if (svga->seqaddr == 0x0e) { svga->seqregs[0x0e] = val; svga->chain4 &= ~0x02; - if (svga->gdcreg[5] & 0x40) + if ((svga->gdcreg[5] & 0x40) && svga->lowres) svga->chain4 |= (svga->seqregs[0x0e] & 0x02); svga_recalctimings(svga); return; @@ -288,7 +338,7 @@ et4000_out(uint16_t addr, uint8_t val, void *priv) case 0x3cf: if ((svga->gdcaddr & 15) == 5) { svga->chain4 &= ~0x02; - if (val & 0x40) + if ((val & 0x40) && svga->lowres) svga->chain4 |= (svga->seqregs[0x0e] & 0x02); } else if ((svga->gdcaddr & 15) == 6) { if (!(svga->crtc[0x36] & 0x10) && !(val & 0x08)) { @@ -599,24 +649,27 @@ et4000_recalctimings(svga_t *svga) const et4000_t *dev = (et4000_t *) svga->priv; svga->ma_latch |= (svga->crtc[0x33] & 3) << 16; + + svga->hblankstart = (((svga->crtc[0x3f] & 0x4) >> 2) << 8) + svga->crtc[2]; + if (svga->crtc[0x35] & 1) - svga->vblankstart += 0x400; + svga->vblankstart |= 0x400; if (svga->crtc[0x35] & 2) - svga->vtotal += 0x400; + svga->vtotal |= 0x400; if (svga->crtc[0x35] & 4) - svga->dispend += 0x400; + svga->dispend |= 0x400; if (svga->crtc[0x35] & 8) - svga->vsyncstart += 0x400; + svga->vsyncstart |= 0x400; if (svga->crtc[0x35] & 0x10) - svga->split += 0x400; + svga->split |= 0x400; if (!svga->rowoffset) svga->rowoffset = 0x100; if (svga->crtc[0x3f] & 1) - svga->htotal += 256; - if (svga->attrregs[0x16] & 0x20) + svga->htotal |= 0x100; + if (svga->attrregs[0x16] & 0x20) { svga->hdisp <<= 1; - - svga->hblankstart = (((svga->crtc[0x3f] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; + svga->dots_per_clock <<= 1; + } switch (((svga->miscout >> 2) & 3) | ((svga->crtc[0x34] << 1) & 4)) { case 0: @@ -637,10 +690,12 @@ et4000_recalctimings(svga_t *svga) case 15: case 16: svga->hdisp /= 2; + svga->dots_per_clock /= 2; break; case 24: svga->hdisp /= 3; + svga->dots_per_clock /= 3; break; default: @@ -659,9 +714,17 @@ et4000_recalctimings(svga_t *svga) } } - if ((svga->seqregs[0x0e] & 0x02) && ((svga->gdcreg[5] & 0x60) >= 0x40)) { - svga->ma_latch <<= (1 << 0); - svga->rowoffset <<= (1 << 0); + if ((svga->bpp == 8) && ((svga->gdcreg[5] & 0x60) >= 0x40)) { + svga->map8 = svga->pallook; + if (svga->lowres) + svga->render = svga_render_8bpp_lowres; + else + svga->render = svga_render_8bpp_highres; + } + + if ((svga->seqregs[0x0e] & 0x02) && ((svga->gdcreg[5] & 0x60) >= 0x40) && svga->lowres) { + svga->ma_latch <<= 1; + svga->rowoffset <<= 1; svga->render = svga_render_8bpp_highres; } @@ -671,14 +734,6 @@ et4000_recalctimings(svga_t *svga) else if (svga->render == svga_render_8bpp_highres) svga->render = svga_render_8bpp_tseng_highres; } - - if ((svga->bpp == 8) && ((svga->gdcreg[5] & 0x60) >= 0x40)) { - svga->map8 = svga->pallook; - if (svga->lowres) - svga->render = svga_render_8bpp_lowres; - else - svga->render = svga_render_8bpp_highres; - } } static void @@ -689,7 +744,8 @@ et4000_kasan_recalctimings(svga_t *svga) et4000_recalctimings(svga); if (svga->render == svga_render_text_80 && (et4000->kasan_cfg_regs[0] & 8)) { - svga->ma_latch -= 3; + svga->hdisp += svga->dots_per_clock; + svga->ma_latch -= 5; svga->ca_adj = (et4000->kasan_cfg_regs[0] >> 6) - 3; svga->ksc5601_sbyte_mask = (et4000->kasan_cfg_regs[0] & 4) << 5; if ((et4000->kasan_cfg_regs[0] & 0x23) == 0x20 && (et4000->kasan_cfg_regs[4] & 0x80) && ((svga->crtc[0x37] & 0x0B) == 0x0A)) diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 69a995208..39b5b9ecc 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -431,24 +431,27 @@ et4000w32p_recalctimings(svga_t *svga) et4000w32p_t *et4000 = (et4000w32p_t *) svga->priv; svga->ma_latch |= (svga->crtc[0x33] & 0x7) << 16; - if (svga->crtc[0x35] & 0x01) - svga->vblankstart += 0x400; - if (svga->crtc[0x35] & 0x02) - svga->vtotal += 0x400; - if (svga->crtc[0x35] & 0x04) - svga->dispend += 0x400; - if (svga->crtc[0x35] & 0x08) - svga->vsyncstart += 0x400; - if (svga->crtc[0x35] & 0x10) - svga->split += 0x400; - if (svga->crtc[0x3F] & 0x80) - svga->rowoffset += 0x100; - if (svga->crtc[0x3F] & 0x01) - svga->htotal += 256; - if (svga->attrregs[0x16] & 0x20) - svga->hdisp <<= 1; - svga->hblankstart = (((svga->crtc[0x3f] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; + svga->hblankstart = (((svga->crtc[0x3f] & 0x4) >> 2) << 8) + svga->crtc[2]; + + if (svga->crtc[0x35] & 0x01) + svga->vblankstart |= 0x400; + if (svga->crtc[0x35] & 0x02) + svga->vtotal |= 0x400; + if (svga->crtc[0x35] & 0x04) + svga->dispend |= 0x400; + if (svga->crtc[0x35] & 0x08) + svga->vsyncstart |= 0x400; + if (svga->crtc[0x35] & 0x10) + svga->split |= 0x400; + if (svga->crtc[0x3F] & 0x80) + svga->rowoffset |= 0x100; + if (svga->crtc[0x3F] & 0x01) + svga->htotal |= 0x100; + if (svga->attrregs[0x16] & 0x20) { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + } svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen); @@ -474,32 +477,6 @@ et4000w32p_recalctimings(svga_t *svga) } } -#if 0 - if (svga->adv_flags & FLAG_NOSKEW) { - /* On the Cardex ET4000/W32p-based cards, adjust text mode clocks by 1. */ - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /* Text mode */ - svga->ma_latch--; - - if (svga->seqregs[1] & 8) /*40 column*/ - svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18; - else - svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9; - } else { - /* Also adjust the graphics mode clocks in some cases. */ - if ((svga->gdcreg[5] & 0x40) && (svga->bpp != 32)) { - if ((svga->bpp == 15) || (svga->bpp == 16) || (svga->bpp == 24)) - svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18; - else - svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9; - } else if ((svga->gdcreg[5] & 0x40) == 0) { - svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9; - if (svga->hdisp == 648 || svga->hdisp == 808 || svga->hdisp == 1032) - svga->hdisp -= 8; - } - } - } -#endif - if (et4000->type == ET4000W32) { if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { if (svga->gdcreg[5] & 0x40) { @@ -522,8 +499,10 @@ et4000w32p_recalctimings(svga_t *svga) switch (svga->bpp) { case 15: case 16: - if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + } if (et4000->type <= ET4000W32P_REVC) { if (et4000->type == ET4000W32P_REVC) { if (svga->hdisp != 1024) @@ -534,6 +513,7 @@ et4000w32p_recalctimings(svga_t *svga) break; case 24: svga->hdisp /= 3; + svga->dots_per_clock /= 3; if (et4000->type <= ET4000W32P_REVC) et4000->adjust_cursor = 2; if ((et4000->type == ET4000W32P_DIAMOND) && ((svga->hdisp == (640 / 2)) || (svga->hdisp == 1232))) { @@ -553,15 +533,8 @@ et4000w32p_recalctimings(svga_t *svga) else svga->render = svga_render_text_80; } else { - if (svga->adv_flags & FLAG_NOSKEW) { - svga->ma_latch--; - } - switch (svga->gdcreg[5] & 0x60) { case 0x00: - if (et4000->rev == 5) - svga->ma_latch++; - if (svga->seqregs[1] & 8) /* Low res (320) */ svga->render = svga_render_4bpp_lowres; else @@ -2809,7 +2782,6 @@ et4000w32p_init(const device_t *info) et4000->svga.ramdac = device_add(&stg_ramdac_device); et4000->svga.clock_gen = et4000->svga.ramdac; et4000->svga.getclock = stg_getclock; - et4000->svga.adv_flags |= FLAG_NOSKEW; break; case ET4000W32P_REVC: @@ -2834,7 +2806,6 @@ et4000w32p_init(const device_t *info) et4000->svga.ramdac = device_add(&stg_ramdac_device); et4000->svga.clock_gen = et4000->svga.ramdac; et4000->svga.getclock = stg_getclock; - et4000->svga.adv_flags |= FLAG_NOSKEW; break; case ET4000W32P_CARDEX: @@ -2847,7 +2818,6 @@ et4000w32p_init(const device_t *info) et4000->svga.ramdac = device_add(&stg_ramdac_device); et4000->svga.clock_gen = et4000->svga.ramdac; et4000->svga.getclock = stg_getclock; - et4000->svga.adv_flags |= FLAG_NOSKEW; break; case ET4000W32P_DIAMOND: diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index 803d5658c..b87d93665 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -454,14 +454,10 @@ ht216_out(uint16_t addr, uint8_t val, void *priv) break; case 0x46e8: - if ((ht216->id == 0x7152) && ht216->isabus) - io_removehandler(0x0105, 0x0001, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); io_removehandler(0x03c0, 0x0020, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); mem_mapping_disable(&svga->mapping); mem_mapping_disable(&ht216->linear_mapping); if (val & 8) { - if ((ht216->id == 0x7152) && ht216->isabus) - io_sethandler(0x0105, 0x0001, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); io_sethandler(0x03c0, 0x0020, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216); mem_mapping_enable(&svga->mapping); ht216_remap(ht216); @@ -718,7 +714,7 @@ ht216_recalctimings(svga_t *svga) svga->vram_display_mask = (ht216->ht_regs[0xf6] & 0x40) ? ht216->vram_mask : 0x3ffff; if (ht216->ht_regs[0xe0] & 0x20) - svga->hblankstart = ((ht216->ht_regs[0xca] >> 2) << 8) + svga->crtc[4] + 1; + svga->hblankstart = ((ht216->ht_regs[0xca] >> 2) << 8) + svga->crtc[4]; } static void diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index a53199324..702fb7e32 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -386,7 +386,7 @@ static const device_config_t mda_config[] = { }; const device_t mda_device = { - .name = "MDA", + .name = "IBM MDA", .internal_name = "mda", .flags = DEVICE_ISA, .local = 0, diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index 44a33db2e..f40385fef 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -469,7 +469,7 @@ typedef struct mystique_t { lfb_base, ctrl_base, iload_base, ma_latch_old, maccess, mctlwtst, maccess_running, softrap_pending_val; - + atomic_uint status; atomic_bool softrap_status_read; @@ -502,7 +502,7 @@ typedef struct mystique_t { int xoff, yoff, selline, ydst, length_cur, iload_rem_count, idump_end_of_line, words, ta_key, ta_mask, lastpix_r, lastpix_g, - lastpix_b, highv_line, beta, dither; + lastpix_b, highv_line, beta, dither, err, k1, k2; int pattern[8][16]; @@ -764,13 +764,13 @@ mystique_out(uint16_t addr, uint8_t val, void *priv) old = mystique->crtcext_regs[mystique->crtcext_idx]; if (mystique->crtcext_idx < 6) mystique->crtcext_regs[mystique->crtcext_idx] = val; - + if ((mystique->type >= MGA_1064SG) && (mystique->crtcext_idx == 0) && (mystique->crtcext_regs[3] & CRTCX_R3_MGAMODE)) { svga->rowoffset = svga->crtc[0x13] | ((mystique->crtcext_regs[0] & CRTCX_R0_OFFSET_MASK) << 4); - if (!(mystique->type >= MGA_2164W)) + if (!(mystique->type >= MGA_2164W)) svga->rowoffset <<= 1; svga->ma_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 16) | @@ -794,7 +794,7 @@ mystique_out(uint16_t addr, uint8_t val, void *priv) } } - if (mystique->crtcext_idx == 4) { + if (mystique->crtcext_idx == 4) { if (svga->gdcreg[6] & 0xc) { /*64k banks*/ if (mystique->type >= MGA_2164W) { @@ -815,6 +815,7 @@ mystique_out(uint16_t addr, uint8_t val, void *priv) } } } + svga_recalctimings(svga); break; default: @@ -944,7 +945,7 @@ mystique_recalctimings(svga_t *svga) if (mystique->crtcext_regs[1] & CRTCX_R1_HTOTAL8) svga->htotal |= 0x100; - svga->hblankstart = (((mystique->crtcext_regs[1] & 0x02) >> 2) << 8) + svga->crtc[2] + 1; + svga->hblankstart = (((mystique->crtcext_regs[1] & 0x02) >> 2) << 8) + svga->crtc[2]; if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL10) svga->vtotal |= 0x400; @@ -976,11 +977,10 @@ mystique_recalctimings(svga_t *svga) svga->hdisp_time = svga->hdisp; svga->rowoffset = svga->crtc[0x13] | ((mystique->crtcext_regs[0] & CRTCX_R0_OFFSET_MASK) << 4); - svga->dots_per_clock = 8; - svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | - (((mystique->crtcext_regs[1] & 0x40) >> 6) << 6); - - svga->hblank_overscan = 0; + svga->dots_per_clock = 8; + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((mystique->crtcext_regs[1] & 0x40) >> 6) << 6); + svga->hblank_end_mask = 0x0000007f; if (mystique->type != MGA_2164W && mystique->type != MGA_2064W) svga->lut_map = !!(mystique->xmiscctrl & XMISCCTRL_RAMCS); @@ -1138,7 +1138,7 @@ mystique_recalc_mapping(mystique_t *mystique) switch (svga->gdcreg[6] & 0x0C) { case 0x0: /*128k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); - svga->banked_mask = 0x1ffff; + svga->banked_mask = 0xffff; break; case 0x4: /*64k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); @@ -2394,10 +2394,10 @@ mystique_accel_ctrl_write_l(uint32_t addr, uint32_t val, void *priv) break; case REG_SHIFT: - mystique->dwgreg.funcnt = val & 0xff; + mystique->dwgreg.funcnt = val & 0x7f; mystique->dwgreg.xoff = val & 7; mystique->dwgreg.yoff = (val >> 4) & 7; - mystique->dwgreg.stylelen = (val >> 16) & 0xff; + mystique->dwgreg.stylelen = (val >> 16) & 0x7f; break; case REG_PITCH: @@ -2601,7 +2601,7 @@ mystique_accel_ctrl_write_l(uint32_t addr, uint32_t val, void *priv) case REG_ALPHACTRL: mystique->dwgreg.alphactrl = val; break; - + case REG_ALPHASTART: mystique->dwgreg.alphastart = val; break; @@ -2617,7 +2617,7 @@ mystique_accel_ctrl_write_l(uint32_t addr, uint32_t val, void *priv) case REG_FOGCOL: mystique->dwgreg.fogcol = val; break; - + case REG_FOGSTART: mystique->dwgreg.fogstart = val; break; @@ -2678,7 +2678,7 @@ mystique_ctrl_write_l(uint32_t addr, uint32_t val, void *priv) wake_fifo_thread(mystique); } /* HACK: For DirectX 9.0b Direct3D testing on Windows 98 SE. - + The 4.12.013 drivers give an out-of-bounds busmastering range when dxdiag enumerates Direct3D, with exactly 16384 bytes of difference. Don't attempt busmastering in such cases. This isn't ideal, but there are no more crashes faced in this case. */ if ((mystique->dma.primend & DMA_ADDR_MASK) < (mystique->dma.primaddress & DMA_ADDR_MASK) && ((mystique->dma.primaddress & DMA_ADDR_MASK) - (mystique->dma.primend & DMA_ADDR_MASK)) == 0x4000) @@ -2811,15 +2811,16 @@ static uint8_t mystique_readb_linear(uint32_t addr, void *priv) { const svga_t *svga = (svga_t *) priv; - mystique_t *mystique = (mystique_t *) svga->priv; - - if (mystique->type < MGA_1064SG) { - if (!svga->fast) - return svga_read_linear(addr, priv); - } cycles -= svga->monitor->mon_video_timing_read_b; + if (!svga->fast) { + if (svga->chain2_read) { + addr &= ~1; + addr <<= 2; + } + } + addr &= svga->decode_mask; if (addr >= svga->vram_max) return 0xff; @@ -2859,17 +2860,16 @@ static void mystique_writeb_linear(uint32_t addr, uint8_t val, void *priv) { svga_t *svga = (svga_t *) priv; - mystique_t *mystique = (mystique_t *) svga->priv; - - if (mystique->type < MGA_1064SG) { - if (!svga->fast) { - svga_write_linear(addr, val, priv); - return; - } - } cycles -= svga->monitor->mon_video_timing_write_b; + if (!svga->fast) { + if (svga->chain2_write) { + addr &= ~1; + addr <<= 2; + } + } + addr &= svga->decode_mask; if (addr >= svga->vram_max) return; @@ -3229,7 +3229,7 @@ mystique_softrap_pending_timer(void *priv) mystique_update_irqs(mystique); mystique->softrap_pending--; } - + } static void @@ -4309,21 +4309,19 @@ z_check_32(uint32_t z, uint32_t old_z, uint32_t z_mode) // mystique->dwgreg.dwgc } static void -blit_line(mystique_t *mystique, int closed) +blit_line(mystique_t *mystique, int closed, int autoline) { svga_t *svga = &mystique->svga; uint32_t src = 0; uint32_t dst; uint32_t old_dst; - int x; - int len = 0; + int x = mystique->dwgreg.xdst; int z_write; switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { case DWGCTRL_ATYPE_RSTR: case DWGCTRL_ATYPE_RPL: - x = mystique->dwgreg.xdst; - while (len <= mystique->dwgreg.length) { + while (mystique->dwgreg.length >= 0) { if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { case MACCESS_PWIDTH_8: @@ -4334,7 +4332,10 @@ blit_line(mystique_t *mystique, int closed) if (closed) { svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; - } else if (!closed && (len < mystique->dwgreg.length)) { + } else if (!closed && (mystique->dwgreg.length > 0) && ((mystique->dwgreg.err > 0) || (mystique->dwgreg.err < 0)) && !autoline) { + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; + } else if (!closed && (mystique->dwgreg.length > 0) && autoline) { svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; } @@ -4348,7 +4349,10 @@ blit_line(mystique_t *mystique, int closed) if (closed) { ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; - } else if (!closed && (len < mystique->dwgreg.length)) { + } else if (!closed && (mystique->dwgreg.length > 0) && ((mystique->dwgreg.err > 0) || (mystique->dwgreg.err < 0)) && !autoline) { + ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + } else if (!closed && (mystique->dwgreg.length > 0) && autoline) { ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; } @@ -4362,7 +4366,10 @@ blit_line(mystique_t *mystique, int closed) if (closed) { *(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; - } else if (!closed && (len < mystique->dwgreg.length)) { + } else if (!closed && (mystique->dwgreg.length > 0) && ((mystique->dwgreg.err > 0) || (mystique->dwgreg.err < 0)) && !autoline) { + *(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; + } else if (!closed && (mystique->dwgreg.length > 0) && autoline) { *(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; } @@ -4376,7 +4383,10 @@ blit_line(mystique_t *mystique, int closed) if (closed) { ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst; svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; - } else if (!closed && (len < mystique->dwgreg.length)) { + } else if (!closed && (mystique->dwgreg.length > 0) && ((mystique->dwgreg.err > 0) || (mystique->dwgreg.err < 0)) && !autoline) { + ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; + } else if (!closed && (mystique->dwgreg.length > 0) && autoline) { ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst; svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; } @@ -4387,28 +4397,34 @@ blit_line(mystique_t *mystique, int closed) } } + if (!mystique->dwgreg.length) + break; + if (mystique->dwgreg.sgn.sdydxl) x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); - else + else { + mystique->dwgreg.ydst += (mystique->dwgreg.sgn.sdy ? -1 : 1); + mystique->dwgreg.ydst &= 0x7fffff; mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); - - if ((int32_t) mystique->dwgreg.ar[1] >= 0) { - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; - if (mystique->dwgreg.sgn.sdydxl) + } + if (mystique->dwgreg.err >= 0) { + mystique->dwgreg.err += mystique->dwgreg.k2; + if (mystique->dwgreg.sgn.sdydxl) { + mystique->dwgreg.ydst += (mystique->dwgreg.sgn.sdy ? -1 : 1); + mystique->dwgreg.ydst &= 0x7fffff; mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); - else + } else x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); } else - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + mystique->dwgreg.err += mystique->dwgreg.k1; - len++; + mystique->dwgreg.length--; } break; case DWGCTRL_ATYPE_I: case DWGCTRL_ATYPE_ZI: z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI); - x = mystique->dwgreg.xdst; while (mystique->dwgreg.length > 0) { if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { bool z_check_pass = false; @@ -4471,8 +4487,8 @@ blit_line(mystique_t *mystique, int closed) mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10]; mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14]; - if ((int32_t) mystique->dwgreg.ar[1] >= 0) { - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + if (mystique->dwgreg.err >= 0) { + mystique->dwgreg.err += mystique->dwgreg.k2; if (mystique->dwgreg.sgn.sdydxl) mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); @@ -4490,7 +4506,7 @@ blit_line(mystique_t *mystique, int closed) mystique->dwgreg.dr[8] += mystique->dwgreg.dr[11]; mystique->dwgreg.dr[12] += mystique->dwgreg.dr[15]; } else - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + mystique->dwgreg.err += mystique->dwgreg.k1; mystique->dwgreg.length--; } @@ -4507,7 +4523,7 @@ blit_line(mystique_t *mystique, int closed) } static void -blit_autoline(mystique_t *mystique, int closed) +blit_line_start(mystique_t *mystique, int closed, int autoline) { int start_x = (int32_t) mystique->dwgreg.ar[5]; int start_y = (int32_t) mystique->dwgreg.ar[6]; @@ -4516,29 +4532,37 @@ blit_autoline(mystique_t *mystique, int closed) int dx = end_x - start_x; int dy = end_y - start_y; - if (ABS(dx) > ABS(dy)) { - mystique->dwgreg.sgn.sdydxl = 1; - mystique->dwgreg.ar[0] = 2 * ABS(dy); - mystique->dwgreg.ar[1] = 2 * ABS(dy) - ABS(dx) - ((start_y > end_y) ? 1 : 0); - mystique->dwgreg.ar[2] = 2 * ABS(dy) - 2 * ABS(dx); - mystique->dwgreg.length = ABS(end_x - start_x); + if (autoline) { + if (ABS(dx) > ABS(dy)) { + mystique->dwgreg.sgn.sdydxl = 1; + mystique->dwgreg.k1 = 2 * ABS(dy); + mystique->dwgreg.err = 2 * ABS(dy) - ABS(dx) - ((start_y > end_y) ? 1 : 0); + mystique->dwgreg.k2 = 2 * ABS(dy) - 2 * ABS(dx); + mystique->dwgreg.length = ABS(end_x - start_x); + } else { + mystique->dwgreg.sgn.sdydxl = 0; + mystique->dwgreg.k1 = 2 * ABS(dx); + mystique->dwgreg.err = 2 * ABS(dx) - ABS(dy) - ((start_y > end_y) ? 1 : 0); + mystique->dwgreg.k2 = 2 * ABS(dx) - 2 * ABS(dy); + mystique->dwgreg.length = ABS(end_y - start_y); + } + mystique->dwgreg.sgn.sdxl = (start_x > end_x) ? 1 : 0; + mystique->dwgreg.sgn.sdy = (start_y > end_y) ? 1 : 0; } else { - mystique->dwgreg.sgn.sdydxl = 0; - mystique->dwgreg.ar[0] = 2 * ABS(dx); - mystique->dwgreg.ar[1] = 2 * ABS(dx) - ABS(dy) - ((start_y > end_y) ? 1 : 0); - mystique->dwgreg.ar[2] = 2 * ABS(dx) - 2 * ABS(dy); - mystique->dwgreg.length = ABS(end_y - start_y); + mystique->dwgreg.k1 = (int32_t) mystique->dwgreg.ar[0]; + mystique->dwgreg.err = (int32_t) mystique->dwgreg.ar[1]; + mystique->dwgreg.k2 = (int32_t) mystique->dwgreg.ar[2]; } - mystique->dwgreg.sgn.sdxl = (start_x > end_x) ? 1 : 0; - mystique->dwgreg.sgn.sdy = (start_y > end_y) ? 1 : 0; - blit_line(mystique, closed); + blit_line(mystique, closed, autoline); - mystique->dwgreg.ar[5] = end_x; - mystique->dwgreg.xdst = end_x; - mystique->dwgreg.ar[6] = end_y; - mystique->dwgreg.ydst = end_y; - mystique->dwgreg.ydst_lin = ((int32_t) (int16_t) mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; + if (autoline) { + mystique->dwgreg.ar[5] = end_x; + mystique->dwgreg.xdst = end_x; + mystique->dwgreg.ar[6] = end_y; + mystique->dwgreg.ydst = end_y; + mystique->dwgreg.ydst_lin = ((int32_t) (int16_t) mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; + } } static void @@ -4552,6 +4576,8 @@ blit_trap(mystique_t *mystique) uint32_t b_back; int z_write; int y; + int err_l = (int32_t)mystique->dwgreg.ar[1]; + int err_r = (int32_t)mystique->dwgreg.ar[4]; const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { @@ -4562,8 +4588,14 @@ blit_trap(mystique_t *mystique) int16_t x_l = mystique->dwgreg.fxleft & 0xffff; int16_t x_r = mystique->dwgreg.fxright & 0xffff; int yoff = (mystique->dwgreg.yoff + mystique->dwgreg.ydst) & 7; + int len; - while (x_l != x_r) { + if (x_l > x_r) + len = x_l - x_r; + else + len = x_r - x_l; + + while (len > 0) { if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && trans[x_l & 3]) { int xoff = (mystique->dwgreg.xoff + (x_l & 7)) & 15; int pattern = mystique->dwgreg.pattern[yoff][xoff]; @@ -4595,24 +4627,21 @@ blit_trap(mystique_t *mystique) fatal("TRAP BLK/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); } } - if (x_l > x_r) - x_l--; - else - x_l++; - + len--; + x_l++; } - while ((int32_t) mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + while ((err_l < 0) && mystique->dwgreg.ar[0]) { + err_l += mystique->dwgreg.ar[0]; mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); } - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + err_l += mystique->dwgreg.ar[2]; - while ((int32_t) mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { - mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; + while ((err_r < 0) && mystique->dwgreg.ar[6]) { + err_r += mystique->dwgreg.ar[6]; mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); } - mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; + err_r += mystique->dwgreg.ar[5]; mystique->dwgreg.ydst++; mystique->dwgreg.ydst &= 0x7fffff; @@ -4628,8 +4657,14 @@ blit_trap(mystique_t *mystique) int16_t x_l = mystique->dwgreg.fxleft & 0xffff; int16_t x_r = mystique->dwgreg.fxright & 0xffff; int yoff = (mystique->dwgreg.yoff + mystique->dwgreg.ydst) & 7; + int len; - while (x_l != x_r) { + if (x_l > x_r) + len = x_l - x_r; + else + len = x_r - x_l; + + while (len > 0) { if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && trans[x_l & 3]) { int xoff = (mystique->dwgreg.xoff + (x_l & 7)) & 15; int pattern = mystique->dwgreg.pattern[yoff][xoff]; @@ -4674,23 +4709,21 @@ blit_trap(mystique_t *mystique) fatal("TRAP RSTR PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); } } - if (x_l > x_r) - x_l--; - else - x_l++; + x_l++; + len--; } - while ((int32_t) mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + while ((err_l < 0) && mystique->dwgreg.ar[0]) { + err_l += mystique->dwgreg.ar[0]; mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); } - mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + err_l += mystique->dwgreg.ar[2]; - while ((int32_t) mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { - mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; + while ((err_r < 0) && mystique->dwgreg.ar[6]) { + err_r += mystique->dwgreg.ar[6]; mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); } - mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; + err_r += mystique->dwgreg.ar[5]; mystique->dwgreg.ydst++; mystique->dwgreg.ydst &= 0x7fffff; @@ -5793,27 +5826,32 @@ blit_iload_highv(mystique_t *mystique) static void mystique_start_blit(mystique_t *mystique) { + svga_t *svga = &mystique->svga; uint64_t start_time = plat_timer_read(); uint64_t end_time; + /*Make sure we don't get any artifacts.*/ + svga->chain2_write = 0; + svga->chain2_read = 0; + mystique->dwgreg.dwgctrl_running = mystique->dwgreg.dwgctrl; mystique->maccess_running = mystique->maccess; switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) { case DWGCTRL_OPCODE_LINE_OPEN: - blit_line(mystique, 0); + blit_line_start(mystique, 0, 0); break; case DWGCTRL_OPCODE_AUTOLINE_OPEN: - blit_autoline(mystique, 0); + blit_line_start(mystique, 0, 1); break; case DWGCTRL_OPCODE_LINE_CLOSE: - blit_line(mystique, 1); + blit_line_start(mystique, 1, 0); break; case DWGCTRL_OPCODE_AUTOLINE_CLOSE: - blit_autoline(mystique, 1); + blit_line_start(mystique, 1, 1); break; case DWGCTRL_OPCODE_TRAP: @@ -5882,9 +5920,9 @@ mystique_hwcursor_draw(svga_t *svga, int displine) case XCURCTRL_CURMODE_XGA: for (uint8_t x = 0; x < 64; x++) { if (!(dat[1] & (1ULL << 63))) - svga->monitor->target_buffer->line[displine][offset + svga->x_add] = (dat[0] & (1ULL << 63)) ? svga_lookup_lut_ram(svga, mystique->cursor.col[1]) : svga_lookup_lut_ram(svga, mystique->cursor.col[0]); + svga->monitor->target_buffer->line[displine][(offset + svga->x_add) & 2047] = (dat[0] & (1ULL << 63)) ? svga_lookup_lut_ram(svga, mystique->cursor.col[1]) : svga_lookup_lut_ram(svga, mystique->cursor.col[0]); else if (dat[0] & (1ULL << 63)) - svga->monitor->target_buffer->line[displine][offset + svga->x_add] ^= 0xffffff; + svga->monitor->target_buffer->line[displine][(offset + svga->x_add) & 2047] ^= 0xffffff; offset++; dat[0] <<= 1; @@ -5927,15 +5965,6 @@ mystique_pci_read(UNUSED(int func), int addr, void *priv) mystique_t *mystique = (mystique_t *) priv; uint8_t ret = 0x00; - if (mystique->type >= MGA_1164SG) - { - /* Mystique 220, Millennium II and later Matrox cards swap MGABASE1 and 2. */ - if (addr >= 0x10 && addr <= 0x13) - addr += 0x4; - else if (addr >= 0x14 && addr <= 0x17) - addr -= 0x4; - } - if ((addr >= 0x30) && (addr <= 0x33) && !(mystique->pci_regs[0x43] & 0x40)) ret = 0x00; else @@ -5990,25 +6019,46 @@ mystique_pci_read(UNUSED(int func), int addr, void *priv) case 0x10: ret = 0x00; - break; /*Control aperture*/ + break; /*Control aperture for Millennium and Mystique, LFB for Mystique 220 and later*/ case 0x11: - ret = (mystique->ctrl_base >> 8) & 0xc0; + if (mystique->type >= MGA_1164SG) + ret = 0x00; + else + ret = (mystique->ctrl_base >> 8) & 0xc0; break; case 0x12: - ret = mystique->ctrl_base >> 16; + if (mystique->type >= MGA_1164SG) + ret = (mystique->type >= MGA_2164W) ? 0x00 : ((mystique->lfb_base >> 16) & 0x80); + else + ret = mystique->ctrl_base >> 16; break; case 0x13: - ret = mystique->ctrl_base >> 24; + if (mystique->type >= MGA_1164SG) + ret = mystique->lfb_base >> 24; + else + ret = mystique->ctrl_base >> 24; break; case 0x14: ret = 0x00; - break; /*Linear frame buffer*/ + break; /*LFB for Millennium and Mystique, Control aperture for Mystique 220 and later*/ + case 0x15: + if (mystique->type >= MGA_1164SG) + ret = (mystique->ctrl_base >> 8) & 0xc0; + else + ret = 0x00; + break; case 0x16: - ret = (mystique->type >= MGA_2164W) ? 0x00 : ((mystique->lfb_base >> 16) & 0x80); + if (mystique->type >= MGA_1164SG) + ret = mystique->ctrl_base >> 16; + else + ret = (mystique->lfb_base >> 16) & 0x80; break; case 0x17: - ret = mystique->lfb_base >> 24; + if (mystique->type >= MGA_1164SG) + ret = mystique->ctrl_base >> 24; + else + ret = mystique->lfb_base >> 24; break; case 0x18: @@ -6046,9 +6096,9 @@ mystique_pci_read(UNUSED(int func), int addr, void *priv) case 0x33: ret = mystique->pci_regs[0x33]; break; - + case 0x34: - ret = mystique->type == MGA_G100 ? 0xdc : 0x00; + ret = (mystique->type == MGA_G100) ? 0xdc : 0x00; break; case 0x3c: @@ -6089,7 +6139,7 @@ mystique_pci_read(UNUSED(int func), int addr, void *priv) case 0xdc: ret = 0x01; break; - + case 0xdd: ret = 0xf0; break; @@ -6097,7 +6147,7 @@ mystique_pci_read(UNUSED(int func), int addr, void *priv) case 0xde: ret = 0x21; break; - + /* No support for turning off the video adapter yet. */ case 0xe0: ret = 0x0; @@ -6106,19 +6156,19 @@ mystique_pci_read(UNUSED(int func), int addr, void *priv) case 0xf0: ret = 0x02; break; - + case 0xf1: ret = 0x00; break; - + case 0xf2: ret = 0x10; break; - + case 0xf4: ret = 0x1; break; - + case 0xf5: ret = 0x2; break; @@ -6126,15 +6176,15 @@ mystique_pci_read(UNUSED(int func), int addr, void *priv) case 0xf7: ret = 0x1; break; - + case 0xf8: ret = mystique->pci_regs[0xf8] & 0x7; break; - + case 0xf9: ret = mystique->pci_regs[0xf9] & 0x3; break; - + case 0xfb: ret = mystique->pci_regs[0xfb]; break; @@ -6151,15 +6201,6 @@ mystique_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) { mystique_t *mystique = (mystique_t *) priv; - if (mystique->type >= MGA_1164SG) - { - /* Mystique 220, Millennium II and later Matrox cards swap MGABASE1 and 2. */ - if (addr >= 0x10 && addr <= 0x13) - addr += 0x4; - else if (addr >= 0x14 && addr <= 0x17) - addr -= 0x4; - } - switch (addr) { case PCI_REG_COMMAND: mystique->pci_regs[PCI_REG_COMMAND] = (val & 0x27) | 0x80; @@ -6175,27 +6216,61 @@ mystique_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) break; case 0x11: - mystique->ctrl_base = (mystique->ctrl_base & 0xffff0000) | ((val & 0xc0) << 8); - mystique_recalc_mapping(mystique); + if (mystique->type >= MGA_1164SG) + break; + else { + mystique->ctrl_base = (mystique->ctrl_base & 0xffff0000) | ((val & 0xc0) << 8); + mystique_recalc_mapping(mystique); + } break; case 0x12: - mystique->ctrl_base = (mystique->ctrl_base & 0xff00c000) | (val << 16); - mystique_recalc_mapping(mystique); + if (mystique->type >= MGA_1164SG) { + if (mystique->type >= MGA_2164W) + break; + mystique->lfb_base = (mystique->lfb_base & 0xff000000) | ((val & 0x80) << 16); + mystique_recalc_mapping(mystique); + } else { + mystique->ctrl_base = (mystique->ctrl_base & 0xff00c000) | (val << 16); + mystique_recalc_mapping(mystique); + } break; case 0x13: - mystique->ctrl_base = (mystique->ctrl_base & 0x00ffc000) | (val << 24); - mystique_recalc_mapping(mystique); + if (mystique->type >= MGA_1164SG) { + if (mystique->type >= MGA_2164W) + mystique->lfb_base = val << 24; + else + mystique->lfb_base = (mystique->lfb_base & 0x00800000) | (val << 24); + + mystique_recalc_mapping(mystique); + } else { + mystique->ctrl_base = (mystique->ctrl_base & 0x00ffc000) | (val << 24); + mystique_recalc_mapping(mystique); + } break; + case 0x15: + if (mystique->type >= MGA_1164SG) { + mystique->ctrl_base = (mystique->ctrl_base & 0xffff0000) | ((val & 0xc0) << 8); + mystique_recalc_mapping(mystique); + } + break; case 0x16: - if (mystique->type >= MGA_2164W) - break; - mystique->lfb_base = (mystique->lfb_base & 0xff000000) | ((val & 0x80) << 16); - mystique_recalc_mapping(mystique); + if (mystique->type >= MGA_1164SG) { + mystique->ctrl_base = (mystique->ctrl_base & 0xff00c000) | (val << 16); + mystique_recalc_mapping(mystique); + } else { + mystique->lfb_base = (mystique->lfb_base & 0xff000000) | ((val & 0x80) << 16); + mystique_recalc_mapping(mystique); + } break; case 0x17: - mystique->lfb_base = (mystique->lfb_base & ((mystique->type >= MGA_2164W) ? 0x00000000 : 0x00800000)) | (val << 24); - mystique_recalc_mapping(mystique); + if (mystique->type >= MGA_1164SG) { + mystique->ctrl_base = (mystique->ctrl_base & 0x00ffc000) | (val << 24); + mystique_recalc_mapping(mystique); + } else { + mystique->lfb_base = (mystique->lfb_base & 0x00800000) | (val << 24); + mystique_recalc_mapping(mystique); + } break; case 0x1a: @@ -6216,8 +6291,8 @@ mystique_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) if (addr == 0x30) mystique->pci_regs[addr] &= 1; if (mystique->pci_regs[0x30] & 0x01) { - uint32_t addr = (mystique->pci_regs[0x32] << 16) | (mystique->pci_regs[0x33] << 24); - mem_mapping_set_addr(&mystique->bios_rom.mapping, addr, (mystique->type == MGA_G100) ? 0x10000 : 0x8000); + uint32_t biosaddr = (mystique->pci_regs[0x32] << 16) | (mystique->pci_regs[0x33] << 24); + mem_mapping_set_addr(&mystique->bios_rom.mapping, biosaddr, (mystique->type == MGA_G100) ? 0x10000 : 0x8000); } else mem_mapping_disable(&mystique->bios_rom.mapping); return; @@ -6240,8 +6315,8 @@ mystique_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) if (addr == 0x43) { if (val & 0x40) { if (mystique->pci_regs[0x30] & 0x01) { - uint32_t addr = (mystique->pci_regs[0x32] << 16) | (mystique->pci_regs[0x33] << 24); - mem_mapping_set_addr(&mystique->bios_rom.mapping, addr, (mystique->type == MGA_G100) ? 0x10000 : 0x8000); + uint32_t biosaddr = (mystique->pci_regs[0x32] << 16) | (mystique->pci_regs[0x33] << 24); + mem_mapping_set_addr(&mystique->bios_rom.mapping, biosaddr, (mystique->type == MGA_G100) ? 0x10000 : 0x8000); } else mem_mapping_disable(&mystique->bios_rom.mapping); } else @@ -6277,11 +6352,11 @@ mystique_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) case 0xf8: mystique->pci_regs[0xf8] = val & 0x7; break; - + case 0xf9: mystique->pci_regs[0xf9] = val & 0x3; break; - + case 0xfb: mystique->pci_regs[0xfb] = val; break; @@ -6369,8 +6444,8 @@ mystique_init(const device_t *info) mystique->svga.clock_gen = mystique->svga.ramdac; mystique->svga.getclock = tvp3026_getclock; mystique->svga.conv_16to32 = tvp3026_conv_16to32; - if (mystique->vram_size >= 16) - mystique->svga.decode_mask = mystique->svga.vram_mask; + if (mystique->type == MGA_2164W) + mystique->svga.decode_mask = 0xffffff; tvp3026_gpio(mystique_tvp3026_gpio_read, mystique_tvp3026_gpio_write, mystique, mystique->svga.ramdac); } else { video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_matrox_mystique); @@ -6381,8 +6456,8 @@ mystique_init(const device_t *info) NULL); mystique->svga.clock_gen = mystique; mystique->svga.getclock = mystique_getclock; - if (mystique->vram_size >= 16) - mystique->svga.decode_mask = mystique->svga.vram_mask; + if (mystique->type == MGA_G100) + mystique->svga.decode_mask = 0xffffff; } io_sethandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique); @@ -6455,7 +6530,7 @@ mystique_init(const device_t *info) timer_add(&mystique->softrap_pending_timer, mystique_softrap_pending_timer, (void *) mystique, 1); mystique->status = STATUS_ENDPRDMASTS; - + mystique->softrap_status_read = 1; mystique->svga.vsync_callback = mystique_vsync_callback; diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index ad197f302..30666e82c 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -51,7 +51,7 @@ typedef struct paradise_t { uint32_t read_bank[4], write_bank[4]; int interlace; - int check, check2; + int check; struct { uint8_t reg_block_ptr; @@ -79,6 +79,7 @@ paradise_in(uint16_t addr, void *priv) { paradise_t *paradise = (paradise_t *) priv; svga_t *svga = ¶dise->svga; + uint8_t temp = 0; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; @@ -109,13 +110,14 @@ paradise_in(uint16_t addr, void *priv) } switch (svga->gdcaddr) { case 0x0b: + temp = svga->gdcreg[0x0b]; if (paradise->type == WD90C30) { if (paradise->vram_mask == ((512 << 10) - 1)) { - svga->gdcreg[0x0b] |= 0xc0; - svga->gdcreg[0x0b] &= ~0x40; + temp &= ~0x40; + temp |= 0xc0; } } - return svga->gdcreg[0x0b]; + return temp; case 0x0f: return (svga->gdcreg[0x0f] & 0x17) | 0x80; @@ -184,9 +186,10 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) return; } + old = svga->gdcreg[svga->gdcaddr]; switch (svga->gdcaddr) { case 6: - if ((svga->gdcreg[6] & 0x0c) != (val & 0x0c)) { + if (old ^ (val & 0x0c)) { switch (val & 0x0c) { case 0x00: /*128k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); @@ -208,9 +211,9 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) default: break; } + svga->gdcreg[6] = val; + paradise_remap(paradise); } - svga->gdcreg[6] = val; - paradise_remap(paradise); return; case 9: @@ -222,6 +225,10 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) svga->gdcreg[0x0b] = val; paradise_remap(paradise); return; + case 0x0e: + svga->gdcreg[0x0e] = val; + svga_recalctimings(svga); + return; default: break; @@ -258,15 +265,6 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) } break; - case 0x46e8: - io_removehandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise); - mem_mapping_disable(¶dise->svga.mapping); - if (val & 8) { - io_sethandler(0x03c0, 0x0020, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise); - mem_mapping_enable(¶dise->svga.mapping); - } - break; - default: break; } @@ -277,7 +275,7 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) void paradise_remap(paradise_t *paradise) { - const svga_t *svga = ¶dise->svga; + svga_t *svga = ¶dise->svga; paradise->check = 0; @@ -319,8 +317,6 @@ paradise_recalctimings(svga_t *svga) { const paradise_t *paradise = (paradise_t *) svga->priv; - svga->lowres = !(svga->gdcreg[0x0e] & 0x01); - if (paradise->type == WD90C30) { if (svga->crtc[0x3e] & 0x01) svga->vtotal |= 0x400; @@ -335,50 +331,42 @@ paradise_recalctimings(svga_t *svga) svga->interlace = !!(svga->crtc[0x2d] & 0x20); - if (!svga->interlace && svga->lowres && (svga->hdisp >= 1024) && ((svga->gdcreg[5] & 0x60) == 0) && (svga->miscout >= 0x27) && (svga->miscout <= 0x2f) && ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1))) { /*Horrible tweak to re-enable the interlace after returning to + if (!svga->interlace && !(svga->gdcreg[0x0e] & 0x01) && (svga->hdisp >= 1024) && ((svga->gdcreg[5] & 0x60) == 0) && (svga->miscout >= 0x27) && (svga->miscout <= 0x2f) && ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1))) { /*Horrible tweak to re-enable the interlace after returning to a windowed DOS box in Win3.x*/ svga->interlace = 1; } } - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - svga->interlace = 0; - } - if (paradise->type < WD90C30) { - if ((svga->bpp >= 8) && !svga->lowres) { - svga->render = svga_render_8bpp_highres; - } - } else { - if ((svga->bpp >= 8) && !svga->lowres) { - if (svga->bpp == 16) { - svga->render = svga_render_16bpp_highres; - svga->hdisp >>= 1; - if (svga->hdisp == 788) - svga->hdisp += 12; - if (svga->hdisp == 800) - svga->ma_latch -= 3; - } else if (svga->bpp == 15) { - svga->render = svga_render_15bpp_highres; - svga->hdisp >>= 1; - if (svga->hdisp == 788) - svga->hdisp += 12; - if (svga->hdisp == 800) - svga->ma_latch -= 3; - } else { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if ((svga->bpp >= 8) && (svga->gdcreg[0x0e] & 0x01)) { svga->render = svga_render_8bpp_highres; } } + } else { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if ((svga->bpp >= 8) && (svga->gdcreg[0x0e] & 0x01)) { + if (svga->bpp == 16) { + svga->render = svga_render_16bpp_highres; + svga->hdisp >>= 1; + if (svga->hdisp == 788) + svga->hdisp += 12; + if (svga->hdisp == 800) + svga->ma_latch -= 3; + } else if (svga->bpp == 15) { + svga->render = svga_render_15bpp_highres; + svga->hdisp >>= 1; + if (svga->hdisp == 788) + svga->hdisp += 12; + if (svga->hdisp == 800) + svga->ma_latch -= 3; + } else { + svga->render = svga_render_8bpp_highres; + } + } + } } - - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - if (svga->hdisp == 360) - svga->hdisp <<= 1; - if (svga->seqregs[1] & 8) { - svga->render = svga_render_text_40; - } else - svga->render = svga_render_text_80; - } + svga->vram_display_mask = (svga->crtc[0x2f] & 0x02) ? 0x3ffff : paradise->vram_mask; } static void @@ -389,10 +377,15 @@ paradise_write(uint32_t addr, uint8_t val, void *priv) uint32_t prev_addr; uint32_t prev_addr2; + if (!(svga->gdcreg[5] & 0x40)) { + svga_write(addr, val, svga); + return; + } + addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; /*Could be done in a better way but it works.*/ - if (!svga->lowres) { + if (svga->gdcreg[0x0e] & 0x01) { if (paradise->check) { prev_addr = addr & 3; prev_addr2 = addr & 0xfffc; @@ -427,7 +420,6 @@ paradise_write(uint32_t addr, uint8_t val, void *priv) } } } - svga_write_linear(addr, val, svga); } static void @@ -438,10 +430,15 @@ paradise_writew(uint32_t addr, uint16_t val, void *priv) uint32_t prev_addr; uint32_t prev_addr2; + if (!(svga->gdcreg[5] & 0x40)) { + svga_writew(addr, val, svga); + return; + } + addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; /*Could be done in a better way but it works.*/ - if (!svga->lowres) { + if (svga->gdcreg[0x0e] & 0x01) { if (paradise->check) { prev_addr = addr & 3; prev_addr2 = addr & 0xfffc; @@ -476,7 +473,6 @@ paradise_writew(uint32_t addr, uint16_t val, void *priv) } } } - svga_writew_linear(addr, val, svga); } @@ -488,10 +484,14 @@ paradise_read(uint32_t addr, void *priv) uint32_t prev_addr; uint32_t prev_addr2; + if (!(svga->gdcreg[5] & 0x40)) { + return svga_read(addr, svga); + } + addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; /*Could be done in a better way but it works.*/ - if (!svga->lowres) { + if (svga->gdcreg[0x0e] & 0x01) { if (paradise->check) { prev_addr = addr & 3; prev_addr2 = addr & 0xfffc; @@ -526,7 +526,6 @@ paradise_read(uint32_t addr, void *priv) } } } - return svga_read_linear(addr, svga); } static uint16_t @@ -537,10 +536,14 @@ paradise_readw(uint32_t addr, void *priv) uint32_t prev_addr; uint32_t prev_addr2; + if (!(svga->gdcreg[5] & 0x40)) { + return svga_readw(addr, svga); + } + addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; /*Could be done in a better way but it works.*/ - if (!svga->lowres) { + if (svga->gdcreg[0x0e] & 0x01) { if (paradise->check) { prev_addr = addr & 3; prev_addr2 = addr & 0xfffc; @@ -575,7 +578,6 @@ paradise_readw(uint32_t addr, void *priv) } } } - return svga_readw_linear(addr, svga); } @@ -641,7 +643,6 @@ paradise_init(const device_t *info, uint32_t memsize) case WD90C11: svga->crtc[0x36] = '1'; svga->crtc[0x37] = '1'; - io_sethandler(0x46e8, 0x0001, paradise_in, NULL, NULL, paradise_out, NULL, NULL, paradise); break; case WD90C30: svga->crtc[0x36] = '3'; diff --git a/src/video/vid_pgc.c b/src/video/vid_pgc.c index aa1517ddf..354c7e265 100644 --- a/src/video/vid_pgc.c +++ b/src/video/vid_pgc.c @@ -2736,7 +2736,7 @@ pgc_standalone_init(const device_t *info) } const device_t pgc_device = { - .name = "PGC", + .name = "IBM PGC", .internal_name = "pgc", .flags = DEVICE_ISA, .local = 0, diff --git a/src/video/vid_rtg310x.c b/src/video/vid_rtg310x.c index eef95a910..e82763d15 100644 --- a/src/video/vid_rtg310x.c +++ b/src/video/vid_rtg310x.c @@ -29,7 +29,8 @@ #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> -#define BIOS_ROM_PATH "roms/video/rtg/realtekrtg3106.BIN" +#define RTG_3105_BIOS_ROM_PATH "roms/video/rtg/RTG3105I.VBI" +#define RTG_3106_BIOS_ROM_PATH "roms/video/rtg/realtekrtg3106.BIN" typedef struct { const char *name; @@ -86,18 +87,18 @@ rtg_in(uint16_t addr, void *priv) return svga->crtcreg; case 0x3d5: - if (!(svga->crtc[0x1e] & 0x80) && (svga->crtcreg > 0x18)) - return 0xff; if (svga->crtcreg == 0x1a) return dev->type << 6; if (svga->crtcreg == 0x1e) { + ret = svga->crtc[0x1e]; + ret &= ~3; if (dev->vram_size == 1024) ret = 2; else if (dev->vram_size == 512) ret = 1; else ret = 0; - return svga->crtc[0x1e] | ret; + return ret; } return svga->crtc[svga->crtcreg]; @@ -208,13 +209,12 @@ rtg_out(uint16_t addr, uint8_t val, void *priv) static void rtg_recalctimings(svga_t *svga) { - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + const rtg_t *dev = (rtg_t *) svga->priv; + svga->ma_latch |= ((svga->crtc[0x19] & 0x10) << 16) | ((svga->crtc[0x19] & 0x40) << 17); svga->interlace = (svga->crtc[0x19] & 1); - svga->lowres = svga->attrregs[0x10] & 0x40; - /*Clock table not available, currently a guesswork*/ switch (((svga->miscout >> 2) & 3) | ((svga->gdcreg[0x0c] & 0x20) >> 3)) { case 0: @@ -258,50 +258,41 @@ rtg_recalctimings(svga_t *svga) break; } - if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { - switch (svga->gdcreg[5] & 0x60) { - case 0x00: - if (svga->seqregs[1] & 8) /*Low res (320)*/ - svga->render = svga_render_4bpp_lowres; - else { - svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5); - svga->hdisp++; - svga->hdisp *= 8; + if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + switch (svga->gdcreg[5] & 0x60) { + case 0x00: + if (svga->seqregs[1] & 8) /*Low res (320)*/ + svga->render = svga_render_4bpp_lowres; + else { + if (svga->hdisp == 1280) + svga->rowoffset >>= 1; - if (svga->hdisp == 1280) - svga->rowoffset >>= 1; - - svga->render = svga_render_4bpp_highres; - } - break; - case 0x20: /*4 colours*/ - if (svga->seqregs[1] & 8) /*Low res (320)*/ - svga->render = svga_render_2bpp_lowres; - else - svga->render = svga_render_2bpp_highres; - break; - case 0x40: - case 0x60: - svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5); - svga->hdisp++; - svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; - if (svga->crtc[0x19] & 2) { - if (svga->hdisp == 1280) { - svga->hdisp >>= 1; - } else - svga->rowoffset <<= 1; - - svga->render = svga_render_8bpp_highres; - } else { - if (svga->lowres) - svga->render = svga_render_8bpp_lowres; + svga->render = svga_render_4bpp_highres; + } + break; + case 0x20: /*4 colours*/ + if (svga->seqregs[1] & 8) /*Low res (320)*/ + svga->render = svga_render_2bpp_lowres; else - svga->render = svga_render_8bpp_highres; - } - break; + svga->render = svga_render_2bpp_highres; + break; + case 0x40: + case 0x60: + if (svga->crtc[0x19] & 2) { + if (svga->hdisp == 1280) + svga->hdisp >>= 1; + else if (dev->type == 2) + svga->rowoffset <<= 1; - default: - break; + svga->render = svga_render_8bpp_highres; + } else + svga->render = svga_render_8bpp_lowres; + break; + + default: + break; + } } } } @@ -316,13 +307,24 @@ rtg_init(const device_t *info) memset(dev, 0x00, sizeof(rtg_t)); dev->name = info->name; dev->type = info->local; - fn = BIOS_ROM_PATH; + fn = NULL; switch (dev->type) { - case 2: /* ISA RTG3106 */ - dev->vram_size = device_get_config_int("memory") << 10; + case 1: /* ISA RTG3105 */ + fn = RTG_3105_BIOS_ROM_PATH; + dev->vram_size = device_get_config_int("memory"); video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_rtg_isa); - svga_init(info, &dev->svga, dev, dev->vram_size, + svga_init(info, &dev->svga, dev, dev->vram_size << 10, + rtg_recalctimings, rtg_in, rtg_out, + NULL, NULL); + io_sethandler(0x03c0, 32, + rtg_in, NULL, NULL, rtg_out, NULL, NULL, dev); + break; + case 2: /* ISA RTG3106 */ + fn = RTG_3106_BIOS_ROM_PATH; + dev->vram_size = device_get_config_int("memory"); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_rtg_isa); + svga_init(info, &dev->svga, dev, dev->vram_size << 10, rtg_recalctimings, rtg_in, rtg_out, NULL, NULL); io_sethandler(0x03c0, 32, @@ -371,12 +373,45 @@ rtg_force_redraw(void *priv) } static int -rtg_available(void) +rtg3105_available(void) { - return rom_present(BIOS_ROM_PATH); + return rom_present(RTG_3105_BIOS_ROM_PATH); } -static const device_config_t rtg_config[] = { +static int +rtg3106_available(void) +{ + return rom_present(RTG_3106_BIOS_ROM_PATH); +} + +static const device_config_t rtg3105_config[] = { + // clang-format off + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 512, + .selection = { + { + .description = "256 KB", + .value = 256 + }, + { + .description = "512 KB", + .value = 512 + }, + { + .description = "" + } + } + }, + { + .type = CONFIG_END + } + // clang-format on +}; + +static const device_config_t rtg3106_config[] = { // clang-format off { .name = "memory", @@ -407,16 +442,30 @@ static const device_config_t rtg_config[] = { // clang-format on }; +const device_t realtek_rtg3105_device = { + .name = "Realtek RTG3105 (ISA)", + .internal_name = "rtg3105", + .flags = DEVICE_ISA, + .local = 1, + .init = rtg_init, + .close = rtg_close, + .reset = NULL, + { .available = rtg3105_available }, + .speed_changed = rtg_speed_changed, + .force_redraw = rtg_force_redraw, + .config = rtg3105_config +}; + const device_t realtek_rtg3106_device = { .name = "Realtek RTG3106 (ISA)", .internal_name = "rtg3106", - .flags = DEVICE_ISA | DEVICE_AT, + .flags = DEVICE_ISA, .local = 2, .init = rtg_init, .close = rtg_close, .reset = NULL, - { .available = rtg_available }, + { .available = rtg3106_available }, .speed_changed = rtg_speed_changed, .force_redraw = rtg_force_redraw, - .config = rtg_config + .config = rtg3106_config }; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 6de3ffce7..46ed8eba0 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -63,6 +63,7 @@ #define ROM_PHOENIX_TRIO64 "roms/video/s3/86c764x1.bin" #define ROM_DIAMOND_STEALTH64_764 "roms/video/s3/stealt64.bin" #define ROM_TRIO64V2_DX_VBE20 "roms/video/s3/86c775_2.bin" +#define ROM_STB_POWERGRAPH_64_VIDEO "roms/video/s3/VBIOS.BIN" #define ROM_PHOENIX_TRIO64VPLUS "roms/video/s3/64V1506.ROM" #define ROM_CARDEX_TRIO64VPLUS "roms/video/s3/S3T64VP.VBI" #define ROM_DIAMOND_STEALTH_SE "roms/video/s3/DiamondStealthSE.VBI" @@ -80,6 +81,7 @@ enum { S3_PARADISE_BAHAMAS64, S3_DIAMOND_STEALTH64_964, S3_PHOENIX_TRIO32, + S3_PHOENIX_TRIO32_ONBOARD, S3_PHOENIX_TRIO64, S3_PHOENIX_TRIO64_ONBOARD, S3_PHOENIX_VISION864, @@ -93,6 +95,7 @@ enum { S3_AMI_86C924, S3_TRIO64V2_DX, S3_TRIO64V2_DX_ONBOARD, + S3_STB_POWERGRAPH_64_VIDEO, S3_PHOENIX_TRIO64VPLUS, S3_PHOENIX_TRIO64VPLUS_ONBOARD, S3_CARDEX_TRIO64VPLUS, @@ -945,10 +948,6 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.cmd = (s3->accel.cmd & 0xff) | (val << 8); s3->accel.ssv_state = 0; s3->accel_start(-1, 0, 0xffffffff, 0, s3); - if (s3->bpp == 3) { - if (!(s3->accel.multifunc[0xe] & 0x200) && !(svga->crtc[0x32] & 0x40)) - s3->accel.multifunc[0xe] &= ~0x10; - } break; case 0x994a: @@ -984,16 +983,16 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0xa148: case 0xa2e8: if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.bkgd_color = (s3->accel.bkgd_color & 0xff00ffff) | (val << 16); + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); else - s3->accel.bkgd_color = (s3->accel.bkgd_color & 0xffffff00) | val; + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; break; case 0xa149: case 0xa2e9: if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.bkgd_color = (s3->accel.bkgd_color & 0x00ffffff) | (val << 24); + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); else - s3->accel.bkgd_color = (s3->accel.bkgd_color & 0xffff00ff) | (val << 8); + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); if (!(s3->accel.multifunc[0xe] & 0x200)) s3->accel.multifunc[0xe] ^= 0x10; @@ -1004,34 +1003,41 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xa14a: case 0xa2ea: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.bkgd_color = (s3->accel.bkgd_color & 0xffffff00) | val; - else - s3->accel.bkgd_color = (s3->accel.bkgd_color & 0xff00ffff) | (val << 16); + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; + } break; case 0xa14b: case 0xa2eb: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.bkgd_color = (s3->accel.bkgd_color & 0xffff00ff) | (val << 8); - else - s3->accel.bkgd_color = (s3->accel.bkgd_color & 0x00ffffff) | (val << 24); - if (!(s3->accel.multifunc[0xe] & 0x200)) + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); s3->accel.multifunc[0xe] ^= 0x10; + } break; case 0xa548: case 0xa6e8: if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.frgd_color = (s3->accel.frgd_color & 0xff00ffff) | (val << 16); + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); else - s3->accel.frgd_color = (s3->accel.frgd_color & 0xffffff00) | val; + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; break; case 0xa549: case 0xa6e9: if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.frgd_color = (s3->accel.frgd_color & 0x00ffffff) | (val << 24); + s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); else - s3->accel.frgd_color = (s3->accel.frgd_color & 0xffff00ff) | (val << 8); + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); if (!(s3->accel.multifunc[0xe] & 0x200)) s3->accel.multifunc[0xe] ^= 0x10; @@ -1042,34 +1048,41 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xa54a: case 0xa6ea: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.frgd_color = (s3->accel.frgd_color & 0xffffff00) | val; - else - s3->accel.frgd_color = (s3->accel.frgd_color & 0xff00ffff) | (val << 16); + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; + } break; case 0xa54b: case 0xa6eb: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.frgd_color = (s3->accel.frgd_color & 0xffff00ff) | (val << 8); - else - s3->accel.frgd_color = (s3->accel.frgd_color & 0x00ffffff) | (val << 24); - if (!(s3->accel.multifunc[0xe] & 0x200)) + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); s3->accel.multifunc[0xe] ^= 0x10; + } break; case 0xa948: case 0xaae8: if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.wrt_mask = (s3->accel.wrt_mask & 0xff00ffff) | (val << 16); + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); else - s3->accel.wrt_mask = (s3->accel.wrt_mask & 0xffffff00) | val; + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; break; case 0xa949: case 0xaae9: if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.wrt_mask = (s3->accel.wrt_mask & 0x00ffffff) | (val << 24); + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); else - s3->accel.wrt_mask = (s3->accel.wrt_mask & 0xffff00ff) | (val << 8); + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); if (!(s3->accel.multifunc[0xe] & 0x200)) s3->accel.multifunc[0xe] ^= 0x10; @@ -1080,85 +1093,106 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xa94a: case 0xaaea: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.wrt_mask = (s3->accel.wrt_mask & 0xffffff00) | val; - else - s3->accel.wrt_mask = (s3->accel.wrt_mask & 0xff00ffff) | (val << 16); + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; + } break; case 0xa94b: case 0xaaeb: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.wrt_mask = (s3->accel.wrt_mask & 0xffff00ff) | (val << 8); - else - s3->accel.wrt_mask = (s3->accel.wrt_mask & 0x00ffffff) | (val << 24); - if (!(s3->accel.multifunc[0xe] & 0x200)) + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); s3->accel.multifunc[0xe] ^= 0x10; + } break; case 0xad48: case 0xaee8: if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.rd_mask = (s3->accel.rd_mask & 0xff00ffff) | (val << 16); + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); else - s3->accel.rd_mask = (s3->accel.rd_mask & 0xffffff00) | val; + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; break; case 0xad49: case 0xaee9: if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.rd_mask = (s3->accel.rd_mask & 0x00ffffff) | (val << 24); + s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); else - s3->accel.rd_mask = (s3->accel.rd_mask & 0xffff00ff) | (val << 8); + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); if (!(s3->accel.multifunc[0xe] & 0x200)) s3->accel.multifunc[0xe] ^= 0x10; break; case 0xad4a: case 0xaeea: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.rd_mask = (s3->accel.rd_mask & 0xffffff00) | val; - else - s3->accel.rd_mask = (s3->accel.rd_mask & 0xff00ffff) | (val << 16); + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; + } break; case 0xad4b: case 0xaeeb: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.rd_mask = (s3->accel.rd_mask & 0xffff00ff) | (val << 8); - else - s3->accel.rd_mask = (s3->accel.rd_mask & 0x00ffffff) | (val << 24); - if (!(s3->accel.multifunc[0xe] & 0x200)) + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); s3->accel.multifunc[0xe] ^= 0x10; + } break; case 0xb148: case 0xb2e8: if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.color_cmp = (s3->accel.color_cmp & 0xff00ffff) | (val << 16); + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); else - s3->accel.color_cmp = (s3->accel.color_cmp & 0xffffff00) | val; + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val; break; case 0xb149: case 0xb2e9: if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.color_cmp = (s3->accel.color_cmp & 0x00ffffff) | (val << 24); + s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); else - s3->accel.color_cmp = (s3->accel.color_cmp & 0xffff00ff) | (val << 8); + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); if (!(s3->accel.multifunc[0xe] & 0x200)) s3->accel.multifunc[0xe] ^= 0x10; break; case 0xb14a: case 0xb2ea: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.color_cmp = (s3->accel.color_cmp & 0xffffff00) | val; - else - s3->accel.color_cmp = (s3->accel.color_cmp & 0xff00ffff) | (val << 16); + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); + else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val; + } break; case 0xb14b: case 0xb2eb: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.color_cmp = (s3->accel.color_cmp & 0xffff00ff) | (val << 8); - else - s3->accel.color_cmp = (s3->accel.color_cmp & 0x00ffffff) | (val << 24); - if (!(s3->accel.multifunc[0xe] & 0x200)) + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); + else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); s3->accel.multifunc[0xe] ^= 0x10; + } break; case 0xb548: @@ -1192,34 +1226,41 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0xe548: case 0xe6e8: if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.pat_bg_color = (s3->accel.pat_bg_color & 0xff00ffff) | (val << 16); + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x00ff0000) | (val << 16); else - s3->accel.pat_bg_color = (s3->accel.pat_bg_color & 0xffffff00) | val; + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x000000ff) | val; break; case 0xe549: case 0xe6e9: if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.pat_bg_color = (s3->accel.pat_bg_color & 0x00ffffff) | (val << 24); + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0xff000000) | (val << 24); else - s3->accel.pat_bg_color = (s3->accel.pat_bg_color & 0xffff00ff) | (val << 8); + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x0000ff00) | (val << 8); if (!(s3->accel.multifunc[0xe] & 0x200)) s3->accel.multifunc[0xe] ^= 0x10; break; case 0xe54a: case 0xe6ea: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.pat_bg_color = (s3->accel.pat_bg_color & 0xffffff00) | val; - else - s3->accel.pat_bg_color = (s3->accel.pat_bg_color & 0xff00ffff) | (val << 16); + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x00ff0000) | (val << 16); + else + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x000000ff) | val; + } break; case 0xe54b: case 0xe6eb: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.pat_bg_color = (s3->accel.pat_bg_color & 0xffff00ff) | (val << 8); - else - s3->accel.pat_bg_color = (s3->accel.pat_bg_color & 0x00ffffff) | (val << 24); - if (!(s3->accel.multifunc[0xe] & 0x200)) + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0xff000000) | (val << 24); + else + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x0000ff00) | (val << 8); s3->accel.multifunc[0xe] ^= 0x10; + } break; case 0xe948: case 0xeae8: @@ -1240,34 +1281,41 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0xed48: case 0xeee8: if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.pat_fg_color = (s3->accel.pat_fg_color & 0xff00ffff) | (val << 16); + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x00ff0000) | (val << 16); else - s3->accel.pat_fg_color = (s3->accel.pat_fg_color & 0xffffff00) | val; + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x000000ff) | val; break; case 0xed49: case 0xeee9: if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.pat_fg_color = (s3->accel.pat_fg_color & 0x00ffffff) | (val << 24); + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0xff000000) | (val << 24); else - s3->accel.pat_fg_color = (s3->accel.pat_fg_color & 0xffff00ff) | (val << 8); + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x0000ff00) | (val << 8); if (!(s3->accel.multifunc[0xe] & 0x200)) s3->accel.multifunc[0xe] ^= 0x10; break; case 0xed4a: case 0xeeea: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.pat_fg_color = (s3->accel.pat_fg_color & 0xffffff00) | val; - else - s3->accel.pat_fg_color = (s3->accel.pat_fg_color & 0xff00ffff) | (val << 16); + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x00ff0000) | (val << 16); + else + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x000000ff) | val; + } break; case 0xed4b: case 0xeeeb: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.pat_fg_color = (s3->accel.pat_fg_color & 0xffff00ff) | (val << 8); - else - s3->accel.pat_fg_color = (s3->accel.pat_fg_color & 0x00ffffff) | (val << 24); - if (!(s3->accel.multifunc[0xe] & 0x200)) + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0xff000000) | (val << 24); + else + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x0000ff00) | (val << 8); s3->accel.multifunc[0xe] ^= 0x10; + } break; case 0xe148: @@ -2780,6 +2828,10 @@ s3_out(uint16_t addr, uint8_t val, void *priv) case 0x50: s3->bpp = (svga->crtc[0x50] >> 4) & 3; + if (s3->bpp == 3) { + if (!(s3->accel.multifunc[0xe] & 0x200)) /*On True Color mode change, reset bit 4 of Misc Index register*/ + s3->accel.multifunc[0xe] &= ~0x10; + } break; case 0x5c: @@ -3029,7 +3081,8 @@ s3_in(uint16_t addr, void *priv) temp = svga->seqregs[svga->seqaddr]; /* This is needed for the Intel Advanced/ATX's built-in S3 Trio64V+ BIOS to not get stuck in an infinite loop. */ - if (((s3->card_type == S3_PHOENIX_TRIO64VPLUS_ONBOARD) || + if (((s3->card_type == S3_STB_POWERGRAPH_64_VIDEO) || + (s3->card_type == S3_PHOENIX_TRIO64VPLUS_ONBOARD) || (s3->card_type == S3_CARDEX_TRIO64VPLUS)) && (svga->seqaddr == 0x17)) svga->seqregs[svga->seqaddr] ^= 0x01; return temp; @@ -3152,8 +3205,18 @@ s3_recalctimings(svga_t *svga) int clk_sel = (svga->miscout >> 2) & 3; uint8_t mask = 0xc0; - svga->hdisp = svga->hdisp_old; + if (svga->crtc[0x33] & 0x20) { + /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ + if (!svga->scrblank && svga->attr_palette_enable) + svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; + } else { + if (!svga->scrblank && svga->attr_palette_enable && (svga->crtc[0x43] & 0x80)) { + /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); + } + } + svga->hdisp = svga->hdisp_old; svga->ma_latch |= (s3->ma_ext << 16); if (s3->chip >= S3_86C928) { @@ -3161,7 +3224,7 @@ s3_recalctimings(svga_t *svga) svga->htotal |= 0x100; if (svga->crtc[0x5d] & 0x02) { svga->hdisp_time |= 0x100; - svga->hdisp |= 0x100 * svga->dots_per_clock; + svga->hdisp |= (0x100 * svga->dots_per_clock); } if (svga->crtc[0x5e] & 0x01) svga->vtotal |= 0x400; @@ -3250,39 +3313,29 @@ s3_recalctimings(svga_t *svga) if (svga->crtc[0x33] & 0x20) { /* The S3 version of the Cirrus' special blanking mode, with identical behavior. */ - svga->hblankstart = (((svga->crtc[0x5d] & 0x02) >> 1) << 8) + svga->crtc[1] + - ((svga->crtc[3] >> 5) & 3) + 1; - svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3); - - /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ - if (!svga->scrblank && svga->attr_palette_enable) - svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; - - /* No overscan in this mode. */ - svga->hblank_overscan = 0; + svga->hblankstart = (((svga->crtc[0x5d] & 0x02) >> 1) << 8) + svga->crtc[1]/* + + ((svga->crtc[3] >> 5) & 3) + 1*/; + svga->hblank_end_val = svga->htotal - 1 /* + ((svga->crtc[3] >> 5) & 3)*/; svga->monitor->mon_overscan_y = 0; svga->monitor->mon_overscan_x = 0; /* Also make sure vertical blanking starts on display end. */ svga->vblankstart = svga->dispend; + + if (s3->chip >= S3_VISION964) + svga->hblank_end_mask = 0x7f; } else if (s3->chip >= S3_86C801) { - if (!svga->scrblank && svga->attr_palette_enable && (svga->crtc[0x43] & 0x80)) { - /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ - svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); - } + svga->hblankstart = (((svga->crtc[0x5d] & 0x04) >> 2) << 8) + svga->crtc[2]; - svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; - - if (svga->crtc[0x5d] & 0x04) - svga->hblankstart += 0x100; if (s3->chip >= S3_VISION964) { /* NOTE: The S3 Trio64V+ datasheet says this is bit 7, but then where is bit 6? The datasheets for the pre-Trio64V+ cards say +64, which implies bit 6, and, contrary to VGADOC, it also exists on Trio32, Trio64, Vision868, and Vision968. */ - svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | - (((svga->crtc[0x5d] & 0x08) >> 3) << 6); + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((svga->crtc[0x5d] & 0x08) >> 3) << 6); + svga->hblank_end_mask = 0x7f; } } @@ -3330,20 +3383,17 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 1280: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; break; case 2048: /*Account for the 1280x1024 resolution*/ switch (svga->hdisp) { case 320: svga->hdisp <<= 2; - svga->hblankstart <<= 2; - svga->hblank_end_val <<= 2; + svga->dots_per_clock <<= 2; break; case 640: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; break; default: break; @@ -3364,8 +3414,7 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 640: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: break; @@ -3383,8 +3432,7 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; default: break; } @@ -3396,32 +3444,24 @@ s3_recalctimings(svga_t *svga) break; case S3_VISION968: switch (s3->card_type) { - case S3_PHOENIX_VISION968: - case S3_NUMBER9_9FX_771: - svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + case S3_MIROVIDEO40SV_ERGO_968: + if (svga->hdisp == 832) + svga->hdisp -= 32; break; + case S3_NUMBER9_9FX_771: + case S3_PHOENIX_VISION968: case S3_SPEA_MERCURY_P64V: + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + if (svga->hdisp == 832) + svga->hdisp -= 32; + break; case S3_ELSAWIN2KPROX: switch (s3->width) { case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; - default: - break; - } - break; - case S3_MIROVIDEO40SV_ERGO_968: - switch (s3->width) { - case 1152: - case 1280: - svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; - break; + svga->dots_per_clock <<= 1; default: break; } @@ -3465,16 +3505,14 @@ s3_recalctimings(svga_t *svga) case S3_86C911: case S3_86C924: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; case S3_86C801: switch (s3->card_type) { case S3_PHOENIX_86C801: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: @@ -3488,22 +3526,19 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_86C805: case S3_86C805_ONBOARD: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; case S3_SPEA_MIRAGE_86C805: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; switch (s3->width) { case 800: case 1024: if (svga->hdisp == 400) { /*SPEA specific drivers + its VBE RAM BIOS...*/ svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; } break; default: @@ -3520,8 +3555,7 @@ s3_recalctimings(svga_t *svga) case S3_METHEUS_86C928: if (!s3->color_16bit) { svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; } switch (svga->hdisp) { /*This might be a driver issue*/ case 800: @@ -3545,8 +3579,7 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 640: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: break; @@ -3559,8 +3592,7 @@ s3_recalctimings(svga_t *svga) break; case S3_VISION864: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; case S3_VISION964: switch (s3->card_type) { @@ -3569,8 +3601,7 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; break; default: break; @@ -3586,8 +3617,7 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_VISION868: case S3_NUMBER9_9FX_531: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: @@ -3596,11 +3626,15 @@ s3_recalctimings(svga_t *svga) break; case S3_VISION968: switch (s3->card_type) { + case S3_MIROVIDEO40SV_ERGO_968: + if (svga->hdisp == 832) + svga->hdisp -= 32; + break; case S3_NUMBER9_9FX_771: case S3_PHOENIX_VISION968: + case S3_SPEA_MERCURY_P64V: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; /* TODO: Is this still needed? */ if (svga->hdisp == 832) svga->hdisp -= 32; @@ -3611,8 +3645,7 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; break; default: break; @@ -3626,8 +3659,7 @@ s3_recalctimings(svga_t *svga) case S3_TRIO64: case S3_TRIO32: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: @@ -3663,16 +3695,14 @@ s3_recalctimings(svga_t *svga) case S3_86C911: case S3_86C924: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; case S3_86C801: switch (s3->card_type) { case S3_PHOENIX_86C801: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: @@ -3686,8 +3716,7 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_86C805: case S3_86C805_ONBOARD: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; case S3_SPEA_MIRAGE_86C805: @@ -3698,8 +3727,7 @@ s3_recalctimings(svga_t *svga) if (svga->hdisp == 400) { /*SPEA specific drivers + its VBE RAM BIOS...*/ svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; } break; default: @@ -3715,8 +3743,7 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_METHEUS_86C928: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; switch (svga->hdisp) { /*This might be a driver issue*/ case 800: s3->width = 1024; @@ -3739,8 +3766,7 @@ s3_recalctimings(svga_t *svga) switch (s3->width) { case 640: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: break; @@ -3753,16 +3779,14 @@ s3_recalctimings(svga_t *svga) break; case S3_VISION864: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; case S3_VISION868: switch (s3->card_type) { case S3_PHOENIX_VISION868: case S3_NUMBER9_9FX_531: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: @@ -3776,8 +3800,7 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; break; default: break; @@ -3790,11 +3813,15 @@ s3_recalctimings(svga_t *svga) break; case S3_VISION968: switch (s3->card_type) { + case S3_MIROVIDEO40SV_ERGO_968: + if (svga->hdisp == 832) + svga->hdisp -= 32; + break; case S3_NUMBER9_9FX_771: case S3_PHOENIX_VISION968: + case S3_SPEA_MERCURY_P64V: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; /* TODO: Is this still needed? */ if (svga->hdisp == 832) svga->hdisp -= 32; @@ -3805,8 +3832,7 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; break; default: break; @@ -3820,8 +3846,7 @@ s3_recalctimings(svga_t *svga) case S3_TRIO64: case S3_TRIO32: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: @@ -3864,8 +3889,7 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_AMI_86C924: svga->hdisp = (svga->hdisp << 1) / 3; - svga->hblankstart = (svga->hblankstart << 1) / 3; - svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; + svga->dots_per_clock = (svga->dots_per_clock << 1) / 3; /* TODO: Is this still needed? */ if (svga->hdisp == 645) svga->hdisp -= 5; @@ -3879,8 +3903,7 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_86C801: case S3_SPEA_MIRAGE_86C801: svga->hdisp = (svga->hdisp << 1) / 3; - svga->hblankstart = (svga->hblankstart << 1) / 3; - svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; + svga->dots_per_clock = (svga->dots_per_clock << 1) / 3; break; default: break; @@ -3894,8 +3917,7 @@ s3_recalctimings(svga_t *svga) case S3_SPEA_MIRAGE_86C805: case S3_86C805_ONBOARD: svga->hdisp = (svga->hdisp << 1) / 3; - svga->hblankstart = (svga->hblankstart << 1) / 3; - svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; + svga->dots_per_clock = (svga->dots_per_clock << 1) / 3; break; default: break; @@ -3905,8 +3927,7 @@ s3_recalctimings(svga_t *svga) switch (s3->card_type) { case S3_SPEA_MERCURY_LITE_PCI: svga->hdisp = (svga->hdisp << 1) / 3; - svga->hblankstart = (svga->hblankstart << 1) / 3; - svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; + svga->dots_per_clock = (svga->dots_per_clock << 1) / 3; break; default: break; @@ -3914,33 +3935,13 @@ s3_recalctimings(svga_t *svga) break; case S3_VISION864: svga->hdisp = (svga->hdisp << 1) / 3; - svga->hblankstart = (svga->hblankstart << 1) / 3; - svga->hblank_end_val = (svga->hblank_end_val << 1) / 3; - break; - case S3_VISION968: - switch (s3->card_type) { - case S3_MIROVIDEO40SV_ERGO_968: - switch (s3->width) { - case 1280: - svga->hdisp = ((svga->hdisp << 1) / 3) << 1; - svga->hblankstart = (svga->hblankstart << 1) / 3; - svga->hblank_end_val = ((svga->hblank_end_val << 1) / 3) << 1; - break; - default: - break; - } - break; - - default: - break; - } + svga->dots_per_clock = (svga->dots_per_clock << 1) / 3; break; case S3_TRIO64: case S3_TRIO32: svga->hdisp /= 3; - svga->hblankstart /= 3; - svga->hblank_end_val /= 3; + svga->dots_per_clock /= 3; break; default: @@ -3969,7 +3970,8 @@ s3_recalctimings(svga_t *svga) svga->hdisp = 640; } } else { - if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) + if ((s3->card_type == S3_MIROVIDEO40SV_ERGO_968) || + (s3->card_type == S3_PHOENIX_VISION968) || (s3->card_type == S3_SPEA_MERCURY_P64V)) svga->hdisp = s3->width; } #endif @@ -3982,8 +3984,7 @@ s3_recalctimings(svga_t *svga) case S3_PHOENIX_VISION868: case S3_NUMBER9_9FX_531: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: break; @@ -3996,8 +3997,7 @@ s3_recalctimings(svga_t *svga) case 800: case 1024: svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; default: break; @@ -4008,8 +4008,7 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; break; default: break; @@ -4021,11 +4020,15 @@ s3_recalctimings(svga_t *svga) break; case S3_VISION968: switch (s3->card_type) { + case S3_MIROVIDEO40SV_ERGO_968: + if (svga->hdisp == 832) + svga->hdisp -= 32; + break; case S3_NUMBER9_9FX_771: case S3_PHOENIX_VISION968: + case S3_SPEA_MERCURY_P64V: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; /* TODO: Is this still needed? */ if (svga->hdisp == 832) svga->hdisp -= 32; @@ -4036,8 +4039,7 @@ s3_recalctimings(svga_t *svga) case 1280: case 1600: svga->hdisp <<= 1; - svga->hblankstart <<= 1; - svga->hblank_end_val <<= 1; + svga->dots_per_clock <<= 1; break; default: break; @@ -4105,13 +4107,19 @@ s3_recalctimings(svga_t *svga) if (svga->crtc[0x31] & 0x08) { svga->vram_display_mask = s3->vram_mask; if (svga->bpp == 8) { - svga->render = svga_render_8bpp_highres; /*Enhanced 4bpp mode, just like the 8bpp mode per spec.*/ + /*Enhanced 4bpp mode, just like the 8bpp mode per the spec. */ + svga->render = svga_render_8bpp_highres; svga->rowoffset <<= 1; } } } } } + + if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64)) + svga->hoverride = 1; + else + svga->hoverride = 0; } static void @@ -4125,6 +4133,12 @@ s3_trio64v_recalctimings(svga_t *svga) svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); } + if ((svga->crtc[0x33] & 0x20) ||((svga->crtc[0x67] & 0xc) == 0xc)) { + /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ + if (!svga->scrblank && svga->attr_palette_enable) + svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; + } + svga->hdisp = svga->hdisp_old; if (svga->crtc[0x5d] & 0x01) svga->htotal |= 0x100; @@ -4170,18 +4184,11 @@ s3_trio64v_recalctimings(svga_t *svga) break; } - if ((svga->crtc[0x33] & 0x20) ||((svga->crtc[0x67] & 0xc) == 0xc)) { + if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) { /* The S3 version of the Cirrus' special blanking mode, with identical behavior. */ - svga->hblankstart = (((svga->crtc[0x5d] & 0x02) >> 1) << 8) + svga->crtc[1] + - ((svga->crtc[3] >> 5) & 3) + 1; - svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3); - - /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ - if (!svga->scrblank && svga->attr_palette_enable) - svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; - - /* No overscan in this mode. */ - svga->hblank_overscan = 0; + svga->hblankstart = (((svga->crtc[0x5d] & 0x02) >> 1) << 8) + svga->crtc[1]/* + + ((svga->crtc[3] >> 5) & 3)*/; + svga->hblank_end_val = svga->htotal - 1 /* + ((svga->crtc[3] >> 5) & 3)*/; svga->monitor->mon_overscan_y = 0; svga->monitor->mon_overscan_x = 0; @@ -4189,7 +4196,7 @@ s3_trio64v_recalctimings(svga_t *svga) /* Also make sure vertical blanking starts on display end. */ svga->vblankstart = svga->dispend; } else { - svga->hblankstart = (((svga->crtc[0x5d] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; + svga->hblankstart = (((svga->crtc[0x5d] & 0x04) >> 2) << 8) + svga->crtc[2]; /* NOTE: The S3 Trio64V+ datasheet says this is bit 7, but then where is bit 6? The datasheets for the pre-Trio64V+ cards say +64, which implies bit 6, @@ -4197,6 +4204,7 @@ s3_trio64v_recalctimings(svga_t *svga) and Vision968. */ svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | (((svga->crtc[0x5d] & 0x08) >> 3) << 6); + svga->hblank_end_mask = 0x7f; } if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/ @@ -4220,20 +4228,17 @@ s3_trio64v_recalctimings(svga_t *svga) case 15: svga->render = svga_render_15bpp_highres; svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; case 16: svga->render = svga_render_16bpp_highres; svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; break; case 24: svga->render = svga_render_24bpp_highres; svga->hdisp /= 3; - svga->hblankstart >>= 1; - svga->hblank_end_val /= 3; + svga->dots_per_clock /= 3; break; case 32: svga->render = svga_render_32bpp_highres; @@ -4275,15 +4280,11 @@ s3_trio64v_recalctimings(svga_t *svga) svga->render = svga_render_8bpp_highres; break; case 3: /*KRGB-16 (1.5.5.5)*/ - svga->htotal >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->multiplier = 0.5; svga->render = svga_render_15bpp_highres; break; case 5: /*RGB-16 (5.6.5)*/ - svga->htotal >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->multiplier = 0.5; svga->render = svga_render_16bpp_highres; break; case 6: /*RGB-24 (8.8.8)*/ @@ -4297,6 +4298,8 @@ s3_trio64v_recalctimings(svga_t *svga) break; } } + + svga->hoverride = 1; } static void @@ -8084,8 +8087,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.cy &= 0xfff; } - s3->accel.cur_x = s3->accel.cx; - s3->accel.cur_y = s3->accel.cy; + s3->accel.cur_x = s3->accel.cx & 0xfff; + s3->accel.cur_y = s3->accel.cy & 0xfff; } break; @@ -8178,8 +8181,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.cx &= 0xfff; s3->accel.cy &= 0xfff; } - s3->accel.cur_x = s3->accel.cx; - s3->accel.cur_y = s3->accel.cy; + s3->accel.cur_x = s3->accel.cx & 0xfff; + s3->accel.cur_y = s3->accel.cy & 0xfff; } else { /*Bresenham*/ if (s3->accel.b2e8_pix && s3_cpu_src(s3) && (count == 16)) { /*Stupid undocumented 0xB2E8 on 911/924*/ count = s3->accel.maj_axis_pcnt + 1; @@ -8273,8 +8276,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.cx &= 0xfff; s3->accel.cy &= 0xfff; } - s3->accel.cur_x = s3->accel.cx; - s3->accel.cur_y = s3->accel.cy; + s3->accel.cur_x = s3->accel.cx & 0xfff; + s3->accel.cur_y = s3->accel.cy & 0xfff; } break; @@ -9478,6 +9481,7 @@ s3_reset(void *priv) case S3_PHOENIX_TRIO64: case S3_PHOENIX_TRIO64_ONBOARD: + case S3_STB_POWERGRAPH_64_VIDEO: case S3_CARDEX_TRIO64VPLUS: case S3_PHOENIX_TRIO64VPLUS: case S3_PHOENIX_TRIO64VPLUS_ONBOARD: @@ -9684,6 +9688,14 @@ s3_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio32_vlb); break; + case S3_PHOENIX_TRIO32_ONBOARD: + bios_fn = NULL; + chip = S3_TRIO32; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio32_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio32_vlb); + break; case S3_DIAMOND_STEALTH_SE: bios_fn = ROM_DIAMOND_STEALTH_SE; chip = S3_TRIO32; @@ -9713,6 +9725,14 @@ s3_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); break; + case S3_STB_POWERGRAPH_64_VIDEO: + bios_fn = ROM_STB_POWERGRAPH_64_VIDEO; + chip = S3_TRIO64V; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_vlb); + break; case S3_PHOENIX_TRIO64VPLUS: bios_fn = ROM_PHOENIX_TRIO64VPLUS; chip = S3_TRIO64V; @@ -10159,6 +10179,7 @@ s3_init(const device_t *info) break; case S3_PHOENIX_TRIO32: + case S3_PHOENIX_TRIO32_ONBOARD: case S3_DIAMOND_STEALTH_SE: svga->decode_mask = (4 << 20) - 1; s3->id = 0xe1; /*Trio32*/ @@ -10172,6 +10193,7 @@ s3_init(const device_t *info) case S3_PHOENIX_TRIO64: case S3_PHOENIX_TRIO64_ONBOARD: + case S3_STB_POWERGRAPH_64_VIDEO: case S3_PHOENIX_TRIO64VPLUS: case S3_PHOENIX_TRIO64VPLUS_ONBOARD: case S3_CARDEX_TRIO64VPLUS: @@ -10411,6 +10433,12 @@ s3_phoenix_trio64_available(void) return rom_present(ROM_PHOENIX_TRIO64); } +static int +s3_stb_powergraph_64_video_available(void) +{ + return rom_present(ROM_STB_POWERGRAPH_64_VIDEO); +} + static int s3_phoenix_trio64vplus_available(void) { @@ -10928,6 +10956,20 @@ const device_t s3_9fx_pci_device = { .config = s3_9fx_config }; +const device_t s3_phoenix_trio32_onboard_vlb_device = { + .name = "S3 Trio32 VLB On-Board (Phoenix)", + .internal_name = "px_trio32_onboard_vlb", + .flags = DEVICE_VLB, + .local = S3_PHOENIX_TRIO32_ONBOARD, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = NULL }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_phoenix_trio32_config +}; + const device_t s3_phoenix_trio32_vlb_device = { .name = "S3 Trio32 VLB (Phoenix)", .internal_name = "px_trio32_vlb", @@ -10942,6 +10984,20 @@ const device_t s3_phoenix_trio32_vlb_device = { .config = s3_phoenix_trio32_config }; +const device_t s3_phoenix_trio32_onboard_pci_device = { + .name = "S3 Trio32 PCI On-Board (Phoenix)", + .internal_name = "px_trio32_onboard_pci", + .flags = DEVICE_PCI, + .local = S3_PHOENIX_TRIO32_ONBOARD, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = NULL }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_phoenix_trio32_config +}; + const device_t s3_phoenix_trio32_pci_device = { .name = "S3 Trio32 PCI (Phoenix)", .internal_name = "px_trio32_pci", @@ -11026,6 +11082,21 @@ const device_t s3_phoenix_trio64_pci_device = { .config = s3_standard_config }; +const device_t s3_stb_powergraph_64_video_vlb_device = { + .name = "S3 Trio64V+ (STB PowerGraph 64 Video) VLB", + .name = "S3 Trio64V+ PCI (Phoenix)", + .internal_name = "px_trio64vplus_pci", + .flags = DEVICE_VLB, + .local = S3_STB_POWERGRAPH_64_VIDEO, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_stb_powergraph_64_video_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config +}; + const device_t s3_phoenix_trio64vplus_onboard_pci_device = { .name = "S3 Trio64V+ PCI On-Board (Phoenix)", .internal_name = "px_trio64vplus_onboard_pci", diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index a0bf98815..be6382ec9 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -783,6 +783,12 @@ s3_virge_recalctimings(svga_t *svga) svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); } + if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) { + /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ + if (!svga->scrblank && svga->attr_palette_enable) + svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; + } + if (svga->crtc[0x5d] & 0x01) svga->htotal += 0x100; if (svga->crtc[0x5d] & 0x02) { @@ -820,16 +826,9 @@ s3_virge_recalctimings(svga_t *svga) if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) { /* The S3 version of the Cirrus' special blanking mode, with identical behavior. */ - svga->hblankstart = (((svga->crtc[0x5d] & 0x02) >> 1) << 8) + svga->crtc[1] + - ((svga->crtc[3] >> 5) & 3) + 1; - svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3); - - /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ - if (!svga->scrblank && svga->attr_palette_enable) - svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; - - /* No overscan in this mode. */ - svga->hblank_overscan = 0; + svga->hblankstart = (((svga->crtc[0x5d] & 0x02) >> 1) << 8) + svga->crtc[1]/* + + ((svga->crtc[3] >> 5) & 3) + 1*/; + svga->hblank_end_val = svga->htotal - 1 /* + ((svga->crtc[3] >> 5) & 3)*/; svga->monitor->mon_overscan_y = 0; svga->monitor->mon_overscan_x = 0; @@ -837,10 +836,11 @@ s3_virge_recalctimings(svga_t *svga) /* Also make sure vertical blanking starts on display end. */ svga->vblankstart = svga->dispend; } else { - svga->hblankstart = (((svga->crtc[0x5d] & 0x04) >> 2) << 8) + svga->crtc[2] + 1; + svga->hblankstart = (((svga->crtc[0x5d] & 0x04) >> 2) << 8) + svga->crtc[2]; - svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | - (((svga->crtc[0x5d] & 0x08) >> 3) << 6); + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((svga->crtc[0x5d] & 0x08) >> 3) << 6); + svga->hblank_end_mask = 0x7f; } if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/ @@ -862,19 +862,21 @@ s3_virge_recalctimings(svga_t *svga) case 15: svga->render = svga_render_15bpp_highres; if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) { - svga->htotal >>= 1; + // svga->htotal >>= 1; + // if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) + // svga->hblank_end_val = svga->htotal - 1; svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; } break; case 16: svga->render = svga_render_16bpp_highres; if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) { - svga->htotal >>= 1; + // svga->htotal >>= 1; + // if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) + // svga->hblank_end_val = svga->htotal - 1; svga->hdisp >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + svga->dots_per_clock >>= 1; } break; case 24: @@ -921,15 +923,17 @@ s3_virge_recalctimings(svga_t *svga) svga->render = svga_render_8bpp_highres; break; case 3: /*KRGB-16 (1.5.5.5)*/ - svga->htotal >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + // svga->htotal >>= 1; + // if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) + // svga->hblank_end_val = svga->htotal - 1; + // svga->dots_per_clock >>= 1; svga->render = svga_render_15bpp_highres; break; case 5: /*RGB-16 (5.6.5)*/ - svga->htotal >>= 1; - svga->hblankstart >>= 1; - svga->hblank_end_val >>= 1; + // svga->htotal >>= 1; + // if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) + // svga->hblank_end_val = svga->htotal - 1; + // svga->dots_per_clock >>= 1; svga->render = svga_render_16bpp_highres; break; case 6: /*RGB-24 (8.8.8)*/ diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 692bfef27..cbb7f12e8 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -222,6 +222,7 @@ svga_out(uint16_t addr, uint8_t val, void *priv) svga_log("3C3: VGA ON = %d.\n", val & 0x01); vga_on = val & 0x01; + svga_recalctimings(svga); break; case 0x3c4: svga->seqaddr = val; @@ -567,11 +568,15 @@ svga_set_ramdac_type(svga_t *svga, int type) void svga_recalctimings(svga_t *svga) { - const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; double crtcconst; double _dispontime; double _dispofftime; double disptime; + double crtcconst8514 = 0.0; + double _dispontime8514 = 0.0; + double _dispofftime8514 = 0.0; + double disptime8514 = 0.0; #ifdef ENABLE_SVGA_LOG int vsyncend; int vblankend; @@ -641,10 +646,17 @@ svga_recalctimings(svga_t *svga) svga->render = svga_render_blank; if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ - if (svga->seqregs[1] & 8) - svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; - else - svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9; + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { + if (svga->seqregs[1] & 8) + svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; + else + svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9; + } else { + if (svga->seqregs[1] & 8) + svga->hdisp *= 16; + else + svga->hdisp *= 8; + } if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ if (svga->seqregs[1] & 8) { /*40 column*/ @@ -738,24 +750,31 @@ svga_recalctimings(svga_t *svga) } else svga->monitor->mon_overscan_x = 16; - svga->hblankstart = svga->crtc[2] + 1; + svga->hblankstart = svga->crtc[2]; svga->hblank_end_val = (svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00); + svga->hblank_end_mask = 0x0000003f; svga_log("htotal = %i, hblankstart = %i, hblank_end_val = %02X\n", svga->htotal, svga->hblankstart, svga->hblank_end_val); - svga->hblank_end_len = 0x00000040; - svga->hblank_overscan = 1; - if (!svga->scrblank && svga->attr_palette_enable) { /* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */ - if (svga->seqregs[1] & 8) - svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); - else - svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 8 : 9); + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { + if (svga->seqregs[1] & 8) + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18); + else + svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 8 : 9); + } else { + if (svga->seqregs[1] & 8) + svga->dots_per_clock = 16; + else + svga->dots_per_clock = 8; + } } else svga->dots_per_clock = 1; + svga->multiplier = 1.0; + if (svga->recalctimings_ex) svga->recalctimings_ex(svga); @@ -768,19 +787,60 @@ svga_recalctimings(svga_t *svga) xga_recalctimings(svga); if (!svga->hoverride) { - svga->hblankend = (svga->hblankstart & ~(svga->hblank_end_len - 1)) | svga->hblank_end_val; - if (svga->hblankend <= svga->hblankstart) - svga->hblankend += svga->hblank_end_len; - svga->hblankend += svga->hblank_ext; - + uint32_t dot = svga->hblankstart; + uint32_t adj_dot = svga->hblankstart; + /* Verified with both the Voodoo 3 and the S3 cards: compare 7 bits if bit 7 is set, + otherwise compare 6 bits. */ + uint32_t eff_mask = (svga->hblank_end_val & ~0x0000003f) ? svga->hblank_end_mask : 0x0000003f; svga->hblank_sub = 0; - if (svga->hblankend > svga->htotal) { - svga->hblankend &= (svga->hblank_end_len - 1); - svga->hblank_sub = svga->hblankend + svga->hblank_overscan; - svga->hdisp -= (svga->hblank_sub * svga->dots_per_clock); + svga_log("HDISP=%d, CRTC1+1=%d, Blank: %04i-%04i, Total: %04i, Mask: %02X, ADJ_DOT=%04i.\n", svga->hdisp, svga->crtc[1] + 1, svga->hblankstart, svga->hblank_end_val, + svga->htotal, eff_mask, adj_dot); + + while (adj_dot < (svga->htotal << 1)) { + if (dot == svga->htotal) + dot = 0; + + if (adj_dot >= svga->htotal) + svga->hblank_sub++; + + svga_log("Loop: adjdot=%d, htotal=%d, dotmask=%02x, hblankendvalmask=%02x, blankendval=%02x.\n", adj_dot, svga->htotal, dot & eff_mask, svga->hblank_end_val & eff_mask, svga->hblank_end_val); + if ((dot & eff_mask) == (svga->hblank_end_val & eff_mask)) + break; + + dot++; + adj_dot++; + } + + svga->hdisp -= (svga->hblank_sub * svga->dots_per_clock); + } + +#ifdef TBD + if (ibm8514_active && (svga->dev8514 != NULL)) { + if (dev->on[0] || dev->on[1]) { + uint32_t dot8514 = dev->h_blankstart; + uint32_t adj_dot8514 = dev->h_blankstart; + uint32_t eff_mask8514 = 0x0000003f; + dev->hblank_sub = 0; + + while (adj_dot8514 < (dev->h_total << 1)) { + if (dot8514 == dev->h_total) + dot8514 = 0; + + if (adj_dot8514 >= dev->h_total) + dev->hblank_sub++; + + if ((dot8514 & eff_mask8514) == (dev->h_blank_end_val & eff_mask8514)) + break; + + dot8514++; + adj_dot8514++; + } + + dev->h_disp -= dev->hblank_sub; } } +#endif if (svga->hdisp >= 2048) svga->monitor->mon_overscan_x = 0; @@ -792,6 +852,10 @@ svga_recalctimings(svga_t *svga) svga->dispend = svga->vblankstart; crtcconst = svga->clock * svga->char_width; + if (ibm8514_active && (svga->dev8514 != NULL)) { + if (dev->on[0] || dev->on[1]) + crtcconst8514 = svga->clock8514; + } #ifdef ENABLE_SVGA_LOG vsyncend = (svga->vsyncstart & 0xfffffff0) | (svga->crtc[0x11] & 0x0f); @@ -830,9 +894,16 @@ svga_recalctimings(svga_t *svga) svga->htotal, hdispstart, hdispend, hsyncstart, hsyncend, svga->hblankstart, svga->hblankend); - disptime = svga->htotal; + disptime = svga->htotal * svga->multiplier; _dispontime = svga->hdisp_time; + if (ibm8514_active && (svga->dev8514 != NULL)) { + if (dev->on[0] || dev->on[1]) { + disptime8514 = dev->h_total ? dev->h_total : TIMER_USEC; + _dispontime8514 = dev->hdisped; + } + } + if (svga->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; @@ -849,12 +920,42 @@ svga_recalctimings(svga_t *svga) if (svga->dispofftime < TIMER_USEC) svga->dispofftime = TIMER_USEC; + if (ibm8514_active && (svga->dev8514 != NULL)) { + if (dev->on[0] || dev->on[1]) { + _dispofftime8514 = disptime8514 - _dispontime8514; + _dispontime8514 *= crtcconst8514; + _dispofftime8514 *= crtcconst8514; + + dev->dispontime = (uint64_t) (_dispontime8514); + dev->dispofftime = (uint64_t) (_dispofftime8514); + if (dev->dispontime < TIMER_USEC) + dev->dispontime = TIMER_USEC; + if (dev->dispofftime < TIMER_USEC) + dev->dispofftime = TIMER_USEC; + + timer_disable(&svga->timer); + timer_set_delay_u64(&svga->timer8514, TIMER_USEC); + } else { + timer_disable(&svga->timer8514); + timer_set_delay_u64(&svga->timer, TIMER_USEC); + } + } + if (!svga->force_old_addr) svga_recalc_remap_func(svga); /* Inform the user interface of any DPMS mode changes. */ if (svga->dpms) { if (!svga->dpms_ui) { + /* Make sure to black out the entire screen to avoid lingering image. */ + int y_add = enable_overscan ? svga->monitor->mon_overscan_y : 0; + int x_add = enable_overscan ? svga->monitor->mon_overscan_x : 0; + int y_start = enable_overscan ? 0 : (svga->monitor->mon_overscan_y >> 1); + int x_start = enable_overscan ? 0 : (svga->monitor->mon_overscan_x >> 1); + video_wait_for_buffer_monitor(svga->monitor_index); + memset(svga->monitor->target_buffer->dat, 0, svga->monitor->target_buffer->w * svga->monitor->target_buffer->h * 4); + video_blit_memtoscreen_monitor(x_start, y_start, svga->monitor->mon_xsize + x_add, svga->monitor->mon_ysize + y_add, svga->monitor_index); + video_wait_for_buffer_monitor(svga->monitor_index); svga->dpms_ui = 1; ui_sb_set_text_w(plat_get_string(IDS_2143)); } @@ -892,7 +993,7 @@ svga_do_render(svga_t *svga) if (svga->dac_hwcursor_on) { if (!svga->override && svga->dac_hwcursor_draw) - svga->dac_hwcursor_draw(svga, svga->displine + svga->y_add); + svga->dac_hwcursor_draw(svga, (svga->displine + svga->y_add + ((svga->dac_hwcursor_latch.y >= 0) ? 0 : svga->dac_hwcursor_latch.y)) & 2047); svga->dac_hwcursor_on--; if (svga->dac_hwcursor_on && svga->interlace) svga->dac_hwcursor_on--; @@ -900,7 +1001,7 @@ svga_do_render(svga_t *svga) if (svga->hwcursor_on) { if (!svga->override && svga->hwcursor_draw) - svga->hwcursor_draw(svga, svga->displine + svga->y_add); + svga->hwcursor_draw(svga, (svga->displine + svga->y_add + ((svga->hwcursor_latch.y >= 0) ? 0 : svga->hwcursor_latch.y)) & 2047); svga->hwcursor_on--; if (svga->hwcursor_on && svga->interlace) svga->hwcursor_on--; @@ -911,7 +1012,6 @@ void svga_poll(void *priv) { svga_t *svga = (svga_t *) priv; - ibm8514_t *dev = (ibm8514_t *) svga->dev8514; xga_t *xga = (xga_t *) svga->xga; uint32_t x; uint32_t blink_delay; @@ -921,10 +1021,6 @@ svga_poll(void *priv) int old_ma; if (!svga->override) { - if (ibm8514_active && dev && (dev->on[0] || dev->on[1])) { - ibm8514_poll(dev, svga); - return; - } if (xga_active && xga && xga->on) { if ((xga->disp_cntl_2 & 7) >= 2) { xga_poll(xga, svga); @@ -934,22 +1030,22 @@ svga_poll(void *priv) } if (!svga->linepos) { - if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena) { + if (svga->displine == ((svga->hwcursor_latch.y < 0) ? 0 : svga->hwcursor_latch.y) && svga->hwcursor_latch.ena) { svga->hwcursor_on = svga->hwcursor_latch.cur_ysize - svga->hwcursor_latch.yoff; svga->hwcursor_oddeven = 0; } - if (svga->displine == (svga->hwcursor_latch.y + 1) && svga->hwcursor_latch.ena && svga->interlace) { + if (svga->displine == (((svga->hwcursor_latch.y < 0) ? 0 : svga->hwcursor_latch.y) + 1) && svga->hwcursor_latch.ena && svga->interlace) { svga->hwcursor_on = svga->hwcursor_latch.cur_ysize - (svga->hwcursor_latch.yoff + 1); svga->hwcursor_oddeven = 1; } - if (svga->displine == svga->dac_hwcursor_latch.y && svga->dac_hwcursor_latch.ena) { + if (svga->displine == ((svga->dac_hwcursor_latch.y < 0) ? 0 : svga->dac_hwcursor_latch.y) && svga->dac_hwcursor_latch.ena) { svga->dac_hwcursor_on = svga->dac_hwcursor_latch.cur_ysize - svga->dac_hwcursor_latch.yoff; svga->dac_hwcursor_oddeven = 0; } - if (svga->displine == (svga->dac_hwcursor_latch.y + 1) && svga->dac_hwcursor_latch.ena && svga->interlace) { + if (svga->displine == (((svga->dac_hwcursor_latch.y < 0) ? 0 : svga->dac_hwcursor_latch.y) + 1) && svga->dac_hwcursor_latch.ena && svga->interlace) { svga->dac_hwcursor_on = svga->dac_hwcursor_latch.cur_ysize - (svga->dac_hwcursor_latch.yoff + 1); svga->dac_hwcursor_oddeven = 1; } @@ -1278,7 +1374,6 @@ svga_init(const device_t *info, svga_t *svga, void *priv, int memsize, svga->ramdac_type = RAMDAC_6BIT; svga->map8 = svga->pallook; - svga->hblank_overscan = 1; /* Do at least 1 character of overscan after horizontal blanking. */ return 0; } @@ -1323,14 +1418,10 @@ svga_decode_addr(svga_t *svga, uint32_t addr, int write) } if (memory_map_mode <= 1) { - if (svga->adv_flags & FLAG_EXTRA_BANKS) - addr = (addr & 0x17fff) + svga->extra_banks[(addr >> 15) & 1]; - else { - if (write) - addr += svga->write_bank; - else - addr += svga->read_bank; - } + if (write) + addr += svga->write_bank; + else + addr += svga->read_bank; } return addr; @@ -1782,14 +1873,14 @@ svga_doblit(int wx, int wy, svga_t *svga) p = &svga->monitor->target_buffer->line[i & 0x7ff][0]; for (j = 0; j < (svga->monitor->mon_xsize + x_add); j++) - p[j] = svga->overscan_color; + p[j] = svga->dpms ? 0 : svga->overscan_color; } for (i = 0; i < bottom; i++) { p = &svga->monitor->target_buffer->line[(svga->monitor->mon_ysize + svga->y_add + i) & 0x7ff][0]; for (j = 0; j < (svga->monitor->mon_xsize + x_add); j++) - p[j] = svga->overscan_color; + p[j] = svga->dpms ? 0 : svga->overscan_color; } } diff --git a/src/video/vid_svga_render.c b/src/video/vid_svga_render.c index 5a2728f8a..9b395ea6c 100644 --- a/src/video/vid_svga_render.c +++ b/src/video/vid_svga_render.c @@ -717,7 +717,7 @@ void svga_render_8bpp_lowres(svga_t *svga) { svga_render_indexed_gfx(svga, false void svga_render_8bpp_highres(svga_t *svga) { svga_render_indexed_gfx(svga, true, true); } void -svga_render_8bpp_incompatible_highres(svga_t *svga) +svga_render_8bpp_clone_highres(svga_t *svga) { int x; uint32_t *p; diff --git a/src/video/vid_table.c b/src/video/vid_table.c index cec106373..5b9c3f8f3 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -80,7 +80,7 @@ video_cards[] = { { &vid_none_device }, { &vid_internal_device }, { &atiega800p_device }, - { &mach8_isa_device, VIDEO_FLAG_TYPE_8514 }, + { &mach8_vga_isa_device, VIDEO_FLAG_TYPE_8514 }, { &mach32_isa_device, VIDEO_FLAG_TYPE_8514 }, { &mach64gx_isa_device }, { &ati28800k_device }, @@ -133,6 +133,7 @@ video_cards[] = { { &pgc_device }, { &cga_pravetz_device }, { &radius_svga_multiview_isa_device }, + { &realtek_rtg3105_device }, { &realtek_rtg3106_device }, { &s3_diamond_stealth_vram_isa_device }, { &s3_orchid_86c911_isa_device }, @@ -206,6 +207,7 @@ video_cards[] = { { &s3_virge_357_pci_device }, { &s3_diamond_stealth_4000_pci_device }, { &s3_trio3d2x_pci_device }, + { &chips_69000_device }, { &millennium_device }, { &millennium_ii_device }, { &mystique_device }, @@ -252,6 +254,7 @@ video_cards[] = { { &s3_spea_mirage_p64_vlb_device }, { &s3_phoenix_vision968_vlb_device }, { &s3_phoenix_vision868_vlb_device }, + { &s3_stb_powergraph_64_video_vlb_device }, { &ht216_32_standalone_device }, { &tgui9400cxi_device }, { &tgui9440_vlb_device }, diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index 7bed43ac2..490c724ce 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -76,7 +76,8 @@ #include <86box/vid_svga_render.h> #define ROM_TGUI_9400CXI "roms/video/tgui9440/9400CXI.VBI" -#define ROM_TGUI_9440 "roms/video/tgui9440/BIOS.BIN" +#define ROM_TGUI_9440_VLB "roms/video/tgui9440/trident_9440_vlb.bin" +#define ROM_TGUI_9440_PCI "roms/video/tgui9440/BIOS.BIN" #define ROM_TGUI_96xx "roms/video/tgui9660/Union.VBI" #define EXT_CTRL_16BIT 0x01 @@ -891,7 +892,6 @@ tgui_recalcmapping(tgui_t *tgui) } } else { mem_mapping_disable(&tgui->linear_mapping); - mem_mapping_disable(&tgui->accel_mapping); switch (svga->gdcreg[6] & 0xC) { case 0x0: /*128k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); @@ -899,12 +899,6 @@ tgui_recalcmapping(tgui_t *tgui) break; case 0x4: /*64k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - if ((svga->crtc[0x36] & 0x03) == 0x01) - mem_mapping_set_addr(&tgui->accel_mapping, 0xb4000, 0x4000); - else if ((svga->crtc[0x36] & 0x03) == 0x02) - mem_mapping_set_addr(&tgui->accel_mapping, 0xbc000, 0x4000); - else if ((svga->crtc[0x36] & 0x03) == 0x03) - mem_mapping_set_addr(&tgui->accel_mapping, tgui->ge_base, 0x4000); svga->banked_mask = 0xffff; break; case 0x8: /*32k at B0000*/ @@ -919,6 +913,18 @@ tgui_recalcmapping(tgui_t *tgui) default: break; } + + if (tgui->pci && tgui->linear_base) /*Assume that, with PCI, linear addressing is always enabled.*/ + mem_mapping_set_addr(&tgui->linear_mapping, tgui->linear_base, tgui->linear_size); + + if ((svga->crtc[0x36] & 0x03) == 0x01) + mem_mapping_set_addr(&tgui->accel_mapping, 0xb4000, 0x4000); + else if ((svga->crtc[0x36] & 0x03) == 0x02) + mem_mapping_set_addr(&tgui->accel_mapping, 0xbc000, 0x4000); + else if ((svga->crtc[0x36] & 0x03) == 0x03) + mem_mapping_set_addr(&tgui->accel_mapping, tgui->ge_base, 0x4000); + else + mem_mapping_disable(&tgui->accel_mapping); } if (tgui->type >= TGUI_9440) { @@ -982,7 +988,7 @@ tgui_pci_read(UNUSED(int func), int addr, void *priv) return (tgui->type == TGUI_9440) ? 0x94 : 0x96; case PCI_REG_COMMAND: - return tgui->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ + return tgui->pci_regs[PCI_REG_COMMAND] | 0x80; /*Respond to IO and memory accesses*/ case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ @@ -1043,11 +1049,12 @@ tgui_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) switch (addr) { case PCI_REG_COMMAND: - tgui->pci_regs[PCI_REG_COMMAND] = (val & 0x23); - if (val & PCI_COMMAND_IO) { + tgui->pci_regs[PCI_REG_COMMAND] = val & 0x23; + if (val & PCI_COMMAND_IO) tgui_set_io(tgui); - } else + else tgui_remove_io(tgui); + tgui_recalcmapping(tgui); break; @@ -3141,11 +3148,14 @@ tgui_init(const device_t *info) bios_fn = ROM_TGUI_9400CXI; break; case TGUI_9440: - bios_fn = (info->local & ONBOARD) ? NULL : ROM_TGUI_9440; + if (tgui->pci) + bios_fn = (info->local & ONBOARD) ? NULL : ROM_TGUI_9440_PCI; + else + bios_fn = ROM_TGUI_9440_VLB; break; case TGUI_9660: case TGUI_9680: - bios_fn = ROM_TGUI_96xx; + bios_fn = (info->local & ONBOARD) ? NULL : ROM_TGUI_96xx; break; default: free(tgui); @@ -3193,7 +3203,7 @@ tgui_init(const device_t *info) pci_add_card(PCI_ADD_VIDEO | PCI_ADD_STRICT, tgui_pci_read, tgui_pci_write, tgui, &tgui->pci_slot); } - tgui->pci_regs[PCI_REG_COMMAND] = 7; + tgui->pci_regs[PCI_REG_COMMAND] = 0x83; if (tgui->has_bios) { tgui->pci_regs[0x30] = 0x00; @@ -3218,9 +3228,15 @@ tgui9400cxi_available(void) } static int -tgui9440_available(void) +tgui9440_vlb_available(void) { - return rom_present(ROM_TGUI_9440); + return rom_present(ROM_TGUI_9440_VLB); +} + +static int +tgui9440_pci_available(void) +{ + return rom_present(ROM_TGUI_9440_PCI); } static int @@ -3338,7 +3354,7 @@ const device_t tgui9440_vlb_device = { .init = tgui_init, .close = tgui_close, .reset = NULL, - { .available = tgui9440_available }, + { .available = tgui9440_vlb_available }, .speed_changed = tgui_speed_changed, .force_redraw = tgui_force_redraw, .config = tgui9440_config @@ -3352,7 +3368,7 @@ const device_t tgui9440_pci_device = { .init = tgui_init, .close = tgui_close, .reset = NULL, - { .available = tgui9440_available }, + { .available = tgui9440_pci_available }, .speed_changed = tgui_speed_changed, .force_redraw = tgui_force_redraw, .config = tgui9440_config @@ -3386,6 +3402,20 @@ const device_t tgui9660_pci_device = { .config = tgui96xx_config }; +const device_t tgui9660_onboard_pci_device = { + .name = "Trident TGUI 9660XGi On-Board PCI", + .internal_name = "tgui9660_onboard_pci", + .flags = DEVICE_PCI, + .local = TGUI_9660 | ONBOARD, + .init = tgui_init, + .close = tgui_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = tgui_speed_changed, + .force_redraw = tgui_force_redraw, + .config = tgui96xx_config +}; + const device_t tgui9680_pci_device = { .name = "Trident TGUI 9680XGi PCI", .internal_name = "tgui9680_pci", diff --git a/src/video/vid_tvp3026_ramdac.c b/src/video/vid_tvp3026_ramdac.c index a28cc2aed..b50d0406b 100644 --- a/src/video/vid_tvp3026_ramdac.c +++ b/src/video/vid_tvp3026_ramdac.c @@ -65,7 +65,7 @@ typedef struct tvp3026_ramdac_t { static void tvp3026_set_bpp(tvp3026_ramdac_t *ramdac, svga_t *svga) { - if ((ramdac->true_color & 0x80) == 0x80) { + if (ramdac->true_color & 0x80) { if (ramdac->mcr & 0x08) svga->bpp = 8; else @@ -514,9 +514,16 @@ tvp3026_recalctimings(void *priv, svga_t *svga) { const tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) priv; - svga->interlace = (ramdac->ccr & 0x40); + svga->interlace = !!(ramdac->ccr & 0x40); /* TODO: Figure out gamma correction for 15/16 bpp color. */ svga->lut_map = !!(svga->bpp >= 15 && (ramdac->true_color & 0xf0) != 0x00); + + if (!(ramdac->clock_sel & 0x70)) { + if (ramdac->mcr != 0x98) { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + } + } } uint32_t @@ -590,7 +597,7 @@ tvp3026_hwcursor_draw(svga_t *svga, int displine) comb = (b0 | (b1 << 1)); y_pos = displine; - x_pos = offset + svga->x_add; + x_pos = (offset + svga->x_add) & 2047; p = svga->monitor->target_buffer->line[y_pos]; if (offset >= svga->dac_hwcursor_latch.x) { diff --git a/src/video/vid_vga.c b/src/video/vid_vga.c index 43b8a2750..8b2e761a3 100644 --- a/src/video/vid_vga.c +++ b/src/video/vid_vga.c @@ -186,7 +186,7 @@ vga_force_redraw(void *priv) } const device_t vga_device = { - .name = "VGA", + .name = "IBM VGA", .internal_name = "vga", .flags = DEVICE_ISA, .local = 0, @@ -200,7 +200,7 @@ const device_t vga_device = { }; const device_t ps1vga_device = { - .name = "PS/1 VGA", + .name = "IBM PS/1 VGA", .internal_name = "ps1vga", .flags = DEVICE_ISA, .local = 0, @@ -214,7 +214,7 @@ const device_t ps1vga_device = { }; const device_t ps1vga_mca_device = { - .name = "PS/1 VGA", + .name = "IBM PS/1 VGA", .internal_name = "ps1vga_mca", .flags = DEVICE_MCA, .local = 0, diff --git a/src/video/vid_voodoo.c b/src/video/vid_voodoo.c index a34f26503..734179fa9 100644 --- a/src/video/vid_voodoo.c +++ b/src/video/vid_voodoo.c @@ -772,7 +772,7 @@ voodoo_pci_read(int func, int addr, void *priv) switch (addr) { case 0x00: - return 0x1a; /*3dfx*/ + return 0x1a; /*3Dfx*/ case 0x01: return 0x12; @@ -1310,7 +1310,7 @@ static const device_config_t voodoo_config[] = { .type = CONFIG_SELECTION, .selection = { { - .description = "Voodoo Graphics", + .description = "3Dfx Voodoo Graphics", .value = VOODOO_1 }, { @@ -1318,7 +1318,7 @@ static const device_config_t voodoo_config[] = { .value = VOODOO_SB50 }, { - .description = "Voodoo 2", + .description = "3Dfx Voodoo 2", .value = VOODOO_2 }, { @@ -1427,7 +1427,7 @@ static const device_config_t voodoo_config[] = { }; const device_t voodoo_device = { - .name = "3DFX Voodoo Graphics", + .name = "3Dfx Voodoo Graphics", .internal_name = "voodoo", .flags = DEVICE_PCI, .local = 0, diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index 5e28e763c..098e919d4 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -556,26 +556,38 @@ banshee_recalctimings(svga_t *svga) if (banshee->vidProcCfg & VIDPROCCFG_VIDPROC_ENABLE) { /* Video processing mode - assume timings akin to Cirrus' special blanking mode, that is, no overscan and relying on display end to blank. */ - svga->hblankstart = svga->crtc[1] + ((svga->crtc[3] >> 5) & 3) + - (((svga->crtc[0x1a] & 0x04) >> 2) << 8) + 1; - svga->hblank_end_val = ((svga->crtc[3] >> 5) & 3); + if (banshee->vgaInit0 & 0x40) { + svga->hblankstart = svga->crtc[1]/* + ((svga->crtc[3] >> 5) & 3)*/ + + (((svga->crtc[0x1a] & 0x04) >> 2) << 8); + svga->hblank_end_mask = 0x0000007f; + } else { + svga->hblankstart = svga->crtc[1]/* + ((svga->crtc[3] >> 5) & 3)*/; + svga->hblank_end_mask = 0x0000003f; + } + svga->hblank_end_val = svga->htotal - 1 /* + ((svga->crtc[3] >> 5) & 3)*/; /* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */ if (!svga->scrblank && svga->attr_palette_enable) svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8; - /* No overscan in this mode. */ - svga->hblank_overscan = 0; - svga->monitor->mon_overscan_y = 0; svga->monitor->mon_overscan_x = 0; /* Also make sure vertical blanking starts on display end. */ svga->vblankstart = svga->dispend; + + svga->linedbl = 0; } else { - svga->hblankstart = (((svga->crtc[0x1a] & 0x10) >> 4) << 8) + svga->crtc[2] + 1; - svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | - (((svga->crtc[0x1a] & 0x20) >> 5) << 6); + if (banshee->vgaInit0 & 0x40) { + svga->hblankstart = (((svga->crtc[0x1a] & 0x10) >> 4) << 8) + svga->crtc[2]; + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5) | + (((svga->crtc[0x1a] & 0x20) >> 5) << 6); + svga->hblank_end_mask = 0x0000007f; + } else { + svga->hblankstart = svga->crtc[2]; + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | (((svga->crtc[5] & 0x80) >> 7) << 5); + svga->hblank_end_mask = 0x0000003f; + } } /*6 R/W Vertical Retrace Start bit 10 0x10 @@ -640,9 +652,7 @@ banshee_recalctimings(svga_t *svga) if (banshee->vidProcCfg & VIDPROCCFG_2X_MODE) { svga->hdisp *= 2; - svga->htotal *= 2; - svga->hblankstart *= 2; - svga->hblank_end_val *= 2; + svga->dots_per_clock *= 2; } svga->interlace = !!(banshee->vidProcCfg & VIDPROCCFG_INTERLACE); @@ -3533,7 +3543,7 @@ banshee_force_redraw(void *priv) } const device_t voodoo_banshee_device = { - .name = "3dfx Voodoo Banshee", + .name = "3Dfx Voodoo Banshee", .internal_name = "voodoo_banshee_pci", .flags = DEVICE_PCI, .local = 0, diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index 17b6dfdb5..fad5e4124 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -178,8 +178,8 @@ xga_updatemapping(svga_t *svga) } } - xga_log("XGA opmode (extended) = %d, disp mode = %d, aperture = %d.\n", xga->op_mode & 7, - xga->disp_cntl_2 & 7, xga->aperture_cntl); + xga_log("XGA opmode (extended) = %d, disp mode = %d, aperture = %d, on = %d, linear endian reverse = %d.\n", xga->op_mode & 7, + xga->disp_cntl_2 & 7, xga->aperture_cntl, xga->on, xga->linear_endian_reverse); } xga_log("VGA on = %d, map = %02x.\n", vga_on, svga->gdcreg[6] & 0x0c); } @@ -198,7 +198,7 @@ xga_recalctimings(svga_t *svga) xga->h_disp = (xga->hdisp + 1) << 3; - xga->rowoffset = (xga->hdisp + 1); + xga->rowoffset = xga->hdisp + 1; xga->interlace = !!(xga->disp_cntl_1 & 0x08); xga->rowcount = (xga->disp_cntl_2 & 0xc0) >> 6; @@ -213,6 +213,11 @@ xga_recalctimings(svga_t *svga) xga->ma_latch = xga->disp_start_addr; + if ((xga->disp_cntl_2 & 7) == 2) + xga->rowoffset >>= 1; + else if ((xga->disp_cntl_2 & 7) == 4) + xga->rowoffset <<= 1; + xga_log("XGA ClkSel1 = %d, ClkSel2 = %02x.\n", (xga->clk_sel_1 >> 2) & 3, xga->clk_sel_2 & 0x80); switch ((xga->clk_sel_1 >> 2) & 3) { case 0: @@ -410,7 +415,7 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) xga->cursor_data_on = 1; else if ((xga->sprite_pos >= 1) || (((xga->disp_cntl_2 & 7) == 2) || (xga->disp_cntl_2 & 7) == 4)) xga->cursor_data_on = 1; - else if (xga->aperture_cntl == 0) { + else if (!xga->aperture_cntl) { if (xga->linear_endian_reverse && !(xga->access_mode & 8)) xga->cursor_data_on = 0; } @@ -422,10 +427,11 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) xga->cursor_data_on = 1; else xga->cursor_data_on = 0; - } else { + } else xga->cursor_data_on = 0; - } - } + } else if (!xga->sprite_pos && xga->cursor_data_on && !xga->aperture_cntl && xga->linear_endian_reverse) + xga->cursor_data_on = 0; + xga_log("Sprite POS = %d, data on = %d, idx = %d, apcntl = %d\n", xga->sprite_pos, xga->cursor_data_on, xga->sprite_pal_addr_idx, xga->aperture_cntl); @@ -803,7 +809,7 @@ xga_ext_inb(uint16_t addr, void *priv) break; } - xga_log("[%04X:%08X]: EXT INB = %02x, ret = %02x\n", CS, cpu_state.pc, addr, ret); + xga_log("[%04X:%08X]: EXT INB = %02x, ret = %02x.\n\n", CS, cpu_state.pc, addr, ret); return ret; } @@ -998,9 +1004,9 @@ xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int addr += x; if (!skip) { READ(addr, byte); - } else { + } else byte = mem_readb_phys(addr); - } + return byte; case 4: /*16-bit*/ addr += (y * (width << 1)); @@ -1082,6 +1088,7 @@ xga_accel_write_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, ui } else { byte = mem_readb_phys(addr); } + if (xga->linear_endian_reverse) mask = 0x0f << ((1 - (x & 1)) << 2); else { @@ -1233,9 +1240,8 @@ xga_short_stroke(svga_t *svga, uint8_t ssv) } } - if (!y) { + if (!y) break; - } dx += dirx; dy += diry; @@ -1249,50 +1255,28 @@ xga_short_stroke(svga_t *svga, uint8_t ssv) xga->accel.dst_map_y = dy; } -#define SWAP(a, b) \ - tmpswap = a; \ - a = b; \ - b = tmpswap; - static void xga_line_draw_write(svga_t *svga) { xga_t *xga = (xga_t *) svga->xga; uint32_t src_dat; uint32_t dest_dat; - uint32_t old_dest_dat; + uint32_t old_dest_dat = 0x00000000; uint32_t color_cmp = xga->accel.color_cmp; uint32_t plane_mask = xga->accel.plane_mask; uint32_t dstbase = xga->accel.px_map_base[xga->accel.dst_map]; uint32_t srcbase = xga->accel.px_map_base[xga->accel.src_map]; - int dminor; - int destxtmp; - int dmajor; - int err; - int tmpswap; - int steep = 1; - int xdir = (xga->accel.octant & 0x04) ? -1 : 1; - int ydir = (xga->accel.octant & 0x02) ? -1 : 1; int y = xga->accel.blt_width; int x = 0; int16_t dx; int16_t dy; - int draw_pixel; + int16_t cx; + int16_t cy; + int err = xga->accel.bres_err_term; + int draw_pixel = 0; - dminor = xga->accel.bres_k1; - if (xga->accel.bres_k1 & 0x2000) - dminor |= ~0x1fff; - dminor >>= 1; - - destxtmp = xga->accel.bres_k2; - if (xga->accel.bres_k2 & 0x2000) - destxtmp |= ~0x1fff; - - dmajor = -(destxtmp - (dminor << 1)) >> 1; - - err = xga->accel.bres_err_term; - if (xga->accel.bres_err_term & 0x2000) - err |= ~0x1fff; + cx = xga->accel.src_map_x & 0xfff; + cy = xga->accel.src_map_y & 0xfff; dx = xga->accel.dst_map_x & 0x1fff; if (xga->accel.dst_map_x >= 0x1800) @@ -1305,17 +1289,87 @@ xga_line_draw_write(svga_t *svga) if ((xga->accel.command & 0x30) == 0x30) xga_log("Line Draw Write: BLTWIDTH=%d, BLTHEIGHT=%d, FRGDCOLOR=%04x, XDIR=%i, YDIR=%i, steep=%s, ERR=%04x.\n", xga->accel.blt_width, xga->accel.blt_height, xga->accel.frgd_color & 0xffff, xdir, ydir, (xga->accel.octant & 0x01) ? "0" : "1", err); - if (xga->accel.octant & 0x01) { - steep = 0; - SWAP(dx, dy); - SWAP(xdir, ydir); - } if (xga->accel.pat_src == 8) { - while (y >= 0) { - draw_pixel = 1; - if (xga->accel.command & 0xc0) { - if (steep) { + if ((xga->accel.command & 0x30) == 0x30) { + while (y >= 0) { + draw_pixel = 0; + + if (xga->accel.octant & 0x01) { + if (xga->accel.octant & 0x02) { /*Bottom-to-Top*/ + if (x) + draw_pixel = 1; + } else { /*Top-to-Bottom*/ + if (y) + draw_pixel = 1; + } + } else if (!(xga->accel.octant & 0x04) && (err < (xga->accel.bres_k2 + xga->accel.bres_k1))) /*X+*/ + draw_pixel = 1; + else if ((xga->accel.octant & 0x04) && (err >= 0)) /*X-*/ + draw_pixel = 1; + + if (xga->accel.command & 0xc0) { + if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { + if (draw_pixel) { + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, cx, cy, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color; + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0); + + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + ROP(1, dest_dat, src_dat); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + } + } + } + } else { + if (draw_pixel) { + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, cx, cy, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color; + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0); + + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + ROP(1, dest_dat, src_dat); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); + } + } + } + + if (x == xga->accel.blt_width) + break; + + if (xga->accel.octant & 0x01) { + if (xga->accel.octant & 0x02) + dy--; + else + dy++; + + if (err >= 0) { + err += xga->accel.bres_k2; + if (xga->accel.octant & 0x04) + dx--; + else + dx++; + } else + err += xga->accel.bres_k1; + } else { + if (xga->accel.octant & 0x04) + dx--; + else + dx++; + + if (err >= 0) { + err += xga->accel.bres_k2; + if (xga->accel.octant & 0x02) + dy--; + else + dy++; + } else + err += xga->accel.bres_k1; + } + x++; + y--; + } + } else { + while (y >= 0) { + if (xga->accel.command & 0xc0) { if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color; dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0); @@ -1330,54 +1384,9 @@ xga_line_draw_write(svga_t *svga) xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); else if (((xga->accel.command & 0x30) == 0x20) && y) xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - else if ((xga->accel.command & 0x30) == 0x30) { - if (err < 0) - draw_pixel = 0; - else { - if (ydir == -1) { /*Bottom-to-Top*/ - if (!x) - draw_pixel = 0; - } else { /*Top-to-Bottom*/ - if (!y) - draw_pixel = 0; - } - } - if (draw_pixel) - xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - } } } } else { - if ((dy >= xga->accel.mask_map_origin_x_off) && (dy <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dx >= xga->accel.mask_map_origin_y_off) && (dx <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { - src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color; - dest_dat = xga_accel_read_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0); - - if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { - old_dest_dat = dest_dat; - ROP(1, dest_dat, src_dat); - dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); - if ((xga->accel.command & 0x30) == 0) - xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - else if (((xga->accel.command & 0x30) == 0x10) && x) - xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - else if (((xga->accel.command & 0x30) == 0x20) && y) - xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - else if ((xga->accel.command & 0x30) == 0x30) { - if (xdir == -1) { /*Bottom-to-Top*/ - if (!x) - draw_pixel = 0; - } else { /*Top-to-Bottom*/ - if (!y) - draw_pixel = 0; - } - if (draw_pixel) - xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - } - } - } - } - } else { - if (steep) { src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color; dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0); @@ -1391,84 +1400,52 @@ xga_line_draw_write(svga_t *svga) xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); else if (((xga->accel.command & 0x30) == 0x20) && y) xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - else if ((xga->accel.command & 0x30) == 0x30) { - if (err < 0) - draw_pixel = 0; - else { - if (ydir == -1) { /*Bottom-to-Top*/ - if (!x) - draw_pixel = 0; - } else { /*Top-to-Bottom*/ - if (!y) - draw_pixel = 0; - } - } - if (draw_pixel) - xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - } - } - } else { - src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.src_map_x & 0xfff, xga->accel.src_map_y & 0xfff, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1, 1) : xga->accel.frgd_color; - dest_dat = xga_accel_read_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1, 0); - - if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { - old_dest_dat = dest_dat; - ROP(1, dest_dat, src_dat); - dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); - if ((xga->accel.command & 0x30) == 0) - xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - else if (((xga->accel.command & 0x30) == 0x10) && x) - xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - else if (((xga->accel.command & 0x30) == 0x20) && y) - xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - else if ((xga->accel.command & 0x30) == 0x30) { - if (xdir == -1) { /*Bottom-to-Top*/ - if (!x) - draw_pixel = 0; - } else { /*Top-to-Bottom*/ - if (!y) - draw_pixel = 0; - } - if (draw_pixel) - xga_accel_write_map_pixel(svga, dy, dx, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1); - } } } + + if (!y) + break; + + if (xga->accel.octant & 0x01) { + if (xga->accel.octant & 0x02) + dy--; + else + dy++; + + if (err >= 0) { + err += xga->accel.bres_k2; + if (xga->accel.octant & 0x04) + dx--; + else + dx++; + } else + err += xga->accel.bres_k1; + } else { + if (xga->accel.octant & 0x04) + dx--; + else + dx++; + + if (err >= 0) { + err += xga->accel.bres_k2; + if (xga->accel.octant & 0x02) + dy--; + else + dy++; + } else + err += xga->accel.bres_k1; + } + y--; + x++; } - - if (!y) { - break; - } - - while (err >= 0) { - dy += ydir; - err -= (dmajor << 1); - } - - dx += xdir; - err += (dminor << 1); - - x++; - y--; } } - - if (steep) { - xga->accel.dst_map_x = dx; - xga->accel.dst_map_y = dy; - } else { - xga->accel.dst_map_x = dy; - xga->accel.dst_map_y = dx; - } } -#undef SWAP - static void xga_bitblt(svga_t *svga) { xga_t *xga = (xga_t *) svga->xga; - uint8_t area_state = 0; uint32_t src_dat; uint32_t dest_dat; uint32_t old_dest_dat; @@ -1507,6 +1484,7 @@ xga_bitblt(svga_t *svga) xga_log("D(%d,%d), SWH(%d,%d), BLT(%d,%d), dstwidth=%d.\n", dx, dy, xga->accel.x, xga->accel.y, srcwidth, srcheight, dstwidth); xga->accel.pattern = 0; + xga->accel.filling = 0; xga_log("XGA bitblt linear endian reverse=%d, access_mode=%x, octanty=%d, src command = %08x, " "pxsrcmap=%x, pxpatmap=%x, pxdstmap=%x, srcmap=%d, patmap=%d, dstmap=%d, " @@ -1637,76 +1615,66 @@ xga_bitblt(svga_t *svga) xga->accel.px_map_width[0], xga->accel.px_map_width[1], xga->accel.px_map_width[2], xga->accel.px_map_width[3], bkgdcol); - if (((xga->accel.command >> 24) & 0x0f) == 0x0a) { + if ((((xga->accel.command >> 24) & 0x0f) == 0x0a) && ((xga->accel.bkgd_mix & 0x1f) == 5)) { while (xga->accel.y >= 0) { mix = xga_accel_read_pattern_map_pixel(svga, xga->accel.px, xga->accel.py, xga->accel.pat_src, patbase, patwidth + 1); if (mix) - area_state ^= 1; + xga->accel.filling = !xga->accel.filling; if (xga->accel.command & 0xc0) { if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { - if (area_state) - src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; - else - src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol; - - if ((xga->accel.px_map_format[xga->accel.dst_map] & 7) <= 3) - src_dat &= 0xff; - - dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); - if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { - old_dest_dat = dest_dat; - ROP(area_state, dest_dat, src_dat); - dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); - xga_log("1SRCDat=%02x, DSTDat=%02x, Old=%02x, MIX=%d.\n", src_dat, dest_dat, old_dest_dat, area_state); - xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; + if (xga->accel.filling) { + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, 1024, 0); + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + old_dest_dat = dest_dat; + ROP(1, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); + xga_log("1SRCDat=%02x, DSTDat=%02x, Old=%02x, MIX=%d.\n", src_dat, dest_dat, old_dest_dat, area_state); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + } } } } else { if ((dx >= 0) && (dx <= dstwidth) && (dy >= 0) && (dy <= dstheight)) { - if (area_state) - src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; - else - src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol; - - if ((xga->accel.px_map_format[xga->accel.dst_map] & 7) <= 3) - src_dat &= 0xff; - - dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); - if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { - old_dest_dat = dest_dat; - ROP(area_state, dest_dat, src_dat); - dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); - xga_log("2Fill: NumXY(%d,%d): DXY(%d,%d): SRCDat=%02x, DSTDat=%02x, Old=%02x, frgdcol=%02x, bkgdcol=%02x, MIX=%d, frgdmix=%02x, bkgdmix=%02x, dstmapfmt=%02x, srcmapfmt=%02x, srcmapnum=%d.\n", x, y, dx, dy, src_dat, dest_dat, old_dest_dat, frgdcol, bkgdcol, area_state, xga->accel.frgd_mix & 0x1f, xga->accel.bkgd_mix & 0x1f, xga->accel.px_map_format[xga->accel.dst_map] & 0x0f, xga->accel.px_map_format[xga->accel.src_map] & 0x0f, xga->accel.src_map); - xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; + if (xga->accel.filling) { + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); + if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { + old_dest_dat = dest_dat; + ROP(1, dest_dat, src_dat); + dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask); + xga_log("2Fill: NumXY(%d,%d): DXY(%d,%d): SRCDat=%02x, DSTDat=%02x, Old=%02x, frgdcol=%02x, bkgdcol=%02x, MIX=%d, frgdmix=%02x, bkgdmix=%02x, dstmapfmt=%02x, srcmapfmt=%02x, srcmapnum=%d.\n", x, y, dx, dy, src_dat, dest_dat, old_dest_dat, frgdcol, bkgdcol, area_state, xga->accel.frgd_mix & 0x1f, xga->accel.bkgd_mix & 0x1f, xga->accel.px_map_format[xga->accel.dst_map] & 0x0f, xga->accel.px_map_format[xga->accel.src_map] & 0x0f, xga->accel.src_map); + xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1); + } } } } - xga->accel.sx = ((xga->accel.sx + 1) & srcwidth) | (xga->accel.sx & ~srcwidth); - xga->accel.px = ((xga->accel.px + 1) & patwidth) | (xga->accel.px & ~patwidth); + xga->accel.sx = ((xga->accel.sx + xdir) & srcwidth) | (xga->accel.sx & ~srcwidth); + xga->accel.px++; + dx++; xga->accel.x--; if (xga->accel.x < 0) { - area_state = 0; xga->accel.y--; xga->accel.x = xga->accel.blt_width & 0xfff; dx = xga->accel.dst_map_x & 0x1fff; if (xga->accel.dst_map_x >= 0x1800) dx |= ~0x17ff; + xga->accel.sx = xga->accel.src_map_x & 0xfff; xga->accel.px = xga->accel.pat_map_x & 0xfff; xga->accel.sy = ((xga->accel.sy + ydir) & srcheight) | (xga->accel.sy & ~srcheight); - xga->accel.py += ydir; - dy += ydir; + xga->accel.py++; - if (xga->accel.y < 0) { - xga->accel.dst_map_x = dx; - xga->accel.dst_map_y = dy; + dy++; + xga->accel.filling = 0; + + if (xga->accel.y < 0) return; - } } } } else { @@ -1715,11 +1683,11 @@ xga_bitblt(svga_t *svga) if (xga->accel.command & 0xc0) { if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) { - if (mix) { + if (mix) src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; - } else { + else src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol; - } + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { old_dest_dat = dest_dat; @@ -1730,11 +1698,11 @@ xga_bitblt(svga_t *svga) } } else { if ((dx >= 0) && (dx <= dstwidth) && (dy >= 0) && (dy <= dstheight)) { - if (mix) { + if (mix) src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : frgdcol; - } else { + else src_dat = (((xga->accel.command >> 30) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1, 1) : bkgdcol; - } + dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dstwidth + 1, 0); if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) { old_dest_dat = dest_dat; @@ -1760,6 +1728,7 @@ xga_bitblt(svga_t *svga) dx = xga->accel.dst_map_x & 0x1fff; if (xga->accel.dst_map_x >= 0x1800) dx |= ~0x17ff; + xga->accel.sx = xga->accel.src_map_x & 0xfff; xga->accel.px = xga->accel.pat_map_x & 0xfff; @@ -1853,7 +1822,7 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) if (len >= 2) { xga->accel.bres_err_term = val & 0x3fff; if (val & 0x2000) - xga->accel.bres_err_term |= ~0x3fff; + xga->accel.bres_err_term |= ~0x1fff; } else xga->accel.bres_err_term = (xga->accel.bres_err_term & 0x3f00) | val; break; @@ -1861,7 +1830,7 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) if (len == 1) { xga->accel.bres_err_term = (xga->accel.bres_err_term & 0xff) | ((val & 0x3f) << 8); if (val & 0x20) - xga->accel.bres_err_term |= ~0x3fff; + xga->accel.bres_err_term |= ~0x1fff; } break; @@ -1869,7 +1838,7 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) if (len >= 2) { xga->accel.bres_k1 = val & 0x3fff; if (val & 0x2000) - xga->accel.bres_k1 |= ~0x3fff; + xga->accel.bres_k1 |= ~0x1fff; } else xga->accel.bres_k1 = (xga->accel.bres_k1 & 0x3f00) | val; break; @@ -1877,7 +1846,7 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) if (len == 1) { xga->accel.bres_k1 = (xga->accel.bres_k1 & 0xff) | ((val & 0x3f) << 8); if (val & 0x20) - xga->accel.bres_k1 |= ~0x3fff; + xga->accel.bres_k1 |= ~0x1fff; } break; @@ -1885,7 +1854,7 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) if (len >= 2) { xga->accel.bres_k2 = val & 0x3fff; if (val & 0x2000) - xga->accel.bres_k2 |= ~0x3fff; + xga->accel.bres_k2 |= ~0x1fff; } else xga->accel.bres_k2 = (xga->accel.bres_k2 & 0x3f00) | val; break; @@ -1893,7 +1862,7 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) if (len == 1) { xga->accel.bres_k2 = (xga->accel.bres_k2 & 0xff) | ((val & 0x3f) << 8); if (val & 0x20) - xga->accel.bres_k2 |= ~0x3fff; + xga->accel.bres_k2 |= ~0x1fff; } break; @@ -1998,6 +1967,30 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) xga->accel.plane_mask = (xga->accel.plane_mask & 0x00ffffff) | (val << 24); break; + case 0x54: + if (len == 4) + xga->accel.carry_chain = val; + else if (len == 2) + xga->accel.carry_chain = (xga->accel.carry_chain & 0xffff0000) | val; + else + xga->accel.carry_chain = (xga->accel.carry_chain & 0xffffff00) | val; + break; + case 0x55: + if (len == 1) + xga->accel.carry_chain = (xga->accel.carry_chain & 0xffff00ff) | (val << 8); + break; + case 0x56: + if (len == 2) + xga->accel.carry_chain = (xga->accel.carry_chain & 0x0000ffff) | (val << 16); + else + xga->accel.carry_chain = (xga->accel.carry_chain & 0xff00ffff) | (val << 16); + break; + case 0x57: + if (len == 1) + xga->accel.carry_chain = (xga->accel.carry_chain & 0x00ffffff) | (val << 24); + break; + + case 0x58: if (len == 4) xga->accel.frgd_color = val; @@ -2422,7 +2415,7 @@ xga_memio_readl(uint32_t addr, void *priv) temp |= (xga_mem_read(addr + 2, xga, svga) << 16); temp |= (xga_mem_read(addr + 3, xga, svga) << 24); - xga_log("Read MEMIOL = %04x, temp = %08x\n", addr, temp); + xga_log("[%04X:%08X]: Read MEMIOL = %04x, temp = %08x\n", CS, cpu_state.pc, addr, temp); return temp; } @@ -2437,7 +2430,7 @@ xga_hwcursor_draw(svga_t *svga, int displine) int y_pos; int comb = 0; uint32_t *p; - int idx = (xga->cursor_data_on) ? 32 : 0; + int idx = xga->cursor_data_on ? 32 : 0; if (xga->interlace && xga->hwcursor_oddeven) xga->hwcursor_latch.addr += 16; @@ -2532,20 +2525,24 @@ xga_render_4bpp(svga_t *svga) for (int x = 0; x <= xga->h_disp; x += 16) { dat = *(uint32_t *) (&xga->vram[xga->ma & xga->vram_mask]); - p[0] = xga->pallook[(dat >> 4) & 0x0f]; - p[1] = xga->pallook[dat & 0x0f]; - p[2] = xga->pallook[(dat >> 12) & 0x0f]; - p[3] = xga->pallook[(dat >> 8) & 0x0f]; - p[4] = xga->pallook[(dat >> 20) & 0x0f]; - p[5] = xga->pallook[(dat >> 16) & 0x0f]; - p[6] = xga->pallook[(dat >> 28) & 0x0f]; - p[7] = xga->pallook[(dat >> 24) & 0x0f]; + p[0] = xga->pallook[dat & 0x0f]; + p[1] = xga->pallook[(dat >> 4) & 0x0f]; + p[2] = xga->pallook[(dat >> 8) & 0x0f]; + p[3] = xga->pallook[(dat >> 12) & 0x0f]; + p[4] = xga->pallook[(dat >> 16) & 0x0f]; + p[5] = xga->pallook[(dat >> 20) & 0x0f]; + p[6] = xga->pallook[(dat >> 24) & 0x0f]; + p[7] = xga->pallook[(dat >> 28) & 0x0f]; dat = *(uint32_t *) (&xga->vram[(xga->ma + 4) & xga->vram_mask]); - p[9] = xga->pallook[dat & 0x0f]; - p[11] = xga->pallook[(dat >> 8) & 0x0f]; - p[13] = xga->pallook[(dat >> 16) & 0x0f]; - p[15] = xga->pallook[(dat >> 24) & 0x0f]; + p[8] = xga->pallook[dat & 0x0f]; + p[9] = xga->pallook[(dat >> 4) & 0x0f]; + p[10] = xga->pallook[(dat >> 8) & 0x0f]; + p[11] = xga->pallook[(dat >> 12) & 0x0f]; + p[12] = xga->pallook[(dat >> 16) & 0x0f]; + p[13] = xga->pallook[(dat >> 20) & 0x0f]; + p[14] = xga->pallook[(dat >> 24) & 0x0f]; + p[15] = xga->pallook[(dat >> 28) & 0x0f]; xga->ma += 8; p += 16; @@ -2609,7 +2606,7 @@ xga_render_16bpp(svga_t *svga) xga->firstline_draw = xga->displine; xga->lastline_draw = xga->displine; - for (x = 0; x <= (xga->h_disp); x += 8) { + for (x = 0; x <= xga->h_disp; x += 8) { dat = *(uint32_t *) (&xga->vram[(xga->ma + (x << 1)) & xga->vram_mask]); p[x] = video_16to32[dat & 0xffff]; p[x + 1] = video_16to32[dat >> 16]; @@ -2952,9 +2949,8 @@ xga_poll(void *priv, svga_t *svga) video_wait_for_buffer_monitor(svga->monitor_index); } - if (xga->hwcursor_on) { + if (xga->hwcursor_on) xga->changedvram[xga->ma >> 12] = xga->changedvram[(xga->ma >> 12) + 1] = xga->interlace ? 3 : 2; - } xga_do_render(svga); @@ -2976,9 +2972,10 @@ xga_poll(void *priv, svga_t *svga) if (xga->sc == xga->rowcount) { xga->sc = 0; - xga->maback += (xga->rowoffset << (xga->disp_cntl_2 & 7)); + xga->maback += (xga->rowoffset << 3); if (xga->interlace) - xga->maback += (xga->rowoffset << (xga->disp_cntl_2 & 7)); + xga->maback += (xga->rowoffset << 3); + xga->maback &= xga->vram_mask; xga->ma = xga->maback; } else { @@ -2996,6 +2993,7 @@ xga_poll(void *priv, svga_t *svga) xga->ma = xga->maback = (xga->rowoffset << 1); else xga->ma = xga->maback = 0; + xga->ma = (xga->ma << 2); xga->maback = (xga->maback << 2); @@ -3135,6 +3133,8 @@ xga_mca_reset(void *priv) xga->on = 0; vga_on = 1; xga_mca_write(0x102, 0, svga); + xga->linear_endian_reverse = 0; + xga->a5_test = 0; } static void diff --git a/src/video/video.c b/src/video/video.c index 710449746..01c398118 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -831,9 +831,9 @@ destroy_bitmap(bitmap_t *b) bitmap_t * create_bitmap(int x, int y) { - bitmap_t *b = malloc(sizeof(bitmap_t) + (y * sizeof(uint32_t *))); + bitmap_t *b = calloc(sizeof(bitmap_t), (y * sizeof(uint32_t *))); - b->dat = malloc((size_t) x * y * 4); + b->dat = calloc((size_t) x * y, 4); for (int c = 0; c < y; c++) b->line[c] = &(b->dat[c * x]); b->w = x; diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 0de947154..58802c5a4 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -70,6 +70,9 @@ ifeq ($(DEV_BUILD), y) ifndef OPEN_AT OPEN_AT := y endif + ifndef OPL4ML + OPL4ML := y + endif ifndef PAS16 PAS16 := y endif @@ -131,6 +134,9 @@ else ifndef OPEN_AT OPEN_AT := n endif + ifndef OPL4ML + OPL4ML := n + endif ifndef PAS16 PAS16 := n endif @@ -494,6 +500,11 @@ ifeq ($(DEV_BRANCH), y) OPTS += -DUSE_OPEN_AT endif + ifeq ($(OPL4ML), y) + OPTS += -DUSE_OPL4ML + DEVBROBJ += midi_opl4.o midi_opl4_yrw801.o + endif + ifeq ($(PAS16), y) OPTS += -DUSE_PAS16 DEVBROBJ += snd_pas16.o @@ -704,8 +715,6 @@ SNDOBJ := sound.o \ wave8580__ST.o wave8580_P_T.o wave8580_PS_.o \ wave8580_PST.o wave.o \ midi.o \ - midi_opl4.o \ - midi_opl4_yrw801.o \ snd_speaker.o \ snd_pssj.o \ snd_ps1.o \ @@ -744,6 +753,7 @@ VIDOBJ := agpgart.o video.o \ vid_ati68875_ramdac.o \ vid_ati_mach64.o vid_ati68860_ramdac.o \ vid_bt48x_ramdac.o \ + vid_chips_69000.o \ vid_av9194.o vid_icd2061.o vid_ics2494.o vid_ics2595.o \ vid_cl54xx.o \ vid_et3000.o \ diff --git a/src/win/languages/cs-CZ.rc b/src/win/languages/cs-CZ.rc index 6c0982c5c..cbda41e7e 100644 --- a/src/win/languages/cs-CZ.rc +++ b/src/win/languages/cs-CZ.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Grafika:" #define STR_VIDEO_2 "Grafika 2:" #define STR_VOODOO "Použít grafický akcelerátor Voodoo" -#define STR_IBM8514 "Grafika IBM 8514/a" +#define STR_IBM8514 "Grafika IBM 8514/A" #define STR_XGA "Grafika XGA" #define STR_MOUSE "Myš:" @@ -464,7 +464,6 @@ BEGIN IDS_2108 "%u MB (CHS: %i, %i, %i)" IDS_2109 "Disketová mechanika %i (%s): %ls" IDS_2110 "Všechny obrazy (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Rozšířené sektorové obrazy (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Základní sektorové obrazy (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Obrazy magnetického toku (*.FDI)\0*.FDI\0Obrazy povrchu (*.86F;*.MFM)\0*.86F;*.MFM\0Všechny soubory (*.*)\0*.*\0" - IDS_2112 "Nastala chyba při inicializaci knihovny SDL, je potřeba SDL2.dll" IDS_2113 "Opravdu chcete resetovat emulovaný počítač?" IDS_2114 "Opravdu chcete ukončit 86Box?" IDS_2115 "Nastala chyba při inicializaci knihovny Ghostscript" diff --git a/src/win/languages/de-DE.rc b/src/win/languages/de-DE.rc index 031f935cd..9859d3d26 100644 --- a/src/win/languages/de-DE.rc +++ b/src/win/languages/de-DE.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Videokarte:" #define STR_VIDEO_2 "Videokarte 2:" #define STR_VOODOO "Voodoo-Grafik" -#define STR_IBM8514 "IBM 8514/a-Grafik" +#define STR_IBM8514 "IBM 8514/A-Grafik" #define STR_XGA "XGA-Grafik" #define STR_MOUSE "Maus:" @@ -464,7 +464,6 @@ BEGIN IDS_2108 "%u MB (CHS: %i, %i, %i)" IDS_2109 "Diskette %i (%s): %ls" IDS_2110 "Alle Images (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Fortgeschrittene Sektorimages (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Basissektorimages (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Fluximages (*.FDI)\0*.FDI\0Oberflächenimages (*.86F;*.MFM)\0*.86F;*.MFM\0Alle Dateien (*.*)\0*.*\0" - IDS_2112 "SDL konnte nicht initialisiert werden, die Datei SDL2.dll wird benötigt" IDS_2113 "Sind Sie sich sicher, dass Sie einen Hard-Reset für das emulierte System durchführen wollen?" IDS_2114 "Sind Sie sich sicher, dass Sie 86Box beenden wollen?" IDS_2115 "Ghostscript konnte nicht initialisiert werden" diff --git a/src/win/languages/en-GB.rc b/src/win/languages/en-GB.rc index 01e18f71a..a974b1862 100644 --- a/src/win/languages/en-GB.rc +++ b/src/win/languages/en-GB.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Video:" #define STR_VIDEO_2 "Video 2:" #define STR_VOODOO "Voodoo Graphics" -#define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_IBM8514 "IBM 8514/A Graphics" #define STR_XGA "XGA Graphics" #define STR_MOUSE "Mouse:" @@ -293,10 +293,10 @@ END #define STR_JOY3 "Joystick 3..." #define STR_JOY4 "Joystick 4..." -#define STR_SOUND1 "Sound card 1:" -#define STR_SOUND2 "Sound card 2:" -#define STR_SOUND3 "Sound card 3:" -#define STR_SOUND4 "Sound card 4:" +#define STR_SOUND1 "Sound card #1:" +#define STR_SOUND2 "Sound card #2:" +#define STR_SOUND3 "Sound card #3:" +#define STR_SOUND4 "Sound card #4:" #define STR_MIDI_OUT "MIDI Out Device:" #define STR_MIDI_IN "MIDI In Device:" #define STR_MPU401 "Standalone MPU-401" @@ -464,7 +464,6 @@ BEGIN IDS_2108 "%u MB (CHS: %i, %i, %i)" IDS_2109 "Floppy %i (%s): %ls" IDS_2110 "All images (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Advanced sector images (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Basic sector images (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux images (*.FDI)\0*.FDI\0Surface images (*.86F;*.MFM)\0*.86F;*.MFM\0All files (*.*)\0*.*\0" - IDS_2112 "Unable to initialize SDL, SDL2.dll is required" IDS_2113 "Are you sure you want to hard reset the emulated machine?" IDS_2114 "Are you sure you want to exit 86Box?" IDS_2115 "Unable to initialize Ghostscript" diff --git a/src/win/languages/en-US.rc b/src/win/languages/en-US.rc index 6ca6945d6..c12fb4a45 100644 --- a/src/win/languages/en-US.rc +++ b/src/win/languages/en-US.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Video:" #define STR_VIDEO_2 "Video 2:" #define STR_VOODOO "Voodoo Graphics" -#define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_IBM8514 "IBM 8514/A Graphics" #define STR_XGA "XGA Graphics" #define STR_MOUSE "Mouse:" @@ -293,10 +293,10 @@ END #define STR_JOY3 "Joystick 3..." #define STR_JOY4 "Joystick 4..." -#define STR_SOUND1 "Sound card 1:" -#define STR_SOUND2 "Sound card 2:" -#define STR_SOUND3 "Sound card 3:" -#define STR_SOUND4 "Sound card 4:" +#define STR_SOUND1 "Sound card #1:" +#define STR_SOUND2 "Sound card #2:" +#define STR_SOUND3 "Sound card #3:" +#define STR_SOUND4 "Sound card #4:" #define STR_MIDI_OUT "MIDI Out Device:" #define STR_MIDI_IN "MIDI In Device:" #define STR_MPU401 "Standalone MPU-401" @@ -464,7 +464,6 @@ BEGIN IDS_2108 "%u MB (CHS: %i, %i, %i)" IDS_2109 "Floppy %i (%s): %ls" IDS_2110 "All images (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Advanced sector images (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Basic sector images (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux images (*.FDI)\0*.FDI\0Surface images (*.86F;*.MFM)\0*.86F;*.MFM\0All files (*.*)\0*.*\0" - IDS_2112 "Unable to initialize SDL, SDL2.dll is required" IDS_2113 "Are you sure you want to hard reset the emulated machine?" IDS_2114 "Are you sure you want to exit 86Box?" IDS_2115 "Unable to initialize Ghostscript" diff --git a/src/win/languages/es-ES.rc b/src/win/languages/es-ES.rc index 1fd0bceff..4888c09f4 100644 --- a/src/win/languages/es-ES.rc +++ b/src/win/languages/es-ES.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Vídeo:" #define STR_VIDEO_2 "Vídeo 2:" #define STR_VOODOO "Voodoo Graphics" -#define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_IBM8514 "IBM 8514/A Graphics" #define STR_XGA "XGA Graphics" #define STR_MOUSE "Ratón:" @@ -464,7 +464,6 @@ BEGIN IDS_2108 "%u MB (CHS: %i, %i, %i)" IDS_2109 "Disquete %i (%s): %ls" IDS_2110 "Todas las Imágenes (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Advanced sector images (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Basic sector images (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux images (*.FDI)\0*.FDI\0Surface images (*.86F;*.MFM)\0*.86F;*.MFM\0All files (*.*)\0*.*\0" - IDS_2112 "Incapaz de inicializar SDL, se requiere SDL2.dll" IDS_2113 "¿Seguro que quieres resetear la máquina emulada?" IDS_2114 "¿Seguro que quieres cerrar 86Box?" IDS_2115 "Incapaz de inicializar Ghostscript" diff --git a/src/win/languages/fi-FI.rc b/src/win/languages/fi-FI.rc index 3f875cb3d..029cce6c0 100644 --- a/src/win/languages/fi-FI.rc +++ b/src/win/languages/fi-FI.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Näytönohjain:" #define STR_VIDEO_2 "Näytönohjain 2:" #define STR_VOODOO "Voodoo-grafiikkasuoritin" -#define STR_IBM8514 "IBM 8514/a-grafiikkasuoritin" +#define STR_IBM8514 "IBM 8514/A-grafiikkasuoritin" #define STR_XGA "XGA-grafiikkasuoritin" #define STR_MOUSE "Hiiri:" @@ -464,7 +464,6 @@ BEGIN IDS_2108 "%u Mt (CHS: %i, %i, %i)" IDS_2109 "Levyke %i (%s): %ls" IDS_2110 "Kaikki levykuvat (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Kehittyneet sektorilevykuvat (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Perussektorilevykuvat (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux-levykuvat (*.FDI)\0*.FDI\0Pintalevykuvat (*.86F;*.MFM)\0*.86F;*.MFM\0Kaikki tiedostot (*.*)\0*.*\0" - IDS_2112 "SDL:n alustus epäonnistui. Tarvitaan SDL2.dll" IDS_2113 "Haluatko varmasti käynnistää emuloidun tietokoneen uudelleen?" IDS_2114 "Haluatko varmasti sulkea 86Boxin?" IDS_2115 "Ghostscriptin alustus epäonnistui" diff --git a/src/win/languages/fr-FR.rc b/src/win/languages/fr-FR.rc index 1ad5a4da1..425656c28 100644 --- a/src/win/languages/fr-FR.rc +++ b/src/win/languages/fr-FR.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Vidéo:" #define STR_VIDEO_2 "Vidéo 2:" #define STR_VOODOO "Graphique Voodoo" -#define STR_IBM8514 "Graphique IBM 8514/a" +#define STR_IBM8514 "Graphique IBM 8514/A" #define STR_XGA "Graphique XGA" #define STR_MOUSE "Souris:" @@ -464,7 +464,6 @@ BEGIN IDS_2108 "%u Mo (CTS: %i, %i, %i)" IDS_2109 "Disquette %i (%s): %ls" IDS_2110 "Toutes les images (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Images du secteur avancés (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Images du secteur basiques (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Images du flux (*.FDI)\0*.FDI\0Images de surface (*.86F;*.MFM)\0*.86F;*.MFM\0Tous les fichiers (*.*)\0*.*\0" - IDS_2112 "Impossible d'initialiser SDL, SDL2.dll est nécessaire" IDS_2113 "Etes-vous sûr de vouloir réinitialiser la machine émulée ?" IDS_2114 "Etes-vous sûr de vouloir quitter 86Box?" IDS_2115 "Impossible d'initialiser Ghostscript" diff --git a/src/win/languages/hr-HR.rc b/src/win/languages/hr-HR.rc index 9497a7b0d..f01b2a881 100644 --- a/src/win/languages/hr-HR.rc +++ b/src/win/languages/hr-HR.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Video:" #define STR_VIDEO_2 "Video 2:" #define STR_VOODOO "Voodoo grafika" -#define STR_IBM8514 "IBM 8514/a grafika" +#define STR_IBM8514 "IBM 8514/A grafika" #define STR_XGA "XGA grafika" #define STR_MOUSE "Miš:" @@ -464,7 +464,6 @@ BEGIN IDS_2108 "%u MB (CHS: %i, %i, %i)" IDS_2109 "Disketa %i (%s): %ls" IDS_2110 "Sve slike (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Napredne sektorske slike (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Osnovne sektorske slike (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux slike (*.FDI)\0*.FDI\0Površinske slike (*.86F;*.MFM)\0*.86F;*.MFM\0Sve datoteke (*.*)\0*.*\0" - IDS_2112 "Nije moguće inicijalizirati SDL, SDL2.dll je potrebno" IDS_2113 "Jeste li sigurni da želite hard resetirati emulirani sistem?" IDS_2114 "Jeste li sigurni da želite zatvoriti 86Box?" IDS_2115 "Nije moguće inicijalizirati GhostScript" diff --git a/src/win/languages/hu-HU.rc b/src/win/languages/hu-HU.rc index ab91d43f5..52189426a 100644 --- a/src/win/languages/hu-HU.rc +++ b/src/win/languages/hu-HU.rc @@ -288,7 +288,7 @@ END #define STR_VIDEO "Videokártya:" #define STR_VIDEO_2 "Videokártya 2:" #define STR_VOODOO "Voodoo-gyorsítókártya" -#define STR_IBM8514 "IBM 8514/a-gyorsítókártya" +#define STR_IBM8514 "IBM 8514/A-gyorsítókártya" #define STR_XGA "XGA-gyorsítókártya" #define STR_MOUSE "Egér:" @@ -469,7 +469,6 @@ BEGIN IDS_2108 "%u MB (CHS: %i, %i, %i)" IDS_2109 "Floppy %i (%s): %ls" IDS_2110 "Minden képfájl (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Továbbfejlesztett szektor képek (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Alapvető szektor képek (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux képekfájlok (*.FDI)\0*.FDI\0Felületi képfájlok (*.86F;*.MFM)\0*.86F;*.MFM\0Minden fájl (*.*)\0*.*\0" - IDS_2112 "Az SDL inicializálása nem lehetséges, az SDL2.dll fájl szükséges" IDS_2113 "Biztosan szeretné újraindítani az emulált gépet?" IDS_2114 "Biztos benne, hogy ki szeretne lépni a 86Box-ból?" IDS_2115 "Nem sikerült inicializálni a Ghostscript-et" diff --git a/src/win/languages/it-IT.rc b/src/win/languages/it-IT.rc index cb6e7afa1..e5868caa0 100644 --- a/src/win/languages/it-IT.rc +++ b/src/win/languages/it-IT.rc @@ -284,7 +284,7 @@ END #define STR_VIDEO "Video:" #define STR_VIDEO_2 "Video 2:" #define STR_VOODOO "Grafica Voodoo" -#define STR_IBM8514 "Grafica IBM 8514/a" +#define STR_IBM8514 "Grafica IBM 8514/A" #define STR_XGA "Grafica XGA" #define STR_MOUSE "Mouse:" @@ -465,7 +465,6 @@ BEGIN IDS_2108 "%u MB (CHS: %i, %i, %i)" IDS_2109 "Floppy %i (%s): %ls" IDS_2110 "Tutte le immagini (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Immagini da settori avanzati (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Imagini da settori basilari (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Immagini flusso (*.FDI)\0*.FDI\0Immagini da superficie (*.86F;*.MFM)\0*.86F;*.MFM\0Tutti i file (*.*)\0*.*\0" - IDS_2112 "Impossibile inizializzare SDL, SDL2.dll è necessario" IDS_2113 "Sei sicuro di voler riavviare la macchina emulata?" IDS_2114 "Sei sicuro di voler uscire da 86Box?" IDS_2115 "Impossibile inizializzare Ghostscript" diff --git a/src/win/languages/ja-JP.rc b/src/win/languages/ja-JP.rc index bf9509453..4090abf00 100644 --- a/src/win/languages/ja-JP.rc +++ b/src/win/languages/ja-JP.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "ビデオカード:" #define STR_VIDEO_2 "ビデオカード2:" #define STR_VOODOO "Voodooグラフィック" -#define STR_IBM8514 "IBM 8514/aグラフィック" +#define STR_IBM8514 "IBM 8514/Aグラフィック" #define STR_XGA "XGAグラフィック" #define STR_MOUSE "マウス:" @@ -464,7 +464,6 @@ BEGIN IDS_2108 "%u MB (CHS値: %i、%i、%i)" IDS_2109 "フロッピー %i (%s): %ls" IDS_2110 "すべてのイメージ (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0アドバンスド セクター イメージ (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0ベーシック セクター イメージ (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0フラックスイメージ (*.FDI)\0*.FDI\0サーフェス イメージ (*.86F;*.MFM)\0*.86F;*.MFM\0すべてのファイル (*.*)\0*.*\0" - IDS_2112 "SDLが初期化できません。SDL2.dllが必要です" IDS_2113 "使用中のマシンをハードリ セットしますか?" IDS_2114 "86Boxを終了しますか?" IDS_2115 "Ghostscriptが初期化できません" diff --git a/src/win/languages/ko-KR.rc b/src/win/languages/ko-KR.rc index 360d6e36b..7550e0779 100644 --- a/src/win/languages/ko-KR.rc +++ b/src/win/languages/ko-KR.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "비디오 카드:" #define STR_VIDEO_2 "비디오 카드 2:" #define STR_VOODOO "Voodoo 그래픽" -#define STR_IBM8514 "IBM 8514/a 그래픽" +#define STR_IBM8514 "IBM 8514/A 그래픽" #define STR_XGA "XGA 그래픽" #define STR_MOUSE "마우스:" @@ -464,7 +464,6 @@ BEGIN IDS_2108 "%u MB (CHS: %i, %i, %i)" IDS_2109 "플로피 %i (%s): %ls" IDS_2110 "모든 이미지 (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0어드밴스드 섹터 이미지 (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0기본 섹터 이미지 (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0플럭스 이미지 (*.FDI)\0*.FDI\0표면 이미지 (*.86F;*.MFM)\0*.86F;*.MFM\0모든 파일 (*.*)\0*.*\0" - IDS_2112 "SDL을 초기화할 수 없습니다. SDL2.dll이 필요합니다" IDS_2113 "실행중인 머신을 재시작하시겠습니까?" IDS_2114 "86Box를 끝내시겠습니까?" IDS_2115 "Ghostscript를 초기화할 수 없습니다" diff --git a/src/win/languages/pl-PL.rc b/src/win/languages/pl-PL.rc index f835ad9eb..623415045 100644 --- a/src/win/languages/pl-PL.rc +++ b/src/win/languages/pl-PL.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Wideo:" #define STR_VIDEO_2 "Wideo 2:" #define STR_VOODOO "Grafika Voodoo" -#define STR_IBM8514 "Grafika IBM 8514/a" +#define STR_IBM8514 "Grafika IBM 8514/A" #define STR_XGA "Grafika XGA" #define STR_MOUSE "Mysz:" @@ -464,7 +464,6 @@ BEGIN IDS_2108 "%u MB (CHS: %i, %i, %i)" IDS_2109 "Dyskietka %i (%s): %ls" IDS_2110 "Wszystkie obrazy (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Zaawansowane obrazy sektorów (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Podstawowe obrazy sektorów (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux images (*.FDI)\0*.FDI\0Obrazy powierzchniowe (*.86F;*.MFM)\0*.86F;*.MFM\0All files (*.*)\0*.*\0" - IDS_2112 "Nie można zainicjować SDL, wymagany SDL2.dll" IDS_2113 "Jesteś pewien że chcesz wykonać twardy reset emulowanej maszyny?" IDS_2114 "Jesteś pewien że chcesz zakończyć 86Box?" IDS_2115 "Nie można zainicjować Ghostscript" diff --git a/src/win/languages/pt-BR.rc b/src/win/languages/pt-BR.rc index 00e9c243d..4f72a41a4 100644 --- a/src/win/languages/pt-BR.rc +++ b/src/win/languages/pt-BR.rc @@ -286,7 +286,7 @@ END #define STR_VIDEO "Vídeo:" #define STR_VIDEO_2 "Vídeo 2:" #define STR_VOODOO "3DFX Voodoo" -#define STR_IBM8514 "Gráficos IBM 8514/a" +#define STR_IBM8514 "Gráficos IBM 8514/A" #define STR_XGA "Gráficos XGA" #define STR_MOUSE "Mouse:" @@ -467,7 +467,6 @@ BEGIN IDS_2108 "%u MB (CHS: %i, %i, %i)" IDS_2109 "Disquete %i (%s): %ls" IDS_2110 "Todas as imagens (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Imagens de setor avançado (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Imagens de setor básico (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Imagens de fluxo (*.FDI)\0*.FDI\0Imagens de superfície (*.86F;*.MFM)\0*.86F;*.MFM\0Todos os arquivos (*.*)\0*.*\0" - IDS_2112 "Não é possível inicializar o SDL, é necessário o SDL2.dll" IDS_2113 "Tem certeza de que deseja reiniciar completamente a máquina emulada?" IDS_2114 "Tem certeza de que deseja sair do 86Box?" IDS_2115 "Não é possível inicializar o Ghostscript" diff --git a/src/win/languages/pt-PT.rc b/src/win/languages/pt-PT.rc index 88db4f18c..c17cfe362 100644 --- a/src/win/languages/pt-PT.rc +++ b/src/win/languages/pt-PT.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Vídeo:" #define STR_VIDEO_2 "Vídeo 2:" #define STR_VOODOO "Gráficos Voodoo" -#define STR_IBM8514 "Gráficos IBM 8514/a" +#define STR_IBM8514 "Gráficos IBM 8514/A" #define STR_XGA "Gráficos XGA" #define STR_MOUSE "Rato:" @@ -464,7 +464,6 @@ BEGIN IDS_2108 "%u MB (CCS: %i, %i, %i)" IDS_2109 "Disquete %i (%s): %ls" IDS_2110 "Todas as imagens (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Imagens avançadas de sector (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Imagens básicas de sector (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Imagens de fluxo (*.FDI)\0*.FDI\0Imagens de superfície (*.86F;*.MFM)\0*.86F;*.MFM\0Todos os ficheiros (*.*)\0*.*\0" - IDS_2112 "Não foi possível inicializar o SDL. O ficheiro SDL2.dll é necessário!" IDS_2113 "Tem a certeza de que quer um reinício completo da máquina emulada?" IDS_2114 "Tem a certeza de que quer sair do 86Box?" IDS_2115 "Não foi possível inicializar o Ghostscript" diff --git a/src/win/languages/ru-RU.rc b/src/win/languages/ru-RU.rc index 647b43d44..719dd5a35 100644 --- a/src/win/languages/ru-RU.rc +++ b/src/win/languages/ru-RU.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Видеокарта:" #define STR_VIDEO_2 "Видеокарта 2:" #define STR_VOODOO "Ускоритель Voodoo" -#define STR_IBM8514 "Ускоритель IBM 8514/a" +#define STR_IBM8514 "Ускоритель IBM 8514/A" #define STR_XGA "Ускоритель XGA" #define STR_MOUSE "Мышь:" @@ -464,7 +464,6 @@ BEGIN IDS_2108 "%u МБ (CHS: %i, %i, %i)" IDS_2109 "Дисковод %i (%s): %ls" IDS_2110 "Все образы (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Расширенные образы секторов (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Основные образы секторов (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Образы Flux (*.FDI)\0*.FDI\0Образы Surface (*.86F;*.MFM)\0*.86F;*.MFM\0Все файлы (*.*)\0*.*\0" - IDS_2112 "Невозможно инициализировать SDL, требуется SDL2.dll" IDS_2113 "Вы уверены, что хотите выполнить холодную перезагрузку эмулируемой машины?" IDS_2114 "Вы уверены, что хотите выйти из 86Box?" IDS_2115 "Невозможно инициализировать Ghostscript" diff --git a/src/win/languages/sl-SI.rc b/src/win/languages/sl-SI.rc index b3a00c9de..3a8b12dbb 100644 --- a/src/win/languages/sl-SI.rc +++ b/src/win/languages/sl-SI.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Video:" #define STR_VIDEO_2 "Video 2:" #define STR_VOODOO "Voodoo grafika" -#define STR_IBM8514 "IBM 8514/a grafika" +#define STR_IBM8514 "IBM 8514/A grafika" #define STR_XGA "XGA grafika" #define STR_MOUSE "Miška:" @@ -464,7 +464,6 @@ BEGIN IDS_2108 "%u MB (CHS: %i, %i, %i)" IDS_2109 "Disketa %i (%s): %ls" IDS_2110 "Vse slike (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Napredne sektorske slike (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Osnovne sektorske slike (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Tokovne slike (*.FDI)\0*.FDI\0Površinske slike (*.86F;*.MFM)\0*.86F;*.MFM\0Vse datoteke (*.*)\0*.*\0" - IDS_2112 "Ne morem inicializirati SDL, potrebna je knjižica SDL2.dll" IDS_2113 "Ste prepričani, da želite ponovno zagnati emulirani sistem?" IDS_2114 "Ste prepričani, da želite zapreti 86Box?" IDS_2115 "Ne morem inicializirati Ghostscript" diff --git a/src/win/languages/tr-TR.rc b/src/win/languages/tr-TR.rc index 78e7b4b87..80a436c5d 100644 --- a/src/win/languages/tr-TR.rc +++ b/src/win/languages/tr-TR.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Ekran kartı:" #define STR_VIDEO_2 "Ekran kartı 2:" #define STR_VOODOO "Voodoo Grafikleri" -#define STR_IBM8514 "IBM 8514/a Grafikleri" +#define STR_IBM8514 "IBM 8514/A Grafikleri" #define STR_XGA "XGA Grafikleri" #define STR_MOUSE "Fare:" @@ -464,7 +464,6 @@ BEGIN IDS_2108 "%u MB (CHS: %i, %i, %i)" IDS_2109 "Disket %i (%s): %ls" IDS_2110 "Tüm imajlar (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Gelişmiş sektör imajları (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Basit sektör imajları (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux images (*.FDI)\0*.FDI\0Yüzey imajları (*.86F;*.MFM)\0*.86F;*.MFM\0All files (*.*)\0*.*\0" - IDS_2112 "SDL başlatılamadı, SDL2.dll gerekmektedir" IDS_2113 "Emüle edilen makineyi yeniden başlatmak istediğinizden emin misiniz?" IDS_2114 "86Box'tan çıkmak istediğinize emin misiniz?" IDS_2115 "Ghostscript başlatılamadı" diff --git a/src/win/languages/uk-UA.rc b/src/win/languages/uk-UA.rc index 41bf85f1a..53f401e81 100644 --- a/src/win/languages/uk-UA.rc +++ b/src/win/languages/uk-UA.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "Відеокарта:" #define STR_VIDEO_2 "Відеокарта 2:" #define STR_VOODOO "Прискорювач Voodoo" -#define STR_IBM8514 "Прискорювач IBM 8514/a" +#define STR_IBM8514 "Прискорювач IBM 8514/A" #define STR_XGA "Прискорювач XGA" #define STR_MOUSE "Миша:" @@ -464,7 +464,6 @@ BEGIN IDS_2108 "%u МБ (CHS: %i, %i, %i)" IDS_2109 "Дисковод %i (%s): %ls" IDS_2110 "Усі образи (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0Розширені образи секторів (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0Основні образи секторів (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Образи Flux (*.FDI)\0*.FDI\0Образи Surface (*.86F;*.MFM)\0*.86F;*.MFM\0Усі файли (*.*)\0*.*\0" - IDS_2112 "Неможливо ініціалізувати SDL, потрібно SDL2.dll" IDS_2113 "Ви впевнені, що хочете виконати холодне перезавантаження емульованої машини?" IDS_2114 "Ви впевнені, що хочете вийти з 86Box?" IDS_2115 "Неможливо ініціалізувати Ghostscript" diff --git a/src/win/languages/zh-CN.rc b/src/win/languages/zh-CN.rc index 92afaf86d..1139de4ea 100644 --- a/src/win/languages/zh-CN.rc +++ b/src/win/languages/zh-CN.rc @@ -283,7 +283,7 @@ END #define STR_VIDEO "显卡:" #define STR_VIDEO_2 "显卡 2:" #define STR_VOODOO "Voodoo 显卡" -#define STR_IBM8514 "IBM 8514/a 显卡" +#define STR_IBM8514 "IBM 8514/A 显卡" #define STR_XGA "XGA 显卡" #define STR_MOUSE "鼠标:" @@ -464,7 +464,6 @@ BEGIN IDS_2108 "%u MB (CHS: %i, %i, %i)" IDS_2109 "软盘 %i (%s): %ls" IDS_2110 "所有映像 (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0高级扇区映像 (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0基本扇区映像 (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux 映像 (*.FDI)\0*.FDI\0表面映像 (*.86F;*.MFM)\0*.86F;*.MFM\0所有文件 (*.*)\0*.*\0" - IDS_2112 "无法初始化 SDL,需要 SDL2.dll" IDS_2113 "确定要硬重置模拟器吗?" IDS_2114 "确定要退出 86Box 吗?" IDS_2115 "无法初始化 Ghostscript" diff --git a/src/win/languages/zh-TW.rc b/src/win/languages/zh-TW.rc index 039993e5d..58324442d 100644 --- a/src/win/languages/zh-TW.rc +++ b/src/win/languages/zh-TW.rc @@ -274,7 +274,7 @@ END #define STR_MB "MB" #define STR_MEMORY "記憶體:" #define STR_TIME_SYNC "時間同步" -#define STR_DISABLED "禁用" +#define STR_DISABLED "停用" #define STR_ENABLED_LOCAL "啟用 (本地時間)" #define STR_ENABLED_UTC "啟用 (UTC)" #define STR_DYNAREC "動態重編譯器" @@ -283,7 +283,7 @@ END #define STR_VIDEO "顯示卡:" #define STR_VIDEO_2 "顯示卡 2:" #define STR_VOODOO "Voodoo Graphics" -#define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_IBM8514 "IBM 8514/A Graphics" #define STR_XGA "XGA Graphics" #define STR_MOUSE "滑鼠:" @@ -464,7 +464,6 @@ BEGIN IDS_2108 "%u MB (CHS: %i, %i, %i)" IDS_2109 "軟碟 %i (%s): %ls" IDS_2110 "所有映像 (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF)\0*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF\0進階磁區映像 (*.IMD;*.JSON;*.TD0)\0*.IMD;*.JSON;*.TD0\0基本磁區映像 (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?)\0*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?\0Flux 映像 (*.FDI)\0*.FDI\0表面映像 (*.86F;*.MFM)\0*.86F;*.MFM\0所有檔案 (*.*)\0*.*\0" - IDS_2112 "無法初始化 SDL,需要 SDL2.dll" IDS_2113 "確定要硬重設模擬器嗎?" IDS_2114 "確定要退出 86Box 嗎?" IDS_2115 "無法初始化 Ghostscript" @@ -508,7 +507,7 @@ BEGIN IDS_2144 "OpenGL 著色器 (*.GLSL)\0*.GLSL\0所有檔案 (*.*)\0*.*\0" IDS_2145 "OpenGL 選項" IDS_2146 "正在載入一個不受支援的設定" - IDS_2147 "此模擬電腦禁用了基於選定電腦的 CPU 類型過濾。\n\n能夠選中與所選機器本不相容的 CPU,但是可能會遇到與機器 BIOS 或其他軟體不相容的問題。\n\n啟用此設定不受官方支援,並且提交的任何錯誤報告可能會視為無效而關閉。" + IDS_2147 "此模擬電腦停用了基於選定電腦的 CPU 類型過濾。\n\n能夠選中與所選機器本不相容的 CPU,但是可能會遇到與機器 BIOS 或其他軟體不相容的問題。\n\n啟用此設定不受官方支援,並且提交的任何錯誤報告可能會視為無效而關閉。" IDS_2148 "繼續" IDS_2149 "磁帶: %s" IDS_2150 "磁帶映像 (*.PCM;*.RAW;*.WAV;*.CAS)\0*.PCM;*.RAW;*.WAV;*.CAS\0所有檔案 (*.*)\0*.*\0" @@ -591,11 +590,11 @@ BEGIN IDS_5120 "光碟 %i (%s): %s" - IDS_5376 "禁用" + IDS_5376 "停用" IDS_5381 "ATAPI" IDS_5382 "SCSI" - IDS_5632 "禁用" + IDS_5632 "停用" IDS_5637 "ATAPI (%01i:%01i)" IDS_5638 "SCSI (%01i:%02i)" diff --git a/src/win/win_cdrom.c b/src/win/win_cdrom.c index 37b741c29..58bd85c65 100644 --- a/src/win/win_cdrom.c +++ b/src/win/win_cdrom.c @@ -136,6 +136,8 @@ cdrom_mount(uint8_t id, char *fn) cdrom[id].ops->exit(&(cdrom[id])); cdrom[id].ops = NULL; memset(cdrom[id].image_path, 0, sizeof(cdrom[id].image_path)); + if ((fn != NULL) && (strlen(fn) >= 1) && (fn[strlen(fn) - 1] == '/')) + fn[strlen(fn) - 1] = '\\'; cdrom_image_open(&(cdrom[id]), fn); /* Signal media change to the emulated machine. */ if (cdrom[id].insert) diff --git a/src/win/win_joystick.cpp b/src/win/win_joystick.cpp index df8a99a05..9b264a700 100644 --- a/src/win/win_joystick.cpp +++ b/src/win/win_joystick.cpp @@ -36,6 +36,7 @@ plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; joystick_t joystick_state[MAX_JOYSTICKS]; int joysticks_present = 0; +int has_slider = 0; static LPDIRECTINPUT8 lpdi; static LPDIRECTINPUTDEVICE8 lpdi_joystick[2] = { NULL, NULL }; @@ -83,7 +84,7 @@ DIEnumDeviceObjectsCallback( plat_joystick_t *state = (plat_joystick_t *) pvRef; if (lpddoi->guidType == GUID_XAxis || lpddoi->guidType == GUID_YAxis || lpddoi->guidType == GUID_ZAxis || lpddoi->guidType == GUID_RxAxis || lpddoi->guidType == GUID_RyAxis || lpddoi->guidType == GUID_RzAxis) { - if (state->nr_axes < 8) { + if (state->nr_axes < MAX_JOY_AXES) { memcpy(state->axis[state->nr_axes].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); joystick_log("Axis %i : %s %x %x\n", state->nr_axes, state->axis[state->nr_axes].name, lpddoi->dwOfs, lpddoi->dwType); if (lpddoi->guidType == GUID_XAxis) @@ -98,27 +99,24 @@ DIEnumDeviceObjectsCallback( state->axis[state->nr_axes].id = 4; else if (lpddoi->guidType == GUID_RzAxis) state->axis[state->nr_axes].id = 5; + else if (lpddoi->guidType == GUID_Slider) { + state->axis[state->nr_axes].id = 6 + has_slider; + has_slider++; + } state->nr_axes++; } } else if (lpddoi->guidType == GUID_Button) { - if (state->nr_buttons < 32) { + if (state->nr_buttons < MAX_JOY_BUTTONS) { memcpy(state->button[state->nr_buttons].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); joystick_log("Button %i : %s %x %x\n", state->nr_buttons, state->button[state->nr_buttons].name, lpddoi->dwOfs, lpddoi->dwType); state->nr_buttons++; } } else if (lpddoi->guidType == GUID_POV) { - if (state->nr_povs < 4) { + if (state->nr_povs < MAX_JOY_POVS) { memcpy(state->pov[state->nr_povs].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); joystick_log("POV %i : %s %x %x\n", state->nr_povs, state->pov[state->nr_povs].name, lpddoi->dwOfs, lpddoi->dwType); state->nr_povs++; } - } else if (lpddoi->guidType == GUID_Slider) { - if (state->nr_sliders < 2) { - memcpy(state->slider[state->nr_sliders].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); - state->slider[state->nr_sliders].id = state->nr_sliders | SLIDER; - joystick_log("Slider %i : %s %x %x\n", state->nr_sliders, state->slider[state->nr_sliders].name, lpddoi->dwOfs, lpddoi->dwType); - state->nr_sliders++; - } } return DIENUM_CONTINUE; @@ -170,6 +168,7 @@ joystick_init() joystick_log(" Buttons = %i\n", devcaps.dwButtons); joystick_log(" POVs = %i\n", devcaps.dwPOVs); + has_slider = 0; lpdi_joystick[c]->EnumObjects(DIEnumDeviceObjectsCallback, &plat_joystick_state[c], DIDFT_ALL); if (FAILED(lpdi_joystick[c]->SetCooperativeLevel(hwndMain, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE))) @@ -234,8 +233,6 @@ joystick_get_axis(int joystick_nr, int mapping) return 0; else return -cos((2 * M_PI * (double) pov) / 36000.0) * 32767; - } else if (mapping & SLIDER) { - return plat_joystick_state[joystick_nr].s[mapping & 3]; } else return plat_joystick_state[joystick_nr].a[plat_joystick_state[joystick_nr].axis[mapping].id]; } @@ -269,13 +266,13 @@ joystick_process(void) plat_joystick_state[c].a[3] = joystate.lRx; plat_joystick_state[c].a[4] = joystate.lRy; plat_joystick_state[c].a[5] = joystate.lRz; - plat_joystick_state[c].s[0] = joystate.rglSlider[0]; - plat_joystick_state[c].s[1] = joystate.rglSlider[1]; + plat_joystick_state[c].a[6] = joystate.rglSlider[0]; + plat_joystick_state[c].a[7] = joystate.rglSlider[1]; - for (b = 0; b < 16; b++) + for (b = 0; b < MAX_JOY_BUTTONS; b++) plat_joystick_state[c].b[b] = joystate.rgbButtons[b] & 0x80; - for (b = 0; b < 4; b++) + for (b = 0; b < MAX_JOY_POVS; b++) plat_joystick_state[c].p[b] = joystate.rgdwPOV[b]; // joystick_log("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", c, joystick_state[c].x, joystick_state[c].y, joystick_state[c].b[0], joystick_state[c].b[1], joysticks_present); } diff --git a/src/win/win_joystick_rawinput.c b/src/win/win_joystick_rawinput.c index c5c2a3d6e..bb05c3f5c 100644 --- a/src/win/win_joystick_rawinput.c +++ b/src/win/win_joystick_rawinput.c @@ -35,6 +35,29 @@ #include <86box/gameport.h> #include <86box/win.h> +/* These are defined in hidusage.h in the Windows SDK, but not in mingw-w64. */ +#ifndef HID_USAGE_SIMULATION_AILERON +# define HID_USAGE_SIMULATION_AILERON ((USAGE) 0xb0) +#endif +#ifndef HID_USAGE_SIMULATION_ELEVATOR +# define HID_USAGE_SIMULATION_ELEVATOR ((USAGE) 0xb8) +#endif +#ifndef HID_USAGE_SIMULATION_ACCELLERATOR +# define HID_USAGE_SIMULATION_ACCELLERATOR ((USAGE) 0xc4) +#endif +#ifndef HID_USAGE_SIMULATION_BRAKE +# define HID_USAGE_SIMULATION_BRAKE ((USAGE) 0xc5) +#endif +#ifndef HID_USAGE_SIMULATION_CLUTCH +# define HID_USAGE_SIMULATION_CLUTCH ((USAGE) 0xc6) +#endif +#ifndef HID_USAGE_SIMULATION_SHIFTER +# define HID_USAGE_SIMULATION_SHIFTER ((USAGE) 0xc7) +#endif +#ifndef HID_USAGE_SIMULATION_STEERING +# define HID_USAGE_SIMULATION_STEERING ((USAGE) 0xc8) +#endif + #ifdef ENABLE_JOYSTICK_LOG int joystick_do_log = ENABLE_JOYSTICK_LOG; @@ -65,14 +88,14 @@ typedef struct { USHORT bitsize; LONG max; LONG min; - } axis[8]; + } axis[MAX_JOY_AXES]; struct raw_pov_t { USAGE usage; USHORT link; LONG max; LONG min; - } pov[4]; + } pov[MAX_JOY_POVS]; } raw_joystick_t; plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; @@ -85,7 +108,7 @@ raw_joystick_t raw_joystick_state[MAX_PLAT_JOYSTICKS]; void joystick_add_button(raw_joystick_t *rawjoy, plat_joystick_t *joy, USAGE usage) { - if (joy->nr_buttons >= 32) + if (joy->nr_buttons >= MAX_JOY_BUTTONS) return; if (usage < 1 || usage > 128) return; @@ -98,7 +121,7 @@ joystick_add_button(raw_joystick_t *rawjoy, plat_joystick_t *joy, USAGE usage) void joystick_add_axis(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS prop) { - if (joy->nr_axes >= 8) + if (joy->nr_axes >= MAX_JOY_AXES) return; switch (prop->Range.UsageMin) { @@ -120,6 +143,42 @@ joystick_add_axis(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS case HID_USAGE_GENERIC_RZ: sprintf(joy->axis[joy->nr_axes].name, "RZ"); break; + case HID_USAGE_GENERIC_SLIDER: + sprintf(joy->axis[joy->nr_axes].name, "Slider"); + break; + case HID_USAGE_GENERIC_DIAL: + sprintf(joy->axis[joy->nr_axes].name, "Dial"); + break; + case HID_USAGE_GENERIC_WHEEL: + sprintf(joy->axis[joy->nr_axes].name, "Wheel"); + break; + case HID_USAGE_SIMULATION_AILERON: + sprintf(joy->axis[joy->nr_axes].name, "Aileron"); + break; + case HID_USAGE_SIMULATION_ELEVATOR: + sprintf(joy->axis[joy->nr_axes].name, "Elevator"); + break; + case HID_USAGE_SIMULATION_RUDDER: + sprintf(joy->axis[joy->nr_axes].name, "Rudder"); + break; + case HID_USAGE_SIMULATION_THROTTLE: + sprintf(joy->axis[joy->nr_axes].name, "Throttle"); + break; + case HID_USAGE_SIMULATION_ACCELLERATOR: + sprintf(joy->axis[joy->nr_axes].name, "Accelerator"); + break; + case HID_USAGE_SIMULATION_BRAKE: + sprintf(joy->axis[joy->nr_axes].name, "Brake"); + break; + case HID_USAGE_SIMULATION_CLUTCH: + sprintf(joy->axis[joy->nr_axes].name, "Clutch"); + break; + case HID_USAGE_SIMULATION_SHIFTER: + sprintf(joy->axis[joy->nr_axes].name, "Shifter"); + break; + case HID_USAGE_SIMULATION_STEERING: + sprintf(joy->axis[joy->nr_axes].name, "Steering"); + break; default: return; } @@ -147,7 +206,7 @@ joystick_add_axis(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS void joystick_add_pov(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS prop) { - if (joy->nr_povs >= 4) + if (joy->nr_povs >= MAX_JOY_POVS) return; sprintf(joy->pov[joy->nr_povs].name, "POV %d", joy->nr_povs + 1); @@ -395,7 +454,9 @@ win_joystick_handle(PRAWINPUT raw) } plat_joystick_state[j].a[a] = value; - // joystick_log("%s %-06d ", plat_joystick_state[j].axis[a].name, plat_joystick_state[j].a[a]); +#if 0 + joystick_log("%s %-06d ", plat_joystick_state[j].axis[a].name, plat_joystick_state[j].a[a]); +#endif } /* read povs */ diff --git a/src/win/win_jsconf.c b/src/win/win_jsconf.c index 66ad60c73..416e7858d 100644 --- a/src/win/win_jsconf.c +++ b/src/win/win_jsconf.c @@ -54,9 +54,6 @@ rebuild_axis_button_selections(HWND hdlg) sprintf(s, "%s (Y axis)", plat_joystick_state[joystick - 1].pov[d].name); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) (LPCSTR) s); } - for (d = 0; d < plat_joystick_state[joystick - 1].nr_sliders; d++) { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM) (LPCSTR) plat_joystick_state[joystick - 1].slider[d].name); - } SendMessage(h, CB_SETCURSEL, sel, 0); EnableWindow(h, TRUE); } else @@ -111,21 +108,15 @@ get_axis(HWND hdlg, int id) HWND h = GetDlgItem(hdlg, id); int axis_sel = SendMessage(h, CB_GETCURSEL, 0, 0); int nr_axes = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_axes; - int nr_povs = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_povs; if (axis_sel < nr_axes) return axis_sel; axis_sel -= nr_axes; - if (axis_sel < nr_povs * 2) { - if (axis_sel & 1) - return POV_Y | (axis_sel >> 1); - else - return POV_X | (axis_sel >> 1); - } - axis_sel -= nr_povs; - - return SLIDER | (axis_sel >> 1); + if (axis_sel & 1) + return POV_Y | (axis_sel >> 1); + else + return POV_X | (axis_sel >> 1); } static int @@ -188,8 +179,6 @@ joystickconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, UNUSED(LPARAM lPa SendMessage(h, CB_SETCURSEL, nr_axes + (mapping & 3) * 2, 0); else if (mapping & POV_Y) SendMessage(h, CB_SETCURSEL, nr_axes + (mapping & 3) * 2 + 1, 0); - else if (mapping & SLIDER) - SendMessage(h, CB_SETCURSEL, nr_axes + nr_povs * 2 + (mapping & 3), 0); else SendMessage(h, CB_SETCURSEL, mapping, 0); id += 2; diff --git a/src/win/win_ui.c b/src/win/win_ui.c index 73119140c..207158b29 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -76,8 +76,6 @@ int hide_status_bar = 0; int hide_tool_bar = 0; int dpi = 96; -int status_icons_fullscreen = 0; /* unused. */ - extern char openfilestring[512]; extern WCHAR wopenfilestring[512];