From 4f6df76f1092ee1070eda628b4fddf55ce143077 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 4 Jul 2021 17:40:39 +0200 Subject: [PATCH 01/96] Revert "Revert "Merge branch 'feature/machine_and_kb' into master"" This reverts commit f2cd3756dd0e0abaecc0d2f0d912d1dae66e6333. --- src/CMakeLists.txt | 4 +- src/acpi.c | 184 +- src/chipset/CMakeLists.txt | 17 +- src/chipset/ali1531.c | 371 ++-- src/chipset/ali1543.c | 1938 ++++++++++++------ src/chipset/opti391.c | 226 +++ src/chipset/opti895.c | 32 +- src/chipset/vl82c480.c | 25 +- src/config.c | 20 +- src/cpu/386_ops.h | 8 +- src/cpu/x86.c | 11 +- src/cpu/x86_ops_msr.h | 2 + src/device/kbc_at.c | 2324 +++++++++++++++++++++ src/device/kbd_at.c | 1162 +++++++++++ src/device/keyboard_at.c | 2794 ++++++++++++++++---------- src/device/keyboard_xt.c | 236 ++- src/device/mouse_ps2.c | 61 +- src/disk/hdc_ide.c | 59 +- src/disk/hdc_ide_sff8038i.c | 97 +- src/dma.c | 30 +- src/include/86box/acpi.h | 8 +- src/include/86box/chipset.h | 15 +- src/include/86box/hdc_ide.h | 3 + src/include/86box/hdc_ide_sff8038i.h | 6 +- src/include/86box/keyboard.h | 7 +- src/include/86box/machine.h | 149 +- src/include/86box/pci.h | 4 + src/include/86box/pic.h | 5 + src/include/86box/pit.h | 29 +- src/include/86box/port_6x.h | 38 + src/include/86box/sio.h | 2 + src/include/86box/spd.h | 1 + src/include/86box/vid_svga.h | 11 +- src/include/86box/vid_svga_render.h | 2 + src/include/86box/video.h | 5 +- src/log.c | 3 + src/machine/CMakeLists.txt | 5 +- src/machine/m_at.c | 5 + src/machine/m_at_286_386sx.c | 91 +- src/machine/m_at_386dx_486.c | 288 +-- src/machine/m_at_slot1.c | 33 +- src/machine/m_at_socket370.c | 38 +- src/machine/m_at_socket4.c | 406 ++++ src/machine/m_at_socket5.c | 446 ++++ src/machine/m_at_socket7.c | 865 +++----- src/machine/m_at_socket7_3v.c | 514 +++++ src/machine/m_at_socket8.c | 2 + src/machine/m_ps1.c | 2 + src/machine/m_ps2_isa.c | 4 +- src/machine/m_ps2_mca.c | 4 +- src/machine/m_xt.c | 22 - src/machine/m_xt_olivetti.c | 5 + src/machine/m_xt_xi8088.c | 2 + src/machine/machine_table.c | 500 ++++- src/mem/mem.c | 41 +- src/mem/rom.c | 6 +- src/mem/spd.c | 56 + src/pci.c | 3 +- src/pic.c | 44 + src/pit.c | 465 +++-- src/port_6x.c | 214 ++ src/sio/CMakeLists.txt | 2 +- src/sio/sio_fdc37c67x.c | 613 ++++++ src/sio/sio_pc87332.c | 10 + src/sound/snd_sb.c | 3 +- src/usb.c | 3 + src/video/CMakeLists.txt | 4 +- src/video/vid_cl54xx.c | 24 +- src/video/vid_et3000.c | 308 +++ src/video/vid_et4000.c | 153 +- src/video/vid_et4000w32.c | 7 +- src/video/vid_oak_oti.c | 38 +- src/video/vid_s3.c | 30 +- src/video/vid_svga.c | 152 +- src/video/vid_table.c | 2 + src/win/Makefile.mingw | 65 +- src/win/win.c | 3 +- 77 files changed, 11883 insertions(+), 3484 deletions(-) create mode 100644 src/chipset/opti391.c create mode 100644 src/device/kbc_at.c create mode 100644 src/device/kbd_at.c create mode 100644 src/include/86box/port_6x.h create mode 100644 src/machine/m_at_socket4.c create mode 100644 src/machine/m_at_socket5.c create mode 100644 src/machine/m_at_socket7_3v.c create mode 100644 src/port_6x.c create mode 100644 src/sio/sio_fdc37c67x.c create mode 100644 src/video/vid_et3000.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a1f4b9c7c..d4a22abbf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,8 +14,8 @@ # # WIN32 marks us as a GUI app on Windows -add_executable(86Box WIN32 86box.c config.c random.c timer.c io.c acpi.c apm.c - dma.c ddma.c nmi.c pic.c pit.c port_92.c ppi.c pci.c mca.c usb.c +add_executable(86Box WIN32 86box.c config.c log.c random.c timer.c io.c acpi.c apm.c + dma.c ddma.c nmi.c pic.c pit.c port_6x.c port_92.c ppi.c pci.c mca.c usb.c device.c nvr.c nvr_at.c nvr_ps2.c) if(NEW_DYNAREC) diff --git a/src/acpi.c b/src/acpi.c index e9acd971a..0c3af0ed2 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -75,11 +75,15 @@ acpi_update_irq(void *priv) if (sci_level) { if (dev->irq_mode == 1) pci_set_irq(dev->slot, dev->irq_pin); + else if (dev->irq_mode == 2) + pci_set_mirq(5, dev->mirq_is_level); else pci_set_mirq(0xf0 | dev->irq_line, 1); } else { if (dev->irq_mode == 1) pci_clear_irq(dev->slot, dev->irq_pin); + else if (dev->irq_mode == 2) + pci_clear_mirq(5, dev->mirq_is_level); else pci_clear_mirq(0xf0 | dev->irq_line, 1); } @@ -87,22 +91,29 @@ acpi_update_irq(void *priv) static void -acpi_raise_smi(void *priv) +acpi_raise_smi(void *priv, int do_smi) { acpi_t *dev = (acpi_t *) priv; if (dev->regs.glbctl & 0x01) { if ((dev->vendor == VEN_VIA) || (dev->vendor == VEN_VIA_596B)) { - if ((!dev->regs.smi_lock || !dev->regs.smi_active)) { - smi_line = 1; + if ((!dev->regs.smi_lock || !dev->regs.smi_active)) { + if (do_smi) + smi_line = 1; dev->regs.smi_active = 1; } } else if ((dev->vendor == VEN_INTEL) || (dev->vendor == VEN_ALI)) { - smi_line = 1; + if (do_smi) + smi_line = 1; /* Clear bit 16 of GLBCTL. */ - dev->regs.glbctl &= ~0x00010000; - } else if (dev->vendor == VEN_SMC) - smi_line = 1; + if (dev->vendor == VEN_INTEL) + dev->regs.glbctl &= ~0x00010000; + else + dev->regs.ali_soft_smi = 1; + } else if (dev->vendor == VEN_SMC) { + if (do_smi) + smi_line = 1; + } } } @@ -164,8 +175,7 @@ acpi_reg_read_ali(int size, uint16_t addr, void *p) shift16 = (addr & 1) << 3; shift32 = (addr & 3) << 3; - switch(addr) - { + switch(addr) { case 0x10: case 0x11: case 0x12: case 0x13: /* PCNTRL - Processor Control Register (IO) */ ret = (dev->regs.pcntrl >> shift16) & 0xff; @@ -180,39 +190,33 @@ acpi_reg_read_ali(int size, uint16_t addr, void *p) break; case 0x18: case 0x19: /* GPE0_STS - General Purpose Event0 Status Register */ - ret = (dev->regs.gpsts >> shift16) & 0xff; - break; + ret = (dev->regs.gpsts >> shift16) & 0xff; + break; case 0x1a: case 0x1b: /* GPE0_EN - General Purpose Event0 Enable Register */ - ret = (dev->regs.gpen >> shift16) & 0xff; - break; + ret = (dev->regs.gpen >> shift16) & 0xff; + break; case 0x1d: case 0x1c: /* GPE1_STS - General Purpose Event1 Status Register */ - ret = (dev->regs.gpsts >> shift16) & 0xff; - break; + ret = (dev->regs.gpsts1 >> shift16) & 0xff; + break; case 0x1f: case 0x1e: /* GPE1_EN - General Purpose Event1 Enable Register */ - ret = (dev->regs.gpen1 >> shift16) & 0xff; - break; - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: + ret = (dev->regs.gpen1 >> shift16) & 0xff; + break; + case 0x20 ... 0x27: /* GPE1_CTL - General Purpose Event1 Control Register */ - ret = (dev->regs.gpcntrl >> shift32) & 0xff; - break; + ret = (dev->regs.gpcntrl >> shift32) & 0xff; + break; case 0x30: /* PM2_CNTRL - Power Management 2 Control Register( */ - ret = dev->regs.pmcntrl; - break; + ret = dev->regs.pmcntrl; + break; default: ret = acpi_reg_read_common_regs(size, addr, p); break; - } + } + #ifdef ENABLE_ACPI_LOG if (size != 1) acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); @@ -296,6 +300,7 @@ acpi_reg_read_intel(int size, uint16_t addr, void *p) return ret; } + static uint32_t acpi_reg_read_sis(int size, uint16_t addr, void *p) { @@ -703,44 +708,37 @@ acpi_reg_write_ali(int size, uint16_t addr, uint8_t val, void *p) break; case 0x18: case 0x19: /* GPE0_STS - General Purpose Event0 Status Register */ - dev->regs.gpsts &= ~((val << shift16) & 0x0d07); - break; + dev->regs.gpsts &= ~((val << shift16) & 0x0d07); + break; case 0x1a: case 0x1b: /* GPE0_EN - General Purpose Event0 Enable Register */ - dev->regs.gpen = ((dev->regs.gpen & ~(0xff << shift16)) | (val << shift16)) & 0x0d07; - break; + dev->regs.gpen = ((dev->regs.gpen & ~(0xff << shift16)) | (val << shift16)) & 0x0d07; + break; case 0x1d: case 0x1c: /* GPE1_STS - General Purpose Event1 Status Register */ - dev->regs.gpsts &= ~((val << shift16) & 0x0c01); - break; + dev->regs.gpsts1 &= ~((val << shift16) & 0x0c01); + break; case 0x1f: case 0x1e: /* GPE1_EN - General Purpose Event1 Enable Register */ - dev->regs.gpen = ((dev->regs.gpen & ~(0xff << shift16)) | (val << shift16)) & 0x0c01; - break; - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: + dev->regs.gpen1 = ((dev->regs.gpen & ~(0xff << shift16)) | (val << shift16)) & 0x0c01; + break; + case 0x20 ... 0x27: /* GPE1_CTL - General Purpose Event1 Control Register */ - dev->regs.gpcntrl = ((dev->regs.gpcntrl & ~(0xff << shift32)) | (val << shift32)) & 0x00000001; - break; + dev->regs.gpcntrl = ((dev->regs.gpcntrl & ~(0xff << shift32)) | (val << shift32)) & 0x00000001; + break; case 0x30: /* PM2_CNTRL - Power Management 2 Control Register( */ - dev->regs.pmcntrl = val & 1; - break; + dev->regs.pmcntrl = val & 1; + break; default: acpi_reg_write_common_regs(size, addr, val, p); /* Setting GBL_RLS also sets BIOS_STS and generates SMI. */ if ((addr == 0x00) && !(dev->regs.pmsts & 0x20)) - dev->regs.glbctl &= ~0x0002; + dev->regs.gpcntrl &= ~0x0002; else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { - dev->regs.glbsts |= 0x01; - if (dev->regs.glben & 0x02) - acpi_raise_smi(dev); + dev->regs.gpsts1 |= 0x01; + if (dev->regs.gpen1 & 0x01) + acpi_raise_smi(dev, 1); } } } @@ -816,7 +814,7 @@ acpi_reg_write_intel(int size, uint16_t addr, uint8_t val, void *p) else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { dev->regs.glbsts |= 0x01; if (dev->regs.glben & 0x02) - acpi_raise_smi(dev); + acpi_raise_smi(dev, 1); } break; } @@ -973,7 +971,7 @@ acpi_reg_write_via_common(int size, uint16_t addr, uint8_t val, void *p) dev->regs.smicmd = val & 0xff; dev->regs.glbsts |= 0x40; if (dev->regs.glben & 0x40) - acpi_raise_smi(dev); + acpi_raise_smi(dev, 1); } break; case 0x30: case 0x31: case 0x32: case 0x33: @@ -996,7 +994,7 @@ acpi_reg_write_via_common(int size, uint16_t addr, uint8_t val, void *p) else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { dev->regs.glbsts |= 0x20; if (dev->regs.glben & 0x20) - acpi_raise_smi(dev); + acpi_raise_smi(dev, 1); } break; } @@ -1084,7 +1082,7 @@ acpi_reg_write_smc(int size, uint16_t addr, uint8_t val, void *p) else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { dev->regs.glbsts |= 0x01; if (dev->regs.glben & 0x01) - acpi_raise_smi(dev); + acpi_raise_smi(dev, 1); } } @@ -1476,6 +1474,13 @@ acpi_set_irq_line(acpi_t *dev, int irq_line) } +void +acpi_set_mirq_is_level(acpi_t *dev, int mirq_is_level) +{ + dev->mirq_is_level = mirq_is_level; +} + + void acpi_set_gpireg2_default(acpi_t *dev, uint8_t gpireg2_default) { @@ -1491,6 +1496,20 @@ acpi_set_nvr(acpi_t *dev, nvr_t *nvr) } +uint8_t +acpi_ali_soft_smi_status_read(acpi_t *dev) +{ + return dev->regs.ali_soft_smi = 1; +} + + +void +acpi_ali_soft_smi_status_write(acpi_t *dev, uint8_t soft_smi) +{ + dev->regs.ali_soft_smi = soft_smi; +} + + static void acpi_apm_out(uint16_t port, uint8_t val, void *p) { @@ -1500,15 +1519,25 @@ acpi_apm_out(uint16_t port, uint8_t val, void *p) port &= 0x0001; - if (port == 0x0000) { - dev->apm->cmd = val; - if (dev->apm->do_smi) { - if ((dev->vendor == VEN_INTEL) || (dev->vendor == VEN_ALI)) + if (dev->vendor == VEN_ALI) { + if (port == 0x0001) { + acpi_log("ALi SOFT SMI# status set (%i)\n", dev->apm->do_smi); + dev->apm->cmd = val; + // acpi_raise_smi(dev, dev->apm->do_smi); + if (dev->apm->do_smi) + smi_line = 1; + dev->regs.ali_soft_smi = 1; + } else if (port == 0x0003) + dev->apm->stat = val; + } else { + if (port == 0x0000) { + dev->apm->cmd = val; + if (dev->vendor == VEN_INTEL) dev->regs.glbsts |= 0x20; - acpi_raise_smi(dev); - } - } else - dev->apm->stat = val; + acpi_raise_smi(dev, dev->apm->do_smi); + } else + dev->apm->stat = val; + } } @@ -1520,10 +1549,17 @@ acpi_apm_in(uint16_t port, void *p) port &= 0x0001; - if (port == 0x0000) - ret = dev->apm->cmd; - else - ret = dev->apm->stat; + if (dev->vendor == VEN_ALI) { + if (port == 0x0001) + ret = dev->apm->cmd; + else if (port == 0x0003) + ret = dev->apm->stat; + } else { + if (port == 0x0000) + ret = dev->apm->cmd; + else + ret = dev->apm->stat; + } acpi_log("[%04X:%08X] APM read: %04X = %02X\n", CS, cpu_state.pc, port, ret); @@ -1616,8 +1652,14 @@ acpi_init(const device_t *info) dev->irq_line = 9; if ((dev->vendor == VEN_INTEL) || (dev->vendor == VEN_ALI)) { + if (dev->vendor == VEN_ALI) + dev->irq_mode = 2; dev->apm = device_add(&apm_pci_acpi_device); - io_sethandler(0x00b2, 0x0002, acpi_apm_in, NULL, NULL, acpi_apm_out, NULL, NULL, dev); + if (dev->vendor == VEN_ALI) { + acpi_log("Setting I/O handler at port B1\n"); + io_sethandler(0x00b1, 0x0003, acpi_apm_in, NULL, NULL, acpi_apm_out, NULL, NULL, dev); + } else + io_sethandler(0x00b2, 0x0002, acpi_apm_in, NULL, NULL, acpi_apm_out, NULL, NULL, dev); } else if (dev->vendor == VEN_VIA) { dev->i2c = i2c_gpio_init("smbus_vt82c586b"); i2c_smbus = i2c_gpio_get_bus(dev->i2c); diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 76cf45db0..ab8f96e61 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -13,25 +13,18 @@ # Copyright 2020,2021 David Hrdlička. # -add_library(chipset OBJECT acc2168.c cs8230.c ali1217.c ali1429.c ali1489.c et6000.c headland.c - intel_82335.c cs4031.c intel_420ex.c intel_4x0.c intel_sio.c intel_piix.c ../ioapic.c - neat.c opti283.c opti291.c opti495.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 sis_5598.c - umc_8886.c umc_8890.c umc_hb4.c +add_library(chipset OBJECT acc2168.c cs8230.c ali1217.c ali1429.c ali1489.c ali1531.c ali1543.c + headland.c intel_82335.c cs4031.c intel_420ex.c intel_4x0.c intel_sio.c intel_piix.c + ../ioapic.c neat.c opti283.c opti291.c opti391.c opti495.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 sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c stpc.c - via_apollo.c via_pipc.c wd76c10.c - vl82c480.c) + via_apollo.c via_pipc.c vl82c480.c wd76c10.c) if(I450KX) target_sources(chipset PRIVATE intel_i450kx.c) endif() -if(M154X) - target_sources(chipset PRIVATE ali1531.c) - target_sources(chipset PRIVATE ali1543.c) -endif() - if(M6117) target_sources(chipset PRIVATE ali6117.c) endif() diff --git a/src/chipset/ali1531.c b/src/chipset/ali1531.c index c29d831fc..ce161ce7c 100644 --- a/src/chipset/ali1531.c +++ b/src/chipset/ali1531.c @@ -34,6 +34,7 @@ #include <86box/chipset.h> + typedef struct ali1531_t { uint8_t pci_conf[256]; @@ -41,201 +42,287 @@ typedef struct ali1531_t smram_t *smram; } ali1531_t; -void ali1531_shadow_recalc(int cur_reg, ali1531_t *dev) -{ - for (uint32_t i = 0; i < 8; i++) - mem_set_mem_state_both(0xc0000 + ((cur_reg & 1) << 17) + (i << 14), 0x4000, (((dev->pci_conf[0x4c + (cur_reg & 1)] >> i) & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | (((dev->pci_conf[0x4e + (cur_reg & 1)] >> i) & 1) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); - flushmmucache_nopc(); +#ifdef ENABLE_ALI1531_LOG +int ali1531_do_log = ENABLE_ALI1531_LOG; +static void +ali1531_log(const char *fmt, ...) +{ + va_list ap; + + if (ali1531_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } +#else +#define ali1531_log(fmt, ...) +#endif -void ali1531_smm_recalc(uint8_t smm_state, ali1531_t *dev) + +static void +ali1531_smram_recalc(uint8_t val, ali1531_t *dev) { - smram_disable_all(); - if (dev->pci_conf[0x48] & 1) - { - switch (smm_state) - { - case 0: - smram_enable(dev->smram, 0xd0000, 0xb0000, 0x10000, 0, 1); - smram_map(1, 0xd0000, 0x10000, 1); - break; - case 1: - smram_enable(dev->smram, 0xd0000, 0xb0000, 0x10000, 1, 1); - smram_map(1, 0xd0000, 0x10000, 1); - break; - case 2: - smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, 0, 1); - smram_map(1, 0xa0000, 0x20000, (dev->pci_conf[0x48] & 0x10) ? 2 : 1); - break; - case 3: - smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, 1, 1); - smram_map(1, 0xa0000, 0x20000, (dev->pci_conf[0x48] & 0x10) ? 2 : 1); - break; - case 4: - smram_enable(dev->smram, 0x30000, 0xb0000, 0x10000, 0, 1); - smram_map(1, 0x30000, 0x10000, 1); - break; - case 5: - smram_enable(dev->smram, 0x30000, 0xb0000, 0x10000, 1, 1); - smram_map(1, 0x30000, 0x10000, 1); - break; - } + if (val & 1) { + switch (val & 0x0c) { + case 0x00: + ali1531_log("SMRAM: D0000 -> B0000 (%i)\n", val & 2); + smram_enable(dev->smram, 0xd0000, 0xb0000, 0x10000, val & 2, 1); + if (val & 0x10) + mem_set_mem_state_smram_ex(1, 0xd0000, 0x10000, 0x02); + break; + case 0x04: + ali1531_log("SMRAM: A0000 -> A0000 (%i)\n", val & 2); + smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, val & 2, 1); + if (val & 0x10) + mem_set_mem_state_smram_ex(1, 0xa0000, 0x20000, 0x02); + break; + case 0x08: + ali1531_log("SMRAM: 30000 -> B0000 (%i)\n", val & 2); + smram_enable(dev->smram, 0x30000, 0xb0000, 0x10000, val & 2, 1); + if (val & 0x10) + mem_set_mem_state_smram_ex(1, 0x30000, 0x10000, 0x02); + break; + } } flushmmucache_nopc(); } + +static void +ali1531_shadow_recalc(int cur_reg, ali1531_t *dev) +{ + int i, bit, r_reg, w_reg; + uint32_t base, flags = 0; + + shadowbios = shadowbios_write = 0; + + for (i = 0; i < 16; i++) { + base = 0x000c0000 + (i << 14); + bit = i & 7; + r_reg = 0x4c + (i >> 3); + w_reg = 0x4e + (i >> 3); + + flags = (dev->pci_conf[r_reg] & (1 << bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + flags |= ((dev->pci_conf[w_reg] & (1 << bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY); + + if (base >= 0x000e0000) { + if (dev->pci_conf[r_reg] & (1 << bit)) + shadowbios |= 1; + if (dev->pci_conf[w_reg] & (1 << bit)) + shadowbios_write |= 1; + } + + ali1531_log("%08X-%08X shadow: R%c, W%c\n", base, base + 0x00003fff, + (dev->pci_conf[r_reg] & (1 << bit)) ? 'I' : 'E', (dev->pci_conf[w_reg] & (1 << bit)) ? 'I' : 'E'); + mem_set_mem_state_both(base, 0x00004000, flags); + } + + flushmmucache_nopc(); +} + + static void ali1531_write(int func, int addr, uint8_t val, void *priv) { ali1531_t *dev = (ali1531_t *)priv; - switch (addr) - { - case 0x05: - dev->pci_conf[addr] = val & 1; - break; + switch (addr) { + case 0x04: + dev->pci_conf[addr] = val; + break; + case 0x05: + dev->pci_conf[addr] = val & 0x01; + break; - case 0x07: - dev->pci_conf[addr] = val & 0xfe; - break; + case 0x07: + dev->pci_conf[addr] &= ~(val & 0xf8); + break; - case 0x0d: - dev->pci_conf[addr] = val & 0xf8; - break; + case 0x0d: + dev->pci_conf[addr] = val & 0xf8; + break; - case 0x40: - dev->pci_conf[addr] = val & 0xf1; - break; + case 0x2c: /* Subsystem Vendor ID */ + case 0x2d: + case 0x2e: + case 0x2f: + if (dev->pci_conf[0x70] & 0x08) + dev->pci_conf[addr] = val; + break; - case 0x41: - dev->pci_conf[addr] = val & 0xdf; - break; + case 0x40: + dev->pci_conf[addr] = val & 0xf1; + break; - case 0x42: /* L2 Cache */ - dev->pci_conf[addr] = val & 0xf7; - cpu_cache_ext_enabled = !!(val & 1); - cpu_update_waitstates(); - break; + case 0x41: + dev->pci_conf[addr] = (val & 0xd6) | 0x08; + break; - case 0x43: /* L1 Cache */ - dev->pci_conf[addr] = val; - cpu_cache_int_enabled = !!(val & 1); - cpu_update_waitstates(); - break; + case 0x42: /* L2 Cache */ + dev->pci_conf[addr] = val & 0xf7; + cpu_cache_ext_enabled = !!(val & 1); + cpu_update_waitstates(); + break; - case 0x47: - dev->pci_conf[addr] = val & 0xfc; + case 0x43: /* L1 Cache */ + dev->pci_conf[addr] = val; + cpu_cache_int_enabled = !!(val & 1); + cpu_update_waitstates(); + break; - if (mem_size > 0xe00000) - mem_set_mem_state_both(0xe00000, 0x100000, !(val & 0x20) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + case 0x44: + dev->pci_conf[addr] = val; + break; + case 0x45: + dev->pci_conf[addr] = val; + break; - if (mem_size > 0xf00000) - mem_set_mem_state_both(0xf00000, 0x100000, !(val & 0x10) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + case 0x46: + dev->pci_conf[addr] = val; + break; - mem_set_mem_state_both(0xa0000, 0x20000, (val & 8) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); - mem_set_mem_state_both(0x80000, 0x20000, (val & 4) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); - break; + case 0x47: + dev->pci_conf[addr] = val & 0xfc; - case 0x48: /* SMRAM */ - dev->pci_conf[addr] = val; - ali1531_smm_recalc((val >> 1) & 7, dev); - break; + if (mem_size > 0xe00000) + mem_set_mem_state_both(0xe00000, 0x100000, (val & 0x20) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); - case 0x49: - dev->pci_conf[addr] = val & 0x73; - break; + if (mem_size > 0xf00000) + mem_set_mem_state_both(0xf00000, 0x100000, (val & 0x10) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); - case 0x4c: /* Shadow RAM */ - case 0x4d: - case 0x4e: - case 0x4f: - dev->pci_conf[addr] = val; - ali1531_shadow_recalc(addr, dev); - break; + mem_set_mem_state_both(0xa0000, 0x20000, (val & 8) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + mem_set_mem_state_both(0x80000, 0x20000, (val & 4) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); - case 0x57: /* H2PO */ - dev->pci_conf[addr] = val & 0x60; - if (!(val & 0x20)) - outb(0x92, 0x01); - break; + flushmmucache_nopc(); + break; - case 0x58: - dev->pci_conf[addr] = val & 0x83; - break; + case 0x48: /* SMRAM */ + dev->pci_conf[addr] = val; + ali1531_smram_recalc(val, dev); + break; - case 0x5b: - dev->pci_conf[addr] = val & 0x4f; - break; + case 0x49: + dev->pci_conf[addr] = val & 0x73; + break; - case 0x5d: - dev->pci_conf[addr] = val & 0x53; - break; + case 0x4a: + dev->pci_conf[addr] = val; + break; - case 0x5f: - dev->pci_conf[addr] = val & 0x7f; - break; + case 0x4c ... 0x4f: /* Shadow RAM */ + dev->pci_conf[addr] = val; + ali1531_shadow_recalc(val, dev); + break; - case 0x60: /* DRB's */ - case 0x61: + case 0x50: case 0x51: case 0x52: case 0x54: + case 0x55: case 0x56: + dev->pci_conf[addr] = val; + break; + + case 0x57: /* H2PO */ + dev->pci_conf[addr] = val & 0x60; + /* Find where the Shut-down Special cycle is initiated. */ + // if (!(val & 0x20)) + // outb(0x92, 0x01); + break; + + case 0x58: + dev->pci_conf[addr] = val & 0x86; + break; + + case 0x59: case 0x5a: + case 0x5c: + dev->pci_conf[addr] = val; + break; + + case 0x5b: + dev->pci_conf[addr] = val & 0x4f; + break; + + case 0x5d: + dev->pci_conf[addr] = val & 0x53; + break; + + case 0x5f: + dev->pci_conf[addr] = val & 0x7f; + break; + + case 0x60: /* DRB's */ case 0x62: - case 0x63: case 0x64: - case 0x65: case 0x66: - case 0x67: case 0x68: - case 0x69: case 0x6a: - case 0x6b: case 0x6c: - case 0x6d: case 0x6e: + dev->pci_conf[addr] = val; + spd_write_drbs_interleaved(dev->pci_conf, 0x60, 0x6f, 1); + break; + case 0x61: + case 0x63: + case 0x65: + case 0x67: + case 0x69: + case 0x6b: + case 0x6d: case 0x6f: - dev->pci_conf[addr] = val; - spd_write_drbs(dev->pci_conf, 0x60, 0x6f, 1); - break; + dev->pci_conf[addr] = val; + break; - case 0x72: - dev->pci_conf[addr] = val & 0xf; - break; + case 0x70: case 0x71: + dev->pci_conf[addr] = val; + break; - case 0x74: - dev->pci_conf[addr] = val & 0x2b; - break; + case 0x72: + dev->pci_conf[addr] = val & 0x0f; + break; - case 0x80: - dev->pci_conf[addr] = val & 0x84; - break; + case 0x74: + dev->pci_conf[addr] = val & 0x2b; + break; - case 0x81: - dev->pci_conf[addr] = val & 0x81; - break; + case 0x76: case 0x77: + dev->pci_conf[addr] = val; + break; - case 0x83: - dev->pci_conf[addr] = val & 0x10; - break; + case 0x80: + dev->pci_conf[addr] = val & 0x84; + break; - default: - dev->pci_conf[addr] = val; - break; + case 0x81: + dev->pci_conf[addr] = val & 0x81; + break; + + case 0x83: + dev->pci_conf[addr] = val & 0x10; + break; } } + static uint8_t ali1531_read(int func, int addr, void *priv) { ali1531_t *dev = (ali1531_t *)priv; - return dev->pci_conf[addr]; + uint8_t ret = 0xff; + + ret = dev->pci_conf[addr]; + + return ret; } + static void ali1531_reset(void *priv) { ali1531_t *dev = (ali1531_t *)priv; + int i; /* Default Registers */ dev->pci_conf[0x00] = 0xb9; @@ -267,11 +354,20 @@ ali1531_reset(void *priv) ali1531_write(0, 0x42, 0x00, dev); ali1531_write(0, 0x43, 0x00, dev); + ali1531_write(0, 0x47, 0x00, dev); - ali1531_write(0, 0x60, 0x08, dev); - ali1531_write(0, 0x61, 0x40, dev); + ali1531_write(0, 0x48, 0x00, dev); + + for (i = 0; i < 4; i++) + ali1531_write(0, 0x4c + i, 0x00, dev); + + for (i = 0; i < 16; i += 2) { + ali1531_write(0, 0x60 + i, 0x08, dev); + ali1531_write(0, 0x61 + i, 0x40, dev); + } } + static void ali1531_close(void *priv) { @@ -281,6 +377,7 @@ ali1531_close(void *priv) free(dev); } + static void * ali1531_init(const device_t *info) { @@ -296,6 +393,7 @@ ali1531_init(const device_t *info) return dev; } + const device_t ali1531_device = { "ALi M1531 CPU-to-PCI Bridge", DEVICE_PCI, @@ -306,4 +404,5 @@ const device_t ali1531_device = { {NULL}, NULL, NULL, - NULL}; + NULL +}; diff --git a/src/chipset/ali1543.c b/src/chipset/ali1543.c index 158d42ba4..4f0d3cbff 100644 --- a/src/chipset/ali1543.c +++ b/src/chipset/ali1543.c @@ -34,10 +34,12 @@ #include <86box/fdc.h> #include <86box/hdc_ide.h> #include <86box/hdc_ide_sff8038i.h> +#include <86box/keyboard.h> #include <86box/lpt.h> #include <86box/mem.h> #include <86box/nvr.h> #include <86box/pci.h> +#include <86box/pic.h> #include <86box/port_92.h> #include <86box/serial.h> #include <86box/smbus_piix4.h> @@ -47,6 +49,41 @@ #include <86box/chipset.h> + +typedef struct ali1543_t +{ + uint8_t pci_conf[256], pmu_conf[256], usb_conf[256], ide_conf[256], + sio_regs[256], device_regs[8][256], sio_index, in_configuration_mode, + pci_slot, ide_slot, usb_slot, pmu_slot, usb_dev_enable, ide_dev_enable, + pmu_dev_enable; + + apm_t * apm; + acpi_t * acpi; + ddma_t * ddma; + fdc_t * fdc_controller; + nvr_t * nvr; + port_92_t * port_92; + serial_t * uart[2]; + sff8038i_t * ide_controller[2]; + smbus_piix4_t * smbus; + usb_t * usb; + +} ali1543_t; + +/* + Notes: + - Power Managment isn't functioning properly + - IDE isn't functioning properly + - 1543C differences have to be examined + - Some Chipset functionality might be missing + - Device numbers and types might be incorrect + - Code quality is abysmal and needs lot's of cleanup. +*/ + +int ali1533_irq_routing[16] = { PCI_IRQ_DISABLED, 9, 3, 10, 4, 5, 7, 6, + 1, 11, PCI_IRQ_DISABLED, 12, PCI_IRQ_DISABLED, 14, PCI_IRQ_DISABLED, 15 }; + + #ifdef ENABLE_ALI1543_LOG int ali1543_do_log = ENABLE_ALI1543_LOG; static void @@ -65,216 +102,413 @@ ali1543_log(const char *fmt, ...) #define ali1543_log(fmt, ...) #endif -typedef struct ali1543_t + +static void +ali1533_ddma_handler(ali1543_t *dev) { - uint8_t pci_conf[256], pmu_conf[256], usb_conf[256], ide_conf[256], - sio_regs[256], device_regs[8][256], sio_index, in_configuration_mode, - pci_slot, ide_slot, usb_slot, pmu_slot; - - apm_t *apm; - acpi_t *acpi; - ddma_t *ddma; - fdc_t *fdc_controller; - nvr_t *nvr; - port_92_t *port_92; - serial_t *uart[2]; - sff8038i_t *ide_controller[2]; - smbus_piix4_t *smbus; - usb_t *usb; - -} ali1543_t; - -/* - - Notes: - - Power Managment isn't functioning properly - - IDE isn't functioning properly - - 1543C differences have to be examined - - Some Chipset functionality might be missing - - Device numbers and types might be incorrect - - Code quality is abysmal and needs lot's of cleanup. - -*/ - -int ali1533_irq_routing[15] = {9, 3, 0x0a, 4, 5, 7, 6, 1, 0x0b, 0, 0x0c, 0, 0x0e, 0, 0x0f}; - -void ali1533_ddma_handler(ali1543_t *dev) -{ - for (uint8_t i = 0; i < 8; i++) - { - if (i != 4) - ddma_update_io_mapping(dev->ddma, i & 7, dev->pci_conf[0x73] & 0xf, dev->pci_conf[0x73] & 0xf0, dev->pci_conf[0x45] & 2); - } + /* TODO: Find any documentation that actually explains the ALi southbridge DDMA mapping. */ } -void ali5229_ide_handler(ali1543_t *dev); + +static void ali5229_ide_handler(ali1543_t *dev); +static void ali5229_ide_irq_handler(ali1543_t *dev); + +static void ali5229_write(int func, int addr, uint8_t val, void *priv); + static void ali1533_write(int func, int addr, uint8_t val, void *priv) { ali1543_t *dev = (ali1543_t *)priv; + int irq; + ali1543_log("M1533: dev->pci_conf[%02x] = %02x\n", addr, val); - switch (addr) - { - case 0x04: - if (dev->pci_conf[0x5f] & 8) - dev->pci_conf[addr] = val; - break; - case 0x2c: /* Subsystem Vendor ID */ - case 0x2d: - case 0x2e: - case 0x2f: - if (dev->pci_conf[0x74] & 0x40) - dev->pci_conf[addr] = val; - break; + if (func > 0) + return; - case 0x40: - dev->pci_conf[addr] = val & 0x7f; - break; + switch (addr) { + case 0x04: /* Command Register */ + if (!(dev->pci_conf[0x5f] & 0x08)) + dev->pci_conf[0x04] = val; + break; + case 0x05: /* Command Register */ + if (!(dev->pci_conf[0x5f] & 0x08)) + dev->pci_conf[0x04] = val & 0x03; + break; - case 0x42: /* ISA Bus Speed */ - dev->pci_conf[addr] = val & 0xcf; - switch(val & 7) - { - case 0: - cpu_set_isa_speed(7159091); - break; - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - cpu_set_isa_pci_div(val & 7); - break; - } + case 0x07: /* Status Byte */ + dev->pci_conf[addr] &= ~(val & 0x30); + break; - break; + case 0x2c: /* Subsystem Vendor ID */ + case 0x2d: + case 0x2e: + case 0x2f: + if (!(dev->pci_conf[0x74] & 0x40)) + dev->pci_conf[addr] = val; + break; - case 0x43: - dev->pci_conf[addr] = val; - if (val & 0x80) - port_92_add(dev->port_92); - else - port_92_remove(dev->port_92); - break; + case 0x40: + dev->pci_conf[addr] = val & 0x7f; + break; - case 0x44: /* Set IRQ Line for Primary IDE if it's on native mode */ - dev->pci_conf[addr] = 0xdf; - if (dev->ide_conf[0x09] & 1) - sff_set_irq_line(dev->ide_controller[0], ((val & 0x0f) == 0) ? ali1533_irq_routing[(val & 0x0f) - 1] : PCI_IRQ_DISABLED); - break; + case 0x41: + /* TODO: Bit 7 selects keyboard controller type: + 0 = AT, 1 = PS/2 */ + keyboard_at_set_mouse_scan((val & 0x40) ? 1 : 0); + dev->pci_conf[addr] = val & 0xbf; + break; - case 0x45: /* DDMA Enable */ - dev->pci_conf[addr] = 0xcf; - ali1533_ddma_handler(dev); - break; + case 0x42: /* ISA Bus Speed */ + dev->pci_conf[addr] = val & 0xcf; + switch (val & 7) { + case 0: + cpu_set_isa_speed(7159091); + break; + case 1: case 2: case 3: case 4: + case 5: case 6: + cpu_set_isa_pci_div((val & 7) + 1); + break; + } + break; - case 0x48: /* PCI IRQ Routing */ - case 0x49: - dev->pci_conf[addr] = val; - pci_set_irq_routing(((addr & 1) * 2) + 2, (((val >> 4) & 0x0f) == 0) ? ali1533_irq_routing[((val >> 4) & 0x0f) - 1] : PCI_IRQ_DISABLED); - pci_set_irq_routing(((addr & 1) * 2) + 1, ((val & 0x0f) == 0) ? ali1533_irq_routing[(val & 0x0f) - 1] : PCI_IRQ_DISABLED); - break; + case 0x43: + dev->pci_conf[addr] = val; + if (val & 0x80) + port_92_add(dev->port_92); + else + port_92_remove(dev->port_92); + break; - case 0x53: /* USB Enable */ - dev->pci_conf[addr] = val & 0xe7; - ohci_update_mem_mapping(dev->usb, 0x11, 0x12, 0x13, (dev->usb_conf[0x04] & 1) && (!(dev->pci_conf[0x53] & 0x40))); - break; + /* We're going to cheat a little bit here and use MIRQ's as a substitute for the ALi's INTAJ's, + as they work pretty much the same - specifically, we're going to use MIRQ2 and MIRQ3 for them, + as MIRQ0 and MIRQ1 map to the ALi's MBIRQ0 and MBIRQ1. */ + case 0x44: /* Set IRQ Line for Primary IDE if it's on native mode */ + dev->pci_conf[addr] = val & 0xdf; + soft_reset_pci = !!(val & 0x80); + sff_set_irq_level(dev->ide_controller[0], 0, !(val & 0x10)); + sff_set_irq_level(dev->ide_controller[1], 0, !(val & 0x10)); + ali1543_log("INTAJ = IRQ %i\n", ali1533_irq_routing[val & 0x0f]); + pci_set_mirq_routing(PCI_MIRQ0, ali1533_irq_routing[val & 0x0f]); + pci_set_mirq_routing(PCI_MIRQ2, ali1533_irq_routing[val & 0x0f]); + break; - case 0x54: /* USB Control ? */ - dev->pci_conf[addr] = val & 0xdf; - break; + /* TODO: Implement a ROMCS# assertion bitmask for I/O ports. */ + case 0x45: /* DDMA Enable */ + dev->pci_conf[addr] = val & 0xcb; + ali1533_ddma_handler(dev); + break; - case 0x57: - dev->pci_conf[addr] = val & 0xc7; - break; + /* TODO: For 0x47, we need a way to obtain the memory state for an address + and toggle ROMCS#. */ + case 0x47: /* BIOS chip select control */ + dev->pci_conf[addr] = val; + break; - case 0x58: /* IDE Enable */ - dev->pci_conf[addr] = val & 0x7f; - ali5229_ide_handler(dev); - break; + /* PCI IRQ Routing */ + case 0x48: case 0x49: case 0x4a: case 0x4b: + dev->pci_conf[addr] = val; - case 0x59: - case 0x5a: - dev->pci_conf[addr] = val & 0x0e; - break; + pci_set_irq_routing(((addr & 0x03) << 1) + 2, ali1533_irq_routing[(val >> 4) & 0x0f]); + pci_set_irq_routing(((addr & 0x03) << 1) + 1, ali1533_irq_routing[val & 0x0f]); + break; - case 0x5b: - dev->pci_conf[addr] = val & 0x02; - break; + case 0x4c: /* PCI INT to ISA Level to Edge transfer */ + dev->pci_conf[addr] = val; - case 0x5c: - dev->pci_conf[addr] = val & 0x7f; - break; + for (irq = 1; irq < 9; irq++) + pci_set_irq_level(irq, !(val & (1 << (irq - 1)))); + break; - case 0x5d: - dev->pci_conf[addr] = val & 0x02; - break; + case 0x4d: /* MBIRQ0(SIRQI#), MBIRQ1(SIRQII#) Interrupt to ISA IRQ routing table */ + dev->pci_conf[addr] = val; - case 0x5e: - dev->pci_conf[addr] = val & 0xe0; - break; + ali1543_log("SIRQI = IRQ %i; SIRQII = IRQ %i\n", ali1533_irq_routing[(val >> 4) & 0x0f], ali1533_irq_routing[val & 0x0f]); + // pci_set_mirq_routing(PCI_MIRQ0, ali1533_irq_routing[(val >> 4) & 0x0f]); + // pci_set_mirq_routing(PCI_MIRQ1, ali1533_irq_routing[val & 0x0f]); + break; - case 0x5f: - dev->pci_conf[addr] = val; - acpi_update_io_mapping(dev->acpi, (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0), (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); - smbus_piix4_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); - break; + /* I/O cycle posted-write first port definition */ + case 0x50: + dev->pci_conf[addr] = val; + break; + case 0x51: + dev->pci_conf[addr] = val & 0x8f; + break; - case 0x6d: - dev->pci_conf[addr] = val & 0xbf; - break; + /* I/O cycle posted-write second port definition */ + case 0x52: + dev->pci_conf[addr] = val; + break; + case 0x53: + dev->pci_conf[addr] = val & 0xcf; + /* This actually enables/disables the USB *device* rather than the interface itself. */ + dev->usb_dev_enable = !(val & 0x40); + break; - case 0x71: - case 0x72: - dev->pci_conf[addr] = val & 0xef; - break; + /* Hardware setting status bits, read-only (register 0x54) */ - case 0x73: /* DDMA Base Address */ - dev->pci_conf[addr] = val; - ali1533_ddma_handler(dev); - break; + /* Programmable chip select (pin PCSJ) address define */ + case 0x55: case 0x56: + dev->pci_conf[addr] = val; + break; + case 0x57: + dev->pci_conf[addr] = val & 0xc7; + break; - case 0x74: /* USB IRQ Routing */ - dev->pci_conf[addr] = val & 0xdf; - break; + /* IDE interface control + TODO: What is IDSEL address? */ + case 0x58: + dev->pci_conf[addr] = val & 0x7f; + ali1543_log("PCI58: %02X\n", val); + dev->ide_dev_enable = !!(val & 0x40); + switch (val & 0x30) { + case 0x00: + dev->ide_slot = 0x10; /* A27 = slot 16 */ + break; + case 0x10: + dev->ide_slot = 0x0f; /* A26 = slot 15 */ + break; + case 0x20: + dev->ide_slot = 0x0e; /* A25 = slot 14 */ + break; + case 0x30: + dev->ide_slot = 0x0d; /* A24 = slot 13 */ + break; + } + ali1543_log("IDE slot = %02X (A%0i)\n", dev->ide_slot, dev->ide_slot + 11 - 5); + ali5229_ide_irq_handler(dev); + break; - case 0x75: /* Set IRQ Line for Secondary IDE if it's on native mode */ - dev->pci_conf[addr] = val & 0x1f; - if (dev->ide_conf[0x09] & 8) - sff_set_irq_line(dev->ide_controller[1], ((val & 0x0f) == 0) ? ali1533_irq_routing[(val & 0x0f) - 1] : PCI_IRQ_DISABLED); - break; + /* General Purpose input multiplexed pin(GPI) select */ + case 0x59: + dev->pci_conf[addr] = val & 0x0e; + break; - case 0x76: /* PMU IRQ Routing */ - dev->pci_conf[addr] = val & 0x1f; - acpi_set_irq_line(dev->acpi, val & 0x0f); - break; + /* General Purpose output multiplexed pin(GPO) select low */ + case 0x5a: + dev->pci_conf[addr] = val & 0x0f; + break; + /* General Purpose output multiplexed pin(GPO) select high */ + case 0x5b: + dev->pci_conf[addr] = val & 0x02; + break; - case 0x77: /* SMBus IRQ Routing */ - dev->pci_conf[addr] = val & 0x1f; - break; + case 0x5c: + dev->pci_conf[addr] = val & 0x7f; + break; + case 0x5d: + dev->pci_conf[addr] = val & 0x02; + break; - default: - dev->pci_conf[addr] = val; - break; + case 0x5e: + dev->pci_conf[addr] = val & 0xe0; + break; + + case 0x5f: + dev->pci_conf[addr] = val; + dev->pmu_dev_enable = !(val & 0x04); + break; + + case 0x6c: /* Deleted - no idea what it used to do */ + dev->pci_conf[addr] = val; + break; + + case 0x6d: + dev->pci_conf[addr] = val & 0xbf; + break; + + case 0x6e: case 0x70: + dev->pci_conf[addr] = val; + break; + + case 0x71: + dev->pci_conf[addr] = val & 0xef; + break; + + case 0x72: + dev->pci_conf[addr] = val & 0xef; + switch (val & 0x0c) { + case 0x00: + dev->pmu_slot = 0x11; /* A28 = slot 17 */ + break; + case 0x04: + dev->pmu_slot = 0x12; /* A29 = slot 18 */ + break; + case 0x08: + dev->pmu_slot = 0x03; /* A14 = slot 03 */ + break; + case 0x0c: + dev->pmu_slot = 0x04; /* A15 = slot 04 */ + break; + } + ali1543_log("PMU slot = %02X (A%0i)\n", dev->pmu_slot, dev->pmu_slot + 11 - 5); + switch (val & 0x03) { + case 0x00: + dev->usb_slot = 0x14; /* A31 = slot 20 */ + break; + case 0x01: + dev->usb_slot = 0x13; /* A30 = slot 19 */ + break; + case 0x02: + dev->usb_slot = 0x02; /* A13 = slot 02 */ + break; + case 0x03: + dev->usb_slot = 0x01; /* A12 = slot 01 */ + break; + } + ali1543_log("USB slot = %02X (A%0i)\n", dev->usb_slot, dev->usb_slot + 11 - 5); + break; + + case 0x73: /* DDMA Base Address */ + dev->pci_conf[addr] = val; + ali1533_ddma_handler(dev); + break; + + case 0x74: /* USB IRQ Routing - we cheat and use MIRQ4 */ + dev->pci_conf[addr] = val & 0xdf; + /* TODO: MIRQ level/edge control - if bit 4 = 1, it's level */ + pci_set_mirq_routing(PCI_MIRQ4, ali1533_irq_routing[val & 0x0f]); + break; + + case 0x75: /* Set IRQ Line for Secondary IDE if it's on native mode */ + dev->pci_conf[addr] = val & 0x1f; + sff_set_irq_level(dev->ide_controller[0], 1, !(val & 0x10)); + sff_set_irq_level(dev->ide_controller[1], 1, !(val & 0x10)); + ali1543_log("INTBJ = IRQ %i\n", ali1533_irq_routing[val & 0x0f]); + pci_set_mirq_routing(PCI_MIRQ1, ali1533_irq_routing[val & 0x0f]); + pci_set_mirq_routing(PCI_MIRQ3, ali1533_irq_routing[val & 0x0f]); + break; + + case 0x76: /* PMU IRQ Routing - we cheat and use MIRQ5 */ + dev->pci_conf[addr] = val & 0x1f; + acpi_set_mirq_is_level(dev->acpi, !!(val & 0x10)); + pci_set_mirq_routing(PCI_MIRQ5, ali1533_irq_routing[val & 0x0f]); + /* TODO: Tell ACPI to use MIRQ5 */ + break; + + case 0x77: /* SMBus IRQ Routing - we cheat and use MIRQ6 */ + dev->pci_conf[addr] = val & 0x1f; + pci_set_mirq_routing(PCI_MIRQ6, ali1533_irq_routing[val & 0x0f]); + break; } } + static uint8_t ali1533_read(int func, int addr, void *priv) { ali1543_t *dev = (ali1543_t *)priv; + uint8_t ret = 0xff; - if (((dev->pci_conf[0x42] & 0x80) && (addr >= 0x40)) || ((dev->pci_conf[0x5f] & 8) && (addr == 4))) - return 0; - else - return dev->pci_conf[addr]; + if (func == 0) { + if (((dev->pci_conf[0x42] & 0x80) && (addr >= 0x40)) || ((dev->pci_conf[0x5f] & 8) && (addr == 4))) + ret = 0x00; + else { + ret = dev->pci_conf[addr]; + if (addr == 0x41) + ret |= (keyboard_at_get_mouse_scan() << 2); + else if (addr == 0x58) + ret = (ret & 0xbf) | (dev->ide_dev_enable ? 0x40 : 0x00); + } + } + + return ret; } -void ali5229_ide_handler(ali1543_t *dev) + +static void +ali5229_ide_irq_handler(ali1543_t *dev) { + int ctl = 0, ch = 0; + int bit = 0; + + if (dev->ide_conf[0x52] & 0x10) { + ctl ^= 1; + ch ^= 1; + bit ^= 5; + } + + if (dev->ide_conf[0x09] & (1 ^ bit)) { + /* Primary IDE is native. */ + ali1543_log("Primary IDE IRQ mode: Native, Native\n"); + sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 4); + sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 4); + } else { + /* Primary IDE is legacy. */ + switch (dev->pci_conf[0x58] & 0x03) { + case 0x00: + /* SIRQI, SIRQII */ + ali1543_log("Primary IDE IRQ mode: SIRQI, SIRQII\n"); + sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 2); + sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 5); + break; + case 0x01: + /* IRQ14, IRQ15 */ + ali1543_log("Primary IDE IRQ mode: IRQ14, IRQ15\n"); + sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 0); + sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 0); + break; + case 0x02: + /* IRQ14, SIRQII */ + ali1543_log("Primary IDE IRQ mode: IRQ14, SIRQII\n"); + sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 0); + sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 5); + break; + case 0x03: + /* IRQ14, SIRQI */ + ali1543_log("Primary IDE IRQ mode: IRQ14, SIRQI\n"); + sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 0); + sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 2); + break; + } + } + + ctl ^= 1; + + if (dev->ide_conf[0x09] & (4 ^ bit)) { + /* Secondary IDE is native. */ + ali1543_log("Secondary IDE IRQ mode: Native, Native\n"); + sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 4); + sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 4); + } else { + /* Secondary IDE is legacy. */ + switch (dev->pci_conf[0x58] & 0x03) { + case 0x00: + /* SIRQI, SIRQII */ + ali1543_log("Secondary IDE IRQ mode: SIRQI, SIRQII\n"); + sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 2); + sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 5); + break; + case 0x01: + /* IRQ14, IRQ15 */ + ali1543_log("Secondary IDE IRQ mode: IRQ14, IRQ15\n"); + sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 0); + sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 0); + break; + case 0x02: + /* IRQ14, SIRQII */ + ali1543_log("Secondary IDE IRQ mode: IRQ14, SIRQII\n"); + sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 0); + sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 5); + break; + case 0x03: + /* IRQ14, SIRQI */ + ali1543_log("Secondary IDE IRQ mode: IRQ14, SIRQI\n"); + sff_set_irq_mode(dev->ide_controller[ctl], 0 ^ ch, 0); + sff_set_irq_mode(dev->ide_controller[ctl], 1 ^ ch, 2); + break; + } + } +} + + +static void +ali5229_ide_handler(ali1543_t *dev) +{ + uint32_t ch = 0; + uint16_t native_base_pri_addr = (dev->ide_conf[0x11] | dev->ide_conf[0x10] << 8); uint16_t native_side_pri_addr = (dev->ide_conf[0x15] | dev->ide_conf[0x14] << 8); uint16_t native_base_sec_addr = (dev->ide_conf[0x19] | dev->ide_conf[0x18] << 8); @@ -288,505 +522,71 @@ void ali5229_ide_handler(ali1543_t *dev) uint16_t current_pri_base, current_pri_side, current_sec_base, current_sec_side; /* Primary Channel Programming */ - if (!(dev->ide_conf[0x52] & 0x10)) - { - current_pri_base = (!(dev->ide_conf[0x09] & 1)) ? comp_base_pri_addr : native_base_pri_addr; - current_pri_side = (!(dev->ide_conf[0x09] & 1)) ? comp_side_pri_addr : native_side_pri_addr; - } - else - { - current_pri_base = (!(dev->ide_conf[0x09] & 1)) ? comp_base_sec_addr : native_base_sec_addr; - current_pri_side = (!(dev->ide_conf[0x09] & 1)) ? comp_side_sec_addr : native_side_sec_addr; + if (dev->ide_conf[0x52] & 0x10) { + current_pri_base = (!(dev->ide_conf[0x09] & 1)) ? comp_base_sec_addr : native_base_sec_addr; + current_pri_side = (!(dev->ide_conf[0x09] & 1)) ? comp_side_sec_addr : native_side_sec_addr; + } else { + current_pri_base = (!(dev->ide_conf[0x09] & 1)) ? comp_base_pri_addr : native_base_pri_addr; + current_pri_side = (!(dev->ide_conf[0x09] & 1)) ? comp_side_pri_addr : native_side_pri_addr; } /* Secondary Channel Programming */ - if (!(dev->ide_conf[0x52] & 0x10)) - { - current_sec_base = (!(dev->ide_conf[0x09] & 4)) ? comp_base_sec_addr : native_base_sec_addr; - current_sec_side = (!(dev->ide_conf[0x09] & 4)) ? comp_side_sec_addr : native_side_sec_addr; - } - else - { - current_sec_base = (!(dev->ide_conf[0x09] & 4)) ? comp_base_pri_addr : native_base_pri_addr; - current_sec_side = (!(dev->ide_conf[0x09] & 4)) ? comp_side_pri_addr : native_side_pri_addr; + if (dev->ide_conf[0x52] & 0x10) { + current_sec_base = (!(dev->ide_conf[0x09] & 4)) ? comp_base_pri_addr : native_base_pri_addr; + current_sec_side = (!(dev->ide_conf[0x09] & 4)) ? comp_side_pri_addr : native_side_pri_addr; + } else { + current_sec_base = (!(dev->ide_conf[0x09] & 4)) ? comp_base_sec_addr : native_base_sec_addr; + current_sec_side = (!(dev->ide_conf[0x09] & 4)) ? comp_side_sec_addr : native_side_sec_addr; } - /* Both channels use one port */ - if (dev->ide_conf[0x52] & 0x40) - { - current_pri_base = current_sec_base; - current_pri_side = current_sec_side; - } - - if (dev->ide_conf[0x52] & 0x20) - { - current_sec_base = current_pri_base; - current_sec_side = current_pri_side; - } + if (dev->ide_conf[0x52] & 0x10) + ch ^= 8; + ali1543_log("ali5229_ide_handler(): Disabling primary IDE...\n"); ide_pri_disable(); + ali1543_log("ali5229_ide_handler(): Disabling secondary IDE...\n"); ide_sec_disable(); - if (dev->pci_conf[0x58] & 0x40) - { - sff_set_irq_pin(dev->ide_controller[0], dev->ide_conf[0x3d] & 4); - sff_set_irq_pin(dev->ide_controller[1], dev->ide_conf[0x3d] & 4); + if (dev->ide_conf[0x04] & 0x01) { + /* Primary Channel Setup */ + if (dev->ide_conf[0x09] & 0x20) { + ali1543_log("ali5229_ide_handler(): Primary IDE base now %04X...\n", current_pri_base); + ide_set_base(0, current_pri_base); + ali1543_log("ali5229_ide_handler(): Primary IDE side now %04X...\n", current_pri_side); + ide_set_side(0, current_pri_side); - /* Primary Channel Setup */ - if (dev->ide_conf[0x09] & 0x10) - { - ide_pri_enable(); - if (!(dev->ide_conf[0x09] & 1)) - sff_set_irq_line(dev->ide_controller[0], (dev->ide_conf[0x3c] != 0) ? ali1533_irq_routing[(dev->ide_conf[0x3c] & 0x0f) - 1] : PCI_IRQ_DISABLED); + ali1543_log("ali5229_ide_handler(): Enabling primary IDE...\n"); + ide_pri_enable(); - ide_set_base(0, current_pri_base); - ide_set_side(0, current_pri_side); + sff_bus_master_handler(dev->ide_controller[0], dev->ide_conf[0x04] & 0x01, ((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)) + (0 ^ ch)); + ali1543_log("M5229 PRI: BASE %04x SIDE %04x\n", current_pri_base, current_pri_side); + } - sff_bus_master_handler(dev->ide_controller[0], dev->ide_conf[0x09] & 0x80, (dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)); - ali1543_log("M5229 PRI: BASE %04x SIDE %04x\n", current_pri_base, current_pri_side); - } + /* Secondary Channel Setup */ + if (dev->ide_conf[0x09] & 0x10) { + ali1543_log("ali5229_ide_handler(): Secondary IDE base now %04X...\n", current_sec_base); + ide_set_base(1, current_sec_base); + ali1543_log("ali5229_ide_handler(): Secondary IDE side now %04X...\n", current_sec_side); + ide_set_side(1, current_sec_side); - /* Secondary Channel Setup */ - if (dev->ide_conf[0x09] & 8) - { - ide_sec_enable(); - if (!(dev->ide_conf[0x09] & 4)) - sff_set_irq_line(dev->ide_controller[1], (dev->ide_conf[0x3c] != 0) ? ali1533_irq_routing[(dev->ide_conf[0x3c] & 0x0f) - 1] : PCI_IRQ_DISABLED); + ali1543_log("ali5229_ide_handler(): Enabling secondary IDE...\n"); + ide_sec_enable(); - ide_set_base(1, current_sec_base); - ide_set_side(1, current_sec_side); - - sff_bus_master_handler(dev->ide_controller[1], dev->ide_conf[0x09] & 0x80, ((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)) + 8); - ali1543_log("M5229 SEC: BASE %04x SIDE %04x\n", current_sec_base, current_sec_side); - } + sff_bus_master_handler(dev->ide_controller[1], dev->ide_conf[0x04] & 0x01, (((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8))) + (8 ^ ch)); + ali1543_log("M5229 SEC: BASE %04x SIDE %04x\n", current_sec_base, current_sec_side); + } + } else { + sff_bus_master_handler(dev->ide_controller[0], dev->ide_conf[0x04] & 0x01, (dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)); + sff_bus_master_handler(dev->ide_controller[1], dev->ide_conf[0x04] & 0x01, ((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)) + 8); } } + static void -ali5229_write(int func, int addr, uint8_t val, void *priv) +ali5229_chip_reset(ali1543_t *dev) { - ali1543_t *dev = (ali1543_t *)priv; - ali1543_log("M5229: dev->ide_conf[%02x] = %02x\n", addr, val); - - switch (addr) - { - case 0x09: /* Control */ - if (dev->ide_conf[0x4d] & 0x80) - dev->ide_conf[addr] |= val & 0x8f; - else - dev->ide_conf[addr] = val; - ali5229_ide_handler(dev); - break; - - case 0x10: /* Primary Base Address */ - case 0x11: - case 0x12: - case 0x13: - case 0x14: - - case 0x18: /* Secondary Base Address */ - case 0x19: - case 0x1a: - case 0x1b: - case 0x1c: - - case 0x20: /* Bus Mastering Base Address */ - case 0x21: - case 0x22: - case 0x23: - dev->ide_conf[addr] = val; - ali5229_ide_handler(dev); - break; - - /* The machines don't touch anything beyond that point so we avoid any programming */ - - case 0x2c: /* Subsystem Vendor */ - case 0x2d: - case 0x2e: - case 0x2f: - if (dev->ide_conf[0x53] & 0x80) - dev->ide_conf[addr] = val; - break; - - case 0x4d: - dev->ide_conf[addr] = val & 0x80; - break; - - case 0x4f: - dev->ide_conf[addr] = val & 0x3f; - break; - - case 0x50: /* Configuration */ - dev->ide_conf[addr] = val & 0x2b; - break; - - case 0x51: - dev->ide_conf[addr] = val & 0xf7; - break; - - case 0x53: /* Subsystem Vendor ID */ - dev->ide_conf[addr] = val & 0x8b; - break; - - case 0x58: - dev->ide_conf[addr] = val & 3; - break; - - case 0x59: - case 0x5a: - case 0x5b: - dev->ide_conf[addr] = val & 0x7f; - break; - - case 0x5c: - dev->ide_conf[addr] = val & 3; - break; - - case 0x5d: - case 0x5e: - case 0x5f: - dev->ide_conf[addr] = val & 0x7f; - break; - - default: - dev->ide_conf[addr] = val; - break; - } -} - -static uint8_t -ali5229_read(int func, int addr, void *priv) -{ - ali1543_t *dev = (ali1543_t *)priv; - return dev->ide_conf[addr]; -} - -static void -ali5237_write(int func, int addr, uint8_t val, void *priv) -{ - ali1543_t *dev = (ali1543_t *)priv; - ali1543_log("M5237: dev->usb_conf[%02x] = %02x\n", addr, val); - switch (addr) - { - case 0x04: /* USB Enable */ - dev->usb_conf[addr] = val; - ohci_update_mem_mapping(dev->usb, 0x10, 0x11, 0x12, (dev->usb_conf[0x04] & 1) && (!(dev->pci_conf[0x53] & 0x40))); - break; - - case 0x05: - dev->usb_conf[addr] = 0x03; - break; - - case 0x06: - dev->usb_conf[addr] = 0xc0; - break; - - case 0x11: - case 0x12: - case 0x13: /* USB Base I/O */ - dev->usb_conf[addr] = val; - ohci_update_mem_mapping(dev->usb, 0x11, 0x12, 0x13, (dev->usb_conf[0x04] & 1) && (!(dev->pci_conf[0x53] & 0x40))); - break; - - case 0x42: - dev->usb_conf[addr] = 0x10; - break; - - default: - dev->usb_conf[addr] = val; - break; - } -} - -static uint8_t -ali5237_read(int func, int addr, void *priv) -{ - ali1543_t *dev = (ali1543_t *)priv; - return dev->usb_conf[addr]; -} - -static void -ali7101_write(int func, int addr, uint8_t val, void *priv) -{ - ali1543_t *dev = (ali1543_t *)priv; - ali1543_log("M7101: dev->pmu_conf[%02x] = %02x\n", addr, val); - - switch (addr) - { - case 0x04: /* Enable PMU */ - dev->pmu_conf[addr] = val & 0x1f; - acpi_update_io_mapping(dev->acpi, (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0), (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); - smbus_piix4_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); - break; - - case 0x07: - dev->pmu_conf[addr] = val & 0xfe; - break; - - case 0x10: /* PMU Base I/O */ - case 0x11: - if (addr == 0x10) - dev->pmu_conf[addr] = (val & 0xe0) | 1; - else if (addr == 0x11) - dev->pmu_conf[addr] = val; - - acpi_update_io_mapping(dev->acpi, (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0), (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); - break; - - case 0x14: /* SMBus Base I/O */ - case 0x15: - dev->pmu_conf[addr] = val; - smbus_piix4_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); - break; - - case 0x2c: /* Subsystem Vendor ID */ - case 0x2d: - case 0x2e: - case 0x2f: - if (dev->pmu_conf[0xd8] & 0x10) - dev->pmu_conf[addr] = val; - - case 0x40: - dev->pmu_conf[addr] = val & 0x1f; - break; - - case 0x41: - dev->pmu_conf[addr] = val & 0x10; - break; - - case 0x45: - dev->pmu_conf[addr] = val & 0x9f; - break; - - case 0x46: - dev->pmu_conf[addr] = val & 0x18; - break; - - case 0x48: - dev->pmu_conf[addr] = val & 0x9f; - break; - - case 0x49: - dev->pmu_conf[addr] = val & 0x38; - break; - - case 0x4c: - dev->pmu_conf[addr] = val & 5; - break; - - case 0x4d: - dev->pmu_conf[addr] = val & 1; - break; - - case 0x4e: - dev->pmu_conf[addr] = val & 5; - break; - - case 0x4f: - dev->pmu_conf[addr] = val & 1; - break; - - case 0x55: /* APM Timer */ - dev->pmu_conf[addr] = val & 0x7f; - break; - - case 0x59: - dev->pmu_conf[addr] = val & 0x1f; - break; - - case 0x5b: /* ACPI/SMB Base I/O Control */ - dev->pmu_conf[addr] = val & 0x7f; - break; - - case 0x61: - dev->pmu_conf[addr] = val & 0x13; - break; - - case 0x62: - dev->pmu_conf[addr] = val & 0xf1; - break; - - case 0x63: - dev->pmu_conf[addr] = val & 3; - break; - - case 0x65: - dev->pmu_conf[addr] = val & 0x1f; - break; - - case 0x68: - dev->pmu_conf[addr] = val & 7; - break; - - case 0x6e: - dev->pmu_conf[addr] = val & 0xef; - break; - - case 0x6f: - dev->pmu_conf[addr] = val & 7; - break; - - /* Continue Further Later */ - case 0xc0: /* GPO Registers */ - case 0xc1: - case 0xc2: - case 0xc3: - dev->pmu_conf[addr] = val; - acpi_init_gporeg(dev->acpi, dev->pmu_conf[0xc0], dev->pmu_conf[0xc1], dev->pmu_conf[0xc2], dev->pmu_conf[0xc3]); - break; - - case 0xe0: - dev->pmu_conf[addr] = val; - smbus_piix4_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); - break; - - default: - dev->pmu_conf[addr] = val; - break; - } -} - -static uint8_t -ali7101_read(int func, int addr, void *priv) -{ - ali1543_t *dev = (ali1543_t *)priv; - return dev->pmu_conf[addr]; -} - -void ali1533_sio_fdc_handler(ali1543_t *dev) -{ - fdc_remove(dev->fdc_controller); - if (dev->device_regs[0][0x30] & 1) - { - fdc_set_base(dev->fdc_controller, dev->device_regs[0][0x61] | (dev->device_regs[0][0x60] << 8)); - fdc_set_irq(dev->fdc_controller, dev->device_regs[0][0x70] & 0xf); - fdc_set_dma_ch(dev->fdc_controller, dev->device_regs[0][0x74] & 0x07); - ali1543_log("M1543-SIO FDC: ADDR %04x IRQ %02x DMA %02x\n", dev->device_regs[0][0x61] | (dev->device_regs[0][0x60] << 8), dev->device_regs[0][0x70] & 0xf, dev->device_regs[0][0x74] & 0x07); - } -} - -void ali1533_sio_uart_handler(int num, ali1543_t *dev) -{ - serial_remove(dev->uart[num]); - if (dev->device_regs[num + 4][0x30] & 1) - { - serial_setup(dev->uart[num], dev->device_regs[num + 4][0x61] | (dev->device_regs[num + 4][0x60] << 8), dev->device_regs[num + 4][0x70] & 0xf); - ali1543_log("M1543-SIO UART%d: ADDR %04x IRQ %02x\n", num, dev->device_regs[num + 4][0x61] | (dev->device_regs[num + 4][0x60] << 8), dev->device_regs[num + 4][0x70] & 0xf); - } -} - -void ali1533_sio_lpt_handler(ali1543_t *dev) -{ - lpt1_remove(); - if (dev->device_regs[3][0x30] & 1) - { - lpt1_init(dev->device_regs[3][0x61] | (dev->device_regs[3][0x60] << 8)); - lpt1_irq(dev->device_regs[3][0x70] & 0xf); - ali1543_log("M1543-SIO LPT: ADDR %04x IRQ %02x\n", dev->device_regs[3][0x61] | (dev->device_regs[3][0x60] << 8), dev->device_regs[3][0x70] & 0xf); - } -} - -void ali1533_sio_ldn(uint16_t ldn, ali1543_t *dev) -{ - /* We don't include all LDN's */ - switch (ldn) - { - case 0: /* FDC */ - ali1533_sio_fdc_handler(dev); - break; - case 3: /* LPT */ - ali1533_sio_lpt_handler(dev); - break; - case 4: /* UART */ - case 5: - ali1533_sio_uart_handler(ldn - 4, dev); - break; - } -} - -static void -ali1533_sio_write(uint16_t addr, uint8_t val, void *priv) -{ - ali1543_t *dev = (ali1543_t *)priv; - - switch (addr) - { - case 0x3f0: - dev->sio_index = val; - if (dev->sio_index == 0x51) - { - dev->in_configuration_mode = 1; - } - else if (dev->sio_index == 0xbb) - dev->in_configuration_mode = 0; - break; - - case 0x3f1: - if (dev->in_configuration_mode) - { - switch (dev->sio_index) - { - case 0x07: - dev->sio_regs[dev->sio_index] = val & 0x7; - break; - - case 0x22: - dev->sio_regs[dev->sio_index] = val & 0x39; - break; - - case 0x23: - dev->sio_regs[dev->sio_index] = val & 0x38; - break; - - default: - if ((dev->sio_index < 0x30) || (dev->sio_index == 0x51) || (dev->sio_index == 0xbb)) - dev->sio_regs[dev->sio_index] = val; - else if (dev->sio_regs[0x07] <= 7) - dev->device_regs[dev->sio_regs[0x07]][dev->sio_index] = val; - break; - } - } - break; - } - - if ((!dev->in_configuration_mode) && (dev->sio_regs[0x07] <= 7) && (addr == 0x03f0)) - { - ali1533_sio_ldn(dev->sio_regs[0x07], dev); - } -} - -static uint8_t -ali1533_sio_read(uint16_t addr, void *priv) -{ - ali1543_t *dev = (ali1543_t *)priv; - if (dev->sio_index >= 0x30) - return dev->device_regs[dev->sio_regs[0x07]][dev->sio_index]; - else - return dev->sio_regs[dev->sio_index]; -} - -static void -ali1543_reset(void *priv) -{ - ali1543_t *dev = (ali1543_t *)priv; - - /* M1533 */ - dev->pci_conf[0x00] = 0xb9; - dev->pci_conf[0x01] = 0x10; - dev->pci_conf[0x02] = 0x33; - dev->pci_conf[0x03] = 0x15; - dev->pci_conf[0x04] = 0x0f; - dev->pci_conf[0x08] = 0xb4; - dev->pci_conf[0x0a] = 0x01; - dev->pci_conf[0x0b] = 0x06; - - ali1533_write(0, 0x48, 0x00, dev); // Disables all IRQ's - ali1533_write(0, 0x44, 0x00, dev); - ali1533_write(0, 0x74, 0x00, dev); - ali1533_write(0, 0x75, 0x00, dev); - ali1533_write(0, 0x76, 0x00, dev); - /* M5229 */ + memset(dev->ide_conf, 0x00, sizeof(dev->pmu_conf)); dev->ide_conf[0x00] = 0xb9; dev->ide_conf[0x01] = 0x10; dev->ide_conf[0x02] = 0x29; @@ -794,7 +594,6 @@ ali1543_reset(void *priv) dev->ide_conf[0x06] = 0x80; dev->ide_conf[0x07] = 0x02; dev->ide_conf[0x08] = 0x20; - dev->ide_conf[0x09] = 0xfa; dev->ide_conf[0x0a] = 0x01; dev->ide_conf[0x0b] = 0x01; dev->ide_conf[0x10] = 0xf1; @@ -806,10 +605,11 @@ ali1543_reset(void *priv) dev->ide_conf[0x1a] = 0x75; dev->ide_conf[0x1b] = 0x03; dev->ide_conf[0x20] = 0x01; - dev->ide_conf[0x23] = 0xf0; + dev->ide_conf[0x21] = 0xf0; dev->ide_conf[0x3d] = 0x01; - dev->ide_conf[0x3c] = 0x02; - dev->ide_conf[0x3d] = 0x03; + dev->ide_conf[0x3e] = 0x02; + dev->ide_conf[0x3f] = 0x04; + dev->ide_conf[0x53] = 0x03; dev->ide_conf[0x54] = 0x55; dev->ide_conf[0x55] = 0x55; dev->ide_conf[0x63] = 0x01; @@ -817,13 +617,772 @@ ali1543_reset(void *priv) dev->ide_conf[0x67] = 0x01; dev->ide_conf[0x78] = 0x21; + ali5229_write(0, 0x04, 0x01, dev); + ali5229_write(0, 0x10, 0xf1, dev); + ali5229_write(0, 0x11, 0x01, dev); + ali5229_write(0, 0x14, 0xf5, dev); + ali5229_write(0, 0x15, 0x03, dev); + ali5229_write(0, 0x18, 0x71, dev); + ali5229_write(0, 0x19, 0x01, dev); + ali5229_write(0, 0x1a, 0x75, dev); + ali5229_write(0, 0x1b, 0x03, dev); + ali5229_write(0, 0x20, 0x01, dev); + ali5229_write(0, 0x21, 0xf0, dev); + ali5229_write(0, 0x4d, 0x00, dev); + dev->ide_conf[0x09] = 0xfa; + ali5229_write(0, 0x09, 0xfa, dev); + ali5229_write(0, 0x52, 0x00, dev); + + ali5229_write(0, 0x50, 0x00, dev); + sff_set_slot(dev->ide_controller[0], dev->ide_slot); sff_set_slot(dev->ide_controller[1], dev->ide_slot); sff_bus_master_reset(dev->ide_controller[0], (dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)); sff_bus_master_reset(dev->ide_controller[1], ((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)) + 8); ali5229_ide_handler(dev); +} + + +static void +ali5229_write(int func, int addr, uint8_t val, void *priv) +{ + ali1543_t *dev = (ali1543_t *)priv; + ali1543_log("M5229: dev->ide_conf[%02x] = %02x\n", addr, val); + + if (func > 0) + return; + + if (!dev->ide_dev_enable) + return; + + switch (addr) { + case 0x04: /* COM - Command Register */ + ali1543_log("IDE04: %02X\n", val); + dev->ide_conf[addr] = val & 0x45; + ali5229_ide_handler(dev); + break; + + case 0x05: + dev->ide_conf[addr] = val & 0x01; + break; + + case 0x07: + dev->ide_conf[addr] &= ~(val & 0xf1); + break; + + case 0x09: /* Control */ + ali1543_log("IDE09: %02X\n", val); +#ifdef M1543_C + val &= ~(dev->ide_conf[0x43]); + val |= (dev->ide_conf[addr] & dev->ide_conf[0x43]); +#endif + if (dev->ide_conf[0x4d] & 0x80) + dev->ide_conf[addr] = (dev->ide_conf[addr] & 0xfa) | (val & 0x05); + else + dev->ide_conf[addr] = (dev->ide_conf[addr] & 0x8a) | (val & 0x75); + ali5229_ide_handler(dev); + ali5229_ide_irq_handler(dev); + break; + + /* Primary Base Address */ + case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: + + /* Secondary Base Address */ + case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: + + /* Bus Mastering Base Address */ + case 0x20: case 0x21: case 0x22: case 0x23: + dev->ide_conf[addr] = val; + ali5229_ide_handler(dev); + break; + + case 0x2c: /* Subsystem Vendor ID */ + case 0x2d: + case 0x2e: + case 0x2f: + if (!(dev->ide_conf[0x53] & 0x80)) + dev->ide_conf[addr] = val; + break; + + case 0x3c: /* Interrupt Line */ + case 0x3d: /* Interrupt Pin */ + dev->ide_conf[addr] = val; + break; + + /* The machines don't touch anything beyond that point so we avoid any programming */ +#ifdef M1543_C + case 0x43: + dev->ide_conf[addr] = val & 0x7f; + break; +#endif + + case 0x4d: + dev->ide_conf[addr] = val & 0x80; + break; + + case 0x4f: + dev->ide_conf[addr] = val & 0x3f; + break; + + case 0x50: /* Configuration */ + ali1543_log("IDE50: %02X\n", val); + dev->ide_conf[addr] = val & 0x2b; + dev->ide_dev_enable = !!(val & 0x01); + break; + + case 0x51: + dev->ide_conf[addr] = val & 0xf7; + if (val & 0x80) + ali5229_chip_reset(dev); + else if (val & 0x40) { + sff_bus_master_reset(dev->ide_controller[0], (dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)); + sff_bus_master_reset(dev->ide_controller[1], ((dev->ide_conf[0x20] & 0xf0) | (dev->ide_conf[0x21] << 8)) + 8); + } + break; + + case 0x52: /* FCS - Flexible Channel Setting Register */ + dev->ide_conf[addr] = val; + ali5229_ide_handler(dev); + ali5229_ide_irq_handler(dev); + break; + + case 0x53: /* Subsystem Vendor ID */ + dev->ide_conf[addr] = val & 0x8b; + break; + + case 0x54: /* FIFO threshold of primary channel drive 0 and drive 1 */ + case 0x55: /* FIFO threshold of secondary channel drive 0 and drive 1 */ + case 0x56: /* Ultra DMA /33 setting for Primary drive 0 and drive 1 */ + case 0x57: /* Ultra DMA /33 setting for Secondary drive 0 and drive 1 */ + case 0x78: /* IDE clock's frequency (default value is 33 = 21H) */ + dev->ide_conf[addr] = val; + break; + + case 0x58: + dev->ide_conf[addr] = val & 3; + break; + + case 0x59: case 0x5a: + case 0x5b: + dev->ide_conf[addr] = val & 0x7f; + break; + + case 0x5c: + dev->ide_conf[addr] = val & 3; + break; + + case 0x5d: case 0x5e: + case 0x5f: + dev->ide_conf[addr] = val & 0x7f; + break; + } +} + + +static uint8_t +ali5229_read(int func, int addr, void *priv) +{ + ali1543_t *dev = (ali1543_t *)priv; + uint8_t ret = 0xff; + + if (dev->ide_dev_enable && (func == 0)) { + ret = dev->ide_conf[addr]; + if ((addr == 0x09) && !(dev->ide_conf[0x50] & 0x02)) + ret &= 0x0f; + else if (addr == 0x50) + ret = (ret & 0xfe) | (dev->ide_dev_enable ? 0x01 : 0x00); + else if (addr == 0x75) + ret = ide_read_ali_75(); + else if (addr == 0x76) + ret = ide_read_ali_76(); + } + + return ret; +} + + +static void +ali5237_write(int func, int addr, uint8_t val, void *priv) +{ + ali1543_t *dev = (ali1543_t *)priv; + ali1543_log("M5237: dev->usb_conf[%02x] = %02x\n", addr, val); + + if (func > 0) + return; + + if (!dev->usb_dev_enable) + return; + + switch (addr) { + case 0x04: /* USB Enable */ + dev->usb_conf[addr] = val & 0x5f; + ohci_update_mem_mapping(dev->usb, dev->usb_conf[0x11], dev->usb_conf[0x12], dev->usb_conf[0x13], dev->usb_conf[0x04] & 1); + break; + + case 0x05: + dev->usb_conf[addr] = 0x01; + break; + + case 0x07: + dev->usb_conf[addr] &= ~(val & 0xc9); + break; + + case 0x0c: /* Cache Line Size */ + case 0x0d: /* Latency Timer */ + case 0x3c: /* Interrupt Line Register */ + case 0x40 ... 0x43: /* Test Mode Register */ + dev->usb_conf[addr] = val; + break; + + /* USB Base I/O */ + case 0x11: + dev->usb_conf[addr] = val & 0xf0; + ohci_update_mem_mapping(dev->usb, dev->usb_conf[0x11], dev->usb_conf[0x12], dev->usb_conf[0x13], dev->usb_conf[0x04] & 1); + break; + case 0x12: case 0x13: + dev->usb_conf[addr] = val; + ohci_update_mem_mapping(dev->usb, dev->usb_conf[0x11], dev->usb_conf[0x12], dev->usb_conf[0x13], dev->usb_conf[0x04] & 1); + break; + + case 0x2c: /* Subsystem Vendor ID */ + case 0x2d: + case 0x2e: + case 0x2f: + if (!(dev->usb_conf[0x42] & 0x10)) + dev->usb_conf[addr] = val; + break; + } +} + + +static uint8_t +ali5237_read(int func, int addr, void *priv) +{ + ali1543_t *dev = (ali1543_t *)priv; + uint8_t ret = 0xff; + + if (dev->usb_dev_enable && (func == 0)) + ret = dev->usb_conf[addr]; + + return ret; +} + + +static void +ali7101_write(int func, int addr, uint8_t val, void *priv) +{ + ali1543_t *dev = (ali1543_t *)priv; + ali1543_log("M7101: dev->pmu_conf[%02x] = %02x\n", addr, val); + + if (func > 0) + return; + + if (!dev->pmu_dev_enable) + return; + + if ((dev->pmu_conf[0xc9] & 0x01) && (addr >= 0x40) && (addr != 0xc9)) + return; + + switch (addr) { + case 0x04: /* Enable PMU */ + ali1543_log("PMU04: %02X\n", val); + dev->pmu_conf[addr] = val & 0x01; + acpi_update_io_mapping(dev->acpi, (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0), dev->pmu_conf[0x04] & 1); + smbus_piix4_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1)); + break; + + /* PMU Base I/O */ + case 0x10: case 0x11: + if (!(dev->pmu_conf[0x5b] & 0x02)) { + if (addr == 0x10) + dev->pmu_conf[addr] = (val & 0xc0) | 1; + else if (addr == 0x11) + dev->pmu_conf[addr] = val; + + acpi_update_io_mapping(dev->acpi, (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0), dev->pmu_conf[0x04] & 1); + } + break; + + /* SMBus Base I/O */ + case 0x14: case 0x15: + if (!(dev->pmu_conf[0x5b] & 0x04)) { + if (addr == 0x14) + dev->pmu_conf[addr] = (val & 0xe0) | 1; + else if (addr == 0x15) + dev->pmu_conf[addr] = val; + + smbus_piix4_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1)); + } + break; + + /* Subsystem Vendor ID */ + case 0x2c: case 0x2d: case 0x2e: case 0x2f: + if (!(dev->pmu_conf[0xd8] & 0x08)) + dev->pmu_conf[addr] = val; + break; + + case 0x40: + dev->pmu_conf[addr] = val & 0x1f; + pic_set_smi_irq_mask(8, (dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x40] & 0x03)); + break; + case 0x41: + dev->pmu_conf[addr] = val & 0x10; + ali1543_log("PMU41: %02X\n", val); + apm_set_do_smi(dev->acpi->apm, (dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x41] & 0x10)); + break; + + /* TODO: Is the status R/W or R/WC? */ + case 0x42: + dev->pmu_conf[addr] &= ~(val & 0x1f); + break; + case 0x43: + dev->pmu_conf[addr] &= ~(val & 0x10); + if (val & 0x10) + acpi_ali_soft_smi_status_write(dev->acpi, 0); + break; + + case 0x44: + dev->pmu_conf[addr] = val; + break; + case 0x45: + dev->pmu_conf[addr] = val & 0x9f; + break; + case 0x46: + dev->pmu_conf[addr] = val & 0x18; + break; + + /* TODO: Is the status R/W or R/WC? */ + case 0x48: + dev->pmu_conf[addr] &= ~val; + break; + case 0x49: + dev->pmu_conf[addr] &= ~(val & 0x9f); + break; + case 0x4a: + dev->pmu_conf[addr] &= ~(val & 0x38); + break; + + case 0x4c: + dev->pmu_conf[addr] = val & 5; + break; + case 0x4d: + dev->pmu_conf[addr] = val & 1; + break; + + /* TODO: Is the status R/W or R/WC? */ + case 0x4e: + dev->pmu_conf[addr] &= ~(val & 5); + break; + case 0x4f: + dev->pmu_conf[addr] &= ~(val & 1); + break; + + case 0x54: /* Standby timer */ + dev->pmu_conf[addr] = val; + break; + case 0x55: /* APM Timer */ + dev->pmu_conf[addr] = val & 0x7f; + break; + case 0x59: /* Global display timer. */ + dev->pmu_conf[addr] = val & 0x1f; + break; + + case 0x5b: /* ACPI/SMB Base I/O Control */ + dev->pmu_conf[addr] = val & 0x7f; + break; + + case 0x60: + dev->pmu_conf[addr] = val; + break; + case 0x61: + dev->pmu_conf[addr] = val & 0x13; + break; + case 0x62: + dev->pmu_conf[addr] = val & 0xf1; + break; + case 0x63: + dev->pmu_conf[addr] = val & 0x07; + break; + + case 0x64: + dev->pmu_conf[addr] = val; + break; + case 0x65: + dev->pmu_conf[addr] = val & 0x11; + break; + + case 0x68: + dev->pmu_conf[addr] = val & 0x07; + break; + + case 0x6c: case 0x6d: + dev->pmu_conf[addr] = val; + break; + case 0x6e: + dev->pmu_conf[addr] = val & 0xbf; + break; + case 0x6f: + dev->pmu_conf[addr] = val & 0x1f; + break; + + case 0x70: + dev->pmu_conf[addr] = val; + break; + case 0x71: + dev->pmu_conf[addr] = val & 0x3f; + break; + + case 0x72: + dev->pmu_conf[addr] = val & 0x0f; + break; + + /* TODO: Is the status R/W or R/WC? */ + case 0x74: + dev->pmu_conf[addr] &= ~(val & 0x33); + break; + + case 0x75: + dev->pmu_conf[addr] = val; + break; + + case 0x76: + dev->pmu_conf[addr] = val & 0x7f; + break; + + case 0x77: + /* TODO: If bit 1 is clear, then status bit is set even if SMI is disabled. */ + dev->pmu_conf[addr] = val; + pic_set_smi_irq_mask(8, (dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x40] & 0x03)); + ali1543_log("PMU77: %02X\n", val); + apm_set_do_smi(dev->acpi->apm, (dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x41] & 0x10)); + break; + + case 0x78: + dev->pmu_conf[addr] = val; + break; + case 0x79: + dev->pmu_conf[addr] = val & 0x0f; + break; + + case 0x7a: + dev->pmu_conf[addr] = val & 0x02; + break; + + case 0x7b: + dev->pmu_conf[addr] = val & 0x7f; + break; + + case 0x7c ... 0x7f: + dev->pmu_conf[addr] = val; + break; + + case 0x81: + dev->pmu_conf[addr] = val & 0xf0; + break; + + case 0x8c: case 0x8d: + dev->pmu_conf[addr] = val & 0x0f; + break; + + case 0x90: + dev->pmu_conf[addr] = val & 0x01; + break; + + case 0x94: + dev->pmu_conf[addr] = val & 0xf0; + break; + case 0x95 ... 0x97: + dev->pmu_conf[addr] = val; + break; + + case 0xa4: case 0xa5: + dev->pmu_conf[addr] = val; + break; + + case 0xb2: + dev->pmu_conf[addr] = val & 0x01; + break; + + case 0xb3: + dev->pmu_conf[addr] = val & 0x7f; + break; + + case 0xb4: + dev->pmu_conf[addr] = val & 0x7c; + break; + + case 0xb5: case 0xb7: + dev->pmu_conf[addr] = val & 0x0f; + break; + + case 0xbc: + outb(0x70, val); + break; + + case 0xbd: + dev->pmu_conf[addr] = val & 0x0f; + acpi_set_timer32(dev->acpi, val & 0x04); + break; + + case 0xbe: + dev->pmu_conf[addr] = val & 0x03; + break; + + /* Continue Further Later */ + /* GPO Registers */ + case 0xc0: + dev->pmu_conf[addr] = val & 0x0f; + acpi_init_gporeg(dev->acpi, dev->pmu_conf[0xc0], dev->pmu_conf[0xc1], dev->pmu_conf[0xc2] | (dev->pmu_conf[0xc3] << 5), 0x00); + break; + case 0xc1: + dev->pmu_conf[addr] = val & 0x12; + acpi_init_gporeg(dev->acpi, dev->pmu_conf[0xc0], dev->pmu_conf[0xc1], dev->pmu_conf[0xc2] | (dev->pmu_conf[0xc3] << 5), 0x00); + break; + case 0xc2: + dev->pmu_conf[addr] = val & 0x1c; + acpi_init_gporeg(dev->acpi, dev->pmu_conf[0xc0], dev->pmu_conf[0xc1], dev->pmu_conf[0xc2] | (dev->pmu_conf[0xc3] << 5), 0x00); + break; + case 0xc3: + dev->pmu_conf[addr] = val & 0x06; + acpi_init_gporeg(dev->acpi, dev->pmu_conf[0xc0], dev->pmu_conf[0xc1], dev->pmu_conf[0xc2] | (dev->pmu_conf[0xc3] << 5), 0x00); + break; + + case 0xc6: + dev->pmu_conf[addr] = val & 0x06; + break; + + case 0xc8: case 0xc9: + dev->pmu_conf[addr] = val & 0x01; + break; + + case 0xca: + /* TODO: Write to this port causes a beep. */ + dev->pmu_conf[addr] = val; + break; + + case 0xd4: + dev->pmu_conf[addr] = val & 0x01; + break; + + case 0xd8: + dev->pmu_conf[addr] = val & 0xfd; + break; + + case 0xe0: + dev->pmu_conf[addr] = val & 0x03; + smbus_piix4_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); + break; + + case 0xe1: + dev->pmu_conf[addr] = val; + break; + + case 0xe2: + dev->pmu_conf[addr] = val & 0xf8; + break; + + default: + dev->pmu_conf[addr] = val; + break; + } +} + + +static uint8_t +ali7101_read(int func, int addr, void *priv) +{ + ali1543_t *dev = (ali1543_t *)priv; + uint8_t ret = 0xff; + + if (dev->pmu_dev_enable && (func == 0)) { + if ((dev->pmu_conf[0xc9] & 0x01) && (addr >= 0x40) && (addr != 0xc9)) + return 0xff; + + /* TODO: C4, C5 = GPIREG (masks: 0D, 0E) */ + if (addr == 0x43) + ret = acpi_ali_soft_smi_status_read(dev->acpi) ? 0x10 : 0x00; + else if (addr == 0xbc) + ret = inb(0x70); + else + ret = dev->pmu_conf[addr]; + + if (dev->pmu_conf[0x77] & 0x10) { + switch (addr) { + case 0x42: + dev->pmu_conf[addr] &= 0xe0; + break; + case 0x43: + dev->pmu_conf[addr] &= 0xef; + acpi_ali_soft_smi_status_write(dev->acpi, 0); + break; + + case 0x48: + dev->pmu_conf[addr] = 0x00; + break; + case 0x49: + dev->pmu_conf[addr] &= 0x60; + break; + case 0x4a: + dev->pmu_conf[addr] &= 0xc7; + break; + + case 0x4e: + dev->pmu_conf[addr] &= 0xfa; + break; + case 0x4f: + dev->pmu_conf[addr] &= 0xfe; + break; + + case 0x74: + dev->pmu_conf[addr] &= 0xcc; + break; + } + } + } + + return ret; +} + + +static void +ali1533_sio_fdc_handler(ali1543_t *dev) +{ + fdc_remove(dev->fdc_controller); + + if (dev->device_regs[0][0x30] & 1) { + ali1543_log("New FDC base address: %04X\n", dev->device_regs[0][0x61] | (dev->device_regs[0][0x60] << 8)); + fdc_set_base(dev->fdc_controller, dev->device_regs[0][0x61] | (dev->device_regs[0][0x60] << 8)); + fdc_set_irq(dev->fdc_controller, dev->device_regs[0][0x70] & 0xf); + fdc_set_dma_ch(dev->fdc_controller, dev->device_regs[0][0x74] & 0x07); + ali1543_log("M1543-SIO FDC: ADDR %04x IRQ %02x DMA %02x\n", dev->device_regs[0][0x61] | (dev->device_regs[0][0x60] << 8), dev->device_regs[0][0x70] & 0xf, dev->device_regs[0][0x74] & 0x07); + } +} + + +static void +ali1533_sio_uart_handler(int num, ali1543_t *dev) +{ + serial_remove(dev->uart[num]); + + if (dev->device_regs[num + 4][0x30] & 1) { + serial_setup(dev->uart[num], dev->device_regs[num + 4][0x61] | (dev->device_regs[num + 4][0x60] << 8), dev->device_regs[num + 4][0x70] & 0xf); + ali1543_log("M1543-SIO UART%d: ADDR %04x IRQ %02x\n", num, dev->device_regs[num + 4][0x61] | (dev->device_regs[num + 4][0x60] << 8), dev->device_regs[num + 4][0x70] & 0xf); + } +} + + +void +ali1533_sio_lpt_handler(ali1543_t *dev) +{ + lpt1_remove(); + + if (dev->device_regs[3][0x30] & 1) { + lpt1_init(dev->device_regs[3][0x61] | (dev->device_regs[3][0x60] << 8)); + lpt1_irq(dev->device_regs[3][0x70] & 0xf); + ali1543_log("M1543-SIO LPT: ADDR %04x IRQ %02x\n", dev->device_regs[3][0x61] | (dev->device_regs[3][0x60] << 8), dev->device_regs[3][0x70] & 0xf); + } +} + + +void +ali1533_sio_ldn(uint16_t ldn, ali1543_t *dev) +{ + /* We don't include all LDN's */ + switch (ldn) { + case 0: /* FDC */ + ali1533_sio_fdc_handler(dev); + break; + case 3: /* LPT */ + ali1533_sio_lpt_handler(dev); + break; + /* UART */ + case 4: case 5: + ali1533_sio_uart_handler(ldn - 4, dev); + break; + } +} + + +static void +ali1533_sio_write(uint16_t addr, uint8_t val, void *priv) +{ + ali1543_t *dev = (ali1543_t *)priv; + + switch (addr) { + case 0x3f0: + dev->sio_index = val; + if (dev->sio_index == 0x51) + dev->in_configuration_mode = 1; + else if ((dev->sio_index == 0x23) && (dev->in_configuration_mode == 1)) + dev->in_configuration_mode = 2; + else if (dev->sio_index == 0xbb) + dev->in_configuration_mode = 0; + break; + + case 0x3f1: + if (dev->in_configuration_mode == 2) { + switch (dev->sio_index) { + case 0x07: + dev->sio_regs[dev->sio_index] = val & 0x7; + break; + + case 0x22: + dev->sio_regs[dev->sio_index] = val & 0x39; + break; + + case 0x23: + dev->sio_regs[dev->sio_index] = val & 0x38; + break; + + default: + if ((dev->sio_index < 0x30) || (dev->sio_index == 0x51) || (dev->sio_index == 0xbb)) + dev->sio_regs[dev->sio_index] = val; + else if (dev->sio_regs[0x07] <= 7) + dev->device_regs[dev->sio_regs[0x07]][dev->sio_index] = val; + break; + } + } + break; + } + + if ((!dev->in_configuration_mode) && (dev->sio_regs[0x07] <= 7) && (addr == 0x03f0)) + ali1533_sio_ldn(dev->sio_regs[0x07], dev); +} + + +static uint8_t +ali1533_sio_read(uint16_t addr, void *priv) +{ + ali1543_t *dev = (ali1543_t *)priv; + uint8_t ret = 0xff; + + if (addr == 0x03f1) { + if (dev->sio_index >= 0x30) + ret = dev->device_regs[dev->sio_regs[0x07]][dev->sio_index]; + else + ret = dev->sio_regs[dev->sio_index]; + } + + return ret; +} + + +static void +ali1543_reset(void *priv) +{ + ali1543_t *dev = (ali1543_t *)priv; + int i; + + /* Temporarily enable everything. Register writes will disable the devices. */ + dev->ide_dev_enable = 1; + dev->usb_dev_enable = 1; + dev->pmu_dev_enable = 1; + + /* M5229 */ + ali5229_chip_reset(dev); /* M5237 */ + memset(dev->usb_conf, 0x00, sizeof(dev->pmu_conf)); dev->usb_conf[0x00] = 0xb9; dev->usb_conf[0x01] = 0x10; dev->usb_conf[0x02] = 0x37; @@ -837,24 +1396,73 @@ ali1543_reset(void *priv) dev->usb_conf[0x3d] = 0x01; ali5237_write(0, 0x04, 0x00, dev); + ali5237_write(0, 0x10, 0x00, dev); + ali5237_write(0, 0x11, 0x00, dev); + ali5237_write(0, 0x12, 0x00, dev); + ali5237_write(0, 0x13, 0x00, dev); /* M7101 */ + memset(dev->pmu_conf, 0x00, sizeof(dev->pmu_conf)); dev->pmu_conf[0x00] = 0xb9; dev->pmu_conf[0x01] = 0x10; dev->pmu_conf[0x02] = 0x01; dev->pmu_conf[0x03] = 0x71; - dev->pmu_conf[0x04] = 0x0f; dev->pmu_conf[0x05] = 0x00; dev->pmu_conf[0x0a] = 0x01; dev->pmu_conf[0x0b] = 0x06; + dev->pmu_conf[0xe2] = 0x20; acpi_set_slot(dev->acpi, dev->pmu_slot); acpi_set_nvr(dev->acpi, dev->nvr); - ali7101_write(0, 0x04, 0x00, dev); + ali7101_write(0, 0x04, 0x0f, dev); + ali7101_write(0, 0x10, 0x01, dev); + ali7101_write(0, 0x11, 0x00, dev); + ali7101_write(0, 0x12, 0x00, dev); + ali7101_write(0, 0x13, 0x00, dev); + ali7101_write(0, 0x14, 0x01, dev); + ali7101_write(0, 0x15, 0x00, dev); + ali7101_write(0, 0x16, 0x00, dev); + ali7101_write(0, 0x17, 0x00, dev); + ali7101_write(0, 0x40, 0x00, dev); + ali7101_write(0, 0x41, 0x00, dev); + ali7101_write(0, 0x42, 0x00, dev); + ali7101_write(0, 0x43, 0x00, dev); + ali7101_write(0, 0x77, 0x00, dev); + ali7101_write(0, 0xbd, 0x00, dev); ali7101_write(0, 0xc0, 0x00, dev); + ali7101_write(0, 0xc1, 0x00, dev); + ali7101_write(0, 0xc2, 0x00, dev); + ali7101_write(0, 0xc3, 0x00, dev); + ali7101_write(0, 0xe0, 0x00, dev); + + /* Do the bridge last due to device deactivations. */ + /* M1533 */ + dev->pci_conf[0x00] = 0xb9; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x33; + dev->pci_conf[0x03] = 0x15; + dev->pci_conf[0x04] = 0x0f; + dev->pci_conf[0x07] = 0x02; + dev->pci_conf[0x0a] = 0x01; + dev->pci_conf[0x0b] = 0x06; + + ali1533_write(0, 0x48, 0x00, dev); // Disables all IRQ's + ali1533_write(0, 0x44, 0x00, dev); + ali1533_write(0, 0x4d, 0x00, dev); + ali1533_write(0, 0x53, 0x00, dev); + ali1533_write(0, 0x58, 0x00, dev); + ali1533_write(0, 0x5f, 0x00, dev); + ali1533_write(0, 0x72, 0x00, dev); + ali1533_write(0, 0x74, 0x00, dev); + ali1533_write(0, 0x75, 0x00, dev); + ali1533_write(0, 0x76, 0x00, dev); /* M1543 Super I/O */ + memset(dev->sio_regs, 0x00, sizeof(dev->sio_regs)); + for (i = 0; i < 8; i++) + memset(dev->device_regs[i], 0x00, sizeof(dev->device_regs[i])); + dev->device_regs[0][0x60] = 0x03; dev->device_regs[0][0x61] = 0xf0; dev->device_regs[0][0x70] = 0x06; @@ -887,8 +1495,11 @@ ali1543_reset(void *priv) ali1533_sio_uart_handler(0, dev); ali1533_sio_uart_handler(1, dev); ali1533_sio_lpt_handler(dev); + + unmask_a20_in_smm = 1; } + static void ali1543_close(void *priv) { @@ -897,6 +1508,7 @@ ali1543_close(void *priv) free(dev); } + static void * ali1543_init(const device_t *info) { @@ -912,7 +1524,7 @@ ali1543_init(const device_t *info) /* Device 0C: M7101 Power Managment Controller */ dev->pmu_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, ali7101_read, ali7101_write, dev); - /* Device 0D: M5237 USB */ + /* Device 0F: M5237 USB */ dev->usb_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, ali5237_read, ali5237_write, dev); /* Ports 3F0-1h: M1543 Super I/O */ @@ -920,20 +1532,24 @@ ali1543_init(const device_t *info) /* ACPI */ dev->acpi = device_add(&acpi_ali_device); - dev->nvr = device_add(&at_nvr_device); // Generic NVR + dev->nvr = device_add(&piix4_nvr_device); /* APM */ - dev->apm = device_add(&apm_pci_device); + // dev->apm = device_add(&apm_pci_device); /* DMA */ dma_alias_set(); + + dma_set_sg_base(0x04); + dma_set_params(1, 0xffffffff); + dma_ext_mode_init(); dma_high_page_init(); /* DDMA */ dev->ddma = device_add(&ddma_device); /* Floppy Disk Controller */ - dev->fdc_controller = device_add(&fdc_at_device); + dev->fdc_controller = device_add(&fdc_at_smc_device); /* IDE Controllers */ dev->ide_controller[0] = device_add_inst(&sff8038i_device, 1); @@ -950,16 +1566,25 @@ ali1543_init(const device_t *info) dev->smbus = device_add(&piix4_smbus_device); /* Super I/O Configuration Mechanism */ - dev->in_configuration_mode = 1; + dev->in_configuration_mode = 0; /* USB */ dev->usb = device_add(&usb_device); + pci_enable_mirq(0); + pci_enable_mirq(1); + pci_enable_mirq(2); + pci_enable_mirq(3); + pci_enable_mirq(4); + pci_enable_mirq(5); + pci_enable_mirq(6); + ali1543_reset(dev); return dev; } + const device_t ali1543_device = { "ALi M1543 Desktop South Bridge", DEVICE_PCI, @@ -967,7 +1592,8 @@ const device_t ali1543_device = { ali1543_init, ali1543_close, ali1543_reset, - {NULL}, + { NULL }, NULL, NULL, - NULL}; + NULL +}; diff --git a/src/chipset/opti391.c b/src/chipset/opti391.c new file mode 100644 index 000000000..f6b1f2686 --- /dev/null +++ b/src/chipset/opti391.c @@ -0,0 +1,226 @@ +/* + * 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 OPTi 82C391/392 chipset. + * + * Authors: Miran Grca, + * + * Copyright 2021 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/mem.h> +#include <86box/chipset.h> + + +#ifdef ENABLE_OPTI391_LOG +int opti391_do_log = ENABLE_OPTI391_LOG; + +static void +opti391_log(const char *fmt, ...) +{ + va_list ap; + + if (opti391_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define opti391_log(fmt, ...) +#endif + + +typedef struct +{ + uint32_t phys, virt; +} mem_remapping_t; + + +typedef struct +{ + uint8_t index, regs[256]; +} opti391_t; + + +static void +opti391_shadow_recalc(opti391_t *dev) +{ + uint32_t i, base; + uint8_t sh_enable, sh_master; + uint8_t sh_wp, sh_write_internal; + + shadowbios = shadowbios_write = 0; + + /* F0000-FFFFF */ + sh_enable = !(dev->regs[0x22] & 0x80); + if (sh_enable) + mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + else + mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + + sh_write_internal = (dev->regs[0x26] & 0x40); + /* D0000-EFFFF */ + for (i = 0; i < 8; i++) { + base = 0xd0000 + (i << 14); + if (base >= 0xe0000) { + sh_master = (dev->regs[0x22] & 0x40); + sh_wp = (dev->regs[0x22] & 0x10); + } else { + sh_master = (dev->regs[0x22] & 0x20); + sh_wp = (dev->regs[0x22] & 0x08); + } + sh_enable = dev->regs[0x23] & (1 << i); + + if (sh_master) { + if (sh_enable) { + if (sh_wp) + mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + else + mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } else if (sh_write_internal) + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + else + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + } else if (sh_write_internal) + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + else + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + } + + /* C0000-CFFFF */ + sh_master = !(dev->regs[0x26] & 0x10); + sh_wp = (dev->regs[0x26] & 0x20); + for (i = 0; i < 4; i++) { + base = 0xc0000 + (i << 14); + sh_enable = dev->regs[0x26] & (1 << i); + + if (sh_master) { + if (sh_enable) { + if (sh_wp) + mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + else + mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } else if (sh_write_internal) + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + else + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + } else if (sh_write_internal) + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + else + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + } +} + + +static void +opti391_write(uint16_t addr, uint8_t val, void *priv) +{ + opti391_t *dev = (opti391_t *)priv; + + switch (addr) { + case 0x22: + dev->index = val; + break; + + case 0x24: + opti391_log("OPTi 391: dev->regs[%02x] = %02x\n", dev->index, val); + + switch (dev->index) { + case 0x20: + dev->regs[dev->index] = (dev->regs[dev->index] & 0xc0) | (val & 0x3f); + break; + + case 0x21: case 0x24: case 0x25: case 0x27: + case 0x28: case 0x29: case 0x2a: case 0x2b: + dev->regs[dev->index] = val; + break; + + case 0x22: case 0x23: + case 0x26: + dev->regs[dev->index] = val; + opti391_shadow_recalc(dev); + break; + } + break; + } +} + + +static uint8_t +opti391_read(uint16_t addr, void *priv) +{ + opti391_t *dev = (opti391_t *)priv; + uint8_t ret = 0xff; + + if (addr == 0x24) + ret = dev->regs[dev->index]; + + return ret; +} + + +static void +opti391_close(void *priv) +{ + opti391_t *dev = (opti391_t *)priv; + + free(dev); +} + + +static void * +opti391_init(const device_t *info) +{ + opti391_t *dev = (opti391_t *)malloc(sizeof(opti391_t)); + memset(dev, 0x00, sizeof(opti391_t)); + + io_sethandler(0x0022, 0x0001, opti391_read, NULL, NULL, opti391_write, NULL, NULL, dev); + io_sethandler(0x0024, 0x0001, opti391_read, NULL, NULL, opti391_write, NULL, NULL, dev); + + dev->regs[0x21] = 0x84; + dev->regs[0x24] = 0x07; + dev->regs[0x25] = 0xf0; + dev->regs[0x26] = 0x30; + dev->regs[0x27] = 0x91; + dev->regs[0x28] = 0x80; + dev->regs[0x29] = 0x10; + dev->regs[0x2a] = 0x80; + dev->regs[0x2b] = 0x10; + + opti391_shadow_recalc(dev); + + return dev; +} + + +const device_t opti391_device = { + "OPTi 82C391", + 0, + 0, + opti391_init, + opti391_close, + NULL, + { NULL }, + NULL, + NULL, + NULL +}; diff --git a/src/chipset/opti895.c b/src/chipset/opti895.c index 49277d53d..447d64fa3 100644 --- a/src/chipset/opti895.c +++ b/src/chipset/opti895.c @@ -43,6 +43,7 @@ typedef struct } opti895_t; +#define ENABLE_OPTI895_LOG 1 #ifdef ENABLE_OPTI895_LOG int opti895_do_log = ENABLE_OPTI895_LOG; @@ -91,11 +92,15 @@ opti895_recalc(opti895_t *dev) shflags = MEM_READ_INTERNAL; shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; } else { - if (dev->regs[0x26] & 0x40) { - shflags = MEM_READ_EXTANY; + shflags = (dev->regs[0x2d] & (1 << ((i >> 1) + 2))) ? MEM_READ_EXTANY : MEM_READ_EXTERNAL; + if (dev->regs[0x26] & 0x40) shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; - } else - shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY; + else { + if (dev->regs[0x26] & 0x80) + shflags |= (dev->regs[0x2d] & (1 << ((i >> 1) + 2))) ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL; + else + shflags |= MEM_WRITE_EXTERNAL; + } } mem_set_mem_state_both(base, 0x4000, shflags); @@ -108,17 +113,21 @@ opti895_recalc(opti895_t *dev) shflags = MEM_READ_INTERNAL; shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; } else { - if (dev->regs[0x26] & 0x40) { - shflags = MEM_READ_EXTANY; + shflags = (dev->regs[0x2d] & (1 << (i >> 1))) ? MEM_READ_EXTANY : MEM_READ_EXTERNAL; + if (dev->regs[0x26] & 0x40) shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; - } else - shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY; + else { + if (dev->regs[0x26] & 0x80) + shflags |= (dev->regs[0x2d] & (1 << (i >> 1))) ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL; + else + shflags |= MEM_WRITE_EXTERNAL; + } } mem_set_mem_state_both(base, 0x4000, shflags); } - flushmmucache(); + flushmmucache_nopc(); } @@ -138,7 +147,7 @@ opti895_write(uint16_t addr, uint8_t val, void *priv) } break; case 0x24: - if (((dev->idx >= 0x20) && (dev->idx <= 0x2c)) || + if (((dev->idx >= 0x20) && (dev->idx <= 0x2f)) || ((dev->idx >= 0xe0) && (dev->idx <= 0xef))) { dev->regs[dev->idx] = val; opti895_log("dev->regs[%04x] = %08x\n", dev->idx, val); @@ -152,6 +161,7 @@ opti895_write(uint16_t addr, uint8_t val, void *priv) case 0x22: case 0x23: case 0x26: + case 0x2d: opti895_recalc(dev); break; @@ -195,7 +205,7 @@ opti895_read(uint16_t addr, void *priv) ret = dev->regs[dev->idx]; break; case 0x24: - if (((dev->idx >= 0x20) && (dev->idx <= 0x2c)) || + if (((dev->idx >= 0x20) && (dev->idx <= 0x2f)) || ((dev->idx >= 0xe0) && (dev->idx <= 0xef))) { ret = dev->regs[dev->idx]; if (dev->idx == 0xe0) diff --git a/src/chipset/vl82c480.c b/src/chipset/vl82c480.c index 634cb948e..f5cc06d6a 100644 --- a/src/chipset/vl82c480.c +++ b/src/chipset/vl82c480.c @@ -98,9 +98,18 @@ vl82c480_write(uint16_t addr, uint8_t val, void *p) default: dev->regs[dev->idx] = val; break; + case 0x04: + if (dev->regs[0x00] == 0x98) + dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x08) | (val & 0xf7); + else + dev->regs[dev->idx] = val; + break; case 0x05: dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x10) | (val & 0xef); break; + case 0x07: + dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x40) | (val & 0xbf); + break; case 0x0d: case 0x0e: case 0x0f: case 0x10: case 0x11: case 0x12: dev->regs[dev->idx] = val; @@ -163,11 +172,13 @@ vl82c480_init(const device_t *info) vl82c480_t *dev = (vl82c480_t *)malloc(sizeof(vl82c480_t)); memset(dev, 0, sizeof(vl82c480_t)); - dev->regs[0x00] = 0x90; + dev->regs[0x00] = info->local; dev->regs[0x01] = 0xff; dev->regs[0x02] = 0x8a; dev->regs[0x03] = 0x88; dev->regs[0x06] = 0x1b; + if (info->local == 0x98) + dev->regs[0x07] = 0x21; dev->regs[0x08] = 0x38; io_sethandler(0x00ec, 0x0004, vl82c480_read, NULL, NULL, vl82c480_write, NULL, NULL, dev); @@ -181,7 +192,17 @@ vl82c480_init(const device_t *info) const device_t vl82c480_device = { "VLSI VL82c480", 0, - 0, + 0x90, + vl82c480_init, vl82c480_close, NULL, + { NULL }, NULL, NULL, + NULL +}; + + +const device_t vl82c486_device = { + "VLSI VL82c486", + 0, + 0x98, vl82c480_init, vl82c480_close, NULL, { NULL }, NULL, NULL, NULL diff --git a/src/config.c b/src/config.c index d412e1553..e72fb55f7 100644 --- a/src/config.c +++ b/src/config.c @@ -583,20 +583,26 @@ load_machine(void) machine = machine_get_machine_from_internal_name("pc916sx"); else if (! strcmp(p, "cbm_sl386sx16")) machine = machine_get_machine_from_internal_name("cmdsl386sx16"); - else if (! strcmp(p, "olivetti_m300_08")) - machine = machine_get_machine_from_internal_name("m30008"); - else if (! strcmp(p, "olivetti_m300_15")) - machine = machine_get_machine_from_internal_name("m30015"); else if (! strcmp(p, "cbm_sl386sx25")) machine = machine_get_machine_from_internal_name("cmdsl386sx25"); else if (! strcmp(p, "award386dx")) /* ...merged machines... */ - machine = machine_get_machine_from_internal_name("award486"); + machine = machine_get_machine_from_internal_name("award495"); else if (! strcmp(p, "ami386dx")) - machine = machine_get_machine_from_internal_name("ami486"); + machine = machine_get_machine_from_internal_name("ami495"); else if (! strcmp(p, "mr386dx")) - machine = machine_get_machine_from_internal_name("mr486"); + machine = machine_get_machine_from_internal_name("mr495"); + else if (! strcmp(p, "award486")) + machine = machine_get_machine_from_internal_name("award495"); + else if (! strcmp(p, "ami486")) + machine = machine_get_machine_from_internal_name("ami495"); + else if (! strcmp(p, "mr486")) + machine = machine_get_machine_from_internal_name("mr495"); else if (! strcmp(p, "fw6400gx_s1")) machine = machine_get_machine_from_internal_name("fw6400gx"); + else if (! strcmp(p, "p54vl")) + machine = machine_get_machine_from_internal_name("p5vl"); + else if (! strcmp(p, "chariot")) + machine = machine_get_machine_from_internal_name("fmb"); else if (! strcmp(p, "president")) { /* ...and removed machines */ machine = machine_get_machine_from_internal_name("mb500n"); migrate_from = NULL; diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index bc6f56324..613d8842e 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -641,7 +641,7 @@ const OpFn OP_TABLE(c486_0f)[1024] = /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ ILLEGAL, opRDTSC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -663,7 +663,7 @@ const OpFn OP_TABLE(c486_0f)[1024] = /*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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, opRDSHR_a16, opWRSHR_a16, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opSMINT, ILLEGAL, +/*30*/ ILLEGAL, opRDTSC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opSMINT, ILLEGAL, /*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -685,7 +685,7 @@ const OpFn OP_TABLE(c486_0f)[1024] = /*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ ILLEGAL, opRDTSC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -707,7 +707,7 @@ const OpFn OP_TABLE(c486_0f)[1024] = /*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ ILLEGAL, opRDTSC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, diff --git a/src/cpu/x86.c b/src/cpu/x86.c index e652c5d27..a80eb2d21 100644 --- a/src/cpu/x86.c +++ b/src/cpu/x86.c @@ -26,6 +26,7 @@ #include "cpu.h" #include "x86.h" #include <86box/machine.h> +#include <86box/device.h> #include <86box/io.h> #include <86box/mem.h> #include <86box/rom.h> @@ -239,8 +240,10 @@ reset_common(int hard) leave_smm(); /* Needed for the ALi M1533. */ - if (soft_reset_pci && !hard) + if (soft_reset_pci && !hard) { pci_reset(); + device_reset_all_pci(); + } use32 = 0; cpu_cur_status = 0; @@ -264,7 +267,7 @@ reset_common(int hard) } else { loadcs(0xFFFF); cpu_state.pc = 0; - rammask = 0xfffff; + rammask = is286 ? 0xffffff : 0xfffff; } } idt.base = 0; @@ -307,8 +310,10 @@ reset_common(int hard) shadowbios = shadowbios_write = 0; alt_access = cpu_end_block_after_ins = 0; - if (hard) + if (hard) { reset_on_hlt = hlt_reset_pending = 0; + soft_reset_pci = 0; + } if (!is286) reset_808x(hard); diff --git a/src/cpu/x86_ops_msr.h b/src/cpu/x86_ops_msr.h index 6624218e4..227677268 100644 --- a/src/cpu/x86_ops_msr.h +++ b/src/cpu/x86_ops_msr.h @@ -1,11 +1,13 @@ static int opRDTSC(uint32_t fetchdat) { +#if 0 if (!cpu_has_feature(CPU_FEATURE_RDTSC)) { cpu_state.pc = cpu_state.oldpc; x86illegal(); return 1; } +#endif if ((cr4 & CR4_TSD) && CPL) { x86gpf("RDTSC when TSD set and CPL != 0", 0); diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c new file mode 100644 index 000000000..bb756f67d --- /dev/null +++ b/src/device/kbc_at.c @@ -0,0 +1,2324 @@ +/* + * 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. + * + * Intel 8042 (AT keyboard controller) emulation. + * + * + * + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * EngiNerd + * + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2020 EngiNerd. + */ +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include +#include <86box/86box.h> +#include "cpu.h" +#include <86box/timer.h> +#include <86box/io.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/ppi.h> +#include <86box/mem.h> +#include <86box/device.h> +#include <86box/machine.h> +#include <86box/m_xt_xi8088.h> +#include <86box/m_at_t3100e.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/sound.h> +#include <86box/snd_speaker.h> +#include <86box/video.h> +#include <86box/keyboard.h> + + +#define STAT_PARITY 0x80 +#define STAT_RTIMEOUT 0x40 +#define STAT_TTIMEOUT 0x20 +#define STAT_MFULL 0x20 +#define STAT_UNLOCKED 0x10 +#define STAT_CD 0x08 +#define STAT_SYSFLAG 0x04 +#define STAT_IFULL 0x02 +#define STAT_OFULL 0x01 + +#define RESET_DELAY_TIME 1000 /* 100 ms */ + +#define CCB_UNUSED 0x80 +#define CCB_TRANSLATE 0x40 +#define CCB_PCMODE 0x20 +#define CCB_ENABLEKBD 0x10 +#define CCB_IGNORELOCK 0x08 +#define CCB_SYSTEM 0x04 +#define CCB_ENABLEMINT 0x02 +#define CCB_ENABLEKINT 0x01 + +#define CCB_MASK 0x68 +#define MODE_MASK 0x6c + +#define KBC_TYPE_ISA 0x00 /* AT ISA-based chips */ +#define KBC_TYPE_PS2_1 0x04 /* PS2 type, no refresh */ +/* This only differs in that translation is forced off. */ +#define KBC_TYPE_PS2_2 0x05 /* PS2 on PS/2, type 2 */ +#define KBC_TYPE_MASK 0x07 + +#define KBC_FLAG_PS2 0x04 + +/* We need to redefine this: + Currently, we use bits 3-7 for vendor, we should instead use bits 4-7 + for vendor, 0-3 for revision/variant, and have a dev->ps2 flag controlling + controller mode, normally set according to the flags, but togglable on + AMIKey: + 0000 0000 0x00 IBM, AT + 0000 0001 0x01 MR + 0000 0010 0x02 Xi8088, clone of IBM PS/2 type 1 + 0001 0000 0x10 Olivetti + 0010 0000 0x20 Toshiba + 0011 0000 0x30 Quadtel + 0100 0000 0x40 Phoenix MultiKey/42 + 0101 0000 0x50 AMI KF + 0101 0001 0x51 AMI KH + 0101 0010 0x52 AMIKey + 0101 0011 0x53 AMIKey-2 + 0101 0100 0x54 JetKey (clone of AMI KF/AMIKey) + 0110 0000 0x60 Award + 0110 0001 0x61 Award 286 (has some AMI commands apparently) + 0111 0000 0x70 Siemens +*/ + +/* Standard IBM controller */ +#define KBC_VEN_GENERIC 0x00 +/* All commands are standard PS/2 */ +#define KBC_VEN_IBM_MCA 0x08 +/* Standard IBM commands, differs in input port bits */ +#define KBC_VEN_IBM_PS1 0x10 +/* Olivetti - proprietary commands and port 62h with switches + readout */ +#define KBC_VEN_OLIVETTI 0x20 +/* Toshiba T3100e - has a bunch of proprietary commands, also sets + IFULL on command AA */ +#define KBC_VEN_TOSHIBA 0x28 +/* Standard IBM commands, uses input port as a switches readout */ +#define KBC_VEN_NCR 0x30 +/* Xi8088 - standard IBM commands, has a turbo bit on port 61h, and the + polarity of the video type bit in the input port is inverted */ +#define KBC_VEN_XI8088 0x38 +/* QuadtelKey - currently guesswork */ +#define KBC_VEN_QUADTEL 0x40 +/* Phoenix MultiKey/42 - not yet implemented */ +#define KBC_VEN_PHOENIX 0x48 +/* Generic commands, XI8088-like input port handling of video type, + maybe we just need a flag for that? */ +#define KBC_VEN_ACER 0x50 +/* AMI KF/KH/AMIKey/AMIKey-2 */ +#define KBC_VEN_AMI 0xf0 +/* Standard AMI commands, differs in input port bits */ +#define KBC_VEN_INTEL_AMI 0xf8 +#define KBC_VEN_MASK 0xf8 + + +/* Flags should be fully 32-bit: + Bits 7- 0: Vendor and revision/variant; + Bits 15- 8: Input port mask; + Bits 23-16: Input port bits that are always on; + Bits 31-24: Flags: + Bit 0: Invert P1 video type bit polarity; + Bit 1: Is PS/2; + Bit 2: Translation forced always off. + + So for example, the IBM PS/2 type 1 controller flags would be: 00000010 00000000 11111111 00000000 = 0200ff00 . */ + + +typedef struct { + uint8_t *c_in, *c_data, /* Data to controller */ + *d_in, *d_data, /* Data to device */ + *inhibit; + + void (*process)(void *priv); + void *priv; +} kbc_dev_t; + +typedef struct { + uint8_t status, ib, ob, p1, p2, old_p2, p2_locked, fast_a20_phase, + secr_phase, mem_index, ami_stat, ami_mode, + kbc_in, kbc_cmd, kbc_in_cmd, kbc_poll_phase, kbc_to_send, + kbc_send_pending, kbc_channel, kbc_stat_hi, kbc_wait_for_response, inhibit; + + uint8_t mem_int[0x40], mem[0x240]; + + uint16_t last_irq, kbc_phase; + + uint32_t flags; + + kbc_dev_t * kbc_devs[2]; + + pc_timer_t pulse_cb, send_delay_timer; + + uint8_t (*write60_ven)(void *p, uint8_t val); + uint8_t (*write64_ven)(void *p, uint8_t val); + + void * log; +} atkbc_t; + + +enum +{ + CHANNEL_KBC = 0, + CHANNEL_KBD, + CHANNEL_MOUSE +}; + +enum +{ + KBD_MAIN_LOOP = 0, + KBD_CMD_PROCESS +}; + +enum +{ + MOUSE_MAIN_LOOP_1 = 0, + MOUSE_CMD_PROCESS, + MOUSE_CMD_END, + MOUSE_MAIN_LOOP_2 +}; + +enum { + KBC_MAIN_LOOP = 0, + KBC_RESET = 1, + KBC_WAIT = 4, + KBC_WAIT_FOR_KBD, + KBC_WAIT_FOR_MOUSE, + KBC_WAIT_FOR_BOTH +}; + + +static void kbc_wait(atkbc_t *dev, uint8_t flags); + + +/* Bits 0 - 1 = scan code set, bit 6 = translate or not. */ +uint8_t keyboard_mode = 0x42; + +uint8_t * ami_copr = (uint8_t *) "(C)1994 AMI"; + + +uint8_t mouse_queue[16]; +int mouse_queue_start = 0, mouse_queue_end = 0; +static void (*mouse_write)(uint8_t val, void *priv) = NULL; +static void *mouse_p = NULL; +static uint8_t sc_or = 0; +static atkbc_t *saved_kbc = NULL; + + +/* Non-translated to translated scan codes. */ +static const uint8_t nont_to_t[256] = { + 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58, + 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59, + 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a, + 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b, + 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c, + 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d, + 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e, + 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f, + 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60, + 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61, + 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e, + 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76, + 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b, + 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f, + 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45, + 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54, + 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; + + +#define UISTR_LEN 256 +static char kbc_str[UISTR_LEN]; /* UI output string */ + + +extern void ui_sb_bugui(char *__str); + + +static void +kbc_status(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsprintf(kbc_str, fmt, ap); + ui_sb_bugui(kbc_str); + va_end(ap); +} + + +#define ENABLE_KBC_AT_LOG 1 +#if (!defined(RELEASE_BUILD) && defined(ENABLE_KBC_AT_LOG)) +int kbc_at_do_log = ENABLE_KBC_AT_LOG; + + +static void +kbc_log(atkbc_t *dev, const char *fmt, ...) +{ + va_list ap; + + if ((dev == NULL) || (dev->log == NULL)) + return; + + if (kbc_at_do_log) { + va_start(ap, fmt); + log_out(dev->log, fmt, ap); + va_end(ap); + } +} +#else +#define kbc_log(dev, fmt, ...) +#endif + + +static void +kbc_send_to_ob(atkbc_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) +{ + uint8_t ch = (channel > 0) ? channel : 1; + uint8_t do_irq = (dev->mem[0x20] & ch); + int translate = (channel == 1) && (keyboard_mode & 0x60); + + if ((channel == 2) && !(dev->flags & KBC_FLAG_PS2)) + return; + + stat_hi |= dev->inhibit; + + if (!dev->kbc_send_pending) { + dev->kbc_send_pending = 1; + dev->kbc_to_send = val; + dev->kbc_channel = channel; + dev->kbc_stat_hi = stat_hi; + return; + } + + if (translate) { + /* Allow for scan code translation. */ + if (val == 0xf0) { + kbc_log(dev, "Translate is on, F0 prefix detected\n"); + sc_or = 0x80; + return; + } + + /* Skip break code if translated make code has bit 7 set. */ + if ((sc_or == 0x80) && (val & 0x80)) { + kbc_log(dev, "Translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val); + sc_or = 0; + return; + } + } + + dev->last_irq = (ch == 2) ? 0x1000 : 0x0002; + if (do_irq) { + kbc_log(dev, "[%04X:%08X] IRQ %i\n", CS, cpu_state.pc, (ch == 2) ? 12 : 1); + picint(dev->last_irq); + } + kbc_log(dev, "%02X coming from channel %i (%i)\n", val, channel, do_irq); + dev->ob = translate ? (nont_to_t[val] | sc_or) : val; + + dev->status = (dev->status & 0x0f) | (stat_hi | (dev->mem[0x20] & STAT_SYSFLAG) | STAT_OFULL); + if (ch == 2) + dev->status |= STAT_MFULL; + + if (translate && (sc_or == 0x80)) + sc_or = 0; +} + + +static void +write_output(atkbc_t *dev, uint8_t val) +{ + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + kbc_log(dev, "Write output port: %02X (old: %02X)\n", val, dev->p2); + + if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) + val |= ((dev->mem[0x20] << 4) & 0x30); + + dev->kbc_devs[0]->inhibit = (val & 0x40); + dev->kbc_devs[1]->inhibit = (val & 0x08); + + if ((dev->p2 ^ val) & 0x20) { /*IRQ 12*/ + if (val & 0x20) { + kbc_log(dev, "write_output(): IRQ 12\n"); + picint(1 << 12); + } else + picintc(1 << 12); + } + if ((dev->p2 ^ val) & 0x10) { /*IRQ 1*/ + if (val & 0x10) { + kbc_log(dev, "write_output(): IRQ 1\n"); + picint(1 << 1); + } else + picintc(1 << 1); + } + if ((dev->p2 ^ val) & 0x02) { /*A20 enable change*/ + mem_a20_key = val & 0x02; + mem_a20_recalc(); + flushmmucache(); + } + if ((dev->p2 ^ val) & 0x01) { /*Reset*/ + if (! (val & 0x01)) { + /* Pin 0 selected. */ + softresetx86(); /*Pulse reset!*/ + cpu_set_edx(); + smbase = is_am486dxl ? 0x00060000 : 0x00030000; + } + } + /* Mask off the A20 stuff because we use mem_a20_key directly for that. */ + dev->p2 = val; +} + + +static void +write_cmd(atkbc_t *dev, uint8_t val) +{ + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + kbc_log(dev, "Write command byte: %02X (old: %02X)\n", val, dev->mem[0x20]); + + /* PS/2 type 2 keyboard controllers always force the XLAT bit to 0. */ + if ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2) + val &= ~CCB_TRANSLATE; + + dev->mem[0x20] = val; + + /* Scan code translate ON/OFF. */ + keyboard_mode &= 0x93; + keyboard_mode |= (val & MODE_MASK); + + kbc_log(dev, "Keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled"); + + /* ISA AT keyboard controllers use bit 5 for keyboard mode (1 = PC/XT, 2 = AT); + PS/2 (and EISA/PCI) keyboard controllers use it as the PS/2 mouse enable switch. + The AMIKEY firmware apparently uses this bit for something else. */ + if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) { + keyboard_mode &= ~CCB_PCMODE; + /* Update the output port to mirror the KBD DIS and AUX DIS bits, if active. */ + write_output(dev, dev->p2); + + kbc_log(dev, "Mouse interrupt is now %s\n", (val & 0x02) ? "enabled" : "disabled"); + } + + kbc_log(dev, "Command byte now: %02X (%02X)\n", dev->mem[0x20], val); + + dev->status = (dev->status & ~STAT_SYSFLAG) | (val & STAT_SYSFLAG); +} + + +static void +pulse_output(atkbc_t *dev, uint8_t mask) +{ + if (mask != 0x0f) { + dev->old_p2 = dev->p2 & ~(0xf0 | mask); + kbc_log(dev, "pulse_output(): Output port now: %02X\n", dev->p2 & (0xf0 | mask | (dev->mem[0x20] & 0x30))); + write_output(dev, dev->p2 & (0xf0 | mask | (dev->mem[0x20] & 0x30))); + timer_set_delay_u64(&dev->pulse_cb, 6ULL * TIMER_USEC); + } +} + + +static void +set_enable_kbd(atkbc_t *dev, uint8_t enable) +{ + dev->mem[0x20] &= 0xef; + dev->mem[0x20] |= (enable ? 0x00 : 0x10); +} + + +static void +set_enable_mouse(atkbc_t *dev, uint8_t enable) +{ + dev->mem[0x20] &= 0xdf; + dev->mem[0x20] |= (enable ? 0x00 : 0x20); +} + + +static void +kbc_transmit(atkbc_t *dev, uint8_t val) +{ + kbc_send_to_ob(dev, val, 0, 0x00); +} + + +static void +kbc_command(atkbc_t *dev) +{ + uint8_t mask, val = dev->ib; + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + int bad = 1; + + if ((dev->kbc_phase > 0) && (dev->kbc_cmd == 0xac)) { + if (dev-> kbc_phase < 16) + kbc_transmit(dev, dev->mem[dev->kbc_phase]); + else if (dev-> kbc_phase == 16) + kbc_transmit(dev, (dev->p1 & 0xf0) | 0x80); + else if (dev-> kbc_phase == 17) + kbc_transmit(dev, dev->p2); + else if (dev-> kbc_phase == 18) + kbc_transmit(dev, dev->status); + + dev->kbc_phase++; + if (dev->kbc_phase == 19) { + dev->kbc_phase = 0; + dev->kbc_cmd = 0x00; + } + return; + } else if ((dev->kbc_phase > 0) && (dev->kbc_cmd == 0xa0) && (kbc_ven >= KBC_VEN_AMI)) { + val = ami_copr[dev->kbc_phase]; + kbc_transmit(dev, val); + if (val == 0x00) { + dev->kbc_phase = 0; + dev->kbc_cmd = 0x00; + } else + dev->kbc_phase++; + return; + } else if ((dev->kbc_in > 0) && (dev->kbc_cmd == 0xa5) && (dev->flags & KBC_FLAG_PS2)) { + /* load security */ + kbc_log(dev, "Load security\n"); + dev->mem[0x50 + dev->kbc_in - 0x01] = val; + if ((dev->kbc_in == 0x80) && (val != 0x00)) { + /* Security string too long, set it to 0x00. */ + dev->mem[0x50] = 0x00; + dev->kbc_in = 0; + dev->kbc_cmd = 0; + } else if (val == 0x00) { + /* Security string finished. */ + dev->kbc_in = 0; + dev->kbc_cmd = 0; + } else /* Increase pointer and request another byte. */ + dev->kbc_in++; + return; + } + + /* If the written port is 64, go straight to the beginning of the command. */ + if (!(dev->status & STAT_CD) && dev->kbc_in) { + /* Write data to controller. */ + dev->kbc_in = 0; + dev->kbc_phase = 0; + + switch (dev->kbc_cmd) { + case 0x60 ... 0x7f: + if (dev->kbc_cmd == 0x60) + write_cmd(dev, val); + else + dev->mem[(dev->kbc_cmd & 0x1f) + 0x20] = val; + break; + + case 0xc7: /* or input port with system data */ + dev->p1 |= val; + break; + + case 0xcb: /* set keyboard mode */ + kbc_log(dev, "New AMIKey mode: %02X\n", val); + dev->ami_mode = val; + dev->flags &= ~KBC_FLAG_PS2; + if (val & 1) + dev->flags |= KBC_FLAG_PS2; +#if (!defined(RELEASE_BUILD) && defined(ENABLE_KBD_AT_LOG)) + log_set_dev_name(dev->kbc_log, (dev->flags & KBC_FLAG_PS2) ? "AT KBC" : "PS/2 KBC"); +#endif + break; + + case 0xd1: /* write output port */ + if (dev->p2_locked) { + /*If keyboard controller lines P22-P23 are blocked, + we force them to remain unchanged.*/ + val &= ~0x0c; + val |= (dev->p2 & 0x0c); + } + kbc_log(dev, "Write %02X to output port\n", val); + write_output(dev, val); + break; + + case 0xd2: /* write to keyboard output buffer */ + kbc_log(dev, "Write %02X to keyboard output buffer\n", val); + /* Should be channel 1, but we send to 0 to avoid translation, + since bytes output using this command do *NOT* get translated. */ + kbc_send_to_ob(dev, val, 0, 0x00); + break; + + case 0xd3: /* write to mouse output buffer */ + kbc_log(dev, "Write %02X to mouse output buffer\n", val); + if (dev->flags & KBC_FLAG_PS2) + kbc_send_to_ob(dev, val, 2, 0x00); + break; + + case 0xd4: /* write to mouse */ + kbc_log(dev, "Write %02X to mouse\n", val); + + if (dev->flags & KBC_FLAG_PS2) { + set_enable_mouse(dev, 1); + dev->mem[0x20] &= ~0x20; + if (dev->kbc_devs[1] && !dev->kbc_devs[1]->c_in) { + kbc_log(dev, "Transmitting %02X to mouse...\n", dev->ib); + dev->kbc_devs[1]->d_data = val; + dev->kbc_devs[1]->d_in = 1; + dev->kbc_wait_for_response = 2; + } else + kbc_send_to_ob(dev, 0xfe, 2, 0x40); + } + break; + + default: + /* + * Run the vendor-specific handler + * if we have one. Otherwise, or if + * it returns an error, log a bad + * controller command. + */ + if (dev->write60_ven) + bad = dev->write60_ven(dev, val); + + if (bad) + kbc_log(dev, "Bad controller command %02x data %02x\n", dev->kbc_cmd, val); + } + } else { + /* Controller command. */ + kbc_log(dev, "Controller command: %02X\n", val); + dev->kbc_in = 0; + dev->kbc_phase = 0; + + switch (val) { + /* Read data from KBC memory. */ + case 0x20 ... 0x3f: + kbc_transmit(dev, dev->mem[(val & 0x1f) + 0x20]); + break; + + /* Write data to KBC memory. */ + case 0x60 ... 0x7f: + dev->kbc_in = 1; + break; + + case 0xaa: /* self-test */ + kbc_log(dev, "Self-test\n"); + write_output(dev, (dev->flags & KBC_FLAG_PS2) ? 0x4b : 0xcf); + + /* Always reinitialize all queues - the real hardware pulls keyboard and mouse + clocks high, which stops keyboard scanning. */ + dev->in_cmd = dev->mouse_in_cmd = 0; + dev->status &= ~STAT_OFULL; + dev->last_irq = 0; + dev->kbc_phase = 0; + + /* Phoenix MultiKey should have 0x60 | STAT_SYSFLAG. */ + if (dev->flags & KBC_FLAG_PS2) + write_cmd(dev, 0x30 | STAT_SYSFLAG); + else + write_cmd(dev, 0x10 | STAT_SYSFLAG); + kbc_transmit(dev, 0x55); + break; + + case 0xab: /* interface test */ + kbc_log(dev, "Interface test\n"); + /* No error. */ + kbc_transmit(dev, 0x00); + break; + + case 0xac: /* diagnostic dump */ + kbc_log(dev, "Diagnostic dump\n"); + kbc_transmit(dev, dev->mem[0x20]); + dev->kbc_phase = 1; + break; + + case 0xad: /* disable keyboard */ + kbc_log(dev, "Disable keyboard\n"); + set_enable_kbd(dev, 0); + break; + + case 0xae: /* enable keyboard */ + kbc_log(dev, "Enable keyboard\n"); + set_enable_kbd(dev, 1); + break; + + case 0xc7: /* or input port with system data */ + kbc_log(dev, "Phoenix - or input port with system data\n"); + dev->kbc_in = 1; + break; + + case 0xca: /* read keyboard mode */ + kbc_log(dev, "AMI - Read keyboard mode\n"); + kbc_transmit(dev, dev->ami_mode); + break; + + case 0xcb: /* set keyboard mode */ + kbc_log(dev, "ATkbc: AMI - Set keyboard mode\n"); + dev->kbc_in = 1; + break; + + case 0xd0: /* read output port */ + kbc_log(dev, "Read output port\n"); + mask = 0xff; + if (dev->mem[0x20] & 0x10) + mask &= 0xbf; + if ((dev->flags & KBC_FLAG_PS2) && (dev->mem[0x20] & 0x20)) + mask &= 0xf7; + kbc_transmit(dev, dev->p2 & mask); + break; + + case 0xd1: /* write output port */ + kbc_log(dev, "Write output port\n"); + dev->kbc_in = 1; + break; + + case 0xd2: /* write keyboard output buffer */ + kbc_log(dev, "Write keyboard output buffer\n"); + if (dev->flags & KBC_FLAG_PS2) + dev->kbc_in = 1; + else + kbc_transmit(dev, 0x00); /* NCR */ + break; + + case 0xdd: /* disable A20 address line */ + case 0xdf: /* enable A20 address line */ + kbc_log(dev, "%sable A20\n", (val == 0xdd) ? "Dis": "En"); + write_output(dev, (dev->p2 & 0xfd) | (val & 0x02)); + break; + + case 0xe0: /* read test inputs */ + kbc_log(dev, "Read test inputs\n"); + kbc_transmit(dev, 0x00); + break; + + default: + /* + * Unrecognized controller command. + * + * If we have a vendor-specific handler, run + * that. Otherwise, or if that handler fails, + * log a bad command. + */ + if (dev->write64_ven) + bad = dev->write64_ven(dev, val); + + if (bad) + kbc_log(dev, "Bad controller command %02X\n", val); + } + + /* If the command needs data, remember the command. */ + if (dev->kbc_in || (dev->kbc_phase > 0)) + dev->kbc_cmd = val; + } +} + + +static void +kbc_dev_data_to_ob(atkbc_t *dev, uint8_t channel) +{ + if (channel == 0) + return; + + dev->kbc_devs[channel - 1]->c_in = 0; + kbc_log(dev, "Forwarding %02X from channel %i...\n", dev->kbc_devs[channel - 1]->c_data, channel); + kbc_send_to_ob(dev, dev->kbc_devs[channel - 1]->c_data, channel, 0x00); +} + + +static void +kbc_main_loop_scan(atkbc_t *dev) +{ + uint8_t port_dis = dev->mem[0x20] & 0x30; + uint8_t ps2 = (dev->flags & KBC_FLAG_PS2); + + if (!ps2) + port_dis |= 0x20; + + if (!(dev->status & STAT_OFULL)) { + if (port_dis & 0x20) { + if (!(port_dis & 0x10)) { + kbc_log(dev, "kbc_process(): Main loop, Scan: AUX DIS, KBD EN\n"); + /* Enable communication with keyboard. */ + dev->p2 &= 0xbf; + dev->kbc_devs[0]->inhibit = 0; + kbc_wait(dev, 1); + } else + kbc_log(dev, "kbc_process(): Main loop, Scan: AUX DIS, KBD DIS\n"); + } else { + /* Enable communication with mouse. */ + dev->p2 &= 0xf7; + dev->kbc_devs[1]->inhibit = 0; + if (dev->mem[0x20] & 0x10) { + kbc_log(dev, "kbc_process(): Main loop, Scan: AUX EN , KBD DIS\n"); + kbc_wait(dev, 2); + } else { + /* Enable communication with keyboard. */ + kbc_log(dev, "kbc_process(): Main loop, Scan: AUX EN , KBD EN\n"); + dev->p2 &= 0xbf; + dev->kbc_devs[0]->inhibit = 0; + kbc_wait(dev, 3); + } + } + } else + kbc_log(dev, "kbc_process(): Main loop, Scan: IBF not full and OBF full, do nothing\n"); +} + + +static uint8_t +kbc_reset_cmd(atkbc_t *dev) +{ + uint8_t ret = 0; + + if ((dev->status & STAT_CD) || (dev->kbc_poll_phase == KBC_WAIT_FOR_NOBF)) { + kbc_log(dev, " Resetting command\n"); + dev->kbc_phase = 0; + dev->kbc_in = 0; + dev->kbc_in_cmd = 0; + dev->kbc_poll_phase = KBC_MAIN_LOOP; + ret = 1; + } + + return ret; +} + + +static uint8_t +kbc_process_cmd(atkbdt_t *dev, uint8_t restart) +{ + uint8_t ret = 0; + + if (restart) + dev->kbc_in_cmd = 1; + kbc_command(dev); + + if ((dev->kbc_phase == 0) && !dev->kbc_in) + dev->kbc_in_cmd = 0; + else + ret = 1; + + dev->kbc_poll_phase = KBC_MAIN_LOOP; + if (!dev->kbc_wait_for_response && !(dev->status & STAT_OFULL)) + kbc_main_loop_scan(dev); + + return ret; +} + + +static void +kbc_process_ib(atkbc_t *dev) +{ + if ((dev->status & STAT_CD) || (kbc->flags & KBC_FLAG_PS2) || !(dev->status & STAT_OFULL)) + dev->status &= ~STAT_IFULL; + + if (dev->status & STAT_CD) + (void) kbc_process_cmd(dev, 1); + else if ((kbc->flags & KBC_FLAG_PS2) || !(dev->status & STAT_OFULL)) + /* The AT KBC does *NOT* send data to the keyboard if OBF. */ + set_enable_mouse(dev, 1); + dev->mem[0x20] &= ~0x10; + if (dev->kbc_devs[0] && !dev->kbc_devs[0]->c_in) { + dev->kbc_devs[0]->d_data = val; + dev->kbc_devs[0]->d_in = 1; + dev->kbc_wait_for_response = 1; + } else + kbc_send_to_ob(dev, 0xfe, 1, 0x40); + + dev->kbc_poll_phase = KBC_MAIN_LOOP; + if (!dev->kbc_wait_for_response && !(dev->status & STAT_OFULL)) + kbc_main_loop_scan(dev); + } +} + + +static void +kbc_wait(atkbc_t *dev, uint8_t flags) +{ + if ((flags & 1) && dev->kbc_devs[0]->c_in) { + /* Disable communication with mouse. */ + dev->p2 |= 0x08; + dev->kbc_devs[1]->inhibit = 1; + /* Send keyboard byte to host. */ + kbc_dev_data_to_ob(dev, CHANNEL_KBD); + dev->kbc_poll_phase = KBC_MAIN_LOOP; + } else if ((flags & 2) && dev->kbc_devs[1]->c_in) { + /* Disable communication with keyboard. */ + dev->p2 |= 0x40; + dev->kbc_devs[0]->inhibit = 1; + /* Send mouse byte to host. */ + kbc_dev_data_to_ob(dev, CHANNEL_MOUSE); + dev->kbc_poll_phase = KBC_MAIN_LOOP; + } else if (dev->status & STAT_IFULL) { + /* Disable communication with keyboard and mouse. */ + dev->p2 |= 0x48; + dev->kbc_devs[0]->inhibit = dev->kbc_devs[1]->inhibit = 1; + kbc_process_ib(dev); + } else + dev->kbc_poll_phase = KBC_WAIT | flags; +} + + +/* Controller processing */ +static void +kbc_process(atkbc_t *dev) +{ + /* If we're waiting for the response from the keyboard or mouse, do nothing + until the device has repsonded back. */ + if (dev->kbc_wait_for_response > 0) { + if (dev->kbc_devs[dev->kbc_wait_for_response - 1]->c_in) + dev->kbc_wait_for_response = 0; + else + return; + } + + if (dev->kbc_send_pending) { + kbc_log(dev, "Sending delayed %02X on channel %i with high status %02X\n", + dev->kbc_to_send, dev->kbc_channel, dev->kbc_stat_hi); + kbc_send_to_ob(dev, dev->kbc_to_send, dev->kbc_channel, dev->kbc_stat_hi); + dev->kbc_send_pending = 0; + } + + /* Make absolutely sure to do nothing if OBF is full and IBF is empty. */ + if ((dev->kbc_poll_phase == KBC_RESET) || (dev->kbc_poll_phase >= KBC_WAIT_FOR_NIBF) || + !(dev->status & STAT_OFULL) || (dev->status & STAT_IFULL)) switch (dev->kbc_poll_phase) { + case KBC_RESET: + kbc_log(dev, "kbc_process(): Reset loop()\n"); + + if (dev->status & STAT_IFULL) { + dev->status &= ~STAT_IFULL; + + if ((dev->status & STAT_CD) && (dev->ib == 0xaa)) { + (void) kbc_process_cmd(dev, 1); + dev->kbc_poll_phase = KBC_MAIN_LOOP; + } + } + break; + case KBC_MAIN_LOOP: + if (dev->status & STAT_IFULL) { + kbc_log(dev, "kbc_process(): Main loop, IBF full, process\n"); + kbc_process_ib(dev); + } else + kbc_main_loop_scan(dev); + break; + case KBC_SCAN_KBD: + case KBC_SCAN_MOUSE: + case KBC_SCAN_BOTH: + kbc_log(dev, "kbc_process(): Scan: Phase %i\n", dev->kbc_poll_phase); + kbc_wait(dev, dev->kbc_poll_phase & 3); + break; + case KBC_WAIT_FOR_NOBF: + kbc_log(dev, "kbc_process(): Waiting for !OBF\n"); + + if (dev->status & STAT_IFULL) { + /* Host writing a command aborts the current command. */ + (void) !kbc_reset_cmd(dev); + + /* Process the input buffer. */ + kbc_process_ib(dev); + } else if (!dev->status & STAT_OFULL) { + /* Not aborted and OBF cleared - process command. */ + kbc_log(dev, " Continuing commmand\n"); + + if (kbc_process_cmd(dev, 0)) + return; + } + break; + case KBC_WAIT_FOR_IBF: + kbc_log(dev, "kbc_process(): Waiting for IBF\n"); + + if (dev->status & STAT_IFULL) { + /* IBF, process if port 60h, otherwise abort the current command. */ + dev->status &= ~STAT_IFULL; + + if (!kbc_reset_cmd(dev)) + kbc_log(dev, " Continuing commmand\n"); + + /* Process command. */ + if (kbc_process_cmd(dev, 0)) + return; + } + break; + default: + kbc_log(dev, "kbc_process(): Invalid phase %i\n", dev->kbc_poll_phase); + break; + } +} + + +static void +kbd_poll(void *priv) +{ + atkbc_t *dev = (atkbc_t *) priv; + uint8_t i; + + if (dev == NULL) + return; + + timer_advance_u64(&dev->send_delay_timer, (100ULL * TIMER_USEC)); + + /* Device processing */ + for (i = 0; i < 2; i++) { + if (dev->kbc_devs[i] && dev->kbd_devs[i]->priv && dev->kbd_devs[i]->process) + dev->kbc_devs[i]->process(dev->kbc_devs[i]->priv); + } + + /* Controller processing */ + kbc_process(dev); +} + + +static void +pulse_poll(void *priv) +{ + atkbc_t *dev = (atkbc_t *)priv; + + kbc_log(dev, "pulse_poll(): Output port now: %02X\n", dev->p2 | dev->old_p2); + write_output(dev, dev->p2 | dev->old_p2); +} + + +static uint8_t +write64_generic(void *priv, uint8_t val) +{ + atkbc_t *dev = (atkbc_t *)priv; + uint8_t current_drive, fixed_bits; + uint8_t kbc_ven = 0x0; + kbc_ven = dev->flags & KBC_VEN_MASK; + + switch (val) { + case 0xa4: /* check if password installed */ + if (dev->flags & KBC_FLAG_PS2) { + kbc_log(dev, "Check if password installed\n"); + kbc_transmit(dev, (dev->mem[0x50] == 0x00) ? 0xf1 : 0xfa); + return 0; + } + break; + + case 0xa5: /* load security */ + if (dev->flags & KBC_FLAG_PS2) { + kbc_log(dev, "Load security\n"); + dev->kbc_in = 1; + return 0; + } + break; + + case 0xa7: /* disable mouse port */ + if (dev->flags & KBC_FLAG_PS2) { + kbc_log(dev, "Disable mouse port\n"); + return 0; + } + break; + + case 0xa8: /*Enable mouse port*/ + if (dev->flags & KBC_FLAG_PS2) { + kbc_log(dev, "Enable mouse port\n"); + return 0; + } + break; + + case 0xa9: /*Test mouse port*/ + kbc_log(dev, "Test mouse port\n"); + if (dev->flags & KBC_FLAG_PS2) { + /* No error, this is testing the channel 2 interface. */ + kbc_transmit(dev, 0x00); + return 0; + } + break; + + case 0xaf: /* read keyboard version */ + kbc_log(dev, "Read keyboard version\n"); + kbc_transmit(dev, 0x00); + return 0; + + case 0xc0: /* read input port */ + /* IBM PS/1: + Bit 2 and 4 ignored (we return always 0), + Bit 6 must 1 for 5.25" floppy drive, 0 for 3.5". + Intel AMI: + Bit 2 ignored (we return always 1), + Bit 4 must be 1, + Bit 6 must be 1 or else error in SMM. + Acer: + Bit 2 must be 0, + Bit 4 must be 0, + Bit 6 ignored. + P6RP4: + Bit 2 must be 1 or CMOS setup is disabled. */ + kbc_log(dev, "Read input port\n"); + fixed_bits = 4; + /* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */ + if (kbc_ven == KBC_VEN_INTEL_AMI) + fixed_bits |= 0x40; + if (kbc_ven == KBC_VEN_IBM_PS1) { + current_drive = fdc_get_current_drive(); + kbc_transmit(dev, dev->p1 | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00)); + dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc) | (fdd_is_525(current_drive) ? 0x40 : 0x00); + } else if (kbc_ven == KBC_VEN_NCR) { + /* switch settings + * bit 7: keyboard disable + * bit 6: display type (0 color, 1 mono) + * bit 5: power-on default speed (0 high, 1 low) + * bit 4: sense RAM size (0 unsupported, 1 512k on system board) + * bit 3: coprocessor detect + * bit 2: unused + * bit 1: high/auto speed + * bit 0: dma mode + */ + kbc_transmit(dev, (dev->p1 | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf); + dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc); + } else { + if ((dev->flags & KBC_FLAG_PS2) && ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI)) + kbc_transmit(dev, (dev->p1 | fixed_bits) & (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0xeb : 0xef)); + else + kbc_transmit(dev, dev->p1 | fixed_bits); + dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc); + } + return 0; + + case 0xd3: /* write mouse output buffer */ + if (dev->flags & KBC_FLAG_PS2) { + kbc_log(dev, "Write mouse output buffer\n"); + dev->kbc_in = 1; + return 0; + } + break; + + case 0xd4: /* write to mouse */ + kbc_log(dev, "Write to mouse\n"); + dev->kbc_in = 1; + return 0; + + case 0xf0 ... 0xff: + kbc_log(dev, "Pulse %01X\n", val & 0x0f); + pulse_output(dev, val & 0x0f); + return 0; + } + + kbc_log(dev, "Bad command %02X\n", val); + return 1; +} + + +static uint8_t +write60_ami(void *priv, uint8_t val) +{ + atkbc_t *dev = (atkbc_t *)priv; + uint16_t index = 0x00c0; + + switch(dev->kbc_cmd) { + /* 0x40 - 0x5F are aliases for 0x60 - 0x7F */ + case 0x40 ... 0x5f: + kbc_log(dev, "AMI - Alias write to %08X\n", dev->kbc_cmd); + if (dev->kbc_cmd == 0x40) + write_cmd(dev, val); + else + dev->mem[(dev->kbc_cmd & 0x1f) + 0x20] = val; + return 0; + + case 0xaf: /* set extended controller RAM */ + kbc_log(dev, "AMI - Set extended controller RAM, input phase %i\n", dev->secr_phase); + if (dev->secr_phase == 0) { + dev->mem_index = val; + dev->kbc_in = 1; + dev->secr_phase++; + } else if (dev->secr_phase == 1) { + if (dev->mem_index == 0x20) + write_cmd(dev, val); + else + dev->mem[dev->mem_index] = val; + dev->secr_phase = 0; + } + return 0; + + case 0xb8: + kbc_log(dev, "AMIKey-3 - Memory index %02X\n", val); + dev->mem_index = val; + return 0; + + case 0xbb: + kbc_log(dev, "AMIKey-3 - write %02X to memory index %02X\n", val, dev->mem_index); + if (dev->mem_index >= 0x80) { + switch (dev->mem[0x9b] & 0xc0) { + case 0x00: + index = 0x0080; + break; + case 0x40: case 0x80: + index = 0x0000; + break; + case 0xc0: + index = 0x0100; + break; + } + dev->mem[index + dev->mem_index] = val; + } else if (dev->mem_index == 0x60) + write_cmd(dev, val); + else if (dev->mem_index == 0x42) + dev->status = val; + else if (dev->mem_index >= 0x40) + dev->mem[dev->mem_index - 0x40] = val; + else + dev->mem_int[dev->mem_index] = val; + return 0; + + case 0xbd: + kbc_log(dev, "AMIKey-3 - write %02X to config index %02X\n", val, dev->mem_index); + switch (dev->mem_index) { + case 0x00: /* STAT8042 */ + dev->status = val; + break; + case 0x01: /* Password_ptr */ + dev->mem[0x1c] = val; + break; + case 0x02: /* Wakeup_Tsk_Reg */ + dev->mem[0x1e] = val; + break; + case 0x03: /* CCB */ + write_cmd(dev, val); + break; + case 0x04: /* Debounce_time */ + dev->mem[0x4d] = val; + break; + case 0x05: /* Pulse_Width */ + dev->mem[0x4e] = val; + break; + case 0x06: /* Pk_sel_byte */ + dev->mem[0x4c] = val; + break; + case 0x07: /* Func_Tsk_Reg */ + dev->mem[0x7e] = val; + break; + case 0x08: /* TypematicRate */ + dev->mem[0x80] = val; + break; + case 0x09: /* Led_Flag_Byte */ + dev->mem[0x81] = val; + break; + case 0x0a: /* Kbms_Command_St */ + dev->mem[0x87] = val; + break; + case 0x0b: /* Delay_Count_Byte */ + dev->mem[0x86] = val; + break; + case 0x0c: /* KBC_Flags */ + dev->mem[0x9b] = val; + break; + case 0x0d: /* SCODE_HK1 */ + dev->mem[0x50] = val; + break; + case 0x0e: /* SCODE_HK2 */ + dev->mem[0x51] = val; + break; + case 0x0f: /* SCODE_HK3 */ + dev->mem[0x52] = val; + break; + case 0x10: /* SCODE_HK4 */ + dev->mem[0x53] = val; + break; + case 0x11: /* SCODE_HK5 */ + dev->mem[0x54] = val; + break; + case 0x12: /* SCODE_HK6 */ + dev->mem[0x55] = val; + break; + case 0x13: /* TASK_HK1 */ + dev->mem[0x56] = val; + break; + case 0x14: /* TASK_HK2 */ + dev->mem[0x57] = val; + break; + case 0x15: /* TASK_HK3 */ + dev->mem[0x58] = val; + break; + case 0x16: /* TASK_HK4 */ + dev->mem[0x59] = val; + break; + case 0x17: /* TASK_HK5 */ + dev->mem[0x5a] = val; + break; + /* The next 4 bytes have uncertain correspondences. */ + case 0x18: /* Batt_Poll_delay_Time */ + dev->mem[0x5b] = val; + break; + case 0x19: /* Batt_Alarm_Reg1 */ + dev->mem[0x5c] = val; + break; + case 0x1a: /* Batt_Alarm_Reg2 */ + dev->mem[0x5d] = val; + break; + case 0x1b: /* Batt_Alarm_Tsk_Reg */ + dev->mem[0x5e] = val; + break; + case 0x1c: /* Kbc_State1 */ + dev->mem[0x9d] = val; + break; + case 0x1d: /* Aux_Config */ + dev->mem[0x75] = val; + break; + case 0x1e: /* Kbc_State3 */ + dev->mem[0x73] = val; + break; + } + return 0; + + case 0xc1: /* write input port */ + kbc_log(dev, "AMI MegaKey - write %02X to input port\n", val); + dev->p1 = val; + return 0; + + case 0xcb: /* set keyboard mode */ + kbc_log(dev, "AMI - Set keyboard mode\n"); + return 0; + } + + return 1; +} + + +static uint8_t +write64_ami(void *priv, uint8_t val) +{ + atkbc_t *dev = (atkbc_t *)priv; + uint16_t index = 0x00c0; + + switch (val) { + case 0x00 ... 0x1f: + kbc_log(dev, "AMI - Alias read from %08X\n", val); + kbc_transmit(dev, dev->mem[val + 0x20]); + return 0; + + case 0x40 ... 0x5f: + kbc_log(dev, "AMI - Alias write to %08X\n", dev->kbc_cmd); + dev->kbc_in = 1; + return 0; + + case 0xa0: /* copyright message */ + kbc_log(dev, "AMI - Get copyright message\n"); + kbc_transmit(dev, ami_copr[0]); + dev->kbc_phase = 1; + return 0; + + case 0xa1: /* get controller version */ + kbc_log(dev, "AMI - Get controller version\n"); + // kbc_transmit(dev, 'H'); + kbc_transmit(dev, '5'); + return 0; + + case 0xa2: /* clear keyboard controller lines P22/P23 */ + if (!(dev->flags & KBC_FLAG_PS2)) { + kbc_log(dev, "AMI - Clear KBC lines P22 and P23\n"); + write_output(dev, dev->p2 & 0xf3); + kbc_transmit(dev, 0x00); + return 0; + } + break; + + case 0xa3: /* set keyboard controller lines P22/P23 */ + if (!(dev->flags & KBC_FLAG_PS2)) { + kbc_log(dev, "AMI - Set KBC lines P22 and P23\n"); + write_output(dev, dev->p2 | 0x0c); + kbc_transmit(dev, 0x00); + return 0; + } + break; + + case 0xa4: /* write clock = low */ + if (!(dev->flags & KBC_FLAG_PS2)) { + kbc_log(dev, "AMI - Write clock = low\n"); + dev->ami_stat &= 0xfe; + return 0; + } + break; + + case 0xa5: /* write clock = high */ + if (!(dev->flags & KBC_FLAG_PS2)) { + kbc_log(dev, "AMI - Write clock = high\n"); + dev->ami_stat |= 0x01; + return 0; + } + break; + + case 0xa6: /* read clock */ + if (!(dev->flags & KBC_FLAG_PS2)) { + kbc_log(dev, "AMI - Read clock\n"); + kbc_transmit(dev, !!(dev->ami_stat & 1)); + return 0; + } + break; + + case 0xa7: /* write cache bad */ + if (!(dev->flags & KBC_FLAG_PS2)) { + kbc_log(dev, "AMI - Write cache bad\n"); + dev->ami_stat &= 0xfd; + return 0; + } + break; + + case 0xa8: /* write cache good */ + if (!(dev->flags & KBC_FLAG_PS2)) { + kbc_log(dev, "AMI - Write cache good\n"); + dev->ami_stat |= 0x02; + return 0; + } + break; + + case 0xa9: /* read cache */ + if (!(dev->flags & KBC_FLAG_PS2)) { + kbc_log(dev, "AMI - Read cache\n"); + kbc_transmit(dev, !!(dev->ami_stat & 2)); + return 0; + } + break; + + case 0xaf: /* set extended controller RAM */ + kbc_log(dev, "AMI - Set extended controller RAM\n"); + dev->kbc_in = 1; + return 0; + + case 0xb0 ... 0xb3: + /* set KBC lines P10-P13 (input port bits 0-3) low */ + kbc_log(dev, "AMI - Set KBC lines P10-P13 (input port bits 0-3) low\n"); + if (!(dev->flags & KBC_FLAG_PS2) || (val > 0xb1)) { + dev->p1 &= ~(1 << (val & 0x03)); + } + kbc_transmit(dev, 0x00); + return 0; + + case 0xb4: case 0xb5: + /* set KBC lines P22-P23 (output port bits 2-3) low */ + kbc_log(dev, "AMI - Set KBC lines P22-P23 (output port bits 2-3) low\n"); + if (!(dev->flags & KBC_FLAG_PS2)) + write_output(dev, dev->p2 & ~(4 << (val & 0x01))); + kbc_transmit(dev, 0x00); + return 0; + +#if 0 + case 0xb8 ... 0xbb: +#else + case 0xb9: +#endif + /* set KBC lines P10-P13 (input port bits 0-3) high */ + kbc_log(dev, "AMI - Set KBC lines P10-P13 (input port bits 0-3) high\n"); + if (!(dev->flags & KBC_FLAG_PS2) || (val > 0xb9)) { + dev->p1 |= (1 << (val & 0x03)); + kbc_transmit(dev, 0x00); + } + return 0; + + case 0xb8: + kbc_log(dev, "AMIKey-3 - memory index\n"); + dev->kbc_in = 1; + return 0; + + case 0xba: + kbc_log(dev, "AMIKey-3 - read %02X memory from index %02X\n", dev->mem[dev->mem_index], dev->mem_index); + if (dev->mem_index >= 0x80) { + switch (dev->mem[0x9b] & 0xc0) { + case 0x00: + index = 0x0080; + break; + case 0x40: case 0x80: + index = 0x0000; + break; + case 0xc0: + index = 0x0100; + break; + } + kbc_transmit(dev, dev->mem[index + dev->mem_index]); + } else if (dev->mem_index == 0x42) + kbc_transmit(dev, dev->status); + else if (dev->mem_index >= 0x40) + kbc_transmit(dev, dev->mem[dev->mem_index - 0x40]); + else + kbc_transmit(dev, dev->mem_int[dev->mem_index]); + return 0; + + case 0xbb: + kbc_log(dev, "AMIKey-3 - write to memory index %02X\n", dev->mem_index); + dev->kbc_in = 1; + return 0; + +#if 0 + case 0xbc: case 0xbd: + /* set KBC lines P22-P23 (output port bits 2-3) high */ + kbc_log(dev, "AMI - Set KBC lines P22-P23 (output port bits 2-3) high\n"); + if (!(dev->flags & KBC_FLAG_PS2)) + write_output(dev, dev->p2 | (4 << (val & 0x01))); + kbc_transmit(dev, 0x00); + return 0; +#endif + + case 0xbc: + switch (dev->mem_index) { + case 0x00: /* STAT8042 */ + kbc_transmit(dev, dev->status); + break; + case 0x01: /* Password_ptr */ + kbc_transmit(dev, dev->mem[0x1c]); + break; + case 0x02: /* Wakeup_Tsk_Reg */ + kbc_transmit(dev, dev->mem[0x1e]); + break; + case 0x03: /* CCB */ + kbc_transmit(dev, dev->mem[0x20]); + break; + case 0x04: /* Debounce_time */ + kbc_transmit(dev, dev->mem[0x4d]); + break; + case 0x05: /* Pulse_Width */ + kbc_transmit(dev, dev->mem[0x4e]); + break; + case 0x06: /* Pk_sel_byte */ + kbc_transmit(dev, dev->mem[0x4c]); + break; + case 0x07: /* Func_Tsk_Reg */ + kbc_transmit(dev, dev->mem[0x7e]); + break; + case 0x08: /* TypematicRate */ + kbc_transmit(dev, dev->mem[0x80]); + break; + case 0x09: /* Led_Flag_Byte */ + kbc_transmit(dev, dev->mem[0x81]); + break; + case 0x0a: /* Kbms_Command_St */ + kbc_transmit(dev, dev->mem[0x87]); + break; + case 0x0b: /* Delay_Count_Byte */ + kbc_transmit(dev, dev->mem[0x86]); + break; + case 0x0c: /* KBC_Flags */ + kbc_transmit(dev, dev->mem[0x9b]); + break; + case 0x0d: /* SCODE_HK1 */ + kbc_transmit(dev, dev->mem[0x50]); + break; + case 0x0e: /* SCODE_HK2 */ + kbc_transmit(dev, dev->mem[0x51]); + break; + case 0x0f: /* SCODE_HK3 */ + kbc_transmit(dev, dev->mem[0x52]); + break; + case 0x10: /* SCODE_HK4 */ + kbc_transmit(dev, dev->mem[0x53]); + break; + case 0x11: /* SCODE_HK5 */ + kbc_transmit(dev, dev->mem[0x54]); + break; + case 0x12: /* SCODE_HK6 */ + kbc_transmit(dev, dev->mem[0x55]); + break; + case 0x13: /* TASK_HK1 */ + kbc_transmit(dev, dev->mem[0x56]); + break; + case 0x14: /* TASK_HK2 */ + kbc_transmit(dev, dev->mem[0x57]); + break; + case 0x15: /* TASK_HK3 */ + kbc_transmit(dev, dev->mem[0x58]); + break; + case 0x16: /* TASK_HK4 */ + kbc_transmit(dev, dev->mem[0x59]); + break; + case 0x17: /* TASK_HK5 */ + kbc_transmit(dev, dev->mem[0x5a]); + break; + /* The next 4 bytes have uncertain correspondences. */ + case 0x18: /* Batt_Poll_delay_Time */ + kbc_transmit(dev, dev->mem[0x5b]); + break; + case 0x19: /* Batt_Alarm_Reg1 */ + kbc_transmit(dev, dev->mem[0x5c]); + break; + case 0x1a: /* Batt_Alarm_Reg2 */ + kbc_transmit(dev, dev->mem[0x5d]); + break; + case 0x1b: /* Batt_Alarm_Tsk_Reg */ + kbc_transmit(dev, dev->mem[0x5e]); + break; + case 0x1c: /* Kbc_State1 */ + kbc_transmit(dev, dev->mem[0x9d]); + break; + case 0x1d: /* Aux_Config */ + kbc_transmit(dev, dev->mem[0x75]); + break; + case 0x1e: /* Kbc_State3 */ + kbc_transmit(dev, dev->mem[0x73]); + break; + default: + kbc_transmit(dev, 0x00); + break; + } + kbc_log(dev, "AMIKey-3 - read from config index %02X\n", dev->mem_index); + return 0; + + case 0xbd: + kbc_log(dev, "AMIKey-3 - write to config index %02X\n", dev->mem_index); + dev->kbc_in = 1; + return 0; + + case 0xc1: /* write input port */ + kbc_log(dev, "AMIKey-3 - write input port\n"); + dev->kbc_in = 1; + return 0; + + case 0xc8: case 0xc9: + /* + * (un)block KBC lines P22/P23 + * (allow command D1 to change bits 2/3 of the output port) + */ + kbc_log(dev, "AMI - %slock KBC lines P22 and P23\n", (val & 1) ? "B" : "Unb"); + dev->p2_locked = (val & 1); + return 0; + + case 0xef: /* ??? - sent by AMI486 */ + kbc_log(dev, "??? - sent by AMI486\n"); + return 0; + } + + return write64_generic(dev, val); +} + + +static uint8_t +write64_ibm_mca(void *priv, uint8_t val) +{ + atkbc_t *dev = (atkbc_t *)priv; + + switch (val) { + case 0xc1: /*Copy bits 0 to 3 of input port to status bits 4 to 7*/ + kbc_log(dev, "Copy bits 0 to 3 of input port to status bits 4 to 7\n"); + dev->status &= 0x0f; + dev->status |= ((((dev->p1 & 0xfc) | 0x84) & 0x0f) << 4); + return 0; + + case 0xc2: /*Copy bits 4 to 7 of input port to status bits 4 to 7*/ + kbc_log(dev, "Copy bits 4 to 7 of input port to status bits 4 to 7\n"); + dev->status &= 0x0f; + dev->status |= (((dev->p1 & 0xfc) | 0x84) & 0xf0); + return 0; + + case 0xaf: + kbc_log(dev, "Bad KBC command AF\n"); + return 1; + + case 0xf0 ... 0xff: + kbc_log(dev, "Pulse: %01X\n", (val & 0x03) | 0x0c); + pulse_output(dev, (val & 0x03) | 0x0c); + return 0; + } + + return write64_generic(dev, val); +} + + +static uint8_t +write60_quadtel(void *priv, uint8_t val) +{ + atkbc_t *dev = (atkbc_t *)priv; + + switch(dev->kbc_cmd) { + case 0xcf: /*??? - sent by MegaPC BIOS*/ + kbc_log(dev, "??? - sent by MegaPC BIOS\n"); + return 0; + } + + return 1; +} + + +static uint8_t +write64_olivetti(void *priv, uint8_t val) +{ + atkbc_t *dev = (atkbc_t *)priv; + + switch (val) { + /* This appears to be a clone of "Read input port", in which case, the bis would be: + 7: M290 (AT KBC): + Keyboard lock (1 = unlocked, 0 = locked); + M300 (PS/2 KBC): + Bus expansion board present (1 = present, 0 = not present); + 6: Usually: + Display (1 = MDA, 0 = CGA, but can have its polarity inverted); + 5: Manufacturing jumper (1 = not installed, 0 = installed (infinite loop)); + 4: RAM on motherboard (1 = 256 kB, 0 = 512 kB - which machine actually uses this?); + 3: Fast Ram check (if inactive keyboard works erratically); + 2: Keyboard fuse present + This appears to be in-line with PS/2: 1 = no power, 0 = keyboard power normal; + 1: M290 (AT KBC): + Unused; + M300 (PS/2 KBC): + Mouse data in; + 0: M290 (AT KBC): + Unused; + M300 (PS/2 KBC): + Key data in. + */ + case 0x80: /* Olivetti-specific command */ + /* + * bit 7: bus expansion board present (M300) / keyboard unlocked (M290) + * bits 4-6: ??? + * bit 3: fast ram check (if inactive keyboard works erratically) + * bit 2: keyboard fuse present + * bits 0-1: ??? + */ + kbc_transmit(dev, 0x0c | (is386 ? 0x00 : 0x80)); + return 0; + } + + return write64_generic(dev, val); +} + + +static uint8_t +write64_quadtel(void *priv, uint8_t val) +{ + atkbc_t *dev = (atkbc_t *)priv; + + switch (val) { + case 0xaf: + kbc_log(dev, "Bad KBC command AF\n"); + return 1; + + case 0xcf: /*??? - sent by MegaPC BIOS*/ + kbc_log(dev, "??? - sent by MegaPC BIOS\n"); + dev->kbc_in = 1; + return 0; + } + + return write64_generic(dev, val); +} + + +static uint8_t +write60_toshiba(void *priv, uint8_t val) +{ + atkbc_t *dev = (atkbc_t *)priv; + + switch(dev->kbc_cmd) { + case 0xb6: /* T3100e - set color/mono switch */ + kbc_log(dev, "T3100e - Set color/mono switch\n"); + t3100e_mono_set(val); + return 0; + } + + return 1; +} + + +static uint8_t +write64_toshiba(void *priv, uint8_t val) +{ + atkbc_t *dev = (atkbc_t *)priv; + + switch (val) { + case 0xaf: + kbc_log(dev, "Bad KBC command AF\n"); + return 1; + + case 0xb0: /* T3100e: Turbo on */ + kbc_log(dev, "T3100e: Turbo on\n"); + t3100e_turbo_set(1); + return 0; + + case 0xb1: /* T3100e: Turbo off */ + kbc_log(dev, "T3100e: Turbo off\n"); + t3100e_turbo_set(0); + return 0; + + case 0xb2: /* T3100e: Select external display */ + kbc_log(dev, "T3100e: Select external display\n"); + t3100e_display_set(0x00); + return 0; + + case 0xb3: /* T3100e: Select internal display */ + kcd_log("T3100e: Select internal display\n"); + t3100e_display_set(0x01); + return 0; + + case 0xb4: /* T3100e: Get configuration / status */ + kbc_log(dev, "T3100e: Get configuration / status\n"); + kbc_transmit(dev, t3100e_config_get()); + return 0; + + case 0xb5: /* T3100e: Get colour / mono byte */ + kbc_log(dev, "T3100e: Get colour / mono byte\n"); + kbc_transmit(dev, t3100e_mono_get()); + return 0; + + case 0xb6: /* T3100e: Set colour / mono byte */ + kbc_log(dev, "T3100e: Set colour / mono byte\n"); + dev->kbc_in = 1; + return 0; + + case 0xb7: /* T3100e: Emulate PS/2 keyboard */ + case 0xb8: /* T3100e: Emulate AT keyboard */ + dev->flags &= ~KBC_FLAG_PS2; + if (val == 0xb7) { + kbc_log(dev, "T3100e: Emulate PS/2 keyboard\n"); + dev->flags |= KBC_FLAG_PS2; + } else + kbc_log(dev, "T3100e: Emulate AT keyboard\n"); +#if (!defined(RELEASE_BUILD) && defined(ENABLE_KBD_AT_LOG)) + log_set_dev_name(dev->kbc_log, (dev->flags & KBC_FLAG_PS2) ? "AT KBC" : "PS/2 KBC"); +#endif + return 0; + + case 0xbb: /* T3100e: Read 'Fn' key. + Return it for right Ctrl and right Alt; on the real + T3100e, these keystrokes could only be generated + using 'Fn'. */ + kbc_log(dev, "T3100e: Read 'Fn' key\n"); + if (keyboard_recv(0xb8) || /* Right Alt */ + keyboard_recv(0x9d)) /* Right Ctrl */ + kbc_transmit(dev, 0x04); + else + kbc_transmit(dev, 0x00); + return 0; + + case 0xbc: /* T3100e: Reset Fn+Key notification */ + kbc_log(dev, "T3100e: Reset Fn+Key notification\n"); + t3100e_notify_set(0x00); + return 0; + + case 0xc0: /*Read input port*/ + kbc_log(dev, "Read input port\n"); + + /* The T3100e returns all bits set except bit 6 which + * is set by t3100e_mono_set() */ + dev->p1 = (t3100e_mono_get() & 1) ? 0xff : 0xbf; + kbc_transmit(dev, dev->p1); + return 0; + + } + + return write64_generic(dev, val); +} + + +static void +kbc_write(uint16_t port, uint8_t val, void *priv) +{ + atkbc_t *dev = (atkbc_t *)priv; + + kbc_log(dev, "[%04X:%08X] write(%04X, %02X)\n", CS, cpu_state.pc, port, val); + + switch (port) { + case 0x60: + dev->status = (dev->status & ~STAT_CD) | STAT_IFULL; + dev->ib = val; + // kbd_status("Write %02X: %02X, Status = %02X\n", port, val, dev->status); + +#if 0 + if ((dev->fast_a20_phase == 1)/* && ((val == 0xdd) || (val == 0xdf))*/) { + dev->status &= ~STAT_IFULL; + write_output(dev, val); + dev->fast_a20_phase = 0; + } +#endif + break; + case 0x64: + dev->status |= (STAT_CD | STAT_IFULL); + dev->ib = val; + // kbd_status("Write %02X: %02X, Status = %02X\n", port, val, dev->status); + +#if 0 + if (val == 0xd1) { + dev->status &= ~STAT_IFULL; + dev->fast_a20_phase = 1; + } else if (val == 0xfe) { + dev->status &= ~STAT_IFULL; + pulse_output(dev, 0x0e); + } else if ((val == 0xad) || (val == 0xae)) { + dev->status &= ~STAT_IFULL; + if (val & 0x01) + dev->mem[0x20] |= 0x10; + else + dev->mem[0x20] &= ~0x10; + } else if (val == 0xa1) { + dev->status &= ~STAT_IFULL; + kbc_send_to_ob(dev, 'H', 0, 0x00); + } +#endif + break; + } +} + + +static uint8_t +kbc_read(uint16_t port, void *priv) +{ + atkbc_t *dev = (atkbc_t *)priv; + uint8_t ret = 0xff; + + // if (dev->flags & KBC_FLAG_PS2) + // cycles -= ISA_CYCLES(8); + + switch (port) { + case 0x60: + ret = dev->ob; + dev->status &= ~STAT_OFULL; + picintc(dev->last_irq); + dev->last_irq = 0; + break; + + case 0x64: + ret = dev->status; + break; + + default: + kbc_log(dev, "Reading unknown port %02X\n", port); + break; + } + + kbc_log(dev, "[%04X:%08X] read(%04X) = %02X\n",CS, cpu_state.pc, port, ret); + + return(ret); +} + + +static void +kbc_reset(void *priv) +{ + atkbc_t *dev = (atkbc_t *)priv; + int i; + uint8_t kbc_ven = 0x0; + kbc_ven = dev->flags & KBC_VEN_MASK; + + dev->status = STAT_UNLOCKED; + dev->mem[0x20] = 0x01; + dev->mem[0x20] |= CCB_TRANSLATE; + write_output(dev, 0xcf); + dev->last_irq = 0; + dev->secr_phase = 0; + dev->in = 0; + dev->ami_mode = !!(dev->flags & KBC_FLAG_PS2); + + /* Set up the correct Video Type bits. */ + dev->p1 = video_is_mda() ? 0xf0 : 0xb0; + if ((kbc_ven == KBC_VEN_XI8088) || (kbc_ven == KBC_VEN_ACER)) + dev->p1 ^= 0x40; + if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) + dev->inhibit = ((dev->p1 & 0x80) >> 3); + else + dev->inhibit = 0x10; + kbc_log(dev, "Input port = %02x\n", dev->p1); + + keyboard_mode = 0x02 | (dev->mem[0x20] & CCB_TRANSLATE); + + /* Enable keyboard, disable mouse. */ + set_enable_kbd(dev, 1); + keyboard_scan = 1; + set_enable_mouse(dev, 0); + mouse_scan = 0; + + dev->ob = 0xff; + + sc_or = 0; + + dev->mem[0x31] = 0xfe; +} + + +/* Reset the AT keyboard - this is needed for the PCI TRC and is done + until a better solution is found. */ +void +keyboard_at_reset(void) +{ + kbc_reset(SavedKbd); +} + + +void +kbc_dev_attach(kbc_dev_t *kbc_dev, int channel) +{ + if ((channel < 1) || (channel > 2)) + log_fatal(saved_kbc->log, "Attaching device to invalid channel %i\n", channel); + else { + kbc_log(saved_kbc, "Attaching device to channel %i\n", channel); + saved_kbc->kbc_devs[channel - 1] = kbc_dev; + } +} + + +static void +kbc_close(void *priv) +{ + atkbc_t *dev = (atkbc_t *)priv; + + kbc_reset(dev); + + /* Stop timers. */ + timer_disable(&dev->send_delay_timer); + +#if (!defined(RELEASE_BUILD) && defined(ENABLE_KBC_AT_LOG)) + log_close(dev->log); +#endif + + free(dev); +} + + +static void * +kbc_init(const device_t *info) +{ + atkbc_t *dev; + + dev = (atkbc_t *)malloc(sizeof(atkbc_t)); + memset(dev, 0x00, sizeof(atkbc_t)); + + dev->flags = info->local; + + video_reset(gfxcard); + dev->kbc_poll_phase = KBC_RESET; + + io_sethandler(0x0060, 1, kbc_read, NULL, NULL, kbc_write, NULL, NULL, dev); + io_sethandler(0x0064, 1, kbc_read, NULL, NULL, kbc_write, NULL, NULL, dev); + + timer_add(&dev->send_delay_timer, kbd_poll, dev, 1); + timer_add(&dev->pulse_cb, pulse_poll, dev, 0); + +#if (!defined(RELEASE_BUILD) && defined(ENABLE_KBC_AT_LOG)) + dev->kbc_log = log_open((dev->flags & KBC_FLAG_PS2) ? "AT KBC" : "PS/2 KBC"); +#endif + + dev->write60_ven = NULL; + dev->write64_ven = NULL; + + switch(dev->flags & KBC_VEN_MASK) { + case KBC_VEN_ACER: + case KBC_VEN_GENERIC: + case KBC_VEN_NCR: + case KBC_VEN_IBM_PS1: + case KBC_VEN_XI8088: + dev->write64_ven = write64_generic; + break; + + case KBC_VEN_OLIVETTI: + /* The Olivetti controller is a special case - starts directly in the + main loop instead of the reset loop. */ + dev->kbc_poll_phase = KBC_MAIN_LOOP; + dev->write64_ven = write64_olivetti; + break; + + case KBC_VEN_AMI: + case KBC_VEN_INTEL_AMI: + dev->write60_ven = write60_ami; + dev->write64_ven = write64_ami; + break; + + case KBC_VEN_IBM_MCA: + dev->write64_ven = write64_ibm_mca; + break; + + case KBC_VEN_QUADTEL: + dev->write60_ven = write60_quadtel; + dev->write64_ven = write64_quadtel; + break; + + case KBC_VEN_TOSHIBA: + dev->write60_ven = write60_toshiba; + dev->write64_ven = write64_toshiba; + break; + } + + kbc_reset(dev); + + /* Local variable, needed for device attaching. */ + saved_kbc = dev; + + /* Add the actual keyboard. */ + device_add(&keyboard_at_kbd_device); + + return(dev); +} + + +const device_t keyboard_at_device = { + "PC/AT Keyboard", + 0, + KBC_TYPE_ISA | KBC_VEN_GENERIC, + kbc_init, + kbc_close, + kbc_reset, + { NULL }, NULL, NULL, NULL +}; + +const device_t keyboard_at_ami_device = { + "PC/AT Keyboard (AMI)", + 0, + KBC_TYPE_ISA | KBC_VEN_AMI, + kbc_init, + kbc_close, + kbc_reset, + { NULL }, NULL, NULL, NULL +}; + +const device_t keyboard_at_toshiba_device = { + "PC/AT Keyboard (Toshiba)", + 0, + KBC_TYPE_ISA | KBC_VEN_TOSHIBA, + kbc_init, + kbc_close, + kbc_reset, + { NULL }, NULL, NULL, NULL +}; + +const device_t keyboard_at_olivetti_device = { + "PC/AT Keyboard (Olivetti)", + 0, + KBC_TYPE_ISA | KBC_VEN_OLIVETTI, + kbc_init, + kbc_close, + kbc_reset, + { NULL }, NULL, NULL, NULL +}; + +const device_t keyboard_at_ncr_device = { + "PC/AT Keyboard (NCR)", + 0, + KBC_TYPE_ISA | KBC_VEN_NCR, + kbc_init, + kbc_close, + kbc_reset, + { NULL }, NULL, NULL, NULL +}; + +const device_t keyboard_ps2_device = { + "PS/2 Keyboard", + 0, + KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, + kbc_init, + kbc_close, + kbc_reset, + { NULL }, NULL, NULL, NULL +}; + +const device_t keyboard_ps2_ps1_device = { + "PS/2 Keyboard (IBM PS/1)", + 0, + KBC_TYPE_PS2_1 | KBC_VEN_IBM_PS1, + kbc_init, + kbc_close, + kbc_reset, + { NULL }, NULL, NULL, NULL +}; + +const device_t keyboard_ps2_ps1_pci_device = { + "PS/2 Keyboard (IBM PS/1)", + DEVICE_PCI, + KBC_TYPE_PS2_1 | KBC_VEN_IBM_PS1, + kbc_init, + kbc_close, + kbc_reset, + { NULL }, NULL, NULL, NULL +}; + +const device_t keyboard_ps2_xi8088_device = { + "PS/2 Keyboard (Xi8088)", + 0, + KBC_TYPE_PS2_1 | KBC_VEN_XI8088, + kbc_init, + kbc_close, + kbc_reset, + { NULL }, NULL, NULL, NULL +}; + +const device_t keyboard_ps2_ami_device = { + "PS/2 Keyboard (AMI)", + 0, + KBC_TYPE_PS2_1 | KBC_VEN_AMI, + kbc_init, + kbc_close, + kbc_reset, + { NULL }, NULL, NULL, NULL +}; + +const device_t keyboard_ps2_olivetti_device = { + "PS/2 Keyboard (Olivetti)", + 0, + KBC_TYPE_PS2_1 | KBC_VEN_OLIVETTI, + kbc_init, + kbc_close, + kbc_reset, + { NULL }, NULL, NULL, NULL +}; + +const device_t keyboard_ps2_mca_device = { + "PS/2 Keyboard", + 0, + KBC_TYPE_PS2_1 | KBC_VEN_IBM_MCA, + kbc_init, + kbc_close, + kbc_reset, + { NULL }, NULL, NULL, NULL +}; + +const device_t keyboard_ps2_mca_2_device = { + "PS/2 Keyboard", + 0, + KBC_TYPE_PS2_2 | KBC_VEN_IBM_MCA, + kbc_init, + kbc_close, + kbc_reset, + { NULL }, NULL, NULL, NULL +}; + +const device_t keyboard_ps2_quadtel_device = { + "PS/2 Keyboard (Quadtel/MegaPC)", + 0, + KBC_TYPE_PS2_1 | KBC_VEN_QUADTEL, + kbc_init, + kbc_close, + kbc_reset, + { NULL }, NULL, NULL, NULL +}; + +const device_t keyboard_ps2_pci_device = { + "PS/2 Keyboard", + DEVICE_PCI, + KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, + kbc_init, + kbc_close, + kbc_reset, + { NULL }, NULL, NULL, NULL +}; + +const device_t keyboard_ps2_ami_pci_device = { + "PS/2 Keyboard (AMI)", + DEVICE_PCI, + KBC_TYPE_PS2_1 | KBC_VEN_AMI, + kbc_init, + kbc_close, + kbc_reset, + { NULL }, NULL, NULL, NULL +}; + +const device_t keyboard_ps2_intel_ami_pci_device = { + "PS/2 Keyboard (AMI)", + DEVICE_PCI, + KBC_TYPE_PS2_1 | KBC_VEN_INTEL_AMI, + kbc_init, + kbc_close, + kbc_reset, + { NULL }, NULL, NULL, NULL +}; + +const device_t keyboard_ps2_acer_pci_device = { + "PS/2 Keyboard (Acer 90M002A)", + DEVICE_PCI, + KBC_TYPE_PS2_1 | KBC_VEN_ACER, + kbc_init, + kbc_close, + kbc_reset, + { NULL }, NULL, NULL, NULL +}; + + +void +keyboard_at_set_mouse(void (*func)(uint8_t val, void *priv), void *priv) +{ +} + + +void +keyboard_at_adddata_mouse(uint8_t val) +{ + return; +} + + +void +keyboard_at_adddata_mouse_direct(uint8_t val) +{ + return; +} + + +void +keyboard_at_adddata_mouse_cmd(uint8_t val) +{ + return; +} + + +void +keyboard_at_mouse_reset(void) +{ + return; +} + + +uint8_t +keyboard_at_mouse_pos(void) +{ + return ((mouse_queue_end - mouse_queue_start) & 0xf); +} + + +int +keyboard_at_fixed_channel(void) +{ + return 0x000; +} + + +void +keyboard_at_set_mouse_scan(uint8_t val) +{ + atkbc_t *dev = SavedKbd; + uint8_t temp_mouse_scan = val ? 1 : 0; + + if (temp_mouse_scan == !(dev->mem[0x20] & 0x20)) + return; + + set_enable_mouse(dev, val ? 1 : 0); + + kbc_log(dev, "Mouse scan %sabled via PCI\n", mouse_scan ? "en" : "dis"); +} + + +uint8_t +keyboard_at_get_mouse_scan(void) +{ + atkbc_t *dev = SavedKbd; + + return((dev->mem[0x20] & 0x20) ? 0x00 : 0x10); +} + + +void +keyboard_at_set_a20_key(int state) +{ + atkbc_t *dev = SavedKbd; + + write_output(dev, (dev->p2 & 0xfd) | ((!!state) << 1)); +} + + +void +keyboard_at_set_mode(int ps2) +{ + atkbc_t *dev = SavedKbd; + + if (ps2) + dev->flags |= KBC_FLAG_PS2; + else + dev->flags &= ~KBC_FLAG_PS2; +} diff --git a/src/device/kbd_at.c b/src/device/kbd_at.c new file mode 100644 index 000000000..f24177d37 --- /dev/null +++ b/src/device/kbd_at.c @@ -0,0 +1,1162 @@ +/* + * 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. + * + * Intel 8042 (AT keyboard controller) emulation. + * + * + * + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * EngiNerd + * + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2020 EngiNerd. + */ +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include +#include <86box/86box.h> +#include <86box/timer.h> +#include <86box/device.h> +#include <86box/log.h> +#include <86box/keyboard.h> + + +// static uint8_t key_queue[16]; +// static int key_queue_start = 0, key_queue_end = 0; +// static uint8_t kbd_last_scan_code; + +typedef struct { + uint8_t in, cmd, in_cmd, state, last_byte; + + uint8_t queue[16]; + + uint16_t phase; + + int quueue_start, queue_end; + + void * log; + + kbc_dev_t kd; +} atkbd_t; + + +enum +{ + CHANNEL_KBC = 0, + CHANNEL_KBD, + CHANNEL_MOUSE +}; + +enum +{ + KBD_MAIN_LOOP = 0, + KBD_CMD_PROCESS +}; + +enum +{ + MOUSE_MAIN_LOOP_1 = 0, + MOUSE_CMD_PROCESS, + MOUSE_CMD_END, + MOUSE_MAIN_LOOP_2 +}; + +enum { + KBC_MAIN_LOOP = 0, + KBC_RESET = 1, + KBC_WAIT = 4, + KBC_WAIT_FOR_KBD, + KBC_WAIT_FOR_MOUSE, + KBC_WAIT_FOR_BOTH +}; + + +static void kbd_cmd_process(atkbd_t *dev); + + +/* bit 0 = repeat, bit 1 = makes break code? */ +uint8_t keyboard_set3_flags[512]; +uint8_t keyboard_set3_all_repeat; +uint8_t keyboard_set3_all_break; + + +static atkbd_t *SavedKbd = NULL; // FIXME: remove!!! --FvK + + +#ifdef USE_SET1 +static const scancode scancode_set1[512] = { + { { 0},{ 0} }, { { 0x01,0},{ 0x81,0} }, { { 0x02,0},{ 0x82,0} }, { { 0x03,0},{ 0x83,0} }, /*000*/ + { { 0x04,0},{ 0x84,0} }, { { 0x05,0},{ 0x85,0} }, { { 0x06,0},{ 0x86,0} }, { { 0x07,0},{ 0x87,0} }, /*004*/ + { { 0x08,0},{ 0x88,0} }, { { 0x09,0},{ 0x89,0} }, { { 0x0a,0},{ 0x8a,0} }, { { 0x0b,0},{ 0x8b,0} }, /*008*/ + { { 0x0c,0},{ 0x8c,0} }, { { 0x0d,0},{ 0x8d,0} }, { { 0x0e,0},{ 0x8e,0} }, { { 0x0f,0},{ 0x8f,0} }, /*00c*/ + { { 0x10,0},{ 0x90,0} }, { { 0x11,0},{ 0x91,0} }, { { 0x12,0},{ 0x92,0} }, { { 0x13,0},{ 0x93,0} }, /*010*/ + { { 0x14,0},{ 0x94,0} }, { { 0x15,0},{ 0x95,0} }, { { 0x16,0},{ 0x96,0} }, { { 0x17,0},{ 0x97,0} }, /*014*/ + { { 0x18,0},{ 0x98,0} }, { { 0x19,0},{ 0x99,0} }, { { 0x1a,0},{ 0x9a,0} }, { { 0x1b,0},{ 0x9b,0} }, /*018*/ + { { 0x1c,0},{ 0x9c,0} }, { { 0x1d,0},{ 0x9d,0} }, { { 0x1e,0},{ 0x9e,0} }, { { 0x1f,0},{ 0x9f,0} }, /*01c*/ + { { 0x20,0},{ 0xa0,0} }, { { 0x21,0},{ 0xa1,0} }, { { 0x22,0},{ 0xa2,0} }, { { 0x23,0},{ 0xa3,0} }, /*020*/ + { { 0x24,0},{ 0xa4,0} }, { { 0x25,0},{ 0xa5,0} }, { { 0x26,0},{ 0xa6,0} }, { { 0x27,0},{ 0xa7,0} }, /*024*/ + { { 0x28,0},{ 0xa8,0} }, { { 0x29,0},{ 0xa9,0} }, { { 0x2a,0},{ 0xaa,0} }, { { 0x2b,0},{ 0xab,0} }, /*028*/ + { { 0x2c,0},{ 0xac,0} }, { { 0x2d,0},{ 0xad,0} }, { { 0x2e,0},{ 0xae,0} }, { { 0x2f,0},{ 0xaf,0} }, /*02c*/ + { { 0x30,0},{ 0xb0,0} }, { { 0x31,0},{ 0xb1,0} }, { { 0x32,0},{ 0xb2,0} }, { { 0x33,0},{ 0xb3,0} }, /*030*/ + { { 0x34,0},{ 0xb4,0} }, { { 0x35,0},{ 0xb5,0} }, { { 0x36,0},{ 0xb6,0} }, { { 0x37,0},{ 0xb7,0} }, /*034*/ + { { 0x38,0},{ 0xb8,0} }, { { 0x39,0},{ 0xb9,0} }, { { 0x3a,0},{ 0xba,0} }, { { 0x3b,0},{ 0xbb,0} }, /*038*/ + { { 0x3c,0},{ 0xbc,0} }, { { 0x3d,0},{ 0xbd,0} }, { { 0x3e,0},{ 0xbe,0} }, { { 0x3f,0},{ 0xbf,0} }, /*03c*/ + { { 0x40,0},{ 0xc0,0} }, { { 0x41,0},{ 0xc1,0} }, { { 0x42,0},{ 0xc2,0} }, { { 0x43,0},{ 0xc3,0} }, /*040*/ + { { 0x44,0},{ 0xc4,0} }, { { 0x45,0},{ 0xc5,0} }, { { 0x46,0},{ 0xc6,0} }, { { 0x47,0},{ 0xc7,0} }, /*044*/ + { { 0x48,0},{ 0xc8,0} }, { { 0x49,0},{ 0xc9,0} }, { { 0x4a,0},{ 0xca,0} }, { { 0x4b,0},{ 0xcb,0} }, /*048*/ + { { 0x4c,0},{ 0xcc,0} }, { { 0x4d,0},{ 0xcd,0} }, { { 0x4e,0},{ 0xce,0} }, { { 0x4f,0},{ 0xcf,0} }, /*04c*/ + { { 0x50,0},{ 0xd0,0} }, { { 0x51,0},{ 0xd1,0} }, { { 0x52,0},{ 0xd2,0} }, { { 0x53,0},{ 0xd3,0} }, /*050*/ + { { 0x54,0},{ 0xd4,0} }, { { 0x55,0},{ 0xd5,0} }, { { 0x56,0},{ 0xd6,0} }, { { 0x57,0},{ 0xd7,0} }, /*054*/ + { { 0x58,0},{ 0xd8,0} }, { { 0x59,0},{ 0xd9,0} }, { { 0x5a,0},{ 0xda,0} }, { { 0x5b,0},{ 0xdb,0} }, /*058*/ + { { 0x5c,0},{ 0xdc,0} }, { { 0x5d,0},{ 0xdd,0} }, { { 0x5e,0},{ 0xde,0} }, { { 0x5f,0},{ 0xdf,0} }, /*05c*/ + { { 0x60,0},{ 0xe0,0} }, { { 0x61,0},{ 0xe1,0} }, { { 0x62,0},{ 0xe2,0} }, { { 0x63,0},{ 0xe3,0} }, /*060*/ + { { 0x64,0},{ 0xe4,0} }, { { 0x65,0},{ 0xe5,0} }, { { 0x66,0},{ 0xe6,0} }, { { 0x67,0},{ 0xe7,0} }, /*064*/ + { { 0x68,0},{ 0xe8,0} }, { { 0x69,0},{ 0xe9,0} }, { { 0x6a,0},{ 0xea,0} }, { { 0x6b,0},{ 0xeb,0} }, /*068*/ + { { 0x6c,0},{ 0xec,0} }, { { 0x6d,0},{ 0xed,0} }, { { 0x6e,0},{ 0xee,0} }, { { 0x6f,0},{ 0xef,0} }, /*06c*/ + { { 0x70,0},{ 0xf0,0} }, { { 0x71,0},{ 0xf1,0} }, { { 0x72,0},{ 0xf2,0} }, { { 0x73,0},{ 0xf3,0} }, /*070*/ + { { 0x74,0},{ 0xf4,0} }, { { 0x75,0},{ 0xf5,0} }, { { 0x76,0},{ 0xf6,0} }, { { 0x77,0},{ 0xf7,0} }, /*074*/ + { { 0x78,0},{ 0xf8,0} }, { { 0x79,0},{ 0xf9,0} }, { { 0x7a,0},{ 0xfa,0} }, { { 0x7b,0},{ 0xfb,0} }, /*078*/ + { { 0x7c,0},{ 0xfc,0} }, { { 0x7d,0},{ 0xfd,0} }, { { 0x7e,0},{ 0xfe,0} }, { { 0x7f,0},{ 0xff,0} }, /*07c*/ + + { { 0x80,0},{ 0} }, { { 0x81,0},{ 0} }, { { 0x82,0},{ 0} }, { { 0},{ 0} }, /*080*/ + { { 0},{ 0} }, { { 0x85,0},{ 0} }, { { 0x86,0},{ 0} }, { { 0x87,0},{ 0} }, /*084*/ + { { 0x88,0},{ 0} }, { { 0x89,0},{ 0} }, { { 0x8a,0},{ 0} }, { { 0x8b,0},{ 0} }, /*088*/ + { { 0x8c,0},{ 0} }, { { 0x8d,0},{ 0} }, { { 0x8e,0},{ 0} }, { { 0x8f,0},{ 0} }, /*08c*/ + { { 0x90,0},{ 0} }, { { 0x91,0},{ 0} }, { { 0x92,0},{ 0} }, { { 0x93,0},{ 0} }, /*090*/ + { { 0x94,0},{ 0} }, { { 0x95,0},{ 0} }, { { 0x96,0},{ 0} }, { { 0x97,0},{ 0} }, /*094*/ + { { 0x98,0},{ 0} }, { { 0x99,0},{ 0} }, { { 0x9a,0},{ 0} }, { { 0x9b,0},{ 0} }, /*098*/ + { { 0x9c,0},{ 0} }, { { 0x9d,0},{ 0} }, { { 0x9e,0},{ 0} }, { { 0x9f,0},{ 0} }, /*09c*/ + { { 0xa0,0},{ 0} }, { { 0xa1,0},{ 0} }, { { 0xa2,0},{ 0} }, { { 0xa3,0},{ 0} }, /*0a0*/ + { { 0xa4,0},{ 0} }, { { 0xa5,0},{ 0} }, { { 0xa6,0},{ 0} }, { { 0xa7,0},{ 0} }, /*0a4*/ + { { 0xa8,0},{ 0} }, { { 0xa9,0},{ 0} }, { { 0xaa,0},{ 0} }, { { 0xab,0},{ 0} }, /*0a8*/ + { { 0xac,0},{ 0} }, { { 0xad,0},{ 0} }, { { 0xae,0},{ 0} }, { { 0xaf,0},{ 0} }, /*0ac*/ + { { 0xb0,0},{ 0} }, { { 0xb1,0},{ 0} }, { { 0xb2,0},{ 0} }, { { 0xb3,0},{ 0} }, /*0b0*/ + { { 0xb4,0},{ 0} }, { { 0xb5,0},{ 0} }, { { 0xb6,0},{ 0} }, { { 0xb7,0},{ 0} }, /*0b4*/ + { { 0xb8,0},{ 0} }, { { 0xb9,0},{ 0} }, { { 0xba,0},{ 0} }, { { 0xbb,0},{ 0} }, /*0b8*/ + { { 0xbc,0},{ 0} }, { { 0xbd,0},{ 0} }, { { 0xbe,0},{ 0} }, { { 0xbf,0},{ 0} }, /*0bc*/ + { { 0xc0,0},{ 0} }, { { 0xc1,0},{ 0} }, { { 0xc2,0},{ 0} }, { { 0xc3,0},{ 0} }, /*0c0*/ + { { 0xc4,0},{ 0} }, { { 0xc5,0},{ 0} }, { { 0xc6,0},{ 0} }, { { 0xc7,0},{ 0} }, /*0c4*/ + { { 0xc8,0},{ 0} }, { { 0xc9,0},{ 0} }, { { 0xca,0},{ 0} }, { { 0xcb,0},{ 0} }, /*0c8*/ + { { 0xcc,0},{ 0} }, { { 0xcd,0},{ 0} }, { { 0xce,0},{ 0} }, { { 0xcf,0},{ 0} }, /*0cc*/ + { { 0xd0,0},{ 0} }, { { 0xd1,0},{ 0} }, { { 0xd2,0},{ 0} }, { { 0xd3,0},{ 0} }, /*0d0*/ + { { 0xd4,0},{ 0} }, { { 0xd5,0},{ 0} }, { { 0xd6,0},{ 0} }, { { 0xd7,0},{ 0} }, /*0d4*/ + { { 0xd8,0},{ 0} }, { { 0xd9,0},{ 0} }, { { 0xda,0},{ 0} }, { { 0xdb,0},{ 0} }, /*0d8*/ + { { 0xdc,0},{ 0} }, { { 0xdd,0},{ 0} }, { { 0xde,0},{ 0} }, { { 0xdf,0},{ 0} }, /*0dc*/ + { { 0xe0,0},{ 0} }, { { 0xe1,0},{ 0} }, { { 0xe2,0},{ 0} }, { { 0xe3,0},{ 0} }, /*0e0*/ + { { 0xe4,0},{ 0} }, { { 0xe5,0},{ 0} }, { { 0xe6,0},{ 0} }, { { 0xe7,0},{ 0} }, /*0e4*/ + { { 0xe8,0},{ 0} }, { { 0xe9,0},{ 0} }, { { 0xea,0},{ 0} }, { { 0xeb,0},{ 0} }, /*0e8*/ + { { 0xec,0},{ 0} }, { { 0xed,0},{ 0} }, { { 0xee,0},{ 0} }, { { 0xef,0},{ 0} }, /*0ec*/ + { { 0},{ 0} }, { { 0xf1,0},{ 0} }, { { 0xf2,0},{ 0} }, { { 0xf3,0},{ 0} }, /*0f0*/ + { { 0xf4,0},{ 0} }, { { 0xf5,0},{ 0} }, { { 0xf6,0},{ 0} }, { { 0xf7,0},{ 0} }, /*0f4*/ + { { 0xf8,0},{ 0} }, { { 0xf9,0},{ 0} }, { { 0xfa,0},{ 0} }, { { 0xfb,0},{ 0} }, /*0f8*/ + { { 0xfc,0},{ 0} }, { { 0xfd,0},{ 0} }, { { 0xfe,0},{ 0} }, { { 0xff,0},{ 0} }, /*0fc*/ + + { {0xe1,0x1d,0},{0xe1, 0x9d,0} }, { {0xe0,0x01,0},{0xe0, 0x81,0} }, { {0xe0,0x02,0},{0xe0, 0x82,0} }, { {0xe0,0x03,0},{0xe0, 0x83,0} }, /*100*/ + { {0xe0,0x04,0},{0xe0, 0x84,0} }, { {0xe0,0x05,0},{0xe0, 0x85,0} }, { {0xe0,0x06,0},{0xe0, 0x86,0} }, { {0xe0,0x07,0},{0xe0, 0x87,0} }, /*104*/ + { {0xe0,0x08,0},{0xe0, 0x88,0} }, { {0xe0,0x09,0},{0xe0, 0x89,0} }, { {0xe0,0x0a,0},{0xe0, 0x8a,0} }, { {0xe0,0x0b,0},{0xe0, 0x8b,0} }, /*108*/ + { {0xe0,0x0c,0},{0xe0, 0x8c,0} }, { { 0},{ 0} }, { {0xe0,0x0e,0},{0xe0, 0x8e,0} }, { {0xe0,0x0f,0},{0xe0, 0x8f,0} }, /*10c*/ + { {0xe0,0x10,0},{0xe0, 0x90,0} }, { {0xe0,0x11,0},{0xe0, 0x91,0} }, { {0xe0,0x12,0},{0xe0, 0x92,0} }, { {0xe0,0x13,0},{0xe0, 0x93,0} }, /*110*/ + { {0xe0,0x14,0},{0xe0, 0x94,0} }, { {0xe0,0x15,0},{0xe0, 0x95,0} }, { {0xe0,0x16,0},{0xe0, 0x96,0} }, { {0xe0,0x17,0},{0xe0, 0x97,0} }, /*114*/ + { {0xe0,0x18,0},{0xe0, 0x98,0} }, { {0xe0,0x19,0},{0xe0, 0x99,0} }, { {0xe0,0x1a,0},{0xe0, 0x9a,0} }, { {0xe0,0x1b,0},{0xe0, 0x9b,0} }, /*118*/ + { {0xe0,0x1c,0},{0xe0, 0x9c,0} }, { {0xe0,0x1d,0},{0xe0, 0x9d,0} }, { {0xe0,0x1e,0},{0xe0, 0x9e,0} }, { {0xe0,0x1f,0},{0xe0, 0x9f,0} }, /*11c*/ + { {0xe0,0x20,0},{0xe0, 0xa0,0} }, { {0xe0,0x21,0},{0xe0, 0xa1,0} }, { {0xe0,0x22,0},{0xe0, 0xa2,0} }, { {0xe0,0x23,0},{0xe0, 0xa3,0} }, /*120*/ + { {0xe0,0x24,0},{0xe0, 0xa4,0} }, { {0xe0,0x25,0},{0xe0, 0xa5,0} }, { {0xe0,0x26,0},{0xe0, 0xa6,0} }, { { 0},{ 0} }, /*124*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*128*/ + { {0xe0,0x2c,0},{0xe0, 0xac,0} }, { {0xe0,0x2d,0},{0xe0, 0xad,0} }, { {0xe0,0x2e,0},{0xe0, 0xae,0} }, { {0xe0,0x2f,0},{0xe0, 0xaf,0} }, /*12c*/ + { {0xe0,0x30,0},{0xe0, 0xb0,0} }, { {0xe0,0x31,0},{0xe0, 0xb1,0} }, { {0xe0,0x32,0},{0xe0, 0xb2,0} }, { { 0},{ 0} }, /*130*/ + { {0xe0,0x34,0},{0xe0, 0xb4,0} }, { {0xe0,0x35,0},{0xe0, 0xb5,0} }, { { 0},{ 0} }, { {0xe0,0x37,0},{0xe0, 0xb7,0} }, /*134*/ + { {0xe0,0x38,0},{0xe0, 0xb8,0} }, { { 0},{ 0} }, { {0xe0,0x3a,0},{0xe0, 0xba,0} }, { {0xe0,0x3b,0},{0xe0, 0xbb,0} }, /*138*/ + { {0xe0,0x3c,0},{0xe0, 0xbc,0} }, { {0xe0,0x3d,0},{0xe0, 0xbd,0} }, { {0xe0,0x3e,0},{0xe0, 0xbe,0} }, { {0xe0,0x3f,0},{0xe0, 0xbf,0} }, /*13c*/ + { {0xe0,0x40,0},{0xe0, 0xc0,0} }, { {0xe0,0x41,0},{0xe0, 0xc1,0} }, { {0xe0,0x42,0},{0xe0, 0xc2,0} }, { {0xe0,0x43,0},{0xe0, 0xc3,0} }, /*140*/ + { {0xe0,0x44,0},{0xe0, 0xc4,0} }, { { 0},{ 0} }, { {0xe0,0x46,0},{0xe0, 0xc6,0} }, { {0xe0,0x47,0},{0xe0, 0xc7,0} }, /*144*/ + { {0xe0,0x48,0},{0xe0, 0xc8,0} }, { {0xe0,0x49,0},{0xe0, 0xc9,0} }, { { 0},{ 0} }, { {0xe0,0x4b,0},{0xe0, 0xcb,0} }, /*148*/ + { {0xe0,0x4c,0},{0xe0, 0xcc,0} }, { {0xe0,0x4d,0},{0xe0, 0xcd,0} }, { {0xe0,0x4e,0},{0xe0, 0xce,0} }, { {0xe0,0x4f,0},{0xe0, 0xcf,0} }, /*14c*/ + { {0xe0,0x50,0},{0xe0, 0xd0,0} }, { {0xe0,0x51,0},{0xe0, 0xd1,0} }, { {0xe0,0x52,0},{0xe0, 0xd2,0} }, { {0xe0,0x53,0},{0xe0, 0xd3,0} }, /*150*/ + { { 0},{ 0} }, { {0xe0,0x55,0},{0xe0, 0xd5,0} }, { { 0},{ 0} }, { {0xe0,0x57,0},{0xe0, 0xd7,0} }, /*154*/ + { {0xe0,0x58,0},{0xe0, 0xd8,0} }, { {0xe0,0x59,0},{0xe0, 0xd9,0} }, { {0xe0,0x5a,0},{0xe0, 0xaa,0} }, { {0xe0,0x5b,0},{0xe0, 0xdb,0} }, /*158*/ + { {0xe0,0x5c,0},{0xe0, 0xdc,0} }, { {0xe0,0x5d,0},{0xe0, 0xdd,0} }, { {0xe0,0x5e,0},{0xe0, 0xee,0} }, { {0xe0,0x5f,0},{0xe0, 0xdf,0} }, /*15c*/ + { { 0},{ 0} }, { {0xe0,0x61,0},{0xe0, 0xe1,0} }, { {0xe0,0x62,0},{0xe0, 0xe2,0} }, { {0xe0,0x63,0},{0xe0, 0xe3,0} }, /*160*/ + { {0xe0,0x64,0},{0xe0, 0xe4,0} }, { {0xe0,0x65,0},{0xe0, 0xe5,0} }, { {0xe0,0x66,0},{0xe0, 0xe6,0} }, { {0xe0,0x67,0},{0xe0, 0xe7,0} }, /*164*/ + { {0xe0,0x68,0},{0xe0, 0xe8,0} }, { {0xe0,0x69,0},{0xe0, 0xe9,0} }, { {0xe0,0x6a,0},{0xe0, 0xea,0} }, { {0xe0,0x6b,0},{0xe0, 0xeb,0} }, /*168*/ + { {0xe0,0x6c,0},{0xe0, 0xec,0} }, { {0xe0,0x6d,0},{0xe0, 0xed,0} }, { {0xe0,0x6e,0},{0xe0, 0xee,0} }, { { 0},{ 0} }, /*16c*/ + { {0xe0,0x70,0},{0xe0, 0xf0,0} }, { {0xe0,0x71,0},{0xe0, 0xf1,0} }, { {0xe0,0x72,0},{0xe0, 0xf2,0} }, { {0xe0,0x73,0},{0xe0, 0xf3,0} }, /*170*/ + { {0xe0,0x74,0},{0xe0, 0xf4,0} }, { {0xe0,0x75,0},{0xe0, 0xf5,0} }, { { 0},{ 0} }, { {0xe0,0x77,0},{0xe0, 0xf7,0} }, /*174*/ + { {0xe0,0x78,0},{0xe0, 0xf8,0} }, { {0xe0,0x79,0},{0xe0, 0xf9,0} }, { {0xe0,0x7a,0},{0xe0, 0xfa,0} }, { {0xe0,0x7b,0},{0xe0, 0xfb,0} }, /*178*/ + { {0xe0,0x7c,0},{0xe0, 0xfc,0} }, { {0xe0,0x7d,0},{0xe0, 0xfd,0} }, { {0xe0,0x7e,0},{0xe0, 0xfe,0} }, { {0xe0,0x7f,0},{0xe0, 0xff,0} }, /*17c*/ + + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*180*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*184*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*188*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*18c*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*190*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*194*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*198*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*19c*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1ac*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1cc*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1dc*/ + { { 0},{ 0} }, { {0xe0,0xe1,0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xee,0},{ 0} }, { { 0},{ 0} }, /*1ec*/ + { { 0},{ 0} }, { {0xe0,0xf1,0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{ 0} }, { {0xe0,0xff,0},{ 0} } /*1fc*/ +}; +#endif + +static const scancode scancode_set2[512] = { + { { 0},{ 0} }, { { 0x76,0},{ 0xF0,0x76,0} }, { { 0x16,0},{ 0xF0,0x16,0} }, { { 0x1E,0},{ 0xF0,0x1E,0} }, /*000*/ + { { 0x26,0},{ 0xF0,0x26,0} }, { { 0x25,0},{ 0xF0,0x25,0} }, { { 0x2E,0},{ 0xF0,0x2E,0} }, { { 0x36,0},{ 0xF0,0x36,0} }, /*004*/ + { { 0x3D,0},{ 0xF0,0x3D,0} }, { { 0x3E,0},{ 0xF0,0x3E,0} }, { { 0x46,0},{ 0xF0,0x46,0} }, { { 0x45,0},{ 0xF0,0x45,0} }, /*008*/ + { { 0x4E,0},{ 0xF0,0x4E,0} }, { { 0x55,0},{ 0xF0,0x55,0} }, { { 0x66,0},{ 0xF0,0x66,0} }, { { 0x0D,0},{ 0xF0,0x0D,0} }, /*00c*/ + { { 0x15,0},{ 0xF0,0x15,0} }, { { 0x1D,0},{ 0xF0,0x1D,0} }, { { 0x24,0},{ 0xF0,0x24,0} }, { { 0x2D,0},{ 0xF0,0x2D,0} }, /*010*/ + { { 0x2C,0},{ 0xF0,0x2C,0} }, { { 0x35,0},{ 0xF0,0x35,0} }, { { 0x3C,0},{ 0xF0,0x3C,0} }, { { 0x43,0},{ 0xF0,0x43,0} }, /*014*/ + { { 0x44,0},{ 0xF0,0x44,0} }, { { 0x4D,0},{ 0xF0,0x4D,0} }, { { 0x54,0},{ 0xF0,0x54,0} }, { { 0x5B,0},{ 0xF0,0x5B,0} }, /*018*/ + { { 0x5A,0},{ 0xF0,0x5A,0} }, { { 0x14,0},{ 0xF0,0x14,0} }, { { 0x1C,0},{ 0xF0,0x1C,0} }, { { 0x1B,0},{ 0xF0,0x1B,0} }, /*01c*/ + { { 0x23,0},{ 0xF0,0x23,0} }, { { 0x2B,0},{ 0xF0,0x2B,0} }, { { 0x34,0},{ 0xF0,0x34,0} }, { { 0x33,0},{ 0xF0,0x33,0} }, /*020*/ + { { 0x3B,0},{ 0xF0,0x3B,0} }, { { 0x42,0},{ 0xF0,0x42,0} }, { { 0x4B,0},{ 0xF0,0x4B,0} }, { { 0x4C,0},{ 0xF0,0x4C,0} }, /*024*/ + { { 0x52,0},{ 0xF0,0x52,0} }, { { 0x0E,0},{ 0xF0,0x0E,0} }, { { 0x12,0},{ 0xF0,0x12,0} }, { { 0x5D,0},{ 0xF0,0x5D,0} }, /*028*/ + { { 0x1A,0},{ 0xF0,0x1A,0} }, { { 0x22,0},{ 0xF0,0x22,0} }, { { 0x21,0},{ 0xF0,0x21,0} }, { { 0x2A,0},{ 0xF0,0x2A,0} }, /*02c*/ + { { 0x32,0},{ 0xF0,0x32,0} }, { { 0x31,0},{ 0xF0,0x31,0} }, { { 0x3A,0},{ 0xF0,0x3A,0} }, { { 0x41,0},{ 0xF0,0x41,0} }, /*030*/ + { { 0x49,0},{ 0xF0,0x49,0} }, { { 0x4A,0},{ 0xF0,0x4A,0} }, { { 0x59,0},{ 0xF0,0x59,0} }, { { 0x7C,0},{ 0xF0,0x7C,0} }, /*034*/ + { { 0x11,0},{ 0xF0,0x11,0} }, { { 0x29,0},{ 0xF0,0x29,0} }, { { 0x58,0},{ 0xF0,0x58,0} }, { { 0x05,0},{ 0xF0,0x05,0} }, /*038*/ + { { 0x06,0},{ 0xF0,0x06,0} }, { { 0x04,0},{ 0xF0,0x04,0} }, { { 0x0C,0},{ 0xF0,0x0C,0} }, { { 0x03,0},{ 0xF0,0x03,0} }, /*03c*/ + { { 0x0B,0},{ 0xF0,0x0B,0} }, { { 0x83,0},{ 0xF0,0x83,0} }, { { 0x0A,0},{ 0xF0,0x0A,0} }, { { 0x01,0},{ 0xF0,0x01,0} }, /*040*/ + { { 0x09,0},{ 0xF0,0x09,0} }, { { 0x77,0},{ 0xF0,0x77,0} }, { { 0x7E,0},{ 0xF0,0x7E,0} }, { { 0x6C,0},{ 0xF0,0x6C,0} }, /*044*/ + { { 0x75,0},{ 0xF0,0x75,0} }, { { 0x7D,0},{ 0xF0,0x7D,0} }, { { 0x7B,0},{ 0xF0,0x7B,0} }, { { 0x6B,0},{ 0xF0,0x6B,0} }, /*048*/ + { { 0x73,0},{ 0xF0,0x73,0} }, { { 0x74,0},{ 0xF0,0x74,0} }, { { 0x79,0},{ 0xF0,0x79,0} }, { { 0x69,0},{ 0xF0,0x69,0} }, /*04c*/ + { { 0x72,0},{ 0xF0,0x72,0} }, { { 0x7A,0},{ 0xF0,0x7A,0} }, { { 0x70,0},{ 0xF0,0x70,0} }, { { 0x71,0},{ 0xF0,0x71,0} }, /*050*/ + { { 0x84,0},{ 0xF0,0x84,0} }, { { 0x60,0},{ 0xF0,0x60,0} }, { { 0x61,0},{ 0xF0,0x61,0} }, { { 0x78,0},{ 0xF0,0x78,0} }, /*054*/ + { { 0x07,0},{ 0xF0,0x07,0} }, { { 0x0F,0},{ 0xF0,0x0F,0} }, { { 0x17,0},{ 0xF0,0x17,0} }, { { 0x1F,0},{ 0xF0,0x1F,0} }, /*058*/ + { { 0x27,0},{ 0xF0,0x27,0} }, { { 0x2F,0},{ 0xF0,0x2F,0} }, { { 0x37,0},{ 0xF0,0x37,0} }, { { 0x3F,0},{ 0xF0,0x3F,0} }, /*05c*/ + { { 0x47,0},{ 0xF0,0x47,0} }, { { 0x4F,0},{ 0xF0,0x4F,0} }, { { 0x56,0},{ 0xF0,0x56,0} }, { { 0x5E,0},{ 0xF0,0x5E,0} }, /*060*/ + { { 0x08,0},{ 0xF0,0x08,0} }, { { 0x10,0},{ 0xF0,0x10,0} }, { { 0x18,0},{ 0xF0,0x18,0} }, { { 0x20,0},{ 0xF0,0x20,0} }, /*064*/ + { { 0x28,0},{ 0xF0,0x28,0} }, { { 0x30,0},{ 0xF0,0x30,0} }, { { 0x38,0},{ 0xF0,0x38,0} }, { { 0x40,0},{ 0xF0,0x40,0} }, /*068*/ + { { 0x48,0},{ 0xF0,0x48,0} }, { { 0x50,0},{ 0xF0,0x50,0} }, { { 0x57,0},{ 0xF0,0x57,0} }, { { 0x6F,0},{ 0xF0,0x6F,0} }, /*06c*/ + { { 0x13,0},{ 0xF0,0x13,0} }, { { 0x19,0},{ 0xF0,0x19,0} }, { { 0x39,0},{ 0xF0,0x39,0} }, { { 0x51,0},{ 0xF0,0x51,0} }, /*070*/ + { { 0x53,0},{ 0xF0,0x53,0} }, { { 0x5C,0},{ 0xF0,0x5C,0} }, { { 0x5F,0},{ 0xF0,0x5F,0} }, { { 0x62,0},{ 0xF0,0x62,0} }, /*074*/ + { { 0x63,0},{ 0xF0,0x63,0} }, { { 0x64,0},{ 0xF0,0x64,0} }, { { 0x65,0},{ 0xF0,0x65,0} }, { { 0x67,0},{ 0xF0,0x67,0} }, /*078*/ + { { 0x68,0},{ 0xF0,0x68,0} }, { { 0x6A,0},{ 0xF0,0x6A,0} }, { { 0x6D,0},{ 0xF0,0x6D,0} }, { { 0x6E,0},{ 0xF0,0x6E,0} }, /*07c*/ + + { { 0x80,0},{ 0xf0,0x80,0} }, { { 0x81,0},{ 0xf0,0x81,0} }, { { 0x82,0},{ 0xf0,0x82,0} }, { { 0},{ 0} }, /*080*/ + { { 0},{ 0} }, { { 0x85,0},{ 0xf0,0x54,0} }, { { 0x86,0},{ 0xf0,0x86,0} }, { { 0x87,0},{ 0xf0,0x87,0} }, /*084*/ + { { 0x88,0},{ 0xf0,0x88,0} }, { { 0x89,0},{ 0xf0,0x89,0} }, { { 0x8a,0},{ 0xf0,0x8a,0} }, { { 0x8b,0},{ 0xf0,0x8b,0} }, /*088*/ + { { 0x8c,0},{ 0xf0,0x8c,0} }, { { 0x8d,0},{ 0xf0,0x8d,0} }, { { 0x8e,0},{ 0xf0,0x8e,0} }, { { 0x8f,0},{ 0xf0,0x8f,0} }, /*08c*/ + { { 0x90,0},{ 0xf0,0x90,0} }, { { 0x91,0},{ 0xf0,0x91,0} }, { { 0x92,0},{ 0xf0,0x92,0} }, { { 0x93,0},{ 0xf0,0x93,0} }, /*090*/ + { { 0x94,0},{ 0xf0,0x94,0} }, { { 0x95,0},{ 0xf0,0x95,0} }, { { 0x96,0},{ 0xf0,0x96,0} }, { { 0x97,0},{ 0xf0,0x97,0} }, /*094*/ + { { 0x98,0},{ 0xf0,0x98,0} }, { { 0x99,0},{ 0xf0,0x99,0} }, { { 0x9a,0},{ 0xf0,0x9a,0} }, { { 0x9b,0},{ 0xf0,0x9b,0} }, /*098*/ + { { 0x9c,0},{ 0xf0,0x9c,0} }, { { 0x9d,0},{ 0xf0,0x9d,0} }, { { 0x9e,0},{ 0xf0,0x9e,0} }, { { 0x9f,0},{ 0xf0,0x9f,0} }, /*09c*/ + { { 0xa0,0},{ 0xf0,0xa0,0} }, { { 0xa1,0},{ 0xf0,0xa1,0} }, { { 0xa2,0},{ 0xf0,0xa2,0} }, { { 0xa3,0},{ 0xf0,0xa3,0} }, /*0a0*/ + { { 0xa4,0},{ 0xf0,0xa4,0} }, { { 0xa5,0},{ 0xf0,0xa5,0} }, { { 0xa6,0},{ 0xf0,0xa6,0} }, { { 0xa7,0},{ 0xf0,0xa7,0} }, /*0a4*/ + { { 0xa8,0},{ 0xf0,0xa8,0} }, { { 0xa9,0},{ 0xf0,0xa9,0} }, { { 0xaa,0},{ 0xf0,0xaa,0} }, { { 0xab,0},{ 0xf0,0xab,0} }, /*0a8*/ + { { 0xac,0},{ 0xf0,0xac,0} }, { { 0xad,0},{ 0xf0,0xad,0} }, { { 0xae,0},{ 0xf0,0xae,0} }, { { 0xaf,0},{ 0xf0,0xaf,0} }, /*0ac*/ + { { 0xb0,0},{ 0xf0,0xb0,0} }, { { 0xb1,0},{ 0xf0,0xb1,0} }, { { 0xb2,0},{ 0xf0,0xb2,0} }, { { 0xb3,0},{ 0xf0,0xb3,0} }, /*0b0*/ + { { 0xb4,0},{ 0xf0,0xb4,0} }, { { 0xb5,0},{ 0xf0,0xb5,0} }, { { 0xb6,0},{ 0xf0,0xb6,0} }, { { 0xb7,0},{ 0xf0,0xb7,0} }, /*0b4*/ + { { 0xb8,0},{ 0xf0,0xb8,0} }, { { 0xb9,0},{ 0xf0,0xb9,0} }, { { 0xba,0},{ 0xf0,0xba,0} }, { { 0xbb,0},{ 0xf0,0xbb,0} }, /*0b8*/ + { { 0xbc,0},{ 0xf0,0xbc,0} }, { { 0xbd,0},{ 0xf0,0xbd,0} }, { { 0xbe,0},{ 0xf0,0xbe,0} }, { { 0xbf,0},{ 0xf0,0xbf,0} }, /*0bc*/ + { { 0xc0,0},{ 0xf0,0xc0,0} }, { { 0xc1,0},{ 0xf0,0xc1,0} }, { { 0xc2,0},{ 0xf0,0xc2,0} }, { { 0xc3,0},{ 0xf0,0xc3,0} }, /*0c0*/ + { { 0xc4,0},{ 0xf0,0xc4,0} }, { { 0xc5,0},{ 0xf0,0xc5,0} }, { { 0xc6,0},{ 0xf0,0xc6,0} }, { { 0xc7,0},{ 0xf0,0xc7,0} }, /*0c4*/ + { { 0xc8,0},{ 0xf0,0xc8,0} }, { { 0xc9,0},{ 0xf0,0xc9,0} }, { { 0xca,0},{ 0xf0,0xca,0} }, { { 0xcb,0},{ 0xf0,0xcb,0} }, /*0c8*/ + { { 0xcc,0},{ 0xf0,0xcc,0} }, { { 0xcd,0},{ 0xf0,0xcd,0} }, { { 0xce,0},{ 0xf0,0xce,0} }, { { 0xcf,0},{ 0xf0,0xcf,0} }, /*0cc*/ + { { 0xd0,0},{ 0xf0,0xd0,0} }, { { 0xd1,0},{ 0xf0,0xd0,0} }, { { 0xd2,0},{ 0xf0,0xd2,0} }, { { 0xd3,0},{ 0xf0,0xd3,0} }, /*0d0*/ + { { 0xd4,0},{ 0xf0,0xd4,0} }, { { 0xd5,0},{ 0xf0,0xd5,0} }, { { 0xd6,0},{ 0xf0,0xd6,0} }, { { 0xd7,0},{ 0xf0,0xd7,0} }, /*0d4*/ + { { 0xd8,0},{ 0xf0,0xd8,0} }, { { 0xd9,0},{ 0xf0,0xd9,0} }, { { 0xda,0},{ 0xf0,0xda,0} }, { { 0xdb,0},{ 0xf0,0xdb,0} }, /*0d8*/ + { { 0xdc,0},{ 0xf0,0xdc,0} }, { { 0xdd,0},{ 0xf0,0xdd,0} }, { { 0xde,0},{ 0xf0,0xde,0} }, { { 0xdf,0},{ 0xf0,0xdf,0} }, /*0dc*/ + { { 0xe0,0},{ 0xf0,0xe0,0} }, { { 0xe1,0},{ 0xf0,0xe1,0} }, { { 0xe2,0},{ 0xf0,0xe2,0} }, { { 0xe3,0},{ 0xf0,0xe3,0} }, /*0e0*/ + { { 0xe4,0},{ 0xf0,0xe4,0} }, { { 0xe5,0},{ 0xf0,0xe5,0} }, { { 0xe6,0},{ 0xf0,0xe6,0} }, { { 0xe7,0},{ 0xf0,0xe7,0} }, /*0e4*/ + { { 0xe8,0},{ 0xf0,0xe8,0} }, { { 0xe9,0},{ 0xf0,0xe9,0} }, { { 0xea,0},{ 0xf0,0xea,0} }, { { 0xeb,0},{ 0xf0,0xeb,0} }, /*0e8*/ + { { 0xec,0},{ 0xf0,0xec,0} }, { { 0xed,0},{ 0xf0,0xed,0} }, { { 0xee,0},{ 0xf0,0xee,0} }, { { 0xef,0},{ 0xf0,0xef,0} }, /*0ec*/ + { { 0},{ 0} }, { { 0xf1,0},{ 0xf0,0xf1,0} }, { { 0xf2,0},{ 0xf0,0xf2,0} }, { { 0xf3,0},{ 0xf0,0xf3,0} }, /*0f0*/ + { { 0xf4,0},{ 0xf0,0xf4,0} }, { { 0xf5,0},{ 0xf0,0xf5,0} }, { { 0xf6,0},{ 0xf0,0xf6,0} }, { { 0xf7,0},{ 0xf0,0xf7,0} }, /*0f4*/ + { { 0xf8,0},{ 0xf0,0xf8,0} }, { { 0xf9,0},{ 0xf0,0xf9,0} }, { { 0xfa,0},{ 0xf0,0xfa,0} }, { { 0xfb,0},{ 0xf0,0xfb,0} }, /*0f8*/ + { { 0xfc,0},{ 0xf0,0xfc,0} }, { { 0xfd,0},{ 0xf0,0xfd,0} }, { { 0xfe,0},{ 0xf0,0xfe,0} }, { { 0xff,0},{ 0xf0,0xff,0} }, /*0fc*/ + + { {0xe1,0x14,0},{0xe1,0xf0,0x14,0} }, { {0xe0,0x76,0},{0xe0,0xF0,0x76,0} }, { {0xe0,0x16,0},{0xe0,0xF0,0x16,0} }, { {0xe0,0x1E,0},{0xe0,0xF0,0x1E,0} }, /*100*/ + { {0xe0,0x26,0},{0xe0,0xF0,0x26,0} }, { {0xe0,0x25,0},{0xe0,0xF0,0x25,0} }, { {0xe0,0x2E,0},{0xe0,0xF0,0x2E,0} }, { {0xe0,0x36,0},{0xe0,0xF0,0x36,0} }, /*104*/ + { {0xe0,0x3D,0},{0xe0,0xF0,0x3D,0} }, { {0xe0,0x3E,0},{0xe0,0xF0,0x3E,0} }, { {0xe0,0x46,0},{0xe0,0xF0,0x46,0} }, { {0xe0,0x45,0},{0xe0,0xF0,0x45,0} }, /*108*/ + { {0xe0,0x4E,0},{0xe0,0xF0,0x4E,0} }, { { 0},{ 0} }, { {0xe0,0x66,0},{0xe0,0xF0,0x66,0} }, { {0xe0,0x0D,0},{0xe0,0xF0,0x0D,0} }, /*10c*/ + { {0xe0,0x15,0},{0xe0,0xF0,0x15,0} }, { {0xe0,0x1D,0},{0xe0,0xF0,0x1D,0} }, { {0xe0,0x24,0},{0xe0,0xF0,0x24,0} }, { {0xe0,0x2D,0},{0xe0,0xF0,0x2D,0} }, /*110*/ + { {0xe0,0x2C,0},{0xe0,0xF0,0x2C,0} }, { {0xe0,0x35,0},{0xe0,0xF0,0x35,0} }, { {0xe0,0x3C,0},{0xe0,0xF0,0x3C,0} }, { {0xe0,0x43,0},{0xe0,0xF0,0x43,0} }, /*114*/ + { {0xe0,0x44,0},{0xe0,0xF0,0x44,0} }, { {0xe0,0x4D,0},{0xe0,0xF0,0x4D,0} }, { {0xe0,0x54,0},{0xe0,0xF0,0x54,0} }, { {0xe0,0x5B,0},{0xe0,0xF0,0x5B,0} }, /*118*/ + { {0xe0,0x5A,0},{0xe0,0xF0,0x5A,0} }, { {0xe0,0x14,0},{0xe0,0xF0,0x14,0} }, { {0xe0,0x1C,0},{0xe0,0xF0,0x1C,0} }, { {0xe0,0x1B,0},{0xe0,0xF0,0x1B,0} }, /*11c*/ + { {0xe0,0x23,0},{0xe0,0xF0,0x23,0} }, { {0xe0,0x2B,0},{0xe0,0xF0,0x2B,0} }, { {0xe0,0x34,0},{0xe0,0xF0,0x34,0} }, { {0xe0,0x33,0},{0xe0,0xF0,0x33,0} }, /*120*/ + { {0xe0,0x3B,0},{0xe0,0xF0,0x3B,0} }, { {0xe0,0x42,0},{0xe0,0xF0,0x42,0} }, { {0xe0,0x4B,0},{0xe0,0xF0,0x4B,0} }, { { 0},{ 0} }, /*124*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*128*/ + { {0xe0,0x1A,0},{0xe0,0xF0,0x1A,0} }, { {0xe0,0x22,0},{0xe0,0xF0,0x22,0} }, { {0xe0,0x21,0},{0xe0,0xF0,0x21,0} }, { {0xe0,0x2A,0},{0xe0,0xF0,0x2A,0} }, /*12c*/ + { {0xe0,0x32,0},{0xe0,0xF0,0x32,0} }, { {0xe0,0x31,0},{0xe0,0xF0,0x31,0} }, { {0xe0,0x3A,0},{0xe0,0xF0,0x3A,0} }, { { 0},{ 0} }, /*130*/ + { {0xe0,0x49,0},{0xe0,0xF0,0x49,0} }, { {0xe0,0x4A,0},{0xe0,0xF0,0x4A,0} }, { { 0},{ 0} }, { {0xe0,0x7C,0},{0xe0,0xF0,0x7C,0} }, /*134*/ + { {0xe0,0x11,0},{0xe0,0xF0,0x11,0} }, { { 0},{ 0} }, { {0xe0,0x58,0},{0xe0,0xF0,0x58,0} }, { {0xe0,0x05,0},{0xe0,0xF0,0x05,0} }, /*138*/ + { {0xe0,0x06,0},{0xe0,0xF0,0x06,0} }, { {0xe0,0x04,0},{0xe0,0xF0,0x04,0} }, { {0xe0,0x0C,0},{0xe0,0xF0,0x0C,0} }, { {0xe0,0x03,0},{0xe0,0xF0,0x03,0} }, /*13c*/ + { {0xe0,0x0B,0},{0xe0,0xF0,0x0B,0} }, { {0xe0,0x02,0},{0xe0,0xF0,0x02,0} }, { {0xe0,0x0A,0},{0xe0,0xF0,0x0A,0} }, { {0xe0,0x01,0},{0xe0,0xF0,0x01,0} }, /*140*/ + { {0xe0,0x09,0},{0xe0,0xF0,0x09,0} }, { { 0},{ 0} }, { {0xe0,0x7E,0},{0xe0,0xF0,0x7E,0} }, { {0xe0,0x6C,0},{0xe0,0xF0,0x6C,0} }, /*144*/ + { {0xe0,0x75,0},{0xe0,0xF0,0x75,0} }, { {0xe0,0x7D,0},{0xe0,0xF0,0x7D,0} }, { { 0},{ 0} }, { {0xe0,0x6B,0},{0xe0,0xF0,0x6B,0} }, /*148*/ + { {0xe0,0x73,0},{0xe0,0xF0,0x73,0} }, { {0xe0,0x74,0},{0xe0,0xF0,0x74,0} }, { {0xe0,0x79,0},{0xe0,0xF0,0x79,0} }, { {0xe0,0x69,0},{0xe0,0xF0,0x69,0} }, /*14c*/ + { {0xe0,0x72,0},{0xe0,0xF0,0x72,0} }, { {0xe0,0x7A,0},{0xe0,0xF0,0x7A,0} }, { {0xe0,0x70,0},{0xe0,0xF0,0x70,0} }, { {0xe0,0x71,0},{0xe0,0xF0,0x71,0} }, /*150*/ + { { 0},{ 0} }, { {0xe0,0x60,0},{0xe0,0xF0,0x60,0} }, { { 0},{ 0} }, { {0xe0,0x78,0},{0xe0,0xF0,0x78,0} }, /*154*/ + { {0xe0,0x07,0},{0xe0,0xF0,0x07,0} }, { {0xe0,0x0F,0},{0xe0,0xF0,0x0F,0} }, { {0xe0,0x17,0},{0xe0,0xF0,0x17,0} }, { {0xe0,0x1F,0},{0xe0,0xF0,0x1F,0} }, /*158*/ + { {0xe0,0x27,0},{0xe0,0xF0,0x27,0} }, { {0xe0,0x2F,0},{0xe0,0xF0,0x2F,0} }, { {0xe0,0x37,0},{0xe0,0xF0,0x37,0} }, { {0xe0,0x3F,0},{0xe0,0xF0,0x3F,0} }, /*15c*/ + { { 0},{ 0} }, { {0xe0,0x4F,0},{0xe0,0xF0,0x4F,0} }, { {0xe0,0x56,0},{0xe0,0xF0,0x56,0} }, { {0xe0,0x5E,0},{0xe0,0xF0,0x5E,0} }, /*160*/ + { {0xe0,0x08,0},{0xe0,0xF0,0x08,0} }, { {0xe0,0x10,0},{0xe0,0xF0,0x10,0} }, { {0xe0,0x18,0},{0xe0,0xF0,0x18,0} }, { {0xe0,0x20,0},{0xe0,0xF0,0x20,0} }, /*164*/ + { {0xe0,0x28,0},{0xe0,0xF0,0x28,0} }, { {0xe0,0x30,0},{0xe0,0xF0,0x30,0} }, { {0xe0,0x38,0},{0xe0,0xF0,0x38,0} }, { {0xe0,0x40,0},{0xe0,0xF0,0x40,0} }, /*168*/ + { {0xe0,0x48,0},{0xe0,0xF0,0x48,0} }, { {0xe0,0x50,0},{0xe0,0xF0,0x50,0} }, { {0xe0,0x57,0},{0xe0,0xF0,0x57,0} }, { { 0},{ 0} }, /*16c*/ + { {0xe0,0x13,0},{0xe0,0xF0,0x13,0} }, { {0xe0,0x19,0},{0xe0,0xF0,0x19,0} }, { {0xe0,0x39,0},{0xe0,0xF0,0x39,0} }, { {0xe0,0x51,0},{0xe0,0xF0,0x51,0} }, /*170*/ + { {0xe0,0x53,0},{0xe0,0xF0,0x53,0} }, { {0xe0,0x5C,0},{0xe0,0xF0,0x5C,0} }, { { 0},{ 0} }, { {0xe0,0x62,0},{0xe0,0xF0,0x62,0} }, /*174*/ + { {0xe0,0x63,0},{0xe0,0xF0,0x63,0} }, { {0xe0,0x64,0},{0xe0,0xF0,0x64,0} }, { {0xe0,0x65,0},{0xe0,0xF0,0x65,0} }, { {0xe0,0x67,0},{0xe0,0xF0,0x67,0} }, /*178*/ + { {0xe0,0x68,0},{0xe0,0xF0,0x68,0} }, { {0xe0,0x6A,0},{0xe0,0xF0,0x6A,0} }, { {0xe0,0x6D,0},{0xe0,0xF0,0x6D,0} }, { {0xe0,0x6E,0},{0xe0,0xF0,0x6E,0} }, /*17c*/ + + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*180*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*184*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*188*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*18c*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*190*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*194*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*198*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*19c*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1ac*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1cc*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1dc*/ + { { 0},{ 0} }, { {0xe0,0xe1,0},{0xe0,0xF0,0xE1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xee,0},{0xe0,0xF0,0xEE,0} }, { { 0},{ 0} }, /*1ec*/ + { { 0},{ 0} }, { {0xe0,0xf1,0},{0xe0,0xF0,0xF1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{0xe0,0xF0,0xFE,0} }, { {0xe0,0xff,0},{0xe0,0xF0,0xFF,0} } /*1fc*/ +}; + +static const scancode scancode_set3[512] = { + { { 0},{ 0} }, { { 0x08,0},{ 0xf0,0x08,0} }, { { 0x16,0},{ 0xf0,0x16,0} }, { { 0x1E,0},{ 0xf0,0x1E,0} }, /*000*/ + { { 0x26,0},{ 0xf0,0x26,0} }, { { 0x25,0},{ 0xf0,0x25,0} }, { { 0x2E,0},{ 0xf0,0x2E,0} }, { { 0x36,0},{ 0xf0,0x36,0} }, /*004*/ + { { 0x3D,0},{ 0xf0,0x3D,0} }, { { 0x3E,0},{ 0xf0,0x3E,0} }, { { 0x46,0},{ 0xf0,0x46,0} }, { { 0x45,0},{ 0xf0,0x45,0} }, /*008*/ + { { 0x4E,0},{ 0xf0,0x4E,0} }, { { 0x55,0},{ 0xf0,0x55,0} }, { { 0x66,0},{ 0xf0,0x66,0} }, { { 0x0D,0},{ 0xf0,0x0D,0} }, /*00c*/ + { { 0x15,0},{ 0xf0,0x15,0} }, { { 0x1D,0},{ 0xf0,0x1D,0} }, { { 0x24,0},{ 0xf0,0x24,0} }, { { 0x2D,0},{ 0xf0,0x2D,0} }, /*010*/ + { { 0x2C,0},{ 0xf0,0x2C,0} }, { { 0x35,0},{ 0xf0,0x35,0} }, { { 0x3C,0},{ 0xf0,0x3C,0} }, { { 0x43,0},{ 0xf0,0x43,0} }, /*014*/ + { { 0x44,0},{ 0xf0,0x44,0} }, { { 0x4D,0},{ 0xf0,0x4D,0} }, { { 0x54,0},{ 0xf0,0x54,0} }, { { 0x5B,0},{ 0xf0,0x5B,0} }, /*018*/ + { { 0x5A,0},{ 0xf0,0x5A,0} }, { { 0x11,0},{ 0xf0,0x11,0} }, { { 0x1C,0},{ 0xf0,0x1C,0} }, { { 0x1B,0},{ 0xf0,0x1B,0} }, /*01c*/ + { { 0x23,0},{ 0xf0,0x23,0} }, { { 0x2B,0},{ 0xf0,0x2B,0} }, { { 0x34,0},{ 0xf0,0x34,0} }, { { 0x33,0},{ 0xf0,0x33,0} }, /*020*/ + { { 0x3B,0},{ 0xf0,0x3B,0} }, { { 0x42,0},{ 0xf0,0x42,0} }, { { 0x4B,0},{ 0xf0,0x4B,0} }, { { 0x4C,0},{ 0xf0,0x4C,0} }, /*024*/ + { { 0x52,0},{ 0xf0,0x52,0} }, { { 0x0E,0},{ 0xf0,0x0E,0} }, { { 0x12,0},{ 0xf0,0x12,0} }, { { 0x5C,0},{ 0xf0,0x5C,0} }, /*028*/ + { { 0x1A,0},{ 0xf0,0x1A,0} }, { { 0x22,0},{ 0xf0,0x22,0} }, { { 0x21,0},{ 0xf0,0x21,0} }, { { 0x2A,0},{ 0xf0,0x2A,0} }, /*02c*/ + { { 0x32,0},{ 0xf0,0x32,0} }, { { 0x31,0},{ 0xf0,0x31,0} }, { { 0x3A,0},{ 0xf0,0x3A,0} }, { { 0x41,0},{ 0xf0,0x41,0} }, /*030*/ + { { 0x49,0},{ 0xf0,0x49,0} }, { { 0x4A,0},{ 0xf0,0x4A,0} }, { { 0x59,0},{ 0xf0,0x59,0} }, { { 0x7E,0},{ 0xf0,0x7E,0} }, /*034*/ + { { 0x19,0},{ 0xf0,0x19,0} }, { { 0x29,0},{ 0xf0,0x29,0} }, { { 0x14,0},{ 0xf0,0x14,0} }, { { 0x07,0},{ 0xf0,0x07,0} }, /*038*/ + { { 0x0F,0},{ 0xf0,0x0F,0} }, { { 0x17,0},{ 0xf0,0x17,0} }, { { 0x1F,0},{ 0xf0,0x1F,0} }, { { 0x27,0},{ 0xf0,0x27,0} }, /*03c*/ + { { 0x2F,0},{ 0xf0,0x2F,0} }, { { 0x37,0},{ 0xf0,0x37,0} }, { { 0x3F,0},{ 0xf0,0x3F,0} }, { { 0x47,0},{ 0xf0,0x47,0} }, /*040*/ + { { 0x4F,0},{ 0xf0,0x4F,0} }, { { 0x76,0},{ 0xf0,0x76,0} }, { { 0x5F,0},{ 0xf0,0x5F,0} }, { { 0x6C,0},{ 0xf0,0x6C,0} }, /*044*/ + { { 0x75,0},{ 0xf0,0x75,0} }, { { 0x7D,0},{ 0xf0,0x7D,0} }, { { 0x84,0},{ 0xf0,0x84,0} }, { { 0x6B,0},{ 0xf0,0x6B,0} }, /*048*/ + { { 0x73,0},{ 0xf0,0x73,0} }, { { 0x74,0},{ 0xf0,0x74,0} }, { { 0x7C,0},{ 0xf0,0x7C,0} }, { { 0x69,0},{ 0xf0,0x69,0} }, /*04c*/ + { { 0x72,0},{ 0xf0,0x72,0} }, { { 0x7A,0},{ 0xf0,0x7A,0} }, { { 0x70,0},{ 0xf0,0x70,0} }, { { 0x71,0},{ 0xf0,0x71,0} }, /*050*/ + { { 0x57,0},{ 0xf0,0x57,0} }, { { 0x60,0},{ 0xf0,0x60,0} }, { { 0},{ 0} }, { { 0x56,0},{ 0xf0,0x56,0} }, /*054*/ + { { 0x5E,0},{ 0xf0,0x5E,0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*058*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*05c*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*060*/ + { { 0},{ 0} }, { { 0x10,0},{ 0xf0,0x10,0} }, { { 0x18,0},{ 0xf0,0x18,0} }, { { 0x20,0},{ 0xf0,0x20,0} }, /*064*/ + { { 0x28,0},{ 0xf0,0x28,0} }, { { 0x30,0},{ 0xf0,0x30,0} }, { { 0x38,0},{ 0xf0,0x38,0} }, { { 0x40,0},{ 0xf0,0x40,0} }, /*068*/ + { { 0x48,0},{ 0xf0,0x48,0} }, { { 0x50,0},{ 0xf0,0x50,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*06c*/ + { { 0x87,0},{ 0xf0,0x87,0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0x51,0},{ 0xf0,0x51,0} }, /*070*/ + { { 0x53,0},{ 0xf0,0x53,0} }, { { 0x5C,0},{ 0xf0,0x5C,0} }, { { 0},{ 0} }, { { 0x62,0},{ 0xf0,0x62,0} }, /*074*/ + { { 0x63,0},{ 0xf0,0x63,0} }, { { 0x86,0},{ 0xf0,0x86,0} }, { { 0},{ 0} }, { { 0x85,0},{ 0xf0,0x85,0} }, /*078*/ + { { 0x68,0},{ 0xf0,0x68,0} }, { { 0x13,0},{ 0xf0,0x13,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*07c*/ + + { { 0x80,0},{ 0xf0,0x80,0} }, { { 0x81,0},{ 0xf0,0x81,0} }, { { 0x82,0},{ 0xf0,0x82,0} }, { { 0},{ 0} }, /*080*/ + { { 0},{ 0} }, { { 0x85,0},{ 0xf0,0x54,0} }, { { 0x86,0},{ 0xf0,0x86,0} }, { { 0x87,0},{ 0xf0,0x87,0} }, /*084*/ + { { 0x88,0},{ 0xf0,0x88,0} }, { { 0x89,0},{ 0xf0,0x89,0} }, { { 0x8a,0},{ 0xf0,0x8a,0} }, { { 0x8b,0},{ 0xf0,0x8b,0} }, /*088*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0x8e,0},{ 0xf0,0x8e,0} }, { { 0x8f,0},{ 0xf0,0x8f,0} }, /*08c*/ + { { 0x90,0},{ 0xf0,0x90,0} }, { { 0x91,0},{ 0xf0,0x91,0} }, { { 0x92,0},{ 0xf0,0x92,0} }, { { 0x93,0},{ 0xf0,0x93,0} }, /*090*/ + { { 0x94,0},{ 0xf0,0x94,0} }, { { 0x95,0},{ 0xf0,0x95,0} }, { { 0x96,0},{ 0xf0,0x96,0} }, { { 0x97,0},{ 0xf0,0x97,0} }, /*094*/ + { { 0x98,0},{ 0xf0,0x98,0} }, { { 0x99,0},{ 0xf0,0x99,0} }, { { 0x9a,0},{ 0xf0,0x9a,0} }, { { 0x9b,0},{ 0xf0,0x9b,0} }, /*098*/ + { { 0x9c,0},{ 0xf0,0x9c,0} }, { { 0x9d,0},{ 0xf0,0x9d,0} }, { { 0x9e,0},{ 0xf0,0x9e,0} }, { { 0x9f,0},{ 0xf0,0x9f,0} }, /*09c*/ + { { 0xa0,0},{ 0xf0,0xa0,0} }, { { 0xa1,0},{ 0xf0,0xa1,0} }, { { 0xa2,0},{ 0xf0,0xa2,0} }, { { 0xa3,0},{ 0xf0,0xa3,0} }, /*0a0*/ + { { 0xa4,0},{ 0xf0,0xa4,0} }, { { 0xa5,0},{ 0xf0,0xa5,0} }, { { 0xa6,0},{ 0xf0,0xa6,0} }, { { 0xa7,0},{ 0xf0,0xa7,0} }, /*0a4*/ + { { 0xa8,0},{ 0xf0,0xa8,0} }, { { 0xa9,0},{ 0xf0,0xa9,0} }, { { 0xaa,0},{ 0xf0,0xaa,0} }, { { 0xab,0},{ 0xf0,0xab,0} }, /*0a8*/ + { { 0xac,0},{ 0xf0,0xac,0} }, { { 0xad,0},{ 0xf0,0xad,0} }, { { 0xae,0},{ 0xf0,0xae,0} }, { { 0xaf,0},{ 0xf0,0xaf,0} }, /*0ac*/ + { { 0xb0,0},{ 0xf0,0xb0,0} }, { { 0xb1,0},{ 0xf0,0xb1,0} }, { { 0xb2,0},{ 0xf0,0xb2,0} }, { { 0xb3,0},{ 0xf0,0xb3,0} }, /*0b0*/ + { { 0xb4,0},{ 0xf0,0xb4,0} }, { { 0xb5,0},{ 0xf0,0xb5,0} }, { { 0xb6,0},{ 0xf0,0xb6,0} }, { { 0xb7,0},{ 0xf0,0xb7,0} }, /*0b4*/ + { { 0xb8,0},{ 0xf0,0xb8,0} }, { { 0xb9,0},{ 0xf0,0xb9,0} }, { { 0xba,0},{ 0xf0,0xba,0} }, { { 0xbb,0},{ 0xf0,0xbb,0} }, /*0b8*/ + { { 0xbc,0},{ 0xf0,0xbc,0} }, { { 0xbd,0},{ 0xf0,0xbd,0} }, { { 0xbe,0},{ 0xf0,0xbe,0} }, { { 0xbf,0},{ 0xf0,0xbf,0} }, /*0bc*/ + { { 0xc0,0},{ 0xf0,0xc0,0} }, { { 0xc1,0},{ 0xf0,0xc1,0} }, { { 0xc2,0},{ 0xf0,0xc2,0} }, { { 0xc3,0},{ 0xf0,0xc3,0} }, /*0c0*/ + { { 0xc4,0},{ 0xf0,0xc4,0} }, { { 0xc5,0},{ 0xf0,0xc5,0} }, { { 0xc6,0},{ 0xf0,0xc6,0} }, { { 0xc7,0},{ 0xf0,0xc7,0} }, /*0c4*/ + { { 0xc8,0},{ 0xf0,0xc8,0} }, { { 0xc9,0},{ 0xf0,0xc9,0} }, { { 0xca,0},{ 0xf0,0xca,0} }, { { 0xcb,0},{ 0xf0,0xcb,0} }, /*0c8*/ + { { 0xcc,0},{ 0xf0,0xcc,0} }, { { 0xcd,0},{ 0xf0,0xcd,0} }, { { 0xce,0},{ 0xf0,0xce,0} }, { { 0xcf,0},{ 0xf0,0xcf,0} }, /*0cc*/ + { { 0xd0,0},{ 0xf0,0xd0,0} }, { { 0xd1,0},{ 0xf0,0xd0,0} }, { { 0xd2,0},{ 0xf0,0xd2,0} }, { { 0xd3,0},{ 0xf0,0xd3,0} }, /*0d0*/ + { { 0xd4,0},{ 0xf0,0xd4,0} }, { { 0xd5,0},{ 0xf0,0xd5,0} }, { { 0xd6,0},{ 0xf0,0xd6,0} }, { { 0xd7,0},{ 0xf0,0xd7,0} }, /*0d4*/ + { { 0xd8,0},{ 0xf0,0xd8,0} }, { { 0xd9,0},{ 0xf0,0xd9,0} }, { { 0xda,0},{ 0xf0,0xda,0} }, { { 0xdb,0},{ 0xf0,0xdb,0} }, /*0d8*/ + { { 0xdc,0},{ 0xf0,0xdc,0} }, { { 0xdd,0},{ 0xf0,0xdd,0} }, { { 0xde,0},{ 0xf0,0xde,0} }, { { 0xdf,0},{ 0xf0,0xdf,0} }, /*0dc*/ + { { 0xe0,0},{ 0xf0,0xe0,0} }, { { 0xe1,0},{ 0xf0,0xe1,0} }, { { 0xe2,0},{ 0xf0,0xe2,0} }, { { 0xe3,0},{ 0xf0,0xe3,0} }, /*0e0*/ + { { 0xe4,0},{ 0xf0,0xe4,0} }, { { 0xe5,0},{ 0xf0,0xe5,0} }, { { 0xe6,0},{ 0xf0,0xe6,0} }, { { 0xe7,0},{ 0xf0,0xe7,0} }, /*0e4*/ + { { 0xe8,0},{ 0xf0,0xe8,0} }, { { 0xe9,0},{ 0xf0,0xe9,0} }, { { 0xea,0},{ 0xf0,0xea,0} }, { { 0xeb,0},{ 0xf0,0xeb,0} }, /*0e8*/ + { { 0xec,0},{ 0xf0,0xec,0} }, { { 0xed,0},{ 0xf0,0xed,0} }, { { 0xee,0},{ 0xf0,0xee,0} }, { { 0xef,0},{ 0xf0,0xef,0} }, /*0ec*/ + { { 0},{ 0} }, { { 0xf1,0},{ 0xf0,0xf1,0} }, { { 0xf2,0},{ 0xf0,0xf2,0} }, { { 0xf3,0},{ 0xf0,0xf3,0} }, /*0f0*/ + { { 0xf4,0},{ 0xf0,0xf4,0} }, { { 0xf5,0},{ 0xf0,0xf5,0} }, { { 0xf6,0},{ 0xf0,0xf6,0} }, { { 0xf7,0},{ 0xf0,0xf7,0} }, /*0f4*/ + { { 0xf8,0},{ 0xf0,0xf8,0} }, { { 0xf9,0},{ 0xf0,0xf9,0} }, { { 0xfa,0},{ 0xf0,0xfa,0} }, { { 0xfb,0},{ 0xf0,0xfb,0} }, /*0f8*/ + { { 0xfc,0},{ 0xf0,0xfc,0} }, { { 0xfd,0},{ 0xf0,0xfd,0} }, { { 0xfe,0},{ 0xf0,0xfe,0} }, { { 0xff,0},{ 0xf0,0xff,0} }, /*0fc*/ + + { { 0x62,0},{ 0xF0,0x62,0} }, { {0xe0,0x76,0},{0xe0,0xF0,0x76,0} }, { {0xe0,0x16,0},{0xe0,0xF0,0x16,0} }, { {0xe0,0x1E,0},{0xe0,0xF0,0x1E,0} }, /*100*/ + { {0xe0,0x26,0},{0xe0,0xF0,0x26,0} }, { {0xe0,0x25,0},{0xe0,0xF0,0x25,0} }, { {0xe0,0x2E,0},{0xe0,0xF0,0x2E,0} }, { {0xe0,0x36,0},{0xe0,0xF0,0x36,0} }, /*104*/ + { {0xe0,0x3D,0},{0xe0,0xF0,0x3D,0} }, { {0xe0,0x3E,0},{0xe0,0xF0,0x3E,0} }, { {0xe0,0x46,0},{0xe0,0xF0,0x46,0} }, { {0xe0,0x45,0},{0xe0,0xF0,0x45,0} }, /*108*/ + { {0xe0,0x4E,0},{0xe0,0xF0,0x4E,0} }, { { 0},{ 0} }, { {0xe0,0x66,0},{0xe0,0xF0,0x66,0} }, { {0xe0,0x0D,0},{0xe0,0xF0,0x0D,0} }, /*10c*/ + { {0xe0,0x15,0},{0xe0,0xF0,0x15,0} }, { {0xe0,0x1D,0},{0xe0,0xF0,0x1D,0} }, { {0xe0,0x24,0},{0xe0,0xF0,0x24,0} }, { {0xe0,0x2D,0},{0xe0,0xF0,0x2D,0} }, /*110*/ + { {0xe0,0x2C,0},{0xe0,0xF0,0x2C,0} }, { {0xe0,0x35,0},{0xe0,0xF0,0x35,0} }, { {0xe0,0x3C,0},{0xe0,0xF0,0x3C,0} }, { {0xe0,0x43,0},{0xe0,0xF0,0x43,0} }, /*114*/ + { {0xe0,0x44,0},{0xe0,0xF0,0x44,0} }, { {0xe0,0x4D,0},{0xe0,0xF0,0x4D,0} }, { {0xe0,0x54,0},{0xe0,0xF0,0x54,0} }, { {0xe0,0x5B,0},{0xe0,0xF0,0x5B,0} }, /*118*/ + { { 0x79,0},{ 0xf0,0x79,0} }, { { 0x58,0},{ 0xf0,0x58,0} }, { {0xe0,0x1C,0},{0xe0,0xF0,0x1C,0} }, { {0xe0,0x1B,0},{0xe0,0xF0,0x1B,0} }, /*11c*/ + { {0xe0,0x23,0},{0xe0,0xF0,0x23,0} }, { {0xe0,0x2B,0},{0xe0,0xF0,0x2B,0} }, { {0xe0,0x34,0},{0xe0,0xF0,0x34,0} }, { {0xe0,0x33,0},{0xe0,0xF0,0x33,0} }, /*120*/ + { {0xe0,0x3B,0},{0xe0,0xF0,0x3B,0} }, { {0xe0,0x42,0},{0xe0,0xF0,0x42,0} }, { {0xe0,0x4B,0},{0xe0,0xF0,0x4B,0} }, { { 0},{ 0} }, /*124*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*128*/ + { {0xe0,0x1A,0},{0xe0,0xF0,0x1A,0} }, { {0xe0,0x22,0},{0xe0,0xF0,0x22,0} }, { {0xe0,0x21,0},{0xe0,0xF0,0x21,0} }, { {0xe0,0x2A,0},{0xe0,0xF0,0x2A,0} }, /*12c*/ + { {0xe0,0x32,0},{0xe0,0xF0,0x32,0} }, { {0xe0,0x31,0},{0xe0,0xF0,0x31,0} }, { {0xe0,0x3A,0},{0xe0,0xF0,0x3A,0} }, { { 0},{ 0} }, /*130*/ + { {0xe0,0x49,0},{0xe0,0xF0,0x49,0} }, { { 0x77,0},{ 0xf0,0x77,0} }, { { 0},{ 0} }, { { 0x57,0},{ 0xf0,0x57,0} }, /*134*/ + { { 0x39,0},{ 0xf0,0x39,0} }, { { 0},{ 0} }, { {0xe0,0x58,0},{0xe0,0xF0,0x58,0} }, { {0xe0,0x05,0},{0xe0,0xF0,0x05,0} }, /*138*/ + { {0xe0,0x06,0},{0xe0,0xF0,0x06,0} }, { {0xe0,0x04,0},{0xe0,0xF0,0x04,0} }, { {0xe0,0x0C,0},{0xe0,0xF0,0x0C,0} }, { {0xe0,0x03,0},{0xe0,0xF0,0x03,0} }, /*13c*/ + { {0xe0,0x0B,0},{0xe0,0xF0,0x0B,0} }, { {0xe0,0x02,0},{0xe0,0xF0,0x02,0} }, { {0xe0,0x0A,0},{0xe0,0xF0,0x0A,0} }, { {0xe0,0x01,0},{0xe0,0xF0,0x01,0} }, /*140*/ + { {0xe0,0x09,0},{0xe0,0xF0,0x09,0} }, { { 0},{ 0} }, { {0xe0,0x7E,0},{0xe0,0xF0,0x7E,0} }, { { 0x6E,0},{ 0xf0,0x6E,0} }, /*144*/ + { { 0x63,0},{ 0xf0,0x63,0} }, { { 0x6F,0},{ 0xf0,0x6F,0} }, { { 0},{ 0} }, { { 0x61,0},{ 0xf0,0x61,0} }, /*148*/ + { {0xe0,0x73,0},{0xe0,0xF0,0x73,0} }, { { 0x6A,0},{ 0xf0,0x6A,0} }, { {0xe0,0x79,0},{0xe0,0xF0,0x79,0} }, { { 0x65,0},{ 0xf0,0x65,0} }, /*14c*/ + { { 0x60,0},{ 0xf0,0x60,0} }, { { 0x6D,0},{ 0xf0,0x6D,0} }, { { 0x67,0},{ 0xf0,0x67,0} }, { { 0x64,0},{ 0xf0,0x64,0} }, /*150*/ + { { 0xd4,0},{ 0xf0,0xD4,0} }, { {0xe0,0x60,0},{0xe0,0xF0,0x60,0} }, { { 0},{ 0} }, { {0xe0,0x78,0},{0xe0,0xF0,0x78,0} }, /*154*/ + { {0xe0,0x07,0},{0xe0,0xF0,0x07,0} }, { {0xe0,0x0F,0},{0xe0,0xF0,0x0F,0} }, { {0xe0,0x17,0},{0xe0,0xF0,0x17,0} }, { { 0x8B,0},{ 0xf0,0x8B,0} }, /*158*/ + { { 0x8C,0},{ 0xf0,0x8C,0} }, { { 0x8D,0},{ 0xf0,0x8D,0} }, { { 0},{ 0} }, { { 0x7F,0},{ 0xf0,0x7F,0} }, /*15c*/ + { { 0},{ 0} }, { {0xe0,0x4F,0},{0xe0,0xF0,0x4F,0} }, { {0xe0,0x56,0},{0xe0,0xF0,0x56,0} }, { { 0},{ 0} }, /*160*/ + { {0xe0,0x08,0},{0xe0,0xF0,0x08,0} }, { {0xe0,0x10,0},{0xe0,0xF0,0x10,0} }, { {0xe0,0x18,0},{0xe0,0xF0,0x18,0} }, { {0xe0,0x20,0},{0xe0,0xF0,0x20,0} }, /*164*/ + { {0xe0,0x28,0},{0xe0,0xF0,0x28,0} }, { {0xe0,0x30,0},{0xe0,0xF0,0x30,0} }, { {0xe0,0x38,0},{0xe0,0xF0,0x38,0} }, { {0xe0,0x40,0},{0xe0,0xF0,0x40,0} }, /*168*/ + { {0xe0,0x48,0},{0xe0,0xF0,0x48,0} }, { {0xe0,0x50,0},{0xe0,0xF0,0x50,0} }, { {0xe0,0x57,0},{0xe0,0xF0,0x57,0} }, { { 0},{ 0} }, /*16c*/ + { {0xe0,0x13,0},{0xe0,0xF0,0x13,0} }, { {0xe0,0x19,0},{0xe0,0xF0,0x19,0} }, { {0xe0,0x39,0},{0xe0,0xF0,0x39,0} }, { {0xe0,0x51,0},{0xe0,0xF0,0x51,0} }, /*170*/ + { {0xe0,0x53,0},{0xe0,0xF0,0x53,0} }, { {0xe0,0x5C,0},{0xe0,0xF0,0x5C,0} }, { { 0},{ 0} }, { {0xe0,0x62,0},{0xe0,0xF0,0x62,0} }, /*174*/ + { {0xe0,0x63,0},{0xe0,0xF0,0x63,0} }, { {0xe0,0x64,0},{0xe0,0xF0,0x64,0} }, { {0xe0,0x65,0},{0xe0,0xF0,0x65,0} }, { {0xe0,0x67,0},{0xe0,0xF0,0x67,0} }, /*178*/ + { {0xe0,0x68,0},{0xe0,0xF0,0x68,0} }, { {0xe0,0x6A,0},{0xe0,0xF0,0x6A,0} }, { {0xe0,0x6D,0},{0xe0,0xF0,0x6D,0} }, { {0xe0,0x6E,0},{0xe0,0xF0,0x6E,0} }, /*17c*/ + + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*180*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*184*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*188*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*18c*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*190*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*194*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*198*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*19c*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1ac*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1cc*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1dc*/ + { { 0},{ 0} }, { {0xe0,0xe1,0},{0xe0,0xF0,0xE1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xee,0},{0xe0,0xF0,0xEE,0} }, { { 0},{ 0} }, /*1ec*/ + { { 0},{ 0} }, { {0xe0,0xf1,0},{0xe0,0xF0,0xF1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{0xe0,0xF0,0xFE,0} }, { {0xe0,0xff,0},{0xe0,0xF0,0xFF,0} } /*1fc*/ +}; + + +static void add_data_kbd(uint16_t val); + + +#if (!defined(RELEASE_BUILD) && defined(ENABLE_KBD_AT_LOG)) +int kbd_at_do_log = ENABLE_KBD_AT_LOG; + + +static void +kbd_log(atkbd_t *dev, const char *fmt, ...) +{ + va_list ap; + + if ((dev == NULL) || (dev->log == NULL)) + return; + + if (kbd_at_do_log) { + va_start(ap, fmt); + log_out(dev->log, fmt, ap); + va_end(ap); + } +} +#else +#define kbd_log(dev, fmt, ...) +#endif + + +/* TODO: Get rid of keyboard_mode entirely - keyboard.c just need to know which scan codes to + send break codes for and which to repeat. + The break code stuff, though, might also be doable on the AT keyboard side, if F0 F0 + is never sent. */ +static void +set_scancode_map(atkbd_t *dev) +{ + switch (keyboard_mode & 3) { +#ifdef USE_SET1 + case 1: + default: + keyboard_set_table(scancode_set1); + break; +#else + default: +#endif + case 2: + keyboard_set_table(scancode_set2); + break; + + case 3: + keyboard_set_table(scancode_set3); + break; + } + + if (keyboard_mode & 0x20) +#ifdef USE_SET1 + keyboard_set_table(scancode_set1); +#else + keyboard_set_table(scancode_set2); +#endif +} + + + +/* TODO: Move the queues to the device. */ +static void +kbc_queue_reset(uint8_t channel) +{ + if (channel == 2) { + mouse_queue_start = mouse_queue_end = 0; + memset(mouse_queue, 0x00, sizeof(mouse_queue)); + } else if (channel == 1) { + dev->queue_start = dev->queue_end = 0; + memset(dev->queue, 0x00, sizeof(dev->queue)); + } +} + + +static void +add_data_kbd_queue(atkbd_t *dev, uint8_t val) +{ + if (!keyboard_scan || (dev->queue_end >= 16)) { + kbd_log(dev, "Unable to add to queue, conditions: %i, %i\n", !keyboard_scan, (dev->queue_end >= 16)); + return; + } + + kbd_log(dev, "dev->queue[%02X] = %02X;\n", dev->queue_end, val); + dev->queue[dev->queue_end] = val; + dev->queue_end = (dev->queue_end + 1) & 0xf; +} + + +static void +kbd_send_to_host(atkbd_t *dev, uint8_t val) +{ + dev->kd.c_in = 1; + dev->kd.c_data = val; + + dev->last_byte = val; +} + + +static void +kbd_reset(atkbd_t *dev) +{ + kbc_queue_reset(1); + dev->kd.c_in = 0x00; + /* TODO: Move this to the keyboard struct. */ + dev->last_byte = 0x00; + + /* Set scan code set to 2. */ + keyboard_mode = (keyboard_mode & 0xfc) | 0x02; + set_scancode_map(dev); + + dev->phase = 0; + dev->in = 0; + + memset(keyboard_set3_flags, 0, 512); +} + + +static void +kbd_command(atkbd_t *dev) +{ + uint8_t val = dev->kd.d_data; + + if ((dev->phase > 0) && (dev->cmd == 0xff)) { + dev->phase++; + if (dev->phase == RESET_DELAY_TIME) { + kbd_send_to_host(dev, 0xaa); + dev->phase = 0; + dev->cmd = 0x00; + } + return; + } + + if (dev->phase == 2) { + dev->phase = 0; + + switch (dev->cmd) { + case 0xf2: + kbd_send_to_host(dev, 0x83); + break; + default: + log_fatal(dev->log, "Invalid command for phase 2: %02X\n", dev->cmd); + break; + } + + /* Keyboard command is now done. */ + if (dev->phase == 0) + dev->cmd = 0x00; + return; + } else if (dev->phase == 1) { + dev->phase = 0; + + switch (dev->cmd) { + case 0xf0: + kbd_log(dev, "Get scan code set: %02X\n", keyboard_mode & 3); + kbd_send_to_host(dev, keyboard_mode & 3); + break; + case 0xf2: + kbd_send_to_host(dev, 0xab); + dev->phase = 2; + break; + default: + log_fatal(dev->log, "Invalid command for phase 1: %02X\n", dev->cmd); + break; + } + + /* Keyboard command is now done. */ + if (dev->phase == 0) + dev->cmd = 0x00; + return; + } + + if (dev->in && (val < 0xed)) { + dev->in = 0; + dev->phase = 0; + + switch (dev->cmd) { + case 0xed: /* set/reset LEDs */ + kbd_log(dev, "Set LEDs: %02X\n", val); + kbd_send_to_host(dev, 0xfa); + break; + + case 0xf0: /* get/set scancode set */ + kbd_send_to_host(dev, 0xfa); + if (val == 0) + dev->phase = 1; + else { + if ((val <= 3) && (val != 1)) { + keyboard_mode &= 0xfc; + keyboard_mode |= (val & 3); + kbd_log(dev, "Scan code set now: %02X\n", val); + } + set_scancode_map(dev); + } + break; + + case 0xf3: /* set typematic rate/delay */ + kbd_send_to_host(dev, 0xfa); + break; + + default: + kbd_log(dev, "Bad keyboard 0060 write %02X command %02X\n", val, dev->cmd); + kbd_send_to_host(dev, 0xfe); + break; + } + + /* Keyboard command is now done. */ + if (dev->phase == 0) + dev->cmd = 0x00; + } else { + /* No keyboard command in progress. */ + dev->in = 0; + dev->cmd = 0x00; + dev->phase = 0; + + switch (val) { + case 0x00: + kbd_log(dev, "Command 00\n"); + kbd_send_to_host(dev, 0xfa); + break; + + case 0x05: /*??? - sent by NT 4.0*/ + kbd_log(dev, "Command 05 (NT 4.0)\n"); + kbd_send_to_host(dev, 0xfe); + break; + + case 0xed: /* set/reset LEDs */ + kbd_log(dev, "Set/reset LEDs\n"); + kbd_send_to_host(dev, 0xfa); + + dev->in = 1; + break; + + case 0xee: /* diagnostic echo */ + kbd_log(dev, "Diagnostic echo\n"); + kbd_send_to_host(dev, 0xee); + break; + + case 0xef: /* NOP (reserved for future use) */ + kbd_log(dev, "NOP (reserved for future use)\n"); + break; + + case 0xf0: /* get/set scan code set */ + kbd_log(dev, "Get/set scan code set\n"); + kbd_send_to_host(dev, 0xfa); + dev->in = 1; + break; + + case 0xf2: /* read ID */ + /* Fixed as translation will be done in add_data_kbd(). */ + kbd_log(dev, "Read keyboard ID\n"); + /* TODO: After keyboard type selection is implemented, make this + return the correct keyboard ID for the selected type. */ + kbd_send_to_host(dev, 0xfa); + dev->phase = 1; + break; + + case 0xf3: /* set typematic rate/delay */ + kbd_log(dev, "Set typematic rate/delay\n"); + kbd_send_to_host(dev, 0xfa); + dev->in = 1; + break; + + case 0xf4: /* enable keyboard */ + kbd_log(dev, "Enable keyboard\n"); + kbd_send_to_host(dev, 0xfa); + keyboard_scan = 1; + break; + + case 0xf5: /* set defaults and disable keyboard */ + case 0xf6: /* set defaults */ + kbd_log(dev, "Set defaults%s\n", (val == 0xf6) ? "" : " and disable keyboard"); + keyboard_scan = (val == 0xf6); + kbd_log(dev, "val = %02X, keyboard_scan = %i, dev->mem[0x20] = %02X\n", + val, keyboard_scan, dev->mem[0x20]); + kbd_send_to_host(dev, 0xfa); + + keyboard_set3_all_break = 0; + keyboard_set3_all_repeat = 0; + memset(keyboard_set3_flags, 0, 512); + keyboard_mode = (keyboard_mode & 0xfc) | 0x02; + set_scancode_map(dev); + break; + + case 0xf7: /* set all keys to repeat */ + kbd_log(dev, "Set all keys to repeat\n"); + kbd_send_to_host(dev, 0xfa); + keyboard_set3_all_break = 1; + break; + + case 0xf8: /* set all keys to give make/break codes */ + kbd_log(dev, "Set all keys to give make/break codes\n"); + kbd_send_to_host(dev, 0xfa); + keyboard_set3_all_break = 1; + break; + + case 0xf9: /* set all keys to give make codes only */ + kbd_log(dev, "Set all keys to give make codes only\n"); + kbd_send_to_host(dev, 0xfa); + keyboard_set3_all_break = 0; + break; + + case 0xfa: /* set all keys to repeat and give make/break codes */ + kbd_log(dev, "Set all keys to repeat and give make/break codes\n"); + kbd_send_to_host(dev, 0xfa); + keyboard_set3_all_repeat = 1; + keyboard_set3_all_break = 1; + break; + + case 0xfe: /* resend last scan code */ + kbd_log(dev, "Reset last scan code\n"); + kbd_send_to_host(dev, dev->last_byte); + break; + + case 0xff: /* reset */ + kbd_log(dev, "Reset\n"); + kbd_reset(dev); + kbd_send_to_host(dev, 0xfa); + dev->phase = 1; + break; + + default: + kbd_log(dev, "Bad keyboard command %02X\n", val); + kbd_send_to_host(dev, 0xfe); + } + + /* If command needs data, remember command. */ + if ((dev->in == 1) || (dev->phase > 0)) + dev->cmd = val; + } +} + + +static void +kbd_do_command(atkbd_t *dev) +{ + kbd_command(dev); + if (dev->kd.d_in) + dev->state = KBD_CMD_PROCESS; + else if ((dev->phase == 0) && !dev->in) { + dev->in_cmd = 0; + if (dev->kd.d_data != 0xf5) + keyboard_scan = 1; + dev->state = KBD_MAIN_LOOP; + } else { + keyboard_scan = 0; + dev->in_cmd = 1; + dev->state = KBD_CMD_PROCESS; + } +} + + +static void +kbd_nack(atkbd_t *dev) +{ + kbd_send_to_host(dev, 0xfe); + dev->state = KBD_MAIN_LOOP; +} + + +static void +kbd_main_loop(atkbd_t *dev) +{ + uint8_t scan = !dev->kd.inhibit && keyboard_scan; + + if (dev->kd.d_in) { + dev->kd.d_in = 0; + kbd_cmd_process(dev); + } else if (scan && (dev->queue_start != dev->queue_end)) { + /* Scan here. */ + kbd_log(dev, "Get %02X from FIFO\n", dev->queue[dev->queue_start]); + kbd_send_to_host(dev, dev->queue[dev->queue_start]); + dev->queue_start = (dev->queue_start + 1) & 0xf; + } +} + + +static void +kbd_cmd_process(atkbd_t *dev) +{ + uint8_t written = dev->kd.d_in; + + /* We want data, nothing has been written yet, return. */ + if (dev->in && !dev->kd.d_in) + return; + + dev->kd.d_in = 0; + + if (!written && !keyboard_scan && dev->in_cmd && (dev->phase > 0)) { + kbd_log(dev, "Keyboard not written, not scanning, in command, and phase > 0\n"); + kbd_do_command(dev); + } else if (dev->kd.d_data == 0xfe) { + kbd_log(dev, "Send last byte: %02X\n", dev->last_byte); + kbd_send_to_host(dev, dev->last_byte); + dev->state = KBD_MAIN_LOOP; + } else if (dev->kd.d_data == 0xee) { + kbd_log(dev, "Diagnostic echo: EE\n"); + kbd_send_to_host(dev, 0xee); + dev->state = KBD_MAIN_LOOP; + } else if (dev->kd.d_data >= 0xed) { + kbd_log(dev, "Command %02X\n", dev->kd.d_data); + if (!keyboard_scan && dev->in_cmd && (dev->cmd == 0xed)) { + kbd_log(dev, "Not scanning, in command, old command is ED\n"); + keyboard_scan = 1; + dev->in_cmd = 0; + } + kbd_do_command(dev); + } else { + if (!keyboard_scan && dev->in_cmd) { + if ((dev->cmd == 0xf3) && (dev->kd.d_data & 0x80)) { + kbd_log(dev, "Command F3 data %02X has bit 7 set\n", dev->kd.d_data); + kbd_nack(dev); + } else { + kbd_log(dev, "Command %02X data %02X\n", dev->cmd, dev->kd.d_data); + kbd_do_command(dev); + } + } else { + kbd_log(dev, "Scanning or not in command, NACK\n"); + kbd_nack(dev); + } + } +} + + +/* Keyboard processing */ +static void +kbd_process(atkbd_t *dev) +{ + /* The real 8048 keyboard firmware stops transmitting if host wants to transmit. */ + if (dev->kd.c_in && dev->kd.d_in) + dev->kd.c_in = 0; + + /* The host has either acknowledged the transmitted byte or we have not transmitted anything (yet). */ + if (!dev->kd.c_in) switch (dev->state) { + case KBD_MAIN_LOOP: + kbd_main_loop(dev); + break; + case KBD_CMD_PROCESS: + kbd_cmd_process(dev); + break; + } +} + + +static void +add_data_vals(atkbd_t *dev, uint8_t *val, uint8_t len) +{ + int i; + + for (i = 0; i < len; i++) + add_data_kbd_queue(dev, val[i]); +} + + +static void +add_data_kbd(uint16_t val) +{ + atkbd_t *dev = SavedKbd; + uint8_t fake_shift[4]; + uint8_t num_lock = 0, shift_states = 0; + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + + if (dev->in || (dev->phase > 0)) + return; + + keyboard_get_states(NULL, &num_lock, NULL); + shift_states = keyboard_get_shift() & STATE_SHIFT_MASK; + + /* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */ + if ((dev != NULL) && (kbc_ven == KBC_VEN_TOSHIBA) && (keyboard_recv(0xb8) || keyboard_recv(0x9d)) && + (val >= 0x4f) && (val <= 0x54) && (val != 0x4e)) + t3100e_notify_set((val + 2) & 0x0f); + + switch(val) { + case FAKE_LSHIFT_ON: + kbd_log(dev, "Fake left shift on, scan code: "); + if (num_lock) { + if (shift_states) { + kbd_log(dev, "N/A (one or both shifts on)\n"); + break; + } else { + /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ + switch(keyboard_mode & 0x02) { + case 1: + fake_shift[0] = 0xe0; fake_shift[1] = 0x2a; + add_data_vals(dev, fake_shift, 2); + break; + + case 2: + fake_shift[0] = 0xe0; fake_shift[1] = 0x12; + add_data_vals(dev, fake_shift, 2); + break; + + default: + kbd_log(dev, "N/A (scan code set %i)\n", keyboard_mode & 0x02); + break; + } + } + } else { + if (shift_states & STATE_LSHIFT) { + /* Num lock off and left shift pressed. */ + switch(keyboard_mode & 0x02) { + case 1: + fake_shift[0] = 0xe0; fake_shift[1] = 0xaa; + add_data_vals(dev, fake_shift, 2); + break; + + case 2: + fake_shift[0] = 0xe0; fake_shift[1] = 0xf0; fake_shift[2] = 0x12; + add_data_vals(dev, fake_shift, 3); + break; + + default: + kbd_log(dev, "N/A (scan code set %i)\n", keyboard_mode & 0x02); + break; + } + } + if (shift_states & STATE_RSHIFT) { + /* Num lock off and right shift pressed. */ + switch(keyboard_mode & 0x02) { + case 1: + fake_shift[0] = 0xe0; fake_shift[1] = 0xb6; + add_data_vals(dev, fake_shift, 2); + break; + + case 2: + fake_shift[0] = 0xe0; fake_shift[1] = 0xf0; fake_shift[2] = 0x59; + add_data_vals(dev, fake_shift, 3); + break; + + default: + kbd_log(dev, "N/A (scan code set %i)\n", keyboard_mode & 0x02); + break; + } + } + kbd_log(dev, shift_states ? "" : "N/A (both shifts off)\n"); + } + break; + + case FAKE_LSHIFT_OFF: + kbd_log(dev, "Fake left shift off, scan code: "); + if (num_lock) { + if (shift_states) { + kbd_log(dev, "N/A (one or both shifts on)\n"); + break; + } else { + /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ + switch(keyboard_mode & 0x02) { + case 1: + fake_shift[0] = 0xe0; fake_shift[1] = 0xaa; + add_data_vals(dev, fake_shift, 2); + break; + + case 2: + fake_shift[0] = 0xe0; fake_shift[1] = 0xf0; fake_shift[2] = 0x12; + add_data_vals(dev, fake_shift, 3); + break; + + default: + kbd_log(dev, "N/A (scan code set %i)\n", keyboard_mode & 0x02); + break; + } + } + } else { + if (shift_states & STATE_LSHIFT) { + /* Num lock off and left shift pressed. */ + switch(keyboard_mode & 0x02) { + case 1: + fake_shift[0] = 0xe0; fake_shift[1] = 0x2a; + add_data_vals(dev, fake_shift, 2); + break; + + case 2: + fake_shift[0] = 0xe0; fake_shift[1] = 0x12; + add_data_vals(dev, fake_shift, 2); + break; + + default: + kbd_log(dev, "N/A (scan code set %i)\n", keyboard_mode & 0x02); + break; + } + } + if (shift_states & STATE_RSHIFT) { + /* Num lock off and right shift pressed. */ + switch(keyboard_mode & 0x02) { + case 1: + fake_shift[0] = 0xe0; fake_shift[1] = 0x36; + add_data_vals(dev, fake_shift, 2); + break; + + case 2: + fake_shift[0] = 0xe0; fake_shift[1] = 0x59; + add_data_vals(dev, fake_shift, 2); + break; + + default: + kbd_log(dev, "N/A (scan code set %i)\n", keyboard_mode & 0x02); + break; + } + } + kbd_log(dev, shift_states ? "" : "N/A (both shifts off)\n"); + } + break; + + default: + add_data_kbd_queue(dev, val); + break; + } +} + + +static void +kbd_close(void *priv) +{ + atkbd_t *dev = (atkbd_t *)priv; + + kbd_reset(dev); + + keyboard_scan = 0; + keyboard_send = NULL; + + /* Disable the scancode maps. */ + keyboard_set_table(NULL); + +#if (!defined(RELEASE_BUILD) && defined(ENABLE_KBD_AT_LOG)) + log_close(dev->log); +#endif + + kbc_dev_attach(NULL, 1); + + SavedKbd = NULL; + free(dev); +} + + +static void * +kbd_init(const device_t *info) +{ + atkbd_t *dev; + + dev = (atkbd_t *)malloc(sizeof(atkbd_t)); + memset(dev, 0x00, sizeof(atkbd_t)); + + kbc_dev_attach(&(dev->kd), 1); + + kbd_send_to_host(dev, 0xaa); + + keyboard_send = add_data_kbd; + +#if (!defined(RELEASE_BUILD) && defined(ENABLE_KBD_AT_LOG)) + dev->kbd_log = log_open("AT KBD"); +#endif + + kbd_reset(dev); + + /* We need this, sadly. */ + SavedKbd = dev; + + return(dev); +} + + +const device_t keyboard_at_kbd_device = { + "PC/AT Keyboard (Actual keyboard!)", + 0, + 0, + kbd_init, + kbd_close, + kbd_reset, + { NULL }, NULL, NULL, NULL +}; diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index c3fb5b93e..92690db1f 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -57,9 +57,7 @@ #define STAT_IFULL 0x02 #define STAT_OFULL 0x01 -#define PS2_REFRESH_TIME (16 * TIMER_USEC) - -#define RESET_DELAY_TIME (100 * 10) /* 600ms */ +#define RESET_DELAY_TIME 1000 /* 100 ms */ #define CCB_UNUSED 0x80 #define CCB_TRANSLATE 0x40 @@ -74,49 +72,136 @@ #define MODE_MASK 0x6c #define KBC_TYPE_ISA 0x00 /* AT ISA-based chips */ -#define KBC_TYPE_PS2_NOREF 0x01 /* PS2 type, no refresh */ -#define KBC_TYPE_PS2_1 0x02 /* PS2 on PS/2, type 1 */ -#define KBC_TYPE_PS2_2 0x03 /* PS2 on PS/2, type 2 */ -#define KBC_TYPE_MASK 0x03 +#define KBC_TYPE_PS2_1 0x04 /* PS2 type, no refresh */ +/* This only differs in that translation is forced off. */ +#define KBC_TYPE_PS2_2 0x05 /* PS2 on PS/2, type 2 */ +#define KBC_TYPE_MASK 0x07 +#define KBC_FLAG_PS2 0x04 + +/* We need to redefine this: + Currently, we use bits 3-7 for vendor, we should instead use bits 4-7 + for vendor, 0-3 for revision/variant, and have a dev->ps2 flag controlling + controller mode, normally set according to the flags, but togglable on + AMIKey: + 0000 0000 0x00 IBM, AT + 0000 0001 0x01 MR + 0000 0010 0x02 Xi8088, clone of IBM PS/2 type 1 + 0001 0000 0x10 Olivetti + 0010 0000 0x20 Toshiba + 0011 0000 0x30 Quadtel + 0100 0000 0x40 Phoenix MultiKey/42 + 0101 0000 0x50 AMI KF + 0101 0001 0x51 AMI KH + 0101 0010 0x52 AMIKey + 0101 0011 0x53 AMIKey-2 + 0101 0100 0x54 JetKey (clone of AMI KF/AMIKey) + 0110 0000 0x60 Award + 0110 0001 0x61 Award 286 (has some AMI commands apparently) + 0111 0000 0x70 Siemens +*/ + +/* Standard IBM controller */ #define KBC_VEN_GENERIC 0x00 -#define KBC_VEN_AMI 0x04 +/* All commands are standard PS/2 */ #define KBC_VEN_IBM_MCA 0x08 -#define KBC_VEN_QUADTEL 0x0c -#define KBC_VEN_TOSHIBA 0x10 -#define KBC_VEN_XI8088 0x14 -#define KBC_VEN_IBM_PS1 0x18 -#define KBC_VEN_ACER 0x1c -#define KBC_VEN_INTEL_AMI 0x20 -#define KBC_VEN_OLIVETTI 0x24 -#define KBC_VEN_NCR 0x28 -#define KBC_VEN_SAMSUNG 0x2c -#define KBC_VEN_MASK 0x3c +/* Standard IBM commands, differs in input port bits */ +#define KBC_VEN_IBM_PS1 0x10 +/* Olivetti - proprietary commands and port 62h with switches + readout */ +#define KBC_VEN_OLIVETTI 0x20 +/* Toshiba T3100e - has a bunch of proprietary commands, also sets + IFULL on command AA */ +#define KBC_VEN_TOSHIBA 0x28 +/* Standard IBM commands, uses input port as a switches readout */ +#define KBC_VEN_NCR 0x30 +/* Xi8088 - standard IBM commands, has a turbo bit on port 61h, and the + polarity of the video type bit in the input port is inverted */ +#define KBC_VEN_XI8088 0x38 +/* QuadtelKey - currently guesswork */ +#define KBC_VEN_QUADTEL 0x40 +/* Phoenix MultiKey/42 - not yet implemented */ +#define KBC_VEN_PHOENIX 0x48 +/* Generic commands, XI8088-like input port handling of video type, + maybe we just need a flag for that? */ +#define KBC_VEN_ACER 0x50 +/* AMI KF/KH/AMIKey/AMIKey-2 */ +#define KBC_VEN_AMI 0xf0 +/* Standard AMI commands, differs in input port bits */ +#define KBC_VEN_INTEL_AMI 0xf8 +#define KBC_VEN_MASK 0xf8 + + +/* Flags should be fully 32-bit: + Bits 7- 0: Vendor and revision/variant; + Bits 15- 8: Input port mask; + Bits 23-16: Input port bits that are always on; + Bits 31-24: Flags: + Bit 0: Invert P1 video type bit polarity; + Bit 1: Is PS/2; + Bit 2: Translation forced always off. + + So for example, the IBM PS/2 type 1 controller flags would be: 00000010 00000000 11111111 00000000 = 0200ff00 . */ typedef struct { - uint8_t command, status, old_status, out, old_out, secr_phase, - mem_addr, input_port, output_port, old_output_port, - key_command, output_locked, ami_stat, want60, - wantirq, key_wantdata, refresh, first_write; + uint8_t status, ib, ob, p1, p2, old_p2, p2_locked, fast_a20_phase, + secr_phase, mem_index, ami_stat, ami_mode, + kbc_in, kbc_cmd, kbc_in_cmd, kbc_poll_phase, kbc_to_send, + kbc_send_pending, kbc_channel, kbc_stat_hi, kbc_wait_for_response, inhibit, + kbd_in, kbd_cmd, kbd_in_cmd, kbd_written, kbd_data, kbd_poll_phase, kbd_inhibit, + mouse_in, mouse_cmd, mouse_in_cmd, mouse_written, mouse_data, mouse_poll_phase, mouse_inhibit, + kbc_written[3], kbc_data[3]; - uint8_t mem[0x100]; + uint8_t mem_int[0x40], mem[0x240]; - int last_irq, old_last_irq, - reset_delay, - out_new, out_delayed; + uint16_t last_irq, kbc_phase, kbd_phase, mouse_phase; uint32_t flags; - pc_timer_t refresh_time, pulse_cb; + pc_timer_t pulse_cb, send_delay_timer; uint8_t (*write60_ven)(void *p, uint8_t val); uint8_t (*write64_ven)(void *p, uint8_t val); - - pc_timer_t send_delay_timer; } atkbd_t; +enum +{ + CHANNEL_KBC = 0, + CHANNEL_KBD, + CHANNEL_MOUSE +}; + +enum +{ + KBD_MAIN_LOOP = 0, + KBD_CMD_PROCESS +}; + +enum +{ + MOUSE_MAIN_LOOP_1 = 0, + MOUSE_CMD_PROCESS, + MOUSE_CMD_END, + MOUSE_MAIN_LOOP_2 +}; + +enum { + KBC_MAIN_LOOP = 0, + KBC_RESET = 1, + KBC_WAIT = 4, + KBC_WAIT_FOR_KBD, + KBC_WAIT_FOR_MOUSE, + KBC_WAIT_FOR_BOTH +}; + + +static void kbd_cmd_process(atkbd_t *dev); + +static void kbc_wait(atkbd_t *dev, uint8_t flags); + + /* bit 0 = repeat, bit 1 = makes break code? */ uint8_t keyboard_set3_flags[512]; uint8_t keyboard_set3_all_repeat; @@ -125,9 +210,9 @@ uint8_t keyboard_set3_all_break; /* Bits 0 - 1 = scan code set, bit 6 = translate or not. */ uint8_t keyboard_mode = 0x42; +uint8_t * ami_copr = (uint8_t *) "(C)1994 AMI"; + -static uint8_t key_ctrl_queue[16]; -static int key_ctrl_queue_start = 0, key_ctrl_queue_end = 0; static uint8_t key_queue[16]; static int key_queue_start = 0, key_queue_end = 0; uint8_t mouse_queue[16]; @@ -568,9 +653,27 @@ static const scancode scancode_set3[512] = { }; +#define UISTR_LEN 256 +static char kbd_str[UISTR_LEN]; /* UI output string */ static void add_data_kbd(uint16_t val); +extern void ui_sb_bugui(char *__str); + + +static void +kbd_status(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsprintf(kbd_str, fmt, ap); + ui_sb_bugui(kbd_str); + va_end(ap); +} + + +// #define ENABLE_KEYBOARD_AT_LOG 1 #ifdef ENABLE_KEYBOARD_AT_LOG int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG; @@ -631,9 +734,6 @@ kbc_queue_reset(uint8_t channel) } else if (channel == 1) { key_queue_start = key_queue_end = 0; memset(key_queue, 0x00, sizeof(key_queue)); - } else { - key_ctrl_queue_start = key_ctrl_queue_end = 0; - memset(key_ctrl_queue, 0x00, sizeof(key_ctrl_queue)); } } @@ -641,15 +741,6 @@ kbc_queue_reset(uint8_t channel) static void kbc_queue_add(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) { - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - - if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) - stat_hi |= ((dev->input_port & 0x80) ? 0x10 : 0x00); - else - stat_hi |= 0x10; - - dev->status = (dev->status & 0x0f) | stat_hi; - if (channel == 2) { kbd_log("ATkbc: mouse_queue[%02X] = %02X;\n", mouse_queue_end, val); mouse_queue[mouse_queue_end] = val; @@ -658,82 +749,1042 @@ kbc_queue_add(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); key_queue[key_queue_end] = val; key_queue_end = (key_queue_end + 1) & 0xf; - } else { - kbd_log("ATkbc: key_ctrl_queue[%02X] = %02X;\n", key_ctrl_queue_end, val); - key_ctrl_queue[key_ctrl_queue_end] = val; - key_ctrl_queue_end = (key_ctrl_queue_end + 1) & 0xf; - } -} - - -static void -add_to_kbc_queue_front(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) -{ - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - - if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) - stat_hi |= ((dev->input_port & 0x80) ? 0x10 : 0x00); - else - stat_hi |= 0x10; - - kbd_log("ATkbc: Adding %02X to front...\n", val); - dev->wantirq = 0; - if (channel == 2) { - if (dev->mem[0] & 0x02) - picint(0x1000); - } else { - if (dev->mem[0] & 0x01) - picint(2); - } - dev->out = val; - if (channel == 2) - dev->status = (dev->status & ~STAT_IFULL) | (STAT_OFULL | STAT_MFULL) | stat_hi; - else - dev->status = (dev->status & ~(STAT_IFULL | STAT_MFULL)) | STAT_OFULL | stat_hi; - dev->last_irq = 0x0000; + } else + fatal("Adding %02X to invalid channel %02X\n", val, channel); } static void add_data_kbd_queue(atkbd_t *dev, int direct, uint8_t val) { - if ((!keyboard_scan && !direct) || (dev->reset_delay > 0) || (key_queue_end >= 16)) { - kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i, %i\n", !keyboard_scan, (dev->reset_delay > 0), (key_queue_end >= 16)); + if ((!keyboard_scan && !direct) || (key_queue_end >= 16)) { + kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i\n", !keyboard_scan, (key_queue_end >= 16)); return; } - kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); + + kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); kbc_queue_add(dev, val, 1, 0x00); kbd_last_scan_code = val; } - static void -add_data_kbd_direct(atkbd_t *dev, uint8_t val) +kbc_send(atkbd_t *dev, uint8_t val, uint8_t channel) { - int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); - int translate = (keyboard_mode & 0x40); - uint8_t send; - - if (dev->reset_delay) - return; - - translate = translate || (keyboard_mode & 0x40) || xt_mode; - translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); - - if (translate) - send = nont_to_t[val]; - else - send = val; - - add_data_kbd_queue(dev, 1, send); + dev->kbc_written[channel] = 1; + dev->kbc_data[channel] = val; } static void -add_data_kbd_raw(atkbd_t *dev, uint8_t val) +kbd_send_to_host(atkbd_t *dev, uint8_t val) { - add_data_kbd_queue(dev, 1, val); + kbc_send(dev, val, CHANNEL_KBD); +} + + +static void +kbd_chip_reset(atkbd_t *dev) +{ + kbc_queue_reset(1); + dev->kbc_written[1] = 0x00; + kbd_last_scan_code = 0x00; + + /* Set scan code set to 2. */ + keyboard_mode = (keyboard_mode & 0xfc) | 0x02; + set_scancode_map(dev); + + dev->kbd_phase = 0; + dev->kbd_in = 0; +} + + +static void +kbd_command(atkbd_t *dev) +{ + uint8_t val = dev->kbd_data; + + if ((dev->kbd_phase > 0) && (dev->kbd_cmd == 0xff)) { + dev->kbd_phase++; + if (dev->kbd_phase == RESET_DELAY_TIME) { + kbd_send_to_host(dev, 0xaa); + dev->kbd_phase = 0; + dev->kbd_cmd = 0x00; + } + return; + } + + if (dev->kbd_phase == 2) { + dev->kbd_phase = 0; + + switch (dev->kbd_cmd) { + case 0xf2: + kbd_send_to_host(dev, 0x83); + break; + default: + fatal("Invalid command for phase 2: %02X\n", dev->kbd_cmd); + break; + } + + /* Keyboard command is now done. */ + if (dev->kbd_phase == 0) + dev->kbd_cmd = 0x00; + return; + } else if (dev->kbd_phase == 1) { + dev->kbd_phase = 0; + + switch (dev->kbd_cmd) { + case 0xf0: + kbd_log("Get scan code set: %02X\n", keyboard_mode & 3); + kbd_send_to_host(dev, keyboard_mode & 3); + break; + case 0xf2: + kbd_send_to_host(dev, 0xab); + dev->kbd_phase = 2; + break; + default: + fatal("Invalid command for phase 1: %02X\n", dev->kbd_cmd); + break; + } + + /* Keyboard command is now done. */ + if (dev->kbd_phase == 0) + dev->kbd_cmd = 0x00; + return; + } + + if (dev->kbd_in && (val < 0xed)) { + dev->kbd_in = 0; + dev->kbd_phase = 0; + + switch (dev->kbd_cmd) { + case 0xed: /* set/reset LEDs */ + kbd_log("ATkbd: set LEDs [%02x]\n", val); + kbd_send_to_host(dev, 0xfa); + break; + + case 0xf0: /* get/set scancode set */ + kbd_send_to_host(dev, 0xfa); + if (val == 0) + dev->kbd_phase = 1; + else { + if ((val <= 3) && (val != 1)) { + keyboard_mode &= 0xfc; + keyboard_mode |= (val & 3); + kbd_log("Scan code set now: %02X\n", val); + } + set_scancode_map(dev); + } + break; + + case 0xf3: /* set typematic rate/delay */ + kbd_send_to_host(dev, 0xfa); + break; + + default: + kbd_log("ATkbd: bad keyboard 0060 write %02X command %02X\n", val, dev->kbd_cmd); + kbd_send_to_host(dev, 0xfe); + break; + } + + /* Keyboard command is now done. */ + if (dev->kbd_phase == 0) + dev->kbd_cmd = 0x00; + } else { + /* No keyboard command in progress. */ + dev->kbd_in = 0; + dev->kbd_cmd = 0x00; + dev->kbd_phase = 0; + + switch (val) { + case 0x00: + kbd_log("ATkbd: command 00\n"); + kbd_send_to_host(dev, 0xfa); + break; + + case 0x05: /*??? - sent by NT 4.0*/ + kbd_log("ATkbd: command 05 (NT 4.0)\n"); + kbd_send_to_host(dev, 0xfe); + break; + + case 0xed: /* set/reset LEDs */ + kbd_log("ATkbd: set/reset leds\n"); + kbd_send_to_host(dev, 0xfa); + + dev->kbd_in = 1; + break; + + case 0xee: /* diagnostic echo */ + kbd_log("ATkbd: ECHO\n"); + kbd_send_to_host(dev, 0xee); + break; + + case 0xef: /* NOP (reserved for future use) */ + kbd_log("ATkbd: NOP\n"); + break; + + case 0xf0: /* get/set scan code set */ + kbd_log("ATkbd: scan code set\n"); + kbd_send_to_host(dev, 0xfa); + dev->kbd_in = 1; + break; + + case 0xf2: /* read ID */ + /* Fixed as translation will be done in add_data_kbd(). */ + kbd_log("ATkbd: read keyboard id\n"); + /* TODO: After keyboard type selection is implemented, make this + return the correct keyboard ID for the selected type. */ + kbd_send_to_host(dev, 0xfa); + dev->kbd_phase = 1; + break; + + case 0xf3: /* set typematic rate/delay */ + kbd_log("ATkbd: set typematic rate/delay\n"); + kbd_send_to_host(dev, 0xfa); + dev->kbd_in = 1; + break; + + case 0xf4: /* enable keyboard */ + kbd_log("ATkbd: enable keyboard\n"); + kbd_send_to_host(dev, 0xfa); + keyboard_scan = 1; + break; + + case 0xf5: /* set defaults and disable keyboard */ + case 0xf6: /* set defaults */ + kbd_log("ATkbd: set defaults%s\n", (val == 0xf6) ? "" : " and disable keyboard"); + keyboard_scan = (val == 0xf6); + kbd_log("val = %02X, keyboard_scan = %i, dev->mem[0x20] = %02X\n", + val, keyboard_scan, dev->mem[0x20]); + kbd_send_to_host(dev, 0xfa); + + keyboard_set3_all_break = 0; + keyboard_set3_all_repeat = 0; + memset(keyboard_set3_flags, 0, 512); + keyboard_mode = (keyboard_mode & 0xfc) | 0x02; + set_scancode_map(dev); + break; + + case 0xf7: /* set all keys to repeat */ + kbd_log("ATkbd: set all keys to repeat\n"); + kbd_send_to_host(dev, 0xfa); + keyboard_set3_all_break = 1; + break; + + case 0xf8: /* set all keys to give make/break codes */ + kbd_log("ATkbd: set all keys to give make/break codes\n"); + kbd_send_to_host(dev, 0xfa); + keyboard_set3_all_break = 1; + break; + + case 0xf9: /* set all keys to give make codes only */ + kbd_log("ATkbd: set all keys to give make codes only\n"); + kbd_send_to_host(dev, 0xfa); + keyboard_set3_all_break = 0; + break; + + case 0xfa: /* set all keys to repeat and give make/break codes */ + kbd_log("ATkbd: set all keys to repeat and give make/break codes\n"); + kbd_send_to_host(dev, 0xfa); + keyboard_set3_all_repeat = 1; + keyboard_set3_all_break = 1; + break; + + case 0xfe: /* resend last scan code */ + kbd_log("ATkbd: reset last scan code\n"); + kbd_send_to_host(dev, kbd_last_scan_code); + break; + + case 0xff: /* reset */ + kbd_log("ATkbd: kbd reset\n"); + kbd_chip_reset(dev); + kbd_send_to_host(dev, 0xfa); + dev->kbd_phase = 1; + break; + + default: + kbd_log("ATkbd: bad keyboard command %02X\n", val); + kbd_send_to_host(dev, 0xfe); + } + + /* If command needs data, remember command. */ + if ((dev->kbd_in == 1) || (dev->kbd_phase > 0)) + dev->kbd_cmd = val; + } +} + + +static void +kbd_do_command(atkbd_t *dev) +{ + kbd_command(dev); + if (dev->kbd_written) + dev->kbd_poll_phase = KBD_CMD_PROCESS; + else if ((dev->kbd_phase == 0) && !dev->kbd_in) { + dev->kbd_in_cmd = 0; + if (dev->kbd_data != 0xf5) + keyboard_scan = 1; + dev->kbd_poll_phase = KBD_MAIN_LOOP; + } else { + keyboard_scan = 0; + dev->kbd_in_cmd = 1; + dev->kbd_poll_phase = KBD_CMD_PROCESS; + } +} + + +static void +kbd_nack(atkbd_t *dev) +{ + kbd_send_to_host(dev, 0xfe); + dev->kbd_poll_phase = KBD_MAIN_LOOP; +} + + +static void +kbd_main_loop(atkbd_t *dev) +{ + uint8_t scan = !dev->kbd_inhibit && keyboard_scan; + + if (dev->kbd_written) { + dev->kbd_written = 0; + kbd_cmd_process(dev); + } else if (scan && (key_queue_start != key_queue_end)) { + /* Scan here. */ + kbd_log("ATkbd: Get %02X from FIFO\n", key_queue[key_queue_start]); + kbd_send_to_host(dev, key_queue[key_queue_start]); + key_queue_start = (key_queue_start + 1) & 0xf; + } +} + + +static void +kbd_cmd_process(atkbd_t *dev) +{ + uint8_t written = dev->kbd_written; + + /* We want data, nothing has been written yet, return. */ + if (dev->kbd_in && !dev->kbd_written) + return; + + dev->kbd_written = 0; + + if (!written && !keyboard_scan && dev->kbd_in_cmd && (dev->kbd_phase > 0)) { + kbd_log("ATkbd: Keyboard not written, not scanning, in command, and phase > 0\n"); + kbd_do_command(dev); + } else if (dev->kbd_data == 0xfe) { + kbd_log("ATkbd: Send last byte %02X\n", kbd_last_scan_code); + kbd_send_to_host(dev, kbd_last_scan_code); + dev->kbd_poll_phase = KBD_MAIN_LOOP; + } else if (dev->kbd_data == 0xee) { + kbd_log("ATkbd: Echo EE\n"); + kbd_send_to_host(dev, 0xee); + dev->kbd_poll_phase = KBD_MAIN_LOOP; + } else if (dev->kbd_data >= 0xed) { + kbd_log("ATkbd: Command %02X\n", dev->kbd_data); + if (!keyboard_scan && dev->kbd_in_cmd && (dev->kbd_cmd == 0xed)) { + kbd_log("ATkbd: Not scanning, in command, old command is ED\n"); + keyboard_scan = 1; + dev->kbd_in_cmd = 0; + } + kbd_do_command(dev); + } else { + if (!keyboard_scan && dev->kbd_in_cmd) { + if ((dev->kbd_cmd == 0xf3) && (dev->kbd_data & 0x80)) { + kbd_log("ATkbd: Command F3 data %02X has bit 7 set\n", dev->kbd_data); + kbd_nack(dev); + } else { + kbd_log("ATkbd: Command %02X data %02X\n", dev->kbd_cmd, dev->kbd_data); + kbd_do_command(dev); + } + } else { + kbd_log("ATkbd: Scanning or not in command, NACK\n"); + kbd_nack(dev); + } + } +} + + +/* Keyboard processing */ +static void +kbd_process(atkbd_t *dev) +{ + /* The real 8048 keyboard firmware stops transmitting if host wants to transmit. */ + if (dev->kbc_written[1] && dev->kbd_written) + dev->kbc_written[1] = 0; + + /* The host has either acknowledged the transmitted byte or we have not transmitted anything (yet). */ + if (!dev->kbc_written[1]) switch (dev->kbd_poll_phase) { + case KBD_MAIN_LOOP: + kbd_main_loop(dev); + break; + case KBD_CMD_PROCESS: + kbd_cmd_process(dev); + break; + } +} + + +static void +kbc_send_to_ob(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) +{ + uint8_t ch = (channel > 0) ? channel : 1; + uint8_t do_irq = (dev->mem[0x20] & ch); + int translate = (channel == 1) && (keyboard_mode & 0x60); + + if ((channel == 2) && !(dev->flags & KBC_FLAG_PS2)) + return; + + stat_hi |= dev->inhibit; + + if (!dev->kbc_send_pending) { + dev->kbc_send_pending = 1; + dev->kbc_to_send = val; + dev->kbc_channel = channel; + dev->kbc_stat_hi = stat_hi; + return; + } + + if (translate) { + /* Allow for scan code translation. */ + if (val == 0xf0) { + kbd_log("ATkbd: translate is on, F0 prefix detected\n"); + sc_or = 0x80; + return; + } + + /* Skip break code if translated make code has bit 7 set. */ + if ((sc_or == 0x80) && (val & 0x80)) { + kbd_log("ATkbd: translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val); + sc_or = 0; + return; + } + } + + dev->last_irq = (ch == 2) ? 0x1000 : 0x0002; + if (do_irq) { + kbd_log("[%04X:%08X] ATKbc: IRQ %i\n", CS, cpu_state.pc, (ch == 2) ? 12 : 1); + picint(dev->last_irq); + } + kbd_log("ATkbc: %02X coming from channel %i (%i)\n", val, channel, do_irq); + dev->ob = translate ? (nont_to_t[val] | sc_or) : val; + + dev->status = (dev->status & 0x0f) | (stat_hi | (dev->mem[0x20] & STAT_SYSFLAG) | STAT_OFULL); + if (ch == 2) + dev->status |= STAT_MFULL; + + if (translate && (sc_or == 0x80)) + sc_or = 0; +} + + +static void +write_output(atkbd_t *dev, uint8_t val) +{ + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + kbd_log("ATkbc: write output port: %02X (old: %02X)\n", val, dev->p2); + + if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) + val |= ((dev->mem[0x20] << 4) & 0x30); + + dev->kbd_inhibit = (val & 0x40); + dev->mouse_inhibit = (val & 0x08); + + if ((dev->p2 ^ val) & 0x20) { /*IRQ 12*/ + if (val & 0x20) { + kbd_log("ATkbc: write_output(): IRQ 12\n"); + picint(1 << 12); + } else + picintc(1 << 12); + } + if ((dev->p2 ^ val) & 0x10) { /*IRQ 1*/ + if (val & 0x10) { + kbd_log("ATkbc: write_output(): IRQ 1\n"); + picint(1 << 1); + } else + picintc(1 << 1); + } + if ((dev->p2 ^ val) & 0x02) { /*A20 enable change*/ + mem_a20_key = val & 0x02; + mem_a20_recalc(); + flushmmucache(); + } + if ((dev->p2 ^ val) & 0x01) { /*Reset*/ + if (! (val & 0x01)) { + /* Pin 0 selected. */ + softresetx86(); /*Pulse reset!*/ + cpu_set_edx(); + smbase = is_am486dxl ? 0x00060000 : 0x00030000; + } + } + /* Mask off the A20 stuff because we use mem_a20_key directly for that. */ + dev->p2 = val; +} + + +static void +write_cmd(atkbd_t *dev, uint8_t val) +{ + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + kbd_log("ATkbc: write command byte: %02X (old: %02X)\n", val, dev->mem[0x20]); + + /* PS/2 type 2 keyboard controllers always force the XLAT bit to 0. */ + if ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2) + val &= ~CCB_TRANSLATE; + + dev->mem[0x20] = val; + + /* Scan code translate ON/OFF. */ + keyboard_mode &= 0x93; + keyboard_mode |= (val & MODE_MASK); + + kbd_log("ATkbc: keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled"); + + /* ISA AT keyboard controllers use bit 5 for keyboard mode (1 = PC/XT, 2 = AT); + PS/2 (and EISA/PCI) keyboard controllers use it as the PS/2 mouse enable switch. + The AMIKEY firmware apparently uses this bit for something else. */ + if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) { + keyboard_mode &= ~CCB_PCMODE; + /* Update the output port to mirror the KBD DIS and AUX DIS bits, if active. */ + write_output(dev, dev->p2); + + kbd_log("ATkbc: mouse interrupt is now %s\n", (val & 0x02) ? "enabled" : "disabled"); + } + + kbd_log("Command byte now: %02X (%02X)\n", dev->mem[0x20], val); + + dev->status = (dev->status & ~STAT_SYSFLAG) | (val & STAT_SYSFLAG); +} + + +static void +pulse_output(atkbd_t *dev, uint8_t mask) +{ + if (mask != 0x0f) { + dev->old_p2 = dev->p2 & ~(0xf0 | mask); + kbd_log("pulse_output(): Output port now: %02X\n", dev->p2 & (0xf0 | mask | (dev->mem[0x20] & 0x30))); + write_output(dev, dev->p2 & (0xf0 | mask | (dev->mem[0x20] & 0x30))); + timer_set_delay_u64(&dev->pulse_cb, 6ULL * TIMER_USEC); + } +} + + +static void +set_enable_kbd(atkbd_t *dev, uint8_t enable) +{ + dev->mem[0x20] &= 0xef; + dev->mem[0x20] |= (enable ? 0x00 : 0x10); +} + + +static void +set_enable_mouse(atkbd_t *dev, uint8_t enable) +{ + dev->mem[0x20] &= 0xdf; + dev->mem[0x20] |= (enable ? 0x00 : 0x20); +} + + +static void +kbc_transmit(atkbd_t *dev, uint8_t val) +{ + kbc_send_to_ob(dev, val, 0, 0x00); +} + + +static void +kbc_command(atkbd_t *dev) +{ + uint8_t mask, val = dev->ib; + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + int bad = 1; + + if ((dev->kbc_phase > 0) && (dev->kbc_cmd == 0xac)) { + if (dev-> kbc_phase < 16) + kbc_transmit(dev, dev->mem[dev->kbc_phase]); + else if (dev-> kbc_phase == 16) + kbc_transmit(dev, (dev->p1 & 0xf0) | 0x80); + else if (dev-> kbc_phase == 17) + kbc_transmit(dev, dev->p2); + else if (dev-> kbc_phase == 18) + kbc_transmit(dev, dev->status); + + dev->kbc_phase++; + if (dev->kbc_phase == 19) { + dev->kbc_phase = 0; + dev->kbc_cmd = 0x00; + } + return; + } else if ((dev->kbc_phase > 0) && (dev->kbc_cmd == 0xa0) && (kbc_ven >= KBC_VEN_AMI)) { + val = ami_copr[dev->kbc_phase]; + kbc_transmit(dev, val); + if (val == 0x00) { + dev->kbc_phase = 0; + dev->kbc_cmd = 0x00; + } else + dev->kbc_phase++; + return; + } else if ((dev->kbc_in > 0) && (dev->kbc_cmd == 0xa5) && (dev->flags & KBC_FLAG_PS2)) { + /* load security */ + kbd_log("ATkbc: load security\n"); + dev->mem[0x50 + dev->kbc_in - 0x01] = val; + if ((dev->kbc_in == 0x80) && (val != 0x00)) { + /* Security string too long, set it to 0x00. */ + dev->mem[0x50] = 0x00; + dev->kbc_in = 0; + dev->kbc_cmd = 0; + } else if (val == 0x00) { + /* Security string finished. */ + dev->kbc_in = 0; + dev->kbc_cmd = 0; + } else /* Increase pointer and request another byte. */ + dev->kbc_in++; + return; + } + + /* If the written port is 64, go straight to the beginning of the command. */ + if (!(dev->status & STAT_CD) && dev->kbc_in) { + /* Write data to controller. */ + dev->kbc_in = 0; + dev->kbc_phase = 0; + + switch (dev->kbc_cmd) { + case 0x60 ... 0x7f: + if (dev->kbc_cmd == 0x60) + write_cmd(dev, val); + else + dev->mem[(dev->kbc_cmd & 0x1f) + 0x20] = val; + break; + + case 0xc7: /* or input port with system data */ + dev->p1 |= val; + break; + + case 0xcb: /* set keyboard mode */ + kbd_log("New AMIKey mode: %02X\n", val); + dev->ami_mode = val; + dev->flags &= ~KBC_FLAG_PS2; + if (val & 1) + dev->flags |= KBC_FLAG_PS2; + break; + + case 0xd1: /* write output port */ + kbd_log("ATkbc: write output port\n"); + if (dev->p2_locked) { + /*If keyboard controller lines P22-P23 are blocked, + we force them to remain unchanged.*/ + val &= ~0x0c; + val |= (dev->p2 & 0x0c); + } + write_output(dev, val); + break; + + case 0xd2: /* write to keyboard output buffer */ + kbd_log("ATkbc: write to keyboard output buffer\n"); + // kbc_send_to_ob(dev, val, 1, 0x00); + /* Should be channel 1, but we send to 0 to avoid translation, + since bytes output using this command do *NOT* get translated. */ + kbc_send_to_ob(dev, val, 0, 0x00); + break; + + case 0xd3: /* write to mouse output buffer */ + kbd_log("ATkbc: write to mouse output buffer\n"); + if (dev->flags & KBC_FLAG_PS2) + kbc_send_to_ob(dev, val, 2, 0x00); + break; + + case 0xd4: /* write to mouse */ + kbd_log("ATkbc: write to mouse (%02X)\n", val); + + if (dev->flags & KBC_FLAG_PS2) { + set_enable_mouse(dev, 1); + dev->mem[0x20] &= ~0x20; + if (mouse_write && !dev->kbc_written[2]) { + kbd_log("ATkbc: Sending %02X to mouse...\n", dev->ib); + dev->mouse_data = val; + dev->mouse_written = 1; + dev->kbc_wait_for_response = 2; + } else + kbc_send_to_ob(dev, 0xfe, 2, 0x40); + } + break; + + default: + /* + * Run the vendor-specific handler + * if we have one. Otherwise, or if + * it returns an error, log a bad + * controller command. + */ + if (dev->write60_ven) + bad = dev->write60_ven(dev, val); + +#ifdef ENABLE_KEYBOARD_AT_LOG + if (bad) + kbd_log("ATkbc: bad controller command %02x data %02x\n", dev->kbc_cmd, val); +#endif + } + } else { + /* Controller command. */ + kbd_log("ATkbc: Controller command: %02X\n", val); + dev->kbc_in = 0; + dev->kbc_phase = 0; + + switch (val) { + /* Read data from KBC memory. */ + case 0x20 ... 0x3f: + kbc_transmit(dev, dev->mem[(val & 0x1f) + 0x20]); + break; + + /* Write data to KBC memory. */ + case 0x60 ... 0x7f: + dev->kbc_in = 1; + break; + + case 0xaa: /* self-test */ + kbd_log("ATkbc: self-test\n"); + write_output(dev, (dev->flags & KBC_FLAG_PS2) ? 0x4b : 0xcf); + + /* Always reinitialize all queues - the real hardware pulls keyboard and mouse + clocks high, which stops keyboard scanning. */ + kbd_log("ATkbc: self-test reinitialization\n"); + dev->kbd_in_cmd = dev->mouse_in_cmd = 0; + dev->status &= ~STAT_OFULL; + dev->last_irq = 0; + dev->kbc_phase = 0; + + /* Phoenix MultiKey should have 0x60 | STAT_SYSFLAG. */ + if (dev->flags & KBC_FLAG_PS2) + write_cmd(dev, 0x30 | STAT_SYSFLAG); + else + write_cmd(dev, 0x10 | STAT_SYSFLAG); + kbc_transmit(dev, 0x55); + break; + + case 0xab: /* interface test */ + kbd_log("ATkbc: interface test\n"); + /* No error. */ + kbc_transmit(dev, 0x00); + break; + + case 0xac: /* diagnostic dump */ + kbd_log("ATkbc: diagnostic dump\n"); + kbc_transmit(dev, dev->mem[0x20]); + dev->kbc_phase = 1; + break; + + case 0xad: /* disable keyboard */ + kbd_log("ATkbc: disable keyboard\n"); + set_enable_kbd(dev, 0); + break; + + case 0xae: /* enable keyboard */ + kbd_log("ATkbc: enable keyboard\n"); + set_enable_kbd(dev, 1); + break; + + case 0xc7: /* or input port with system data */ + kbd_log("ATkbc: Phoenix - or input port with system data\n"); + dev->kbc_in = 1; + break; + + case 0xca: /* read keyboard mode */ + kbd_log("ATkbc: AMI - read keyboard mode\n"); + kbc_transmit(dev, dev->ami_mode); + break; + + case 0xcb: /* set keyboard mode */ + kbd_log("ATkbc: AMI - set keyboard mode\n"); + dev->kbc_in = 1; + break; + + case 0xd0: /* read output port */ + kbd_log("ATkbc: read output port\n"); + mask = 0xff; + if (dev->mem[0x20] & 0x10) + mask &= 0xbf; + if ((dev->flags & KBC_FLAG_PS2) && (dev->mem[0x20] & 0x20)) + mask &= 0xf7; + kbc_transmit(dev, dev->p2 & mask); + break; + + case 0xd1: /* write output port */ + kbd_log("ATkbc: write output port\n"); + dev->kbc_in = 1; + break; + + case 0xd2: /* write keyboard output buffer */ + kbd_log("ATkbc: write keyboard output buffer\n"); + if (dev->flags & KBC_FLAG_PS2) + dev->kbc_in = 1; + else + kbc_transmit(dev, 0x00); /* NCR */ + break; + + case 0xdd: /* disable A20 address line */ + case 0xdf: /* enable A20 address line */ + kbd_log("ATkbc: %sable A20\n", (val == 0xdd) ? "dis": "en"); + write_output(dev, (dev->p2 & 0xfd) | (val & 0x02)); + break; + + case 0xe0: /* read test inputs */ + kbd_log("ATkbc: read test inputs\n"); + kbc_transmit(dev, 0x00); + break; + + case 0xe1: case 0xea: + kbd_log("ATkbc: setting P23-P21 to %01X\n", val & 0x0e); + write_output(dev, (dev->p2 & 0xf1) | (val & 0x0e)); + break; + + default: + /* + * Unrecognized controller command. + * + * If we have a vendor-specific handler, run + * that. Otherwise, or if that handler fails, + * log a bad command. + */ + if (dev->write64_ven) + bad = dev->write64_ven(dev, val); + + kbd_log(bad ? "ATkbc: bad controller command %02X\n" : "", val); + } + + /* If the command needs data, remember the command. */ + if (dev->kbc_in || (dev->kbc_phase > 0)) + dev->kbc_cmd = val; + } +} + + +static void +kbc_dev_data_to_ob(atkbd_t *dev, uint8_t channel) +{ + dev->kbc_written[channel] = 0; + kbd_log("ATkbd: Forwarding %02X from channel %i...\n", dev->kbc_data[channel], channel); + kbc_send_to_ob(dev, dev->kbc_data[channel], channel, 0x00); +} + + +static void +kbc_main_loop_scan(atkbd_t *dev) +{ + uint8_t port_dis = dev->mem[0x20] & 0x30; + uint8_t ps2 = (dev->flags & KBC_FLAG_PS2); + + if (!ps2) + port_dis |= 0x20; + + if (!(dev->status & STAT_OFULL)) { + if (port_dis & 0x20) { + if (!(port_dis & 0x10)) { + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Main loop\n" + "ATkbc: Scan: AUX DIS, KBD EN\n"); + // kbd_log("ATkbc: Scan: AUX DIS, KBD EN\n"); + /* Enable communication with keyboard. */ + dev->p2 &= 0xbf; + dev->kbd_inhibit = 0; + kbc_wait(dev, 1); + } +#ifdef ENABLE_KEYBOARD_AT_LOG + else { + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Main loop\n" + "ATkbc: Scan: AUX DIS, KBD DIS\n"); + // kbd_log("ATkbc: Scan: AUX DIS, KBD DIS\n"); + } +#endif + } else { + /* Enable communication with mouse. */ + dev->p2 &= 0xf7; + dev->mouse_inhibit = 0; + if (dev->mem[0x20] & 0x10) { + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Main loop\n" + "ATkbc: Scan: AUX EN , KBD DIS\n"); + // kbd_log("ATkbc: Scan: AUX EN , KBD DIS\n"); + kbc_wait(dev, 2); + } else { + /* Enable communication with keyboard. */ + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Main loop\n" + "ATkbc: Scan: AUX EN , KBD EN\n"); + // kbd_log("ATkbc: Scan: AUX EN , KBD EN\n"); + dev->p2 &= 0xbf; + dev->kbd_inhibit = 0; + kbc_wait(dev, 3); + } + } + } +#ifdef ENABLE_KEYBOARD_AT_LOG + else { + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Main loop\n" + "ATkbc: Scan: IBF not full and OBF full, do nothing\n"); + // kbd_log("ATkbc: Scan: IBF not full and OBF full, do nothing\n"); + } +#endif +} + + +static void +kbc_process_ib(atkbd_t *dev) +{ + dev->status &= ~STAT_IFULL; + + if (dev->status & STAT_CD) { + dev->kbc_in_cmd = 1; + kbc_command(dev); + + if ((dev->kbc_phase == 0) && !dev->kbc_in) + dev->kbc_in_cmd = 0; + else + return; + } else { + dev->mem[0x20] &= ~0x10; + dev->kbd_data = dev->ib; + dev->kbd_written = 1; + dev->kbc_wait_for_response = 1; + } + + dev->kbc_poll_phase = KBC_MAIN_LOOP; + if (!dev->kbc_wait_for_response) + kbc_main_loop_scan(dev); +} + + +static void +kbc_wait(atkbd_t *dev, uint8_t flags) +{ + if ((flags & 1) && dev->kbc_written[1]) { + /* Disable communication with mouse. */ + dev->p2 |= 0x08; + dev->mouse_inhibit = 1; + /* Send keyboard byte to host. */ + kbc_dev_data_to_ob(dev, CHANNEL_KBD); + dev->kbc_poll_phase = KBC_MAIN_LOOP; + } else if ((flags & 2) && dev->kbc_written[2]) { + /* Disable communication with keyboard. */ + dev->p2 |= 0x40; + dev->kbd_inhibit = 1; + /* Send mouse byte to host. */ + kbc_dev_data_to_ob(dev, CHANNEL_MOUSE); + dev->kbc_poll_phase = KBC_MAIN_LOOP; + } else if (dev->status & STAT_IFULL) { + /* Disable communication with keyboard and mouse. */ + dev->p2 |= 0x48; + dev->kbd_inhibit = dev->mouse_inhibit = 1; + kbc_process_ib(dev); + } else + dev->kbc_poll_phase = KBC_WAIT | flags; +} + + +/* Controller processing */ +static void +kbc_process(atkbd_t *dev) +{ + // kbd_log("ATkbc: kbc_process()\n"); + + /* If we're waiting for the response from the keyboard or mouse, do nothing + until the device has repsonded back. */ + if (dev->kbc_wait_for_response > 0) { + if (dev->kbc_written[dev->kbc_wait_for_response]) + dev->kbc_wait_for_response = 0; + else + return; + } + + if (dev->kbc_send_pending) { + kbd_log("ATkbc: Sending delayed %02X on channel %i with high status %02X\n", + dev->kbc_to_send, dev->kbc_channel, dev->kbc_stat_hi); + kbc_send_to_ob(dev, dev->kbc_to_send, dev->kbc_channel, dev->kbc_stat_hi); + dev->kbc_send_pending = 0; + } + + if (dev->kbc_poll_phase == KBC_RESET) { + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Reset loop()\n"); + + if (dev->status & STAT_IFULL) { + dev->status &= ~STAT_IFULL; + + if ((dev->status & STAT_CD) && (dev->ib == 0xaa)) { + dev->kbc_in_cmd = 1; + kbc_command(dev); + + if ((dev->kbc_phase == 0) && !dev->kbc_in) + dev->kbc_in_cmd = 0; + + dev->kbc_poll_phase = KBC_MAIN_LOOP; + } + } + + return; + } + + if (dev->kbc_in_cmd || (dev->kbc_phase > 0) || dev->kbc_in) { + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: In a command\n"); + if (!dev->kbc_in && (dev->status & STAT_OFULL)) { + kbd_log("ATkbc: !dev->kbc_in && (dev->status & STAT_OFULL)\n"); + return; /* We do not want input and we're waiting for the host to read the data + we transmitted, but it has not done that yet, do nothing. */ + } else if (dev->kbc_in && !(dev->status & STAT_IFULL)) { + kbd_log("ATkbc: dev->kbc_in && !(dev->status & STAT_IFULL)\n"); + return; /* We want input and the host has not provided us with any yet, do nothing. */ + } +#ifdef ENABLE_KEYBOARD_AT_LOG + else + kbd_log("ATkbc: Normal condition\n"); +#endif + + if (dev->status & STAT_IFULL) { + dev->status &= ~STAT_IFULL; + + if (dev->status & STAT_CD) { + kbd_log("ATkbc: Resetting command\n"); + dev->kbc_phase = 0; + dev->kbc_in = 0; + } + } + + /* Process command. */ + kbc_command(dev); + + if ((dev->kbc_phase == 0) && !dev->kbc_in) + dev->kbc_in_cmd = 0; + else + return; + + if (!(dev->status & STAT_OFULL)) + kbc_main_loop_scan(dev); + /* Make absolutely sure to do nothing if OBF is full and IBF is empty. */ + } else if (!(dev->status & STAT_OFULL) || (dev->status & STAT_IFULL)) switch (dev->kbc_poll_phase) { + case KBC_MAIN_LOOP: + // kbd_log("ATkbc: Main loop\n"); + if (dev->status & STAT_IFULL) { + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Main loop\n" + "ATkbc: IBF full, process\n"); + kbc_process_ib(dev); + } else + kbc_main_loop_scan(dev); + break; + case KBC_WAIT_FOR_KBD: + case KBC_WAIT_FOR_MOUSE: + case KBC_WAIT_FOR_BOTH: + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Scan: Phase %i\n", dev->kbc_poll_phase); + kbc_wait(dev, dev->kbc_poll_phase & 3); + break; + default: + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Scan: Invalid phase %i\n", dev->kbc_poll_phase); + break; + } } @@ -741,105 +1792,29 @@ static void kbd_poll(void *priv) { atkbd_t *dev = (atkbd_t *)priv; -#ifdef ENABLE_KEYBOARD_AT_LOG - const uint8_t channels[4] = { 1, 2, 0, 0 }; -#endif timer_advance_u64(&dev->send_delay_timer, (100ULL * TIMER_USEC)); - if (dev->out_new != -1 && !dev->last_irq) { - dev->wantirq = 0; - if (dev->out_new & 0x100) { - if (dev->mem[0] & 0x02) - picint(0x1000); - kbd_log("ATkbc: %02X coming from channel 2\n"); - dev->out = dev->out_new & 0xff; - dev->out_new = -1; - dev->status = (dev->status & ~STAT_IFULL) | (STAT_OFULL | STAT_MFULL); - dev->last_irq = 0x1000; - } else { - if (dev->mem[0] & 0x01) - picint(2); - kbd_log("ATkbc: %02X coming from channel %i\n", dev->out_new & 0xff, channels[(dev->out_new >> 8) & 0x03]); - dev->out = dev->out_new & 0xff; - dev->out_new = -1; - dev->status = (dev->status & ~(STAT_IFULL | STAT_MFULL)) | STAT_OFULL; - dev->last_irq = 2; - } - } + /* We process all three devices at the same time, in an arbitrary order. */ - if (dev->out_new == -1 && !(dev->status & STAT_OFULL) && key_ctrl_queue_start != key_ctrl_queue_end) { - kbd_log("ATkbc: %02X on channel 0\n", key_ctrl_queue[key_ctrl_queue_start]); - dev->out_new = key_ctrl_queue[key_ctrl_queue_start] | 0x200; - key_ctrl_queue_start = (key_ctrl_queue_start + 1) & 0xf; - } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && dev->out_delayed != -1) { - kbd_log("ATkbc: %02X delayed on channel %i\n", dev->out_delayed & 0xff, channels[(dev->out_delayed >> 8) & 0x03]); - dev->out_new = dev->out_delayed; - dev->out_delayed = -1; - } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && mouse_queue_start != mouse_queue_end) { - kbd_log("ATkbc: %02X on channel 2\n", mouse_queue[mouse_queue_start]); - dev->out_new = mouse_queue[mouse_queue_start] | 0x100; - mouse_queue_start = (mouse_queue_start + 1) & 0xf; - } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && !(dev->mem[0] & 0x10) && key_queue_start != key_queue_end) { - kbd_log("ATkbc: %02X on channel 1\n", key_queue[key_queue_start]); - dev->out_new = key_queue[key_queue_start]; - key_queue_start = (key_queue_start + 1) & 0xf; - } + /* Keyboard processing */ + kbd_process(dev); - if (dev->reset_delay) { - dev->reset_delay--; - if (!dev->reset_delay) { - kbd_log("ATkbc: Sending AA on keyboard reset...\n"); - add_data_kbd_direct(dev, 0xaa); - } - } -} + /* TODO: Mouse processing */ + // mouse_process(dev); - -static void -add_data(atkbd_t *dev, uint8_t val) -{ - kbd_log("ATkbc: add to queue\n"); - - kbd_log("ATkbc: key_ctrl_queue[%02X] = %02X;\n", key_ctrl_queue_end, val); - kbc_queue_add(dev, val, 0, 0x00); - - if (!(dev->out_new & 0x300)) { - dev->out_delayed = dev->out_new; - dev->out_new = -1; - } + /* Controller processing */ + kbc_process(dev); } static void add_data_vals(atkbd_t *dev, uint8_t *val, uint8_t len) { - int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); - int translate = (keyboard_mode & 0x40); int i; - uint8_t or = 0; - uint8_t send; - if (dev->reset_delay) - return; - - translate = translate || (keyboard_mode & 0x40) || xt_mode; - translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); - - for (i = 0; i < len; i++) { - if (translate) { - if (val[i] == 0xf0) { - or = 0x80; - continue; - } - send = nont_to_t[val[i]] | or; - if (or == 0x80) - or = 0; - } else - send = val[i]; - - add_data_kbd_queue(dev, 0, send); - } + for (i = 0; i < len; i++) + add_data_kbd_queue(dev, 0, val[i]); } @@ -847,56 +1822,21 @@ static void add_data_kbd(uint16_t val) { atkbd_t *dev = SavedKbd; - int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); - int translate = (keyboard_mode & 0x40); uint8_t fake_shift[4]; uint8_t num_lock = 0, shift_states = 0; uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - if (dev->reset_delay) + if (dev->kbd_in || (dev->kbd_phase > 0)) return; - translate = translate || (keyboard_mode & 0x40) || xt_mode; - translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); - keyboard_get_states(NULL, &num_lock, NULL); shift_states = keyboard_get_shift() & STATE_SHIFT_MASK; - /* Allow for scan code translation. */ - if (translate && (val == 0xf0)) { - kbd_log("ATkbd: translate is on, F0 prefix detected\n"); - sc_or = 0x80; - return; - } - - /* Skip break code if translated make code has bit 7 set. */ - if (translate && (sc_or == 0x80) && (val & 0x80)) { - kbd_log("ATkbd: translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val); - sc_or = 0; - return; - } - /* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */ - if ((dev != NULL) && (kbc_ven == KBC_VEN_TOSHIBA) && - (keyboard_recv(0xb8) || keyboard_recv(0x9d))) switch (val) { - case 0x4f: t3100e_notify_set(0x01); break; /* End */ - case 0x50: t3100e_notify_set(0x02); break; /* Down */ - case 0x51: t3100e_notify_set(0x03); break; /* PgDn */ - case 0x52: t3100e_notify_set(0x04); break; /* Ins */ - case 0x53: t3100e_notify_set(0x05); break; /* Del */ - case 0x54: t3100e_notify_set(0x06); break; /* SysRQ */ - case 0x45: t3100e_notify_set(0x07); break; /* NumLock */ - case 0x46: t3100e_notify_set(0x08); break; /* ScrLock */ - case 0x47: t3100e_notify_set(0x09); break; /* Home */ - case 0x48: t3100e_notify_set(0x0a); break; /* Up */ - case 0x49: t3100e_notify_set(0x0b); break; /* PgUp */ - case 0x4A: t3100e_notify_set(0x0c); break; /* Keypad -*/ - case 0x4B: t3100e_notify_set(0x0d); break; /* Left */ - case 0x4C: t3100e_notify_set(0x0e); break; /* KP 5 */ - case 0x4D: t3100e_notify_set(0x0f); break; /* Right */ - } + if ((dev != NULL) && (kbc_ven == KBC_VEN_TOSHIBA) && (keyboard_recv(0xb8) || keyboard_recv(0x9d)) && + (val >= 0x4f) && (val <= 0x54) && (val != 0x4e)) + t3100e_notify_set((val + 2) & 0x0f); - kbd_log("ATkbd: translate is %s, ", translate ? "on" : "off"); switch(val) { case FAKE_LSHIFT_ON: kbd_log("fake left shift on, scan code: "); @@ -1029,18 +1969,7 @@ add_data_kbd(uint16_t val) break; default: -#ifdef ENABLE_KEYBOARD_AT_LOG - kbd_log("scan code: "); - if (translate) { - kbd_log("%02X (original: ", (nont_to_t[val] | sc_or)); - if (sc_or == 0x80) - kbd_log("F0 "); - kbd_log("%02X)\n", val); - } else - kbd_log("%02X\n", val); -#endif - - add_data_kbd_queue(dev, 0, translate ? (nont_to_t[val] | sc_or) : val); + add_data_kbd_queue(dev, 0, val); break; } @@ -1049,121 +1978,13 @@ add_data_kbd(uint16_t val) } -static void -write_output(atkbd_t *dev, uint8_t val) -{ - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - kbd_log("ATkbc: write output port: %02X (old: %02X)\n", val, dev->output_port); - - if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) - val |= ((dev->mem[0] << 4) & 0x30); - - if ((dev->output_port ^ val) & 0x20) { /*IRQ 12*/ - if (val & 0x20) - picint(1 << 12); - else - picintc(1 << 12); - } - if ((dev->output_port ^ val) & 0x10) { /*IRQ 1*/ - if (val & 0x10) - picint(1 << 1); - else - picintc(1 << 1); - } - if ((dev->output_port ^ val) & 0x02) { /*A20 enable change*/ - mem_a20_key = val & 0x02; - mem_a20_recalc(); - flushmmucache(); - } - if ((dev->output_port ^ val) & 0x01) { /*Reset*/ - if (! (val & 0x01)) { - /* Pin 0 selected. */ - softresetx86(); /*Pulse reset!*/ - cpu_set_edx(); - smbase = is_am486dxl ? 0x00060000 : 0x00030000; - } - } - /* Mask off the A20 stuff because we use mem_a20_key directly for that. */ - dev->output_port = val; -} - - -static void -write_cmd(atkbd_t *dev, uint8_t val) -{ - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - kbd_log("ATkbc: write command byte: %02X (old: %02X)\n", val, dev->mem[0]); - - if ((val & 1) && (dev->status & STAT_OFULL)) - dev->wantirq = 1; - if (!(val & 1) && dev->wantirq) - dev->wantirq = 0; - - /* PS/2 type 2 keyboard controllers always force the XLAT bit to 0. */ - if ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2) { - val &= ~CCB_TRANSLATE; - dev->mem[0] &= ~CCB_TRANSLATE; - } - - /* Scan code translate ON/OFF. */ - keyboard_mode &= 0x93; - keyboard_mode |= (val & MODE_MASK); - - kbd_log("ATkbc: keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled"); - - /* ISA AT keyboard controllers use bit 5 for keyboard mode (1 = PC/XT, 2 = AT); - PS/2 (and EISA/PCI) keyboard controllers use it as the PS/2 mouse enable switch. - The AMIKEY firmware apparently uses this bit for something else. */ - if ((kbc_ven == KBC_VEN_AMI) || - ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) { - keyboard_mode &= ~CCB_PCMODE; - /* Update the output port to mirror the KBD DIS and AUX DIS bits, if active. */ - write_output(dev, dev->output_port); - - kbd_log("ATkbc: mouse interrupt is now %s\n", (val & 0x02) ? "enabled" : "disabled"); - } - - kbd_log("Command byte now: %02X (%02X)\n", dev->mem[0], val); - - dev->status = (dev->status & ~STAT_SYSFLAG) | (val & STAT_SYSFLAG); -} - - -static void -pulse_output(atkbd_t *dev, uint8_t mask) -{ - if (mask != 0x0f) { - dev->old_output_port = dev->output_port & ~(0xf0 | mask); - kbd_log("pulse_output(): Output port now: %02X\n", dev->output_port & (0xf0 | mask)); - write_output(dev, dev->output_port & (0xf0 | mask)); - timer_set_delay_u64(&dev->pulse_cb, 6ULL * TIMER_USEC); - } -} - - static void pulse_poll(void *priv) { atkbd_t *dev = (atkbd_t *)priv; - kbd_log("pulse_poll(): Output port now: %02X\n", dev->output_port | dev->old_output_port); - write_output(dev, dev->output_port | dev->old_output_port); -} - - -static void -set_enable_kbd(atkbd_t *dev, uint8_t enable) -{ - dev->mem[0] &= 0xef; - dev->mem[0] |= (enable ? 0x00 : 0x10); -} - - -static void -set_enable_mouse(atkbd_t *dev, uint8_t enable) -{ - dev->mem[0] &= 0xdf; - dev->mem[0] |= (enable ? 0x00 : 0x20); + kbd_log("pulse_poll(): Output port now: %02X\n", dev->p2 | dev->old_p2); + write_output(dev, dev->p2 | dev->old_p2); } @@ -1172,49 +1993,70 @@ write64_generic(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; uint8_t current_drive, fixed_bits; - uint8_t kbc_ven = 0x0; - kbc_ven = dev->flags & KBC_VEN_MASK; - + uint8_t kbc_ven = 0x0; + kbc_ven = dev->flags & KBC_VEN_MASK; switch (val) { case 0xa4: /* check if password installed */ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + if (dev->flags & KBC_FLAG_PS2) { kbd_log("ATkbc: check if password installed\n"); - add_data(dev, 0xf1); + kbc_transmit(dev, (dev->mem[0x50] == 0x00) ? 0xf1 : 0xfa); + return 0; + } + break; + + case 0xa5: /* load security */ + if (dev->flags & KBC_FLAG_PS2) { + kbd_log("ATkbc: load security\n"); + dev->kbc_in = 1; return 0; } break; case 0xa7: /* disable mouse port */ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + if (dev->flags & KBC_FLAG_PS2) { kbd_log("ATkbc: disable mouse port\n"); - set_enable_mouse(dev, 0); + // kbc_transmit(dev, 0); return 0; } break; case 0xa8: /*Enable mouse port*/ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + if (dev->flags & KBC_FLAG_PS2) { kbd_log("ATkbc: enable mouse port\n"); - set_enable_mouse(dev, 1); + // kbc_transmit(dev, 1); return 0; } break; case 0xa9: /*Test mouse port*/ kbd_log("ATkbc: test mouse port\n"); - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - add_data(dev, 0x00); /* no error, this is testing the channel 2 interface */ + if (dev->flags & KBC_FLAG_PS2) { + /* No error, this is testing the channel 2 interface. */ + kbc_transmit(dev, 0x00); return 0; } break; case 0xaf: /* read keyboard version */ kbd_log("ATkbc: read keyboard version\n"); - add_data(dev, 0x00); + kbc_transmit(dev, 0x00); return 0; case 0xc0: /* read input port */ + /* IBM PS/1: + Bit 2 and 4 ignored (we return always 0), + Bit 6 must 1 for 5.25" floppy drive, 0 for 3.5". + Intel AMI: + Bit 2 ignored (we return always 1), + Bit 4 must be 1, + Bit 6 must be 1 or else error in SMM. + Acer: + Bit 2 must be 0 (and Acer V10 disables CMOS setup if it's 1), + Bit 4 must be 0, + Bit 6 ignored. + P6RP4: + Bit 2 must be 1 or CMOS setup is disabled. */ kbd_log("ATkbc: read input port\n"); fixed_bits = 4; /* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */ @@ -1222,11 +2064,8 @@ write64_generic(void *priv, uint8_t val) fixed_bits |= 0x40; if (kbc_ven == KBC_VEN_IBM_PS1) { current_drive = fdc_get_current_drive(); - add_to_kbc_queue_front(dev, dev->input_port | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00), - 0, 0x00); - dev->input_port = ((dev->input_port + 1) & 3) | - (dev->input_port & 0xfc) | - (fdd_is_525(current_drive) ? 0x40 : 0x00); + kbc_transmit(dev, dev->p1 | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00)); + dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc) | (fdd_is_525(current_drive) ? 0x40 : 0x00); } else if (kbc_ven == KBC_VEN_NCR) { /* switch settings * bit 7: keyboard disable @@ -1238,39 +2077,34 @@ write64_generic(void *priv, uint8_t val) * bit 1: high/auto speed * bit 0: dma mode */ - add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf, - 0, 0x00); - dev->input_port = ((dev->input_port + 1) & 3) | - (dev->input_port & 0xfc); + kbc_transmit(dev, (dev->p1 | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf); + dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc); } else { - if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) && - ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI)) - add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits) & - (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0xeb : 0xef), 0, 0x00); + pclog("[%04X:%08X] Reading %02X from input port\n", CS, cpu_state.pc, ((dev->p1 | fixed_bits) & 0xf0) | 0x0c); + if ((dev->flags & KBC_FLAG_PS2) && ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI)) + // kbc_transmit(dev, ((dev->p1 | fixed_bits) & 0xf0) | 0x0c); + kbc_transmit(dev, ((dev->p1 | fixed_bits) & 0xf0) | 0x08); + // kbc_transmit(dev, (dev->p1 | fixed_bits) & (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0xeb : 0xef)); else - add_to_kbc_queue_front(dev, dev->input_port | fixed_bits, 0, 0x00); - dev->input_port = ((dev->input_port + 1) & 3) | - (dev->input_port & 0xfc); + kbc_transmit(dev, dev->p1 | fixed_bits); + dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc); } return 0; case 0xd3: /* write mouse output buffer */ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + if (dev->flags & KBC_FLAG_PS2) { kbd_log("ATkbc: write mouse output buffer\n"); - dev->want60 = 1; + dev->kbc_in = 1; return 0; } break; case 0xd4: /* write to mouse */ kbd_log("ATkbc: write to mouse\n"); - dev->want60 = 1; + dev->kbc_in = 1; return 0; - case 0xf0: case 0xf1: case 0xf2: case 0xf3: - case 0xf4: case 0xf5: case 0xf6: case 0xf7: - case 0xf8: case 0xf9: case 0xfa: case 0xfb: - case 0xfc: case 0xfd: case 0xfe: case 0xff: + case 0xf0 ... 0xff: kbd_log("ATkbc: pulse %01X\n", val & 0x0f); pulse_output(dev, val & 0x0f); return 0; @@ -1285,35 +2119,168 @@ static uint8_t write60_ami(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; + uint16_t index = 0x00c0; - switch(dev->command) { - /* 0x40 - 0x5F are aliases for 0x60-0x7F */ - case 0x40: case 0x41: case 0x42: case 0x43: - case 0x44: case 0x45: case 0x46: case 0x47: - case 0x48: case 0x49: case 0x4a: case 0x4b: - 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: case 0x5f: - kbd_log("ATkbc: AMI - alias write to %08X\n", dev->command); - dev->mem[dev->command & 0x1f] = val; - if (dev->command == 0x60) + switch(dev->kbc_cmd) { + /* 0x40 - 0x5F are aliases for 0x60 - 0x7F */ + case 0x40 ... 0x5f: + kbd_log("ATkbc: AMI - alias write to %08X\n", dev->kbc_cmd); + if (dev->kbc_cmd == 0x40) write_cmd(dev, val); + else + dev->mem[(dev->kbc_cmd & 0x1f) + 0x20] = val; return 0; case 0xaf: /* set extended controller RAM */ - kbd_log("ATkbc: AMI - set extended controller RAM\n"); - if (dev->secr_phase == 1) { - dev->mem_addr = val; - dev->want60 = 1; - dev->secr_phase = 2; - } else if (dev->secr_phase == 2) { - dev->mem[dev->mem_addr] = val; + kbd_log("ATkbc: AMI - set extended controller RAM, input phase %i\n", dev->secr_phase); + if (dev->secr_phase == 0) { + dev->mem_index = val; + dev->kbc_in = 1; + dev->secr_phase++; + } else if (dev->secr_phase == 1) { + if (dev->mem_index == 0x20) + write_cmd(dev, val); + else + dev->mem[dev->mem_index] = val; dev->secr_phase = 0; } return 0; + case 0xb8: + kbd_log("ATkbc: AMI MegaKey - memory index %02X\n", val); + dev->mem_index = val; + return 0; + + case 0xbb: + kbd_log("ATkbc: AMI MegaKey - write %02X to memory index %02X\n", val, dev->mem_index); + if (dev->mem_index >= 0x80) { + switch (dev->mem[0x9b] & 0xc0) { + case 0x00: + index = 0x0080; + break; + case 0x40: case 0x80: + index = 0x0000; + break; + case 0xc0: + index = 0x0100; + break; + } + dev->mem[index + dev->mem_index] = val; + } else if (dev->mem_index == 0x60) + write_cmd(dev, val); + else if (dev->mem_index == 0x42) + dev->status = val; + else if (dev->mem_index >= 0x40) + dev->mem[dev->mem_index - 0x40] = val; + else + dev->mem_int[dev->mem_index] = val; + return 0; + + case 0xbd: + kbd_log("ATkbc: AMI MegaKey - write %02X to config index %02X\n", val, dev->mem_index); + switch (dev->mem_index) { + case 0x00: /* STAT8042 */ + dev->status = val; + break; + case 0x01: /* Password_ptr */ + dev->mem[0x1c] = val; + break; + case 0x02: /* Wakeup_Tsk_Reg */ + dev->mem[0x1e] = val; + break; + case 0x03: /* CCB */ + write_cmd(dev, val); + break; + case 0x04: /* Debounce_time */ + dev->mem[0x4d] = val; + break; + case 0x05: /* Pulse_Width */ + dev->mem[0x4e] = val; + break; + case 0x06: /* Pk_sel_byte */ + dev->mem[0x4c] = val; + break; + case 0x07: /* Func_Tsk_Reg */ + dev->mem[0x7e] = val; + break; + case 0x08: /* TypematicRate */ + dev->mem[0x80] = val; + break; + case 0x09: /* Led_Flag_Byte */ + dev->mem[0x81] = val; + break; + case 0x0a: /* Kbms_Command_St */ + dev->mem[0x87] = val; + break; + case 0x0b: /* Delay_Count_Byte */ + dev->mem[0x86] = val; + break; + case 0x0c: /* KBC_Flags */ + dev->mem[0x9b] = val; + break; + case 0x0d: /* SCODE_HK1 */ + dev->mem[0x50] = val; + break; + case 0x0e: /* SCODE_HK2 */ + dev->mem[0x51] = val; + break; + case 0x0f: /* SCODE_HK3 */ + dev->mem[0x52] = val; + break; + case 0x10: /* SCODE_HK4 */ + dev->mem[0x53] = val; + break; + case 0x11: /* SCODE_HK5 */ + dev->mem[0x54] = val; + break; + case 0x12: /* SCODE_HK6 */ + dev->mem[0x55] = val; + break; + case 0x13: /* TASK_HK1 */ + dev->mem[0x56] = val; + break; + case 0x14: /* TASK_HK2 */ + dev->mem[0x57] = val; + break; + case 0x15: /* TASK_HK3 */ + dev->mem[0x58] = val; + break; + case 0x16: /* TASK_HK4 */ + dev->mem[0x59] = val; + break; + case 0x17: /* TASK_HK5 */ + dev->mem[0x5a] = val; + break; + /* The next 4 bytes have uncertain correspondences. */ + case 0x18: /* Batt_Poll_delay_Time */ + dev->mem[0x5b] = val; + break; + case 0x19: /* Batt_Alarm_Reg1 */ + dev->mem[0x5c] = val; + break; + case 0x1a: /* Batt_Alarm_Reg2 */ + dev->mem[0x5d] = val; + break; + case 0x1b: /* Batt_Alarm_Tsk_Reg */ + dev->mem[0x5e] = val; + break; + case 0x1c: /* Kbc_State1 */ + dev->mem[0x9d] = val; + break; + case 0x1d: /* Aux_Config */ + dev->mem[0x75] = val; + break; + case 0x1e: /* Kbc_State3 */ + dev->mem[0x73] = val; + break; + } + return 0; + + case 0xc1: /* write input port */ + kbd_log("ATkbc: AMI MegaKey - write %02X to input port\n", val); + dev->p1 = val; + return 0; + case 0xcb: /* set keyboard mode */ kbd_log("ATkbc: AMI - set keyboard mode\n"); return 0; @@ -1327,62 +2294,50 @@ static uint8_t write64_ami(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; + uint16_t index = 0x00c0; switch (val) { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x05: case 0x06: case 0x07: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0d: case 0x0e: case 0x0f: - case 0x10: case 0x11: case 0x12: case 0x13: - case 0x14: case 0x15: case 0x16: case 0x17: - case 0x18: case 0x19: case 0x1a: case 0x1b: - case 0x1c: case 0x1d: case 0x1e: case 0x1f: + case 0x00 ... 0x1f: kbd_log("ATkbc: AMI - alias read from %08X\n", val); - add_data(dev, dev->mem[val]); + kbc_transmit(dev, dev->mem[val + 0x20]); return 0; - case 0x40: case 0x41: case 0x42: case 0x43: - case 0x44: case 0x45: case 0x46: case 0x47: - case 0x48: case 0x49: case 0x4a: case 0x4b: - 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: case 0x5f: - kbd_log("ATkbc: AMI - alias write to %08X\n", dev->command); - dev->want60 = 1; + case 0x40 ... 0x5f: + kbd_log("ATkbc: AMI - alias write to %08X\n", dev->kbc_cmd); + dev->kbc_in = 1; return 0; case 0xa0: /* copyright message */ - add_data(dev, 0x28); - add_data(dev, 0x00); - break; + kbc_transmit(dev, ami_copr[0]); + dev->kbc_phase = 1; + return 0; case 0xa1: /* get controller version */ kbd_log("ATkbc: AMI - get controller version\n"); - add_data(dev, 'H'); + // kbc_transmit(dev, 'H'); + kbc_transmit(dev, '5'); return 0; case 0xa2: /* clear keyboard controller lines P22/P23 */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - clear KBC lines P22 and P23\n"); - write_output(dev, dev->output_port & 0xf3); - add_data(dev, 0x00); + write_output(dev, dev->p2 & 0xf3); + kbc_transmit(dev, 0x00); return 0; } break; case 0xa3: /* set keyboard controller lines P22/P23 */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - set KBC lines P22 and P23\n"); - write_output(dev, dev->output_port | 0x0c); - add_data(dev, 0x00); + write_output(dev, dev->p2 | 0x0c); + kbc_transmit(dev, 0x00); return 0; } break; case 0xa4: /* write clock = low */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - write clock = low\n"); dev->ami_stat &= 0xfe; return 0; @@ -1390,7 +2345,7 @@ write64_ami(void *priv, uint8_t val) break; case 0xa5: /* write clock = high */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - write clock = high\n"); dev->ami_stat |= 0x01; return 0; @@ -1398,15 +2353,15 @@ write64_ami(void *priv, uint8_t val) break; case 0xa6: /* read clock */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - read clock\n"); - add_data(dev, !!(dev->ami_stat & 1)); + kbc_transmit(dev, !!(dev->ami_stat & 1)); return 0; } break; case 0xa7: /* write cache bad */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - write cache bad\n"); dev->ami_stat &= 0xfd; return 0; @@ -1414,7 +2369,7 @@ write64_ami(void *priv, uint8_t val) break; case 0xa8: /* write cache good */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - write cache good\n"); dev->ami_stat |= 0x02; return 0; @@ -1422,68 +2377,237 @@ write64_ami(void *priv, uint8_t val) break; case 0xa9: /* read cache */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - read cache\n"); - add_data(dev, !!(dev->ami_stat & 2)); + kbc_transmit(dev, !!(dev->ami_stat & 2)); return 0; } break; case 0xaf: /* set extended controller RAM */ kbd_log("ATkbc: set extended controller RAM\n"); - dev->want60 = 1; - dev->secr_phase = 1; + dev->kbc_in = 1; return 0; - case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb0 ... 0xb3: /* set KBC lines P10-P13 (input port bits 0-3) low */ kbd_log("ATkbc: set KBC lines P10-P13 (input port bits 0-3) low\n"); - if (!PCI || (val > 0xb1)) - dev->input_port &= ~(1 << (val & 0x03)); - add_data(dev, 0x00); + if (!(dev->flags & KBC_FLAG_PS2) || (val > 0xb1)) { + dev->p1 &= ~(1 << (val & 0x03)); + } + kbc_transmit(dev, 0x00); return 0; case 0xb4: case 0xb5: /* set KBC lines P22-P23 (output port bits 2-3) low */ kbd_log("ATkbc: set KBC lines P22-P23 (output port bits 2-3) low\n"); - if (! PCI) - write_output(dev, dev->output_port & ~(4 << (val & 0x01))); - add_data(dev, 0x00); + if (!(dev->flags & KBC_FLAG_PS2)) + write_output(dev, dev->p2 & ~(4 << (val & 0x01))); + kbc_transmit(dev, 0x00); return 0; - case 0xb8: case 0xb9: case 0xba: case 0xbb: +#if 0 + case 0xb8 ... 0xbb: +#else + case 0xb9: +#endif /* set KBC lines P10-P13 (input port bits 0-3) high */ kbd_log("ATkbc: set KBC lines P10-P13 (input port bits 0-3) high\n"); - if (!PCI || (val > 0xb9)) { - dev->input_port |= (1 << (val & 0x03)); - add_data(dev, 0x00); + if (!(dev->flags & KBC_FLAG_PS2) || (val > 0xb9)) { + dev->p1 |= (1 << (val & 0x03)); + kbc_transmit(dev, 0x00); } return 0; + case 0xb8: + kbd_log("ATkbc: AMI MegaKey - memory index\n"); + dev->kbc_in = 1; + return 0; + + case 0xba: + kbd_log("ATkbc: AMI MegaKey - read %02X memory from index %02X\n", dev->mem[dev->mem_index], dev->mem_index); + if (dev->mem_index >= 0x80) { + switch (dev->mem[0x9b] & 0xc0) { + case 0x00: + index = 0x0080; + break; + case 0x40: case 0x80: + index = 0x0000; + break; + case 0xc0: + index = 0x0100; + break; + } + kbc_transmit(dev, dev->mem[index + dev->mem_index]); + } else if (dev->mem_index == 0x42) + kbc_transmit(dev, dev->status); + else if (dev->mem_index >= 0x40) + kbc_transmit(dev, dev->mem[dev->mem_index - 0x40]); + else + kbc_transmit(dev, dev->mem_int[dev->mem_index]); + return 0; + + case 0xbb: + kbd_log("ATkbc: AMI MegaKey - write to memory index %02X\n", dev->mem_index); + dev->kbc_in = 1; + return 0; + +#if 0 case 0xbc: case 0xbd: /* set KBC lines P22-P23 (output port bits 2-3) high */ kbd_log("ATkbc: set KBC lines P22-P23 (output port bits 2-3) high\n"); - if (! PCI) - write_output(dev, dev->output_port | (4 << (val & 0x01))); - add_data(dev, 0x00); + if (!(dev->flags & KBC_FLAG_PS2)) + write_output(dev, dev->p2 | (4 << (val & 0x01))); + kbc_transmit(dev, 0x00); + return 0; +#endif + + case 0xbc: + switch (dev->mem_index) { + case 0x00: /* STAT8042 */ + kbc_transmit(dev, dev->status); + break; + case 0x01: /* Password_ptr */ + kbc_transmit(dev, dev->mem[0x1c]); + break; + case 0x02: /* Wakeup_Tsk_Reg */ + kbc_transmit(dev, dev->mem[0x1e]); + break; + case 0x03: /* CCB */ + kbc_transmit(dev, dev->mem[0x20]); + break; + case 0x04: /* Debounce_time */ + kbc_transmit(dev, dev->mem[0x4d]); + break; + case 0x05: /* Pulse_Width */ + kbc_transmit(dev, dev->mem[0x4e]); + break; + case 0x06: /* Pk_sel_byte */ + kbc_transmit(dev, dev->mem[0x4c]); + break; + case 0x07: /* Func_Tsk_Reg */ + kbc_transmit(dev, dev->mem[0x7e]); + break; + case 0x08: /* TypematicRate */ + kbc_transmit(dev, dev->mem[0x80]); + break; + case 0x09: /* Led_Flag_Byte */ + kbc_transmit(dev, dev->mem[0x81]); + break; + case 0x0a: /* Kbms_Command_St */ + kbc_transmit(dev, dev->mem[0x87]); + break; + case 0x0b: /* Delay_Count_Byte */ + kbc_transmit(dev, dev->mem[0x86]); + break; + case 0x0c: /* KBC_Flags */ + kbc_transmit(dev, dev->mem[0x9b]); + break; + case 0x0d: /* SCODE_HK1 */ + kbc_transmit(dev, dev->mem[0x50]); + break; + case 0x0e: /* SCODE_HK2 */ + kbc_transmit(dev, dev->mem[0x51]); + break; + case 0x0f: /* SCODE_HK3 */ + kbc_transmit(dev, dev->mem[0x52]); + break; + case 0x10: /* SCODE_HK4 */ + kbc_transmit(dev, dev->mem[0x53]); + break; + case 0x11: /* SCODE_HK5 */ + kbc_transmit(dev, dev->mem[0x54]); + break; + case 0x12: /* SCODE_HK6 */ + kbc_transmit(dev, dev->mem[0x55]); + break; + case 0x13: /* TASK_HK1 */ + kbc_transmit(dev, dev->mem[0x56]); + break; + case 0x14: /* TASK_HK2 */ + kbc_transmit(dev, dev->mem[0x57]); + break; + case 0x15: /* TASK_HK3 */ + kbc_transmit(dev, dev->mem[0x58]); + break; + case 0x16: /* TASK_HK4 */ + kbc_transmit(dev, dev->mem[0x59]); + break; + case 0x17: /* TASK_HK5 */ + kbc_transmit(dev, dev->mem[0x5a]); + break; + /* The next 4 bytes have uncertain correspondences. */ + case 0x18: /* Batt_Poll_delay_Time */ + kbc_transmit(dev, dev->mem[0x5b]); + break; + case 0x19: /* Batt_Alarm_Reg1 */ + kbc_transmit(dev, dev->mem[0x5c]); + break; + case 0x1a: /* Batt_Alarm_Reg2 */ + kbc_transmit(dev, dev->mem[0x5d]); + break; + case 0x1b: /* Batt_Alarm_Tsk_Reg */ + kbc_transmit(dev, dev->mem[0x5e]); + break; + case 0x1c: /* Kbc_State1 */ + kbc_transmit(dev, dev->mem[0x9d]); + break; + case 0x1d: /* Aux_Config */ + kbc_transmit(dev, dev->mem[0x75]); + break; + case 0x1e: /* Kbc_State3 */ + kbc_transmit(dev, dev->mem[0x73]); + break; + default: + kbc_transmit(dev, 0x00); + break; + } + kbd_log("ATkbc: AMI MegaKey - read from config index %02X\n", dev->mem_index); return 0; - case 0xc8: + case 0xbd: + kbd_log("ATkbc: AMI MegaKey - write to config index %02X\n", dev->mem_index); + dev->kbc_in = 1; + return 0; + + case 0xc1: /* write input port */ + kbd_log("ATkbc: AMI MegaKey - write input port\n"); + dev->kbc_in = 1; + return 0; + + case 0xc4: + /* set KBC line P14 low */ + kbd_log("ATkbc: set KBC line P14 (input port bit 4) low\n"); + dev->p1 &= 0xef; + kbc_transmit(dev, 0x00); + return 0; + case 0xc5: + /* set KBC line P15 low */ + kbd_log("ATkbc: set KBC line P15 (input port bit 5) low\n"); + dev->p1 &= 0xdf; + kbc_transmit(dev, 0x00); + return 0; + + case 0xc8: case 0xc9: /* - * unblock KBC lines P22/P23 + * (un)block KBC lines P22/P23 * (allow command D1 to change bits 2/3 of the output port) */ - kbd_log("ATkbc: AMI - unblock KBC lines P22 and P23\n"); - dev->output_locked = 1; + kbd_log("ATkbc: AMI - %sblock KBC lines P22 and P23\n", (val & 1) ? "" : "un"); + dev->p2_locked = (val & 1); return 0; - case 0xc9: - /* - * block KBC lines P22/P23 - * (disallow command D1 from changing bits 2/3 of the port) - */ - kbd_log("ATkbc: AMI - block KBC lines P22 and P23\n"); - dev->output_locked = 1; + case 0xcc: + /* set KBC line P14 high */ + kbd_log("ATkbc: set KBC line P14 (input port bit 4) high\n"); + dev->p1 |= 0x10; + kbc_transmit(dev, 0x00); + return 0; + case 0xcd: + /* set KBC line P15 high */ + kbd_log("ATkbc: set KBC line P15 (input port bit 5) high\n"); + dev->p1 |= 0x20; + kbc_transmit(dev, 0x00); return 0; case 0xef: /* ??? - sent by AMI486 */ @@ -1504,23 +2628,20 @@ write64_ibm_mca(void *priv, uint8_t val) case 0xc1: /*Copy bits 0 to 3 of input port to status bits 4 to 7*/ kbd_log("ATkbc: copy bits 0 to 3 of input port to status bits 4 to 7\n"); dev->status &= 0x0f; - dev->status |= ((((dev->input_port & 0xfc) | 0x84) & 0x0f) << 4); + dev->status |= ((((dev->p1 & 0xfc) | 0x84) & 0x0f) << 4); return 0; case 0xc2: /*Copy bits 4 to 7 of input port to status bits 4 to 7*/ kbd_log("ATkbc: copy bits 4 to 7 of input port to status bits 4 to 7\n"); dev->status &= 0x0f; - dev->status |= (((dev->input_port & 0xfc) | 0x84) & 0xf0); + dev->status |= (((dev->p1 & 0xfc) | 0x84) & 0xf0); return 0; case 0xaf: kbd_log("ATkbc: bad KBC command AF\n"); return 1; - case 0xf0: case 0xf1: case 0xf2: case 0xf3: - case 0xf4: case 0xf5: case 0xf6: case 0xf7: - case 0xf8: case 0xf9: case 0xfa: case 0xfb: - case 0xfc: case 0xfd: case 0xfe: case 0xff: + case 0xf0 ... 0xff: kbd_log("ATkbc: pulse: %01X\n", (val & 0x03) | 0x0c); pulse_output(dev, (val & 0x03) | 0x0c); return 0; @@ -1535,7 +2656,7 @@ write60_quadtel(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; - switch(dev->command) { + switch(dev->kbc_cmd) { case 0xcf: /*??? - sent by MegaPC BIOS*/ kbd_log("ATkbc: ??? - sent by MegaPC BIOS\n"); return 0; @@ -1544,12 +2665,34 @@ write60_quadtel(void *priv, uint8_t val) return 1; } + static uint8_t write64_olivetti(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; switch (val) { + /* This appears to be a clone of "Read input port", in which case, the bis would be: + 7: M290 (AT KBC): + Keyboard lock (1 = unlocked, 0 = locked); + M300 (PS/2 KBC): + Bus expansion board present (1 = present, 0 = not present); + 6: Usually: + Display (1 = MDA, 0 = CGA, but can have its polarity inverted); + 5: Manufacturing jumper (1 = not installed, 0 = installed (infinite loop)); + 4: RAM on motherboard (1 = 256 kB, 0 = 512 kB - which machine actually uses this?); + 3: Fast Ram check (if inactive keyboard works erratically); + 2: Keyboard fuse present + This appears to be in-line with PS/2: 1 = no power, 0 = keyboard power normal; + 1: M290 (AT KBC): + Unused; + M300 (PS/2 KBC): + Mouse data in; + 0: M290 (AT KBC): + Unused; + M300 (PS/2 KBC): + Key data in. + */ case 0x80: /* Olivetti-specific command */ /* * bit 7: bus expansion board present (M300) / keyboard unlocked (M290) @@ -1558,11 +2701,9 @@ write64_olivetti(void *priv, uint8_t val) * bit 2: keyboard fuse present * bits 0-1: ??? */ - add_to_kbc_queue_front(dev, (0x0c | ((is386) ? 0x00 : 0x80)) & 0xdf, 0, 0x00); - dev->input_port = ((dev->input_port + 1) & 3) | - (dev->input_port & 0xfc); + kbc_transmit(dev, 0x0c | (is386 ? 0x00 : 0x80)); return 0; - } + } return write64_generic(dev, val); } @@ -1580,7 +2721,7 @@ write64_quadtel(void *priv, uint8_t val) case 0xcf: /*??? - sent by MegaPC BIOS*/ kbd_log("ATkbc: ??? - sent by MegaPC BIOS\n"); - dev->want60 = 1; + dev->kbc_in = 1; return 0; } @@ -1593,7 +2734,7 @@ write60_toshiba(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; - switch(dev->command) { + switch(dev->kbc_cmd) { case 0xb6: /* T3100e - set color/mono switch */ kbd_log("ATkbc: T3100e - set color/mono switch\n"); t3100e_mono_set(val); @@ -1636,29 +2777,30 @@ write64_toshiba(void *priv, uint8_t val) case 0xb4: /* T3100e: Get configuration / status */ kbd_log("ATkbc: T3100e: Get configuration / status\n"); - add_data(dev, t3100e_config_get()); + kbc_transmit(dev, t3100e_config_get()); return 0; case 0xb5: /* T3100e: Get colour / mono byte */ kbd_log("ATkbc: T3100e: Get colour / mono byte\n"); - add_data(dev, t3100e_mono_get()); + kbc_transmit(dev, t3100e_mono_get()); return 0; case 0xb6: /* T3100e: Set colour / mono byte */ kbd_log("ATkbc: T3100e: Set colour / mono byte\n"); - dev->want60 = 1; + dev->kbc_in = 1; return 0; case 0xb7: /* T3100e: Emulate PS/2 keyboard */ case 0xb8: /* T3100e: Emulate AT keyboard */ - dev->flags &= ~KBC_TYPE_MASK; + dev->flags &= ~KBC_FLAG_PS2; if (val == 0xb7) { kbd_log("ATkbc: T3100e: Emulate PS/2 keyboard\n"); - dev->flags |= KBC_TYPE_PS2_NOREF; - } else { - kbd_log("ATkbc: T3100e: Emulate AT keyboard\n"); - dev->flags |= KBC_TYPE_ISA; + dev->flags |= KBC_FLAG_PS2; } +#ifdef ENABLE_KEYBOARD_AT_LOG + else + kbd_log("ATkbc: T3100e: Emulate AT keyboard\n"); +#endif return 0; case 0xbb: /* T3100e: Read 'Fn' key. @@ -1668,8 +2810,9 @@ write64_toshiba(void *priv, uint8_t val) kbd_log("ATkbc: T3100e: Read 'Fn' key\n"); if (keyboard_recv(0xb8) || /* Right Alt */ keyboard_recv(0x9d)) /* Right Ctrl */ - add_data(dev, 0x04); - else add_data(dev, 0x00); + kbc_transmit(dev, 0x04); + else + kbc_transmit(dev, 0x00); return 0; case 0xbc: /* T3100e: Reset Fn+Key notification */ @@ -1682,8 +2825,8 @@ write64_toshiba(void *priv, uint8_t val) /* The T3100e returns all bits set except bit 6 which * is set by t3100e_mono_set() */ - dev->input_port = (t3100e_mono_get() & 1) ? 0xff : 0xbf; - add_data(dev, dev->input_port); + dev->p1 = (t3100e_mono_get() & 1) ? 0xff : 0xbf; + kbc_transmit(dev, dev->p1); return 0; } @@ -1696,425 +2839,46 @@ static void kbd_write(uint16_t port, uint8_t val, void *priv) { atkbd_t *dev = (atkbd_t *)priv; - int i = 0, bad = 1; - uint8_t mask, kbc_ven = 0x0; - kbc_ven = dev->flags & KBC_VEN_MASK; - if ((kbc_ven == KBC_VEN_XI8088) && (port == 0x63)) - port = 0x61; - - kbd_log((port == 0x61) ? "" : "ATkbc: write(%04X, %02X)\n", port, val); + kbd_log("[%04X:%08X] ATkbc: write(%04X, %02X)\n", CS, cpu_state.pc, port, val); switch (port) { case 0x60: - dev->status &= ~STAT_CD; - if (dev->want60) { - /* Write data to controller. */ - dev->want60 = 0; + dev->status = (dev->status & ~STAT_CD) | STAT_IFULL; + dev->ib = val; + // kbd_status("Write %02X: %02X, Status = %02X\n", port, val, dev->status); - switch (dev->command) { - case 0x60: case 0x61: case 0x62: case 0x63: - case 0x64: case 0x65: case 0x66: case 0x67: - case 0x68: case 0x69: case 0x6a: case 0x6b: - case 0x6c: case 0x6d: case 0x6e: case 0x6f: - case 0x70: case 0x71: case 0x72: case 0x73: - case 0x74: case 0x75: case 0x76: case 0x77: - case 0x78: case 0x79: case 0x7a: case 0x7b: - case 0x7c: case 0x7d: case 0x7e: case 0x7f: - dev->mem[dev->command & 0x1f] = val; - if (dev->command == 0x60) - write_cmd(dev, val); - break; - - case 0xd1: /* write output port */ - kbd_log("ATkbc: write output port\n"); - if (dev->output_locked) { - /*If keyboard controller lines P22-P23 are blocked, - we force them to remain unchanged.*/ - val &= ~0x0c; - val |= (dev->output_port & 0x0c); - } - write_output(dev, val); - break; - - case 0xd2: /* write to keyboard output buffer */ - kbd_log("ATkbc: write to keyboard output buffer\n"); - add_data_kbd_direct(dev, val); - break; - - case 0xd3: /* write to mouse output buffer */ - kbd_log("ATkbc: write to mouse output buffer\n"); - if (mouse_write && ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) - keyboard_at_adddata_mouse(val); - break; - - case 0xd4: /* write to mouse */ - kbd_log("ATkbc: write to mouse (%02X)\n", val); - - if (val == 0xbb) - break; - - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - set_enable_mouse(dev, 1); - if (mouse_write) - mouse_write(val, mouse_p); - else - add_to_kbc_queue_front(dev, 0xfe, 2, 0x40); - } - break; - - default: - /* - * Run the vendor-specific handler - * if we have one. Otherwise, or if - * it returns an error, log a bad - * controller command. - */ - if (dev->write60_ven) - bad = dev->write60_ven(dev, val); - - if (bad) { - kbd_log("ATkbc: bad controller command %02x data %02x\n", dev->command, val); - add_data_kbd(0xfe); - } - } - } else { - /* Write data to keyboard. */ - dev->mem[0] &= ~0x10; - - if (dev->key_wantdata) { - dev->key_wantdata = 0; - - /* - * Several system BIOSes and OS device drivers - * mess up with this, and repeat the command - * code many times. Fun! - */ - if (val == dev->key_command) { - /* Respond NAK and ignore it. */ - add_data_kbd(0xfe); - dev->key_command = 0x00; - break; - } - - switch (dev->key_command) { - case 0xed: /* set/reset LEDs */ - add_data_kbd_direct(dev, 0xfa); - kbd_log("ATkbd: set LEDs [%02x]\n", val); - break; - - case 0xf0: /* get/set scancode set */ - add_data_kbd_direct(dev, 0xfa); - if (val == 0) { - kbd_log("Get scan code set: %02X\n", keyboard_mode & 3); - add_data_kbd_direct(dev, keyboard_mode & 3); - } else { - if ((val <= 3) && (val != 1)) { - keyboard_mode &= 0xfc; - keyboard_mode |= (val & 3); - kbd_log("Scan code set now: %02X\n", val); - } - set_scancode_map(dev); - } - break; - - case 0xf3: /* set typematic rate/delay */ - add_data_kbd_direct(dev, 0xfa); - break; - - default: - kbd_log("ATkbd: bad keyboard 0060 write %02X command %02X\n", val, dev->key_command); - add_data_kbd_direct(dev, 0xfe); - break; - } - - /* Keyboard command is now done. */ - dev->key_command = 0x00; - } else { - /* No keyboard command in progress. */ - dev->key_command = 0x00; - - set_enable_kbd(dev, 1); - - switch (val) { - case 0x00: - kbd_log("ATkbd: command 00\n"); - add_data_kbd_direct(dev, 0xfa); - break; - - case 0x05: /*??? - sent by NT 4.0*/ - kbd_log("ATkbd: command 05 (NT 4.0)\n"); - add_data_kbd_direct(dev, 0xfe); - break; - - /* Sent by Pentium-era AMI BIOS'es.*/ - case 0x71: case 0x82: - kbd_log("ATkbd: Pentium-era AMI BIOS command %02X\n", val); - break; - - case 0xed: /* set/reset LEDs */ - kbd_log("ATkbd: set/reset leds\n"); - add_data_kbd_direct(dev, 0xfa); - - dev->key_wantdata = 1; - break; - - case 0xee: /* diagnostic echo */ - kbd_log("ATkbd: ECHO\n"); - add_data_kbd_direct(dev, 0xee); - break; - - case 0xef: /* NOP (reserved for future use) */ - kbd_log("ATkbd: NOP\n"); - break; - - case 0xf0: /* get/set scan code set */ - kbd_log("ATkbd: scan code set\n"); - add_data_kbd_direct(dev, 0xfa); - dev->key_wantdata = 1; - break; - - case 0xf2: /* read ID */ - /* Fixed as translation will be done in add_data_kbd(). */ - kbd_log("ATkbd: read keyboard id\n"); - /* TODO: After keyboard type selection is implemented, make this - return the correct keyboard ID for the selected type. */ - add_data_kbd_direct(dev, 0xfa); - add_data_kbd_direct(dev, 0xab); - add_data_kbd_direct(dev, 0x83); - break; - - case 0xf3: /* set typematic rate/delay */ - kbd_log("ATkbd: set typematic rate/delay\n"); - add_data_kbd_direct(dev, 0xfa); - dev->key_wantdata = 1; - break; - - case 0xf4: /* enable keyboard */ - kbd_log("ATkbd: enable keyboard\n"); - add_data_kbd_direct(dev, 0xfa); - keyboard_scan = 1; - break; - - case 0xf5: /* set defaults and disable keyboard */ - case 0xf6: /* set defaults */ - kbd_log("ATkbd: set defaults%s\n", (val == 0xf6) ? "" : " and disable keyboard"); - keyboard_scan = (val == 0xf6); - kbd_log("val = %02X, keyboard_scan = %i, dev->mem[0] = %02X\n", - val, keyboard_scan, dev->mem[0]); - add_data_kbd_direct(dev, 0xfa); - - keyboard_set3_all_break = 0; - keyboard_set3_all_repeat = 0; - memset(keyboard_set3_flags, 0, 512); - keyboard_mode = (keyboard_mode & 0xfc) | 0x02; - set_scancode_map(dev); - break; - - case 0xf7: /* set all keys to repeat */ - kbd_log("ATkbd: set all keys to repeat\n"); - add_data_kbd_direct(dev, 0xfa); - keyboard_set3_all_break = 1; - break; - - case 0xf8: /* set all keys to give make/break codes */ - kbd_log("ATkbd: set all keys to give make/break codes\n"); - add_data_kbd_direct(dev, 0xfa); - keyboard_set3_all_break = 1; - break; - - case 0xf9: /* set all keys to give make codes only */ - kbd_log("ATkbd: set all keys to give make codes only\n"); - add_data_kbd_direct(dev, 0xfa); - keyboard_set3_all_break = 0; - break; - - case 0xfa: /* set all keys to repeat and give make/break codes */ - kbd_log("ATkbd: set all keys to repeat and give make/break codes\n"); - add_data_kbd_direct(dev, 0xfa); - keyboard_set3_all_repeat = 1; - keyboard_set3_all_break = 1; - break; - - case 0xfe: /* resend last scan code */ - kbd_log("ATkbd: reset last scan code\n"); - add_data_kbd_raw(dev, kbd_last_scan_code); - break; - - case 0xff: /* reset */ - kbd_log("ATkbd: kbd reset\n"); - kbc_queue_reset(1); - kbd_last_scan_code = 0x00; - add_data_kbd_direct(dev, 0xfa); - - /* Set scan code set to 2. */ - keyboard_mode = (keyboard_mode & 0xfc) | 0x02; - set_scancode_map(dev); - - dev->reset_delay = RESET_DELAY_TIME; - break; - - default: - kbd_log("ATkbd: bad keyboard command %02X\n", val); - add_data_kbd_direct(dev, 0xfe); - } - - /* If command needs data, remember command. */ - if (dev->key_wantdata == 1) - dev->key_command = val; - } +#if 0 + if ((dev->fast_a20_phase == 1)/* && ((val == 0xdd) || (val == 0xdf))*/) { + dev->status &= ~STAT_IFULL; + write_output(dev, val); + dev->fast_a20_phase = 0; } +#endif break; - - case 0x61: - ppi.pb = (ppi.pb & 0x10) | (val & 0x0f); - - speaker_update(); - speaker_gated = val & 1; - speaker_enable = val & 2; - if (speaker_enable) - was_speaker_enable = 1; - pit_ctr_set_gate(&pit->counters[2], val & 1); - - if (kbc_ven == KBC_VEN_XI8088) - xi8088_turbo_set(!!(val & 0x04)); - break; - case 0x64: - /* Controller command. */ - dev->want60 = 0; - dev->status |= STAT_CD; + dev->status |= (STAT_CD | STAT_IFULL); + dev->ib = val; + // kbd_status("Write %02X: %02X, Status = %02X\n", port, val, dev->status); - switch (val) { - /* Read data from KBC memory. */ - case 0x20: case 0x21: case 0x22: case 0x23: - case 0x24: case 0x25: case 0x26: case 0x27: - case 0x28: case 0x29: case 0x2a: case 0x2b: - case 0x2c: case 0x2d: case 0x2e: case 0x2f: - case 0x30: case 0x31: case 0x32: case 0x33: - case 0x34: case 0x35: case 0x36: case 0x37: - case 0x38: case 0x39: case 0x3a: case 0x3b: - case 0x3c: case 0x3d: case 0x3e: case 0x3f: - add_data(dev, dev->mem[val & 0x1f]); - break; - - /* Write data to KBC memory. */ - case 0x60: case 0x61: case 0x62: case 0x63: - case 0x64: case 0x65: case 0x66: case 0x67: - case 0x68: case 0x69: case 0x6a: case 0x6b: - case 0x6c: case 0x6d: case 0x6e: case 0x6f: - case 0x70: case 0x71: case 0x72: case 0x73: - case 0x74: case 0x75: case 0x76: case 0x77: - case 0x78: case 0x79: case 0x7a: case 0x7b: - case 0x7c: case 0x7d: case 0x7e: case 0x7f: - dev->want60 = 1; - break; - - case 0xaa: /* self-test */ - kbd_log("ATkbc: self-test\n"); - if ((kbc_ven == KBC_VEN_TOSHIBA) || (kbc_ven == KBC_VEN_SAMSUNG)) - dev->status |= STAT_IFULL; - write_output(dev, ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x4b : 0xcf); - - /* Always reinitialize all queues - the real hardware pulls keyboard and mouse - clocks high, which stops keyboard scanning. */ - kbd_log("ATkbc: self-test reinitialization\n"); - dev->out_new = dev->out_delayed = -1; - for (i = 0; i < 3; i++) - kbc_queue_reset(i); - kbd_last_scan_code = 0x00; - dev->status &= ~STAT_OFULL; - dev->last_irq = dev->old_last_irq = 0; - - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) - write_cmd(dev, 0x30 | STAT_SYSFLAG); - else - write_cmd(dev, 0x10 | STAT_SYSFLAG); - add_data(dev, 0x55); - break; - - case 0xab: /* interface test */ - kbd_log("ATkbc: interface test\n"); - add_data(dev, 0x00); /*no error*/ - break; - - case 0xac: /* diagnostic dump */ - kbd_log("ATkbc: diagnostic dump\n"); - for (i = 0; i < 16; i++) - add_data(dev, dev->mem[i]); - add_data(dev, (dev->input_port & 0xf0) | 0x80); - add_data(dev, dev->output_port); - add_data(dev, dev->status); - break; - - case 0xad: /* disable keyboard */ - kbd_log("ATkbc: disable keyboard\n"); - set_enable_kbd(dev, 0); - break; - - case 0xae: /* enable keyboard */ - kbd_log("ATkbc: enable keyboard\n"); - set_enable_kbd(dev, 1); - break; - - case 0xca: /* read keyboard mode */ - kbd_log("ATkbc: AMI - read keyboard mode\n"); - add_data(dev, ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x01 : 0x00); /*ISA mode*/ - break; - - case 0xcb: /* set keyboard mode */ - kbd_log("ATkbc: AMI - set keyboard mode\n"); - dev->want60 = 1; - break; - - case 0xd0: /* read output port */ - kbd_log("ATkbc: read output port\n"); - mask = 0xff; - if (dev->mem[0] & 0x10) - mask &= 0xbf; - if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) && (dev->mem[0] & 0x20)) - mask &= 0xf7; - add_to_kbc_queue_front(dev, dev->output_port & mask, 0, 0x00); - break; - - case 0xd1: /* write output port */ - kbd_log("ATkbc: write output port\n"); - dev->want60 = 1; - break; - - case 0xd2: /* write keyboard output buffer */ - kbd_log("ATkbc: write keyboard output buffer\n"); - dev->want60 = 1; - break; - - case 0xdd: /* disable A20 address line */ - case 0xdf: /* enable A20 address line */ - kbd_log("ATkbc: %sable A20\n", (val == 0xdd) ? "dis": "en"); - write_output(dev, (dev->output_port & 0xfd) | (val & 0x02)); - break; - - case 0xe0: /* read test inputs */ - kbd_log("ATkbc: read test inputs\n"); - add_data(dev, 0x00); - break; - - default: - /* - * Unrecognized controller command. - * - * If we have a vendor-specific handler, run - * that. Otherwise, or if that handler fails, - * log a bad command. - */ - if (dev->write64_ven) - bad = dev->write64_ven(dev, val); - - kbd_log(bad ? "ATkbc: bad controller command %02X\n" : "", val); +#if 0 + if (val == 0xd1) { + dev->status &= ~STAT_IFULL; + dev->fast_a20_phase = 1; + } else if (val == 0xfe) { + dev->status &= ~STAT_IFULL; + pulse_output(dev, 0x0e); + } else if ((val == 0xad) || (val == 0xae)) { + dev->status &= ~STAT_IFULL; + if (val & 0x01) + dev->mem[0x20] |= 0x10; + else + dev->mem[0x20] &= ~0x10; + } else if (val == 0xa1) { + dev->status &= ~STAT_IFULL; + kbc_send_to_ob(dev, 'H', 0, 0x00); } - - /* If the command needs data, remember the command. */ - if (dev->want60) - dev->command = val; +#endif break; } } @@ -2125,83 +2889,20 @@ kbd_read(uint16_t port, void *priv) { atkbd_t *dev = (atkbd_t *)priv; uint8_t ret = 0xff; - uint8_t kbc_ven = 0x0; - kbc_ven = dev->flags & KBC_VEN_MASK; - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) - cycles -= ISA_CYCLES(8); - - if ((kbc_ven == KBC_VEN_XI8088) && (port == 0x63)) - port = 0x61; + // if (dev->flags & KBC_FLAG_PS2) + // cycles -= ISA_CYCLES(8); switch (port) { case 0x60: - ret = dev->out; + ret = dev->ob; dev->status &= ~STAT_OFULL; picintc(dev->last_irq); dev->last_irq = 0; break; - case 0x61: - ret = ppi.pb & ~0xe0; - if (ppispeakon) - ret |= 0x20; - if ((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) { - if (dev->refresh) - ret |= 0x10; - else - ret &= ~0x10; - } - if (kbc_ven == KBC_VEN_XI8088) { - if (xi8088_turbo_get()) - ret |= 0x04; - else - ret &= ~0x04; - } - break; - - case 0x62: - ret = 0xff; - if (kbc_ven == KBC_VEN_OLIVETTI) { - /* SWA on Olivetti M240 mainboard (off=1) */ - ret = 0x00; - if (ppi.pb & 0x8) { - /* Switches 4, 5 - floppy drives (number) */ - int i, fdd_count = 0; - for (i = 0; i < FDD_NUM; i++) { - if (fdd_get_flags(i)) - fdd_count++; - } - if (!fdd_count) - ret |= 0x00; - else - ret |= ((fdd_count - 1) << 2); - /* Switches 6, 7 - monitor type */ - if (video_is_mda()) - ret |= 0x3; - else if (video_is_cga()) - ret |= 0x2; /* 0x10 would be 40x25 */ - else - ret |= 0x0; - } else { - /* bit 2 always on */ - ret |= 0x4; - /* Switch 8 - 8087 FPU. */ - if (hasfpu) - ret |= 0x02; - } - } - break; case 0x64: - ret = (dev->status & 0xfb); - if (dev->mem[0] & STAT_SYSFLAG) - ret |= STAT_SYSFLAG; - /* Only clear the transmit timeout flag on non-PS/2 controllers, as on - PS/2 controller, it is the keyboard/mouse output source bit. */ - // dev->status &= ~STAT_RTIMEOUT; - if (((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) && - (kbc_ven != KBC_VEN_IBM_MCA)) - dev->status &= ~STAT_TTIMEOUT; + ret = dev->status; break; default: @@ -2209,22 +2910,12 @@ kbd_read(uint16_t port, void *priv) break; } - kbd_log((port == 0x61) ? "" : "ATkbc: read(%04X) = %02X\n", port, ret); + kbd_log("[%04X:%08X] ATkbc: read(%04X) = %02X\n",CS, cpu_state.pc, port, ret); return(ret); } -static void -kbd_refresh(void *priv) -{ - atkbd_t *dev = (atkbd_t *)priv; - - dev->refresh = !dev->refresh; - timer_advance_u64(&dev->refresh_time, PS2_REFRESH_TIME); -} - - static void kbd_reset(void *priv) { @@ -2233,25 +2924,26 @@ kbd_reset(void *priv) uint8_t kbc_ven = 0x0; kbc_ven = dev->flags & KBC_VEN_MASK; - dev->first_write = 1; - // dev->status = STAT_UNLOCKED | STAT_CD; dev->status = STAT_UNLOCKED; - dev->mem[0] = 0x01; - dev->mem[0] |= CCB_TRANSLATE; - dev->wantirq = 0; + dev->mem[0x20] = 0x01; + dev->mem[0x20] |= CCB_TRANSLATE; write_output(dev, 0xcf); - dev->last_irq = dev->old_last_irq = 0; + dev->last_irq = 0; dev->secr_phase = 0; - dev->key_wantdata = 0; + dev->kbd_in = 0; + dev->ami_mode = !!(dev->flags & KBC_FLAG_PS2); /* Set up the correct Video Type bits. */ + dev->p1 = video_is_mda() ? 0xf0 : 0xb0; if ((kbc_ven == KBC_VEN_XI8088) || (kbc_ven == KBC_VEN_ACER)) - dev->input_port = video_is_mda() ? 0xb0 : 0xf0; + dev->p1 ^= 0x40; + if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) + dev->inhibit = ((dev->p1 & 0x80) >> 3); else - dev->input_port = video_is_mda() ? 0xf0 : 0xb0; - kbd_log("ATkbc: input port = %02x\n", dev->input_port); + dev->inhibit = 0x10; + kbd_log("ATkbc: input port = %02x\n", dev->p1); - keyboard_mode = 0x02 | (dev->mem[0] & CCB_TRANSLATE); + keyboard_mode = 0x02 | (dev->mem[0x20] & CCB_TRANSLATE); /* Enable keyboard, disable mouse. */ set_enable_kbd(dev, 1); @@ -2259,16 +2951,18 @@ kbd_reset(void *priv) set_enable_mouse(dev, 0); mouse_scan = 0; - dev->out_new = dev->out_delayed = -1; - for (i = 0; i < 3; i++) - kbc_queue_reset(i); - kbd_last_scan_code = 0; + dev->ob = 0xff; sc_or = 0; + for (i = 1; i <= 2; i++) + kbc_queue_reset(i); + memset(keyboard_set3_flags, 0, 512); set_scancode_map(dev); + + dev->mem[0x31] = 0xfe; } @@ -2290,7 +2984,6 @@ kbd_close(void *priv) /* Stop timers. */ timer_disable(&dev->send_delay_timer); - timer_disable(&dev->refresh_time); keyboard_scan = 0; keyboard_send = NULL; @@ -2314,17 +3007,14 @@ kbd_init(const device_t *info) dev->flags = info->local; video_reset(gfxcard); - kbd_reset(dev); + dev->kbc_poll_phase = KBC_RESET; + kbd_send_to_host(dev, 0xaa); - io_sethandler(0x0060, 5, - kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); + io_sethandler(0x0060, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); + io_sethandler(0x0064, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); keyboard_send = add_data_kbd; timer_add(&dev->send_delay_timer, kbd_poll, dev, 1); - - if ((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) - timer_add(&dev->refresh_time, kbd_refresh, dev, 1); - timer_add(&dev->pulse_cb, pulse_poll, dev, 0); dev->write60_ven = NULL; @@ -2340,12 +3030,14 @@ kbd_init(const device_t *info) break; case KBC_VEN_OLIVETTI: + /* The Olivetti controller is a special case - starts directly in the + main loop instead of the reset loop. */ + dev->kbc_poll_phase = KBC_MAIN_LOOP; dev->write64_ven = write64_olivetti; break; case KBC_VEN_AMI: case KBC_VEN_INTEL_AMI: - case KBC_VEN_SAMSUNG: dev->write60_ven = write60_ami; dev->write64_ven = write64_ami; break; @@ -2365,6 +3057,8 @@ kbd_init(const device_t *info) break; } + kbd_reset(dev); + /* We need this, sadly. */ SavedKbd = dev; @@ -2392,16 +3086,6 @@ const device_t keyboard_at_ami_device = { { NULL }, NULL, NULL, NULL }; -const device_t keyboard_at_samsung_device = { - "PC/AT Keyboard (Samsung)", - 0, - KBC_TYPE_ISA | KBC_VEN_SAMSUNG, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - const device_t keyboard_at_toshiba_device = { "PC/AT Keyboard (Toshiba)", 0, @@ -2433,16 +3117,6 @@ const device_t keyboard_at_ncr_device = { }; const device_t keyboard_ps2_device = { - "PS/2 Keyboard", - 0, - KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_ps2_device = { "PS/2 Keyboard", 0, KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, @@ -2455,7 +3129,7 @@ const device_t keyboard_ps2_ps2_device = { const device_t keyboard_ps2_ps1_device = { "PS/2 Keyboard (IBM PS/1)", 0, - KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1, + KBC_TYPE_PS2_1 | KBC_VEN_IBM_PS1, kbd_init, kbd_close, kbd_reset, @@ -2465,7 +3139,7 @@ const device_t keyboard_ps2_ps1_device = { const device_t keyboard_ps2_ps1_pci_device = { "PS/2 Keyboard (IBM PS/1)", DEVICE_PCI, - KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1, + KBC_TYPE_PS2_1 | KBC_VEN_IBM_PS1, kbd_init, kbd_close, kbd_reset, @@ -2485,7 +3159,7 @@ const device_t keyboard_ps2_xi8088_device = { const device_t keyboard_ps2_ami_device = { "PS/2 Keyboard (AMI)", 0, - KBC_TYPE_PS2_NOREF | KBC_VEN_AMI, + KBC_TYPE_PS2_1 | KBC_VEN_AMI, kbd_init, kbd_close, kbd_reset, @@ -2495,7 +3169,7 @@ const device_t keyboard_ps2_ami_device = { const device_t keyboard_ps2_olivetti_device = { "PS/2 Keyboard (Olivetti)", 0, - KBC_TYPE_PS2_NOREF | KBC_VEN_OLIVETTI, + KBC_TYPE_PS2_1 | KBC_VEN_OLIVETTI, kbd_init, kbd_close, kbd_reset, @@ -2525,7 +3199,7 @@ const device_t keyboard_ps2_mca_2_device = { const device_t keyboard_ps2_quadtel_device = { "PS/2 Keyboard (Quadtel/MegaPC)", 0, - KBC_TYPE_PS2_NOREF | KBC_VEN_QUADTEL, + KBC_TYPE_PS2_1 | KBC_VEN_QUADTEL, kbd_init, kbd_close, kbd_reset, @@ -2535,7 +3209,7 @@ const device_t keyboard_ps2_quadtel_device = { const device_t keyboard_ps2_pci_device = { "PS/2 Keyboard", DEVICE_PCI, - KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC, + KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, kbd_init, kbd_close, kbd_reset, @@ -2545,7 +3219,7 @@ const device_t keyboard_ps2_pci_device = { const device_t keyboard_ps2_ami_pci_device = { "PS/2 Keyboard (AMI)", DEVICE_PCI, - KBC_TYPE_PS2_NOREF | KBC_VEN_AMI, + KBC_TYPE_PS2_1 | KBC_VEN_AMI, kbd_init, kbd_close, kbd_reset, @@ -2555,7 +3229,7 @@ const device_t keyboard_ps2_ami_pci_device = { const device_t keyboard_ps2_intel_ami_pci_device = { "PS/2 Keyboard (AMI)", DEVICE_PCI, - KBC_TYPE_PS2_NOREF | KBC_VEN_INTEL_AMI, + KBC_TYPE_PS2_1 | KBC_VEN_INTEL_AMI, kbd_init, kbd_close, kbd_reset, @@ -2565,7 +3239,7 @@ const device_t keyboard_ps2_intel_ami_pci_device = { const device_t keyboard_ps2_acer_pci_device = { "PS/2 Keyboard (Acer 90M002A)", DEVICE_PCI, - KBC_TYPE_PS2_NOREF | KBC_VEN_ACER, + KBC_TYPE_PS2_1 | KBC_VEN_ACER, kbd_init, kbd_close, kbd_reset, @@ -2576,17 +3250,8 @@ const device_t keyboard_ps2_acer_pci_device = { void keyboard_at_set_mouse(void (*func)(uint8_t val, void *priv), void *priv) { - mouse_write = func; - mouse_p = priv; -} - - -void -keyboard_at_adddata_keyboard_raw(uint8_t val) -{ - atkbd_t *dev = SavedKbd; - - add_data_kbd_queue(dev, 0, val); + // mouse_write = func; + // mouse_p = priv; } @@ -2599,10 +3264,30 @@ keyboard_at_adddata_mouse(uint8_t val) } +void +keyboard_at_adddata_mouse_direct(uint8_t val) +{ + // atkbd_t *dev = SavedKbd; + + return; +} + + +void +keyboard_at_adddata_mouse_cmd(uint8_t val) +{ + // atkbd_t *dev = SavedKbd; + + return; +} + + void keyboard_at_mouse_reset(void) { - kbc_queue_reset(2); + // atkbd_t *dev = SavedKbd; + + return; } @@ -2613,13 +3298,22 @@ keyboard_at_mouse_pos(void) } +int +keyboard_at_fixed_channel(void) +{ + // atkbd_t *dev = SavedKbd; + + return 0x000; +} + + void keyboard_at_set_mouse_scan(uint8_t val) { atkbd_t *dev = SavedKbd; uint8_t temp_mouse_scan = val ? 1 : 0; - if (temp_mouse_scan == !(dev->mem[0] & 0x20)) + if (temp_mouse_scan == !(dev->mem[0x20] & 0x20)) return; set_enable_mouse(dev, val ? 1 : 0); @@ -2633,7 +3327,7 @@ keyboard_at_get_mouse_scan(void) { atkbd_t *dev = SavedKbd; - return((dev->mem[0] & 0x20) ? 0x00 : 0x10); + return((dev->mem[0x20] & 0x20) ? 0x00 : 0x10); } @@ -2642,5 +3336,17 @@ keyboard_at_set_a20_key(int state) { atkbd_t *dev = SavedKbd; - write_output(dev, (dev->output_port & 0xfd) | ((!!state) << 1)); + write_output(dev, (dev->p2 & 0xfd) | ((!!state) << 1)); +} + + +void +keyboard_at_set_mode(int ps2) +{ + atkbd_t *dev = SavedKbd; + + if (ps2) + dev->flags |= KBC_FLAG_PS2; + else + dev->flags &= ~KBC_FLAG_PS2; } diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index e68718c68..96a27de42 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -591,20 +591,18 @@ kbd_read(uint16_t port, void *priv) case 0x62: if (kbd->type == 0) ret = 0x00; - else if (kbd->type == 1) { + else if (kbd->type == 1) { if (kbd->pb & 0x04) - ret = ((mem_size-64) / 32) & 0x0f; + ret = ((mem_size - 64) / 32) & 0x0f; else - ret = ((mem_size-64) / 32) >> 4; - } - else if (kbd->type == 8 || kbd->type == 9) { - /* Olivetti M19 or Zenith Data Systems Z-151 */ - if (kbd->pb & 0x04) + ret = ((mem_size - 64) / 32) >> 4; + } else if (kbd->type == 8 || kbd->type == 9) { + /* Olivetti M19 or Zenith Data Systems Z-151 */ + if (kbd->pb & 0x04) ret = kbd->pd & 0xbf; - else - ret = kbd->pd >> 4; - } - else { + else + ret = kbd->pd >> 4; + } else { if (kbd->pb & 0x08) ret = kbd->pd >> 4; else { @@ -632,7 +630,6 @@ kbd_read(uint16_t port, void *priv) case 0x63: if ((kbd->type == 2) || (kbd->type == 3) || (kbd->type == 4) || (kbd->type == 6)) ret = kbd->pd; - break; } @@ -682,119 +679,116 @@ kbd_init(const device_t *info) video_reset(gfxcard); - if (kbd->type <= 3 || kbd-> type == 8) { - + if ((kbd->type <= 3) || (kbd->type == 4) || (kbd->type == 6)) { /* DIP switch readout: bit set = OFF, clear = ON. */ - if (kbd->type != 8) - /* Switches 7, 8 - floppy drives. */ - kbd->pd = get_fdd_switch_settings(); - else - /* Olivetti M19 - * Jumpers J1, J2 - monitor type. - * 01 - mono (high-res) - * 10 - color (low-res, disables 640x400x2 mode) - * 00 - autoswitching - */ - kbd->pd |= 0x00; - - kbd->pd |= get_videomode_switch_settings(); - - /* Switches 3, 4 - memory size. */ - // Note to Compaq/Toshiba keyboard maintainers: type 4 and 6 will never be activated in this block - // Should the top if be closed right after setting floppy drive count? - if ((kbd->type == 3) || (kbd->type == 4) || (kbd->type == 6)) { - switch (mem_size) { - case 256: - kbd->pd |= 0x00; - break; - case 512: - kbd->pd |= 0x04; - break; - case 576: - kbd->pd |= 0x08; - break; - case 640: - default: - kbd->pd |= 0x0c; - break; - } - } else if (kbd->type >= 1) { - switch (mem_size) { - case 64: - kbd->pd |= 0x00; - break; - case 128: - kbd->pd |= 0x04; - break; - case 192: - kbd->pd |= 0x08; - break; - case 256: - default: - kbd->pd |= 0x0c; - break; - } - } else { - switch (mem_size) { - case 16: - kbd->pd |= 0x00; - break; - case 32: - kbd->pd |= 0x04; - break; - case 48: - kbd->pd |= 0x08; - break; - case 64: - default: - kbd->pd |= 0x0c; - break; - } - } + if (kbd->type == 8) + /* Olivetti M19 + * Jumpers J1, J2 - monitor type. + * 01 - mono (high-res) + * 10 - color (low-res, disables 640x400x2 mode) + * 00 - autoswitching + */ + kbd->pd |= 0x00; + else + /* Switches 7, 8 - floppy drives. */ + kbd->pd = get_fdd_switch_settings(); - /* Switch 2 - 8087 FPU. */ - if (hasfpu) - kbd->pd |= 0x02; + kbd->pd |= get_videomode_switch_settings(); - /* Switch 1 - always off. */ - kbd->pd |= 0x01; + /* Switches 3, 4 - memory size. */ + if ((kbd->type == 3) || (kbd->type == 4) || (kbd->type == 6)) { + switch (mem_size) { + case 256: + kbd->pd |= 0x00; + break; + case 512: + kbd->pd |= 0x04; + break; + case 576: + kbd->pd |= 0x08; + break; + case 640: + default: + kbd->pd |= 0x0c; + break; + } + } else if (kbd->type >= 1) { + switch (mem_size) { + case 64: + kbd->pd |= 0x00; + break; + case 128: + kbd->pd |= 0x04; + break; + case 192: + kbd->pd |= 0x08; + break; + case 256: + default: + kbd->pd |= 0x0c; + break; + } + } else { + switch (mem_size) { + case 16: + kbd->pd |= 0x00; + break; + case 32: + kbd->pd |= 0x04; + break; + case 48: + kbd->pd |= 0x08; + break; + case 64: + default: + kbd->pd |= 0x0c; + break; + } + } + + /* Switch 2 - 8087 FPU. */ + if (hasfpu) + kbd->pd |= 0x02; + + /* Switch 1 - always off. */ + kbd->pd |= 0x01; } else if (kbd-> type == 9) { - /* Zenith Data Systems Z-151 - * SW2 switch settings: - * bit 7: monitor frequency - * bits 5-6: autoboot (00-11 resident monitor, 10 hdd, 01 fdd) - * bits 0-4: installed memory - */ - kbd->pd = 0x20; - switch (mem_size) { - case 128: - kbd->pd |= 0x02; - break; - case 192: - kbd->pd |= 0x04; - break; - case 256: - kbd->pd |= 0x02|0x04; - break; - case 320: - kbd->pd |= 0x08; - break; - case 384: - kbd->pd |= 0x02|0x08; - break; - case 448: - kbd->pd |= 0x04|0x08; - break; - case 512: - kbd->pd |= 0x02|0x04|0x08; - break; - case 576: - kbd->pd |= 0x10; - break; - case 640: - default: - kbd->pd |= 0x02|0x10; - break; + /* Zenith Data Systems Z-151 + * SW2 switch settings: + * bit 7: monitor frequency + * bits 5-6: autoboot (00-11 resident monitor, 10 hdd, 01 fdd) + * bits 0-4: installed memory + */ + kbd->pd = 0x20; + switch (mem_size) { + case 128: + kbd->pd |= 0x02; + break; + case 192: + kbd->pd |= 0x04; + break; + case 256: + kbd->pd |= 0x06; + break; + case 320: + kbd->pd |= 0x08; + break; + case 384: + kbd->pd |= 0x0a; + break; + case 448: + kbd->pd |= 0x0c; + break; + case 512: + kbd->pd |= 0x0e; + break; + case 576: + kbd->pd |= 0x10; + break; + case 640: + default: + kbd->pd |= 0x12; + break; } } diff --git a/src/device/mouse_ps2.c b/src/device/mouse_ps2.c index b31ffdd52..f8ba676e0 100644 --- a/src/device/mouse_ps2.c +++ b/src/device/mouse_ps2.c @@ -93,22 +93,27 @@ ps2_write(uint8_t val, void *priv) mouse_t *dev = (mouse_t *)priv; uint8_t temp; + pclog("ps2_write(%02X)\n", val); + if (dev->flags & FLAG_CTRLDAT) { dev->flags &= ~FLAG_CTRLDAT; + if (val == 0xff) + goto mouse_reset; + switch (dev->command) { case 0xe8: /* set mouse resolution */ dev->resolution = val; - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse_cmd(0xfa); break; case 0xf3: /* set sample rate */ dev->sample_rate = val; - keyboard_at_adddata_mouse(0xfa); /* Command response */ + keyboard_at_adddata_mouse_cmd(0xfa); /* Command response */ break; default: - keyboard_at_adddata_mouse(0xfc); + keyboard_at_adddata_mouse_cmd(0xfc); } } else { dev->command = val; @@ -116,21 +121,21 @@ ps2_write(uint8_t val, void *priv) switch (dev->command) { case 0xe6: /* set scaling to 1:1 */ dev->flags &= ~FLAG_SCALED; - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse_cmd(0xfa); break; case 0xe7: /* set scaling to 2:1 */ dev->flags |= FLAG_SCALED; - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse_cmd(0xfa); break; case 0xe8: /* set mouse resolution */ dev->flags |= FLAG_CTRLDAT; - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse_cmd(0xfa); break; case 0xe9: /* status request */ - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse_cmd(0xfa); temp = (dev->flags & 0x30); if (mouse_buttons & 0x01) temp |= 0x01; @@ -138,13 +143,13 @@ ps2_write(uint8_t val, void *priv) temp |= 0x02; if (mouse_buttons & 0x04) temp |= 0x03; - keyboard_at_adddata_mouse(temp); - keyboard_at_adddata_mouse(dev->resolution); - keyboard_at_adddata_mouse(dev->sample_rate); + keyboard_at_adddata_mouse_cmd(temp); + keyboard_at_adddata_mouse_cmd(dev->resolution); + keyboard_at_adddata_mouse_cmd(dev->sample_rate); break; case 0xeb: /* Get mouse data */ - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse_cmd(0xfa); temp = 0; if (dev->x < 0) @@ -157,50 +162,51 @@ ps2_write(uint8_t val, void *priv) temp |= 2; if ((mouse_buttons & 4) && (dev->flags & FLAG_INTELLI)) temp |= 4; - keyboard_at_adddata_mouse(temp); - keyboard_at_adddata_mouse(dev->x & 0xff); - keyboard_at_adddata_mouse(dev->y & 0xff); + keyboard_at_adddata_mouse_cmd(temp); + keyboard_at_adddata_mouse_cmd(dev->x & 0xff); + keyboard_at_adddata_mouse_cmd(dev->y & 0xff); if (dev->flags & FLAG_INTMODE) - keyboard_at_adddata_mouse(dev->z); + keyboard_at_adddata_mouse_cmd(dev->z); break; case 0xf2: /* read ID */ - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse_cmd(0xfa); if (dev->flags & FLAG_INTMODE) - keyboard_at_adddata_mouse(0x03); + keyboard_at_adddata_mouse_cmd(0x03); else - keyboard_at_adddata_mouse(0x00); + keyboard_at_adddata_mouse_cmd(0x00); break; case 0xf3: /* set command mode */ dev->flags |= FLAG_CTRLDAT; - keyboard_at_adddata_mouse(0xfa); /* ACK for command byte */ + keyboard_at_adddata_mouse_cmd(0xfa); /* ACK for command byte */ break; case 0xf4: /* enable */ dev->flags |= FLAG_ENABLED; mouse_scan = 1; - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse_cmd(0xfa); break; case 0xf5: /* disable */ dev->flags &= ~FLAG_ENABLED; mouse_scan = 0; - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse_cmd(0xfa); break; case 0xff: /* reset */ +mouse_reset: dev->mode = MODE_STREAM; dev->flags &= 0x88; - mouse_scan = 0; + mouse_scan = 1; keyboard_at_mouse_reset(); - keyboard_at_adddata_mouse(0xfa); - keyboard_at_adddata_mouse(0xaa); - keyboard_at_adddata_mouse(0x00); + keyboard_at_adddata_mouse_cmd(0xfa); + keyboard_at_adddata_mouse_cmd(0xaa); + keyboard_at_adddata_mouse_cmd(0x00); break; default: - keyboard_at_adddata_mouse(0xfe); + keyboard_at_adddata_mouse_cmd(0xfe); } } @@ -232,6 +238,9 @@ ps2_poll(int x, int y, int z, int b, void *priv) return(0xff); #endif + if ((keyboard_at_fixed_channel() & 0xf00) == 0x200) + return(0xff); + if (!mouse_scan) return(0xff); diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 6953bda83..611ac2978 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -916,13 +916,14 @@ ide_atapi_attach(ide_t *ide) void ide_set_callback(ide_t *ide, double callback) { - ide_log("ide_set_callback(%i)\n", ide->channel); if (!ide) { - ide_log("Set callback failed\n"); + ide_log("ide_set_callback(NULL): Set callback failed\n"); return; } + ide_log("ide_set_callback(%i)\n", ide->channel); + if (callback == 0.0) timer_stop(&ide->timer); else @@ -2500,6 +2501,60 @@ id_not_found: } +uint8_t +ide_read_ali_75(void) +{ + ide_t *ide0, *ide1; + int ch0, ch1; + uint8_t ret = 0x00; + + ch0 = ide_boards[0]->cur_dev; + ch1 = ide_boards[1]->cur_dev; + ide0 = ide_drives[ch0]; + ide1 = ide_drives[ch1]; + + if (ch1) + ret |= 0x08; + if (ch0) + ret |= 0x04; + if (ide1->irqstat) + ret |= 0x02; + if (ide0->irqstat) + ret |= 0x01; + + return ret; +} + + +uint8_t +ide_read_ali_76(void) +{ + ide_t *ide0, *ide1; + int ch0, ch1; + uint8_t ret = 0x00; + + ch0 = ide_boards[0]->cur_dev; + ch1 = ide_boards[1]->cur_dev; + ide0 = ide_drives[ch0]; + ide1 = ide_drives[ch1]; + + if (ide1->atastat & BSY_STAT) + ret |= 0x40; + if (ide1->atastat & DRQ_STAT) + ret |= 0x20; + if (ide1->atastat & ERR_STAT) + ret |= 0x10; + if (ide0->atastat & BSY_STAT) + ret |= 0x04; + if (ide0->atastat & DRQ_STAT) + ret |= 0x02; + if (ide0->atastat & ERR_STAT) + ret |= 0x01; + + return ret; +} + + static void ide_set_handlers(uint8_t board) { diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index 97a77388c..023883720 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -370,30 +370,49 @@ void sff_bus_master_set_irq(int channel, void *priv) { sff8038i_t *dev = (sff8038i_t *) priv; - dev->status &= ~4; + dev->status &= ~0x04; dev->status |= (channel >> 4); channel &= 0x01; - if (dev->status & 0x04) { - sff_log("SFF8038i: Channel %i IRQ raise\n", channel); - if (dev->irq_mode[channel] == 3) - picintlevel(1 << dev->irq_line); - else if ((dev->irq_mode[channel] == 2) && channel && pci_use_mirq(0)) - pci_set_mirq(0, 0); - else if (dev->irq_mode[channel] == 1) - pci_set_irq(dev->slot, dev->irq_pin); - else - picint(1 << (14 + channel)); - } else { - sff_log("SFF8038i: Channel %i IRQ lower\n", channel); - if (dev->irq_mode[channel] == 3) - picintc(1 << dev->irq_line); - else if ((dev->irq_mode[channel] == 2) && channel && pci_use_mirq(0)) - pci_clear_mirq(0, 0); - else if (dev->irq_mode[channel] == 1) - pci_clear_irq(dev->slot, dev->irq_pin); - else - picintc(1 << (14 + channel)); + + switch (dev->irq_mode[channel]) { + case 0: + default: + /* Legacy IRQ mode. */ + if (dev->status & 0x04) + picint(1 << (14 + channel)); + else + picintc(1 << (14 + channel)); + break; + case 1: + /* Native PCI IRQ mode with interrupt pin. */ + if (dev->status & 0x04) + pci_set_irq(dev->slot, dev->irq_pin); + else + pci_clear_irq(dev->slot, dev->irq_pin); + break; + case 2: + case 5: + /* MIRQ 0 or 1. */ + if (dev->status & 0x04) + pci_set_mirq(dev->irq_mode[channel] & 1, 0); + else + pci_clear_mirq(dev->irq_mode[channel] & 1, 0); + break; + case 3: + /* Native PCI IRQ mode with specified interrupt line. */ + if (dev->status & 0x04) + picintlevel(1 << dev->irq_line); + else + picintc(1 << dev->irq_line); + break; + case 4: + /* ALi Aladdin Native PCI INTAJ mode. */ + if (dev->status & 0x04) + pci_set_mirq(channel + 2, dev->irq_level[channel]); + else + pci_clear_mirq(channel + 2, dev->irq_level[channel]); + break; } } @@ -466,10 +485,42 @@ sff_set_irq_line(sff8038i_t *dev, int irq_line) } +void +sff_set_irq_level(sff8038i_t *dev, int channel, int irq_level) +{ + dev->irq_level[channel] = 0; +} + + void sff_set_irq_mode(sff8038i_t *dev, int channel, int irq_mode) { dev->irq_mode[channel] = irq_mode; + + switch (dev->irq_mode[channel]) { + case 0: + default: + /* Legacy IRQ mode. */ + sff_log("[%08X] Setting channel %i to legacy IRQ %i\n", dev, channel, 14 + channel); + break; + case 1: + /* Native PCI IRQ mode with interrupt pin. */ + sff_log("[%08X] Setting channel %i to native PCI INT%c\n", dev, channel, '@' + dev->irq_pin); + break; + case 2: + case 5: + /* MIRQ 0 or 1. */ + sff_log("[%08X] Setting channel %i to PCI MIRQ%i\n", dev, channel, irq_mode & 1); + break; + case 3: + /* Native PCI IRQ mode with specified interrupt line. */ + sff_log("[%08X] Setting channel %i to native PCI IRQ %i\n", dev, channel, dev->irq_line); + break; + case 4: + /* ALi Aladdin Native PCI INTAJ mode. */ + sff_log("[%08X] Setting channel %i to INT%cJ\n", dev, channel, 'A' + channel); + break; + } } @@ -506,9 +557,11 @@ static void ide_set_bus_master(next_id, sff_bus_master_dma, sff_bus_master_set_irq, dev); dev->slot = 7; - dev->irq_mode[0] = dev->irq_mode[1] = 2; + dev->irq_mode[0] = 0; /* Channel 0 goes to IRQ 14. */ + dev->irq_mode[1] = 2; /* Channel 1 goes to MIRQ0. */ dev->irq_pin = PCI_INTA; dev->irq_line = 14; + dev->irq_level[0] = dev->irq_level[1] = 0; next_id++; diff --git a/src/dma.c b/src/dma.c index 54e97f9e6..aa91ad988 100644 --- a/src/dma.c +++ b/src/dma.c @@ -166,6 +166,28 @@ dma_block_transfer(int channel) } +static void +dma_mem_to_mem_transfer(void) +{ + int i; + + if ((dma[0].mode & 0x0c) != 0x08) + fatal("DMA memory to memory transfer: channel 0 mode not read\n"); + if ((dma[1].mode & 0x0c) != 0x04) + fatal("DMA memory to memory transfer: channel 1 mode not write\n"); + + dma_req_is_soft = 1; + + for (i = 0; i <= dma[0].cb; i++) + dma_buffer[i] = dma_channel_read(0); + + for (i = 0; i <= dma[1].cb; i++) + dma_channel_write(1, dma_buffer[i]); + + dma_req_is_soft = 0; +} + + static void dma_sg_write(uint16_t port, uint8_t val, void *priv) { @@ -506,14 +528,18 @@ dma_write(uint16_t addr, uint8_t val, void *priv) case 8: /*Control register*/ dma_command[0] = val; if (val & 0x01) - fatal("Memory-to-memory enable\n"); + pclog("[%08X:%04X] Memory-to-memory enable\n", CS, cpu_state.pc); return; case 9: /*Request register */ channel = (val & 3); if (val & 4) { dma_stat_rq_pc |= (1 << channel); - dma_block_transfer(channel); + if ((channel == 0) && (dma_command[0] & 0x01)) { + pclog("Memory to memory transfer start\n"); + dma_mem_to_mem_transfer(); + } else + dma_block_transfer(channel); } else dma_stat_rq_pc &= ~(1 << channel); break; diff --git a/src/include/86box/acpi.h b/src/include/86box/acpi.h index 08019d352..bcaf89610 100644 --- a/src/include/86box/acpi.h +++ b/src/include/86box/acpi.h @@ -54,7 +54,7 @@ typedef struct { uint8_t acpitst, auxen, auxsts, plvl2, plvl3, smicmd, gpio_dir, - gpio_val, muxcntrl, pad, + gpio_val, muxcntrl, ali_soft_smi, timer32, smireg, gpireg[3], gporeg[4]; uint16_t pmsts, pmen, @@ -83,7 +83,8 @@ typedef struct uint16_t io_base, aux_io_base; int vendor, slot, irq_mode, - irq_pin, irq_line; + irq_pin, irq_line, + mirq_is_level; pc_timer_t timer; nvr_t *nvr; apm_t *apm; @@ -111,8 +112,11 @@ extern void acpi_set_slot(acpi_t *dev, int slot); extern void acpi_set_irq_mode(acpi_t *dev, int irq_mode); extern void acpi_set_irq_pin(acpi_t *dev, int irq_pin); extern void acpi_set_irq_line(acpi_t *dev, int irq_line); +extern void acpi_set_mirq_is_level(acpi_t *dev, int mirq_is_level); extern void acpi_set_gpireg2_default(acpi_t *dev, uint8_t gpireg2_default); extern void acpi_set_nvr(acpi_t *dev, nvr_t *nvr); +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); #ifdef __cplusplus } diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index 2cc8078b1..b0a3cb71f 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -25,10 +25,8 @@ extern const device_t acc2168_device; extern const device_t ali1217_device; extern const device_t ali1429_device; extern const device_t ali1489_device; -#if defined(DEV_BRANCH) && defined(USE_M154X) extern const device_t ali1531_device; extern const device_t ali1543_device; -#endif #if defined(DEV_BRANCH) && defined(USE_M6117) extern const device_t ali6117d_device; #endif @@ -44,9 +42,6 @@ extern const device_t scat_sx_device; extern const device_t cs8230_device; extern const device_t cs4031_device; -/* ETEQ */ -extern const device_t et6000_device; - /* G2 */ extern const device_t gc100_device; extern const device_t gc100a_device; @@ -60,6 +55,7 @@ extern const device_t headland_ht18c_device; /* Intel */ extern const device_t intel_82335_device; extern const device_t i420ex_device; +extern const device_t i420ex_ide_device; extern const device_t i420tx_device; extern const device_t i420zx_device; extern const device_t i430lx_device; @@ -114,7 +110,6 @@ extern const device_t sis_85c496_ls486e_device; extern const device_t sis_85c50x_device; extern const device_t sis_5511_device; extern const device_t sis_5571_device; -extern const device_t sis_5598_device; /* ST */ extern const device_t stpc_client_device; @@ -124,13 +119,6 @@ extern const device_t stpc_atlas_device; extern const device_t stpc_serial_device; extern const device_t stpc_lpt_device; -/* UMC */ -extern const device_t umc_hb4_device; -extern const device_t umc_8890_device; - -extern const device_t umc_8886f_device; -extern const device_t umc_8886af_device; - /* VIA */ extern const device_t via_vt82c49x_device; extern const device_t via_vt82c49x_pci_device; @@ -151,6 +139,7 @@ extern const device_t via_vt82c686b_device; /* VLSI */ extern const device_t vl82c480_device; +extern const device_t vl82c486_device; extern const device_t vlsi_scamp_device; /* WD */ diff --git a/src/include/86box/hdc_ide.h b/src/include/86box/hdc_ide.h index 48b7c8939..c6a7a49f0 100644 --- a/src/include/86box/hdc_ide.h +++ b/src/include/86box/hdc_ide.h @@ -150,5 +150,8 @@ extern int (*ide_bus_master_dma)(int channel, uint8_t *data, int transfer_length extern void (*ide_bus_master_set_irq)(int channel, void *priv); extern void *ide_bus_master_priv[2]; +extern uint8_t ide_read_ali_75(void); +extern uint8_t ide_read_ali_76(void); + #endif /*EMU_IDE_H*/ diff --git a/src/include/86box/hdc_ide_sff8038i.h b/src/include/86box/hdc_ide_sff8038i.h index 43288aa99..305d2d40c 100644 --- a/src/include/86box/hdc_ide_sff8038i.h +++ b/src/include/86box/hdc_ide_sff8038i.h @@ -25,8 +25,8 @@ typedef struct addr; int count, eot, slot, - irq_mode[2], irq_pin, - irq_line; + irq_mode[2], irq_level[2], + irq_pin, irq_line; } sff8038i_t; @@ -47,3 +47,5 @@ extern void sff_set_irq_line(sff8038i_t *dev, int irq_line); extern void sff_set_irq_mode(sff8038i_t *dev, int channel, 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 channel, int irq_level); diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index 3ca6089cc..206feeefc 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -72,14 +72,12 @@ extern const device_t keyboard_xt_olivetti_device; extern const device_t keyboard_xt_zenith_device; extern const device_t keyboard_at_device; extern const device_t keyboard_at_ami_device; -extern const device_t keyboard_at_samsung_device; extern const device_t keyboard_at_toshiba_device; extern const device_t keyboard_at_olivetti_device; extern const device_t keyboard_at_ncr_device; extern const device_t keyboard_ps2_device; extern const device_t keyboard_ps2_ps1_device; extern const device_t keyboard_ps2_ps1_pci_device; -extern const device_t keyboard_ps2_ps2_device; extern const device_t keyboard_ps2_xi8088_device; extern const device_t keyboard_ps2_ami_device; extern const device_t keyboard_ps2_olivetti_device; @@ -108,12 +106,15 @@ extern int keyboard_isfsexit(void); extern int keyboard_ismsexit(void); extern void keyboard_set_is_amstrad(int ams); -extern void keyboard_at_adddata_keyboard_raw(uint8_t val); extern void keyboard_at_adddata_mouse(uint8_t val); +extern void keyboard_at_adddata_mouse_direct(uint8_t val); +extern void keyboard_at_adddata_mouse_cmd(uint8_t val); extern void keyboard_at_mouse_reset(void); extern uint8_t keyboard_at_mouse_pos(void); +extern int keyboard_at_fixed_channel(void); extern void keyboard_at_set_mouse(void (*mouse_write)(uint8_t val,void *), void *); extern void keyboard_at_set_a20_key(int state); +extern void keyboard_at_set_mode(int ps2); extern uint8_t keyboard_at_get_mouse_scan(void); extern void keyboard_at_set_mouse_scan(uint8_t val); extern void keyboard_at_reset(void); diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index f40745a05..c63a3b991 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -96,9 +96,11 @@ enum { MACHINE_TYPE_8086, MACHINE_TYPE_286, MACHINE_TYPE_386SX, + MACHINE_TYPE_486SLC, MACHINE_TYPE_386DX, MACHINE_TYPE_386DX_486, MACHINE_TYPE_486, + MACHINE_TYPE_486_S2, MACHINE_TYPE_486_S3, MACHINE_TYPE_486_MISC, MACHINE_TYPE_SOCKET4, @@ -250,6 +252,8 @@ extern int machine_at_mr286_init(const machine_t *); extern int machine_at_neat_init(const machine_t *); extern int machine_at_neat_ami_init(const machine_t *); +extern int machine_at_quadt386sx_init(const machine_t *); + extern int machine_at_award286_init(const machine_t *); extern int machine_at_gdc212m_init(const machine_t *); extern int machine_at_gw286ct_init(const machine_t *); @@ -283,16 +287,12 @@ extern int machine_at_pja511m_init(const machine_t *); extern int machine_at_pc916sx_init(const machine_t *); -extern int machine_at_m30008_init(const machine_t *); -extern int machine_at_m30015_init(const machine_t *); - #ifdef EMU_DEVICE_H extern const device_t *at_ama932j_get_device(void); extern const device_t *at_flytech386_get_device(void); extern const device_t *at_cmdsl386sx25_get_device(void); extern const device_t *at_spc4620p_get_device(void); extern const device_t *at_spc6033p_get_device(void); -extern const device_t *at_m30008_get_device(void); #endif /* m_at_386dx_486.c */ @@ -310,6 +310,8 @@ extern int machine_at_cs4031_init(const machine_t *); extern int machine_at_pb410a_init(const machine_t *); +extern int machine_at_acerv10_init(const machine_t *); + extern int machine_at_acera1g_init(const machine_t *); extern int machine_at_ali1429_init(const machine_t *); extern int machine_at_winbios1429_init(const machine_t *); @@ -321,9 +323,9 @@ extern int machine_at_opti495_mr_init(const machine_t *); extern int machine_at_vect486vl_init(const machine_t *); extern int machine_at_d824_init(const machine_t *); -extern int machine_at_pcs46c_init(const machine_t *); - extern int machine_at_403tg_init(const machine_t *); +extern int machine_at_403tg_rev_d_init(const machine_t *); +extern int machine_at_403tg_rev_d_mr_init(const machine_t *); extern int machine_at_pc330_6573_init(const machine_t *); extern int machine_at_mvi486_init(const machine_t *); @@ -345,18 +347,16 @@ extern int machine_at_4dps_init(const machine_t *); extern int machine_at_4sa2_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_ninja_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 *); extern int machine_at_486ap4_init(const machine_t *); +extern int machine_at_g486vpa_init(const machine_t *); extern int machine_at_486vipio2_init(const machine_t *); extern int machine_at_abpb4_init(const machine_t *); extern int machine_at_win486pci_init(const machine_t *); -extern int machine_at_atc1415_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_itoxstar_init(const machine_t *); extern int machine_at_arb1479_init(const machine_t *); extern int machine_at_pcm9340_init(const machine_t *); @@ -381,113 +381,122 @@ extern int machine_at_portableiii386_init(const machine_t *); extern const device_t *at_cpqiii_get_device(void); #endif -/* m_at_socket4_5.c */ -extern int machine_at_excalibur_init(const machine_t *); +/* m_at_socket4.c */ +extern void machine_at_premiere_common_init(const machine_t *, int); +extern void machine_at_award_common_init(const machine_t *); -extern int machine_at_pat54pv_init(const machine_t *); +extern void machine_at_sp4_common_init(const machine_t *model); -extern int machine_at_hot543_init(const machine_t *); -extern int machine_at_p54vl_init(const machine_t *); - -extern int machine_at_batman_init(const machine_t *); -extern int machine_at_ambradp60_init(const machine_t *); +extern int machine_at_p5mp3_init(const machine_t *); extern int machine_at_dellxp60_init(const machine_t *); 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_p5mp3_init(const machine_t *); -extern int machine_at_pb520r_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_pb520r_init(const machine_t *); +extern int machine_at_excalibur_init(const machine_t *); + +extern int machine_at_p5vl_init(const machine_t *); + +extern int machine_at_p5sp4_init(const machine_t *); + +#ifdef EMU_DEVICE_H +extern const device_t *at_pb520r_get_device(void); +#endif + +/* m_at_socket5.c */ extern int machine_at_plato_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_p54tp4xe_init(const machine_t *); -extern int machine_at_endeavor_init(const machine_t *); -extern int machine_at_zappa_init(const machine_t *); -extern int machine_at_mb500n_init(const machine_t *); -extern int machine_at_apollo_init(const machine_t *); -extern int machine_at_vectra54_init(const machine_t *); -extern int machine_at_powermatev_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_exp8551_init(const machine_t *); +extern int machine_at_vectra54_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_mb500n_init(const machine_t *); +extern int machine_at_hawk_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_p5sp4_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_hot539_init(const machine_t *); +#ifdef EMU_DEVICE_H +#define at_vectra54_get_device at_endeavor_get_device +#endif + +/* m_at_socket7_3v.c */ +extern int machine_at_p54tp4xe_init(const machine_t *); +extern int machine_at_mr586_init(const machine_t *); +extern int machine_at_gw2katx_init(const machine_t *); +extern int machine_at_thor_init(const machine_t *); +extern int machine_at_mrthor_init(const machine_t *); +extern int machine_at_endeavor_init(const machine_t *); +extern int machine_at_ms5119_init(const machine_t *); +extern int machine_at_pb640_init(const machine_t *); +extern int machine_at_fmb_init(const machine_t *); + +extern int machine_at_acerm3a_init(const machine_t *); +extern int machine_at_ap53_init(const machine_t *); +extern int machine_at_8500tuc_init(const machine_t *); +extern int machine_at_p55t2s_init(const machine_t *); + +extern int machine_at_gw2kte_init(const machine_t *); + +extern int machine_at_ap5s_init(const machine_t *); #ifdef EMU_DEVICE_H extern const device_t *at_endeavor_get_device(void); -#define at_vectra54_get_device at_endeavor_get_device -extern const device_t *at_pb520r_get_device(void); extern const device_t *at_thor_get_device(void); +extern const device_t *at_pb640_get_device(void); #endif -/* m_at_socket7_s7.c */ -extern int machine_at_ap5s_init(const machine_t *); - -extern int machine_at_chariot_init(const machine_t *); -extern int machine_at_mr586_init(const machine_t *); -extern int machine_at_thor_init(const machine_t *); -extern int machine_at_gw2katx_init(const machine_t *); -extern int machine_at_mrthor_init(const machine_t *); -extern int machine_at_pb640_init(const machine_t *); - -extern int machine_at_acerm3a_init(const machine_t *); +/* m_at_socket7.c */ extern int machine_at_acerv35n_init(const machine_t *); -extern int machine_at_ap53_init(const machine_t *); extern int machine_at_p55t2p4_init(const machine_t *); -extern int machine_at_p55t2s_init(const machine_t *); -extern int machine_at_8500tuc_init(const machine_t *); extern int machine_at_m7shi_init(const machine_t *); extern int machine_at_tc430hx_init(const machine_t *); extern int machine_at_equium5200_init(const machine_t *); extern int machine_at_pcv240_init(const machine_t *); extern int machine_at_p65up5_cp55t2d_init(const machine_t *); -extern int machine_at_mb520n_init(const machine_t *); extern int machine_at_p55tvp4_init(const machine_t *); -extern int machine_at_p55va_init(const machine_t *); -extern int machine_at_i430vx_init(const machine_t *); extern int machine_at_5ivg_init(const machine_t *); -extern int machine_at_brio80xx_init(const machine_t *); extern int machine_at_8500tvxa_init(const machine_t *); extern int machine_at_presario2240_init(const machine_t *); extern int machine_at_presario4500_init(const machine_t *); -extern int machine_at_gw2kte_init(const machine_t *); +extern int machine_at_p55va_init(const machine_t *); +extern int machine_at_brio80xx_init(const machine_t *); extern int machine_at_pb680_init(const machine_t *); +extern int machine_at_mb520n_init(const machine_t *); +extern int machine_at_i430vx_init(const machine_t *); extern int machine_at_nupro592_init(const machine_t *); extern int machine_at_tx97_init(const machine_t *); -extern int machine_at_ym430tx_init(const machine_t *); #if defined(DEV_BRANCH) && defined(NO_SIO) extern int machine_at_an430tx_init(const machine_t *); #endif +extern int machine_at_ym430tx_init(const machine_t *); extern int machine_at_mb540n_init(const machine_t *); extern int machine_at_p5mms98_init(const machine_t *); -extern int machine_at_r534f_init(const machine_t *); -extern int machine_at_ms5146_init(const machine_t *); - -#if defined(DEV_BRANCH) && defined(USE_M154X) -extern int machine_at_m560_init(const machine_t *); -extern int machine_at_ms5164_init(const machine_t *); -#endif - extern int machine_at_ficva502_init(const machine_t *); extern int machine_at_ficpa2012_init(const machine_t *); -extern int machine_at_sp97xv_init(const machine_t *); -extern int machine_at_m571_init(const machine_t *); +extern int machine_at_r534f_init(const machine_t *); +extern int machine_at_ms5146_init(const machine_t *); -#ifdef EMU_DEVICE_H -extern const device_t *at_thor_get_device(void); -extern const device_t *at_pb640_get_device(void); -#endif +extern int machine_at_m560_init(const machine_t *); +extern int machine_at_ms5164_init(const machine_t *); -/* m_at_super7_ss7.c */ +/* m_at_sockets7.c */ extern int machine_at_ax59pro_init(const machine_t *); extern int machine_at_mvp3_init(const machine_t *); extern int machine_at_ficva503a_init(const machine_t *); @@ -526,9 +535,6 @@ extern int machine_at_atc6310bxii_init(const machine_t *); extern int machine_at_686bx_init(const machine_t *); extern int machine_at_tsunamiatx_init(const machine_t *); extern int machine_at_p6sba_init(const machine_t *); -#if defined(DEV_BRANCH) && defined(NO_SIO) -extern int machine_at_ergox365_init(const machine_t *); -#endif extern int machine_at_ficka6130_init(const machine_t *); extern int machine_at_p3v133_init(const machine_t *); extern int machine_at_p3v4x_init(const machine_t *); @@ -560,7 +566,6 @@ extern int machine_at_apas3_init(const machine_t *); extern int machine_at_wcf681_init(const machine_t *); extern int machine_at_cuv4xls_init(const machine_t *); extern int machine_at_6via90ap_init(const machine_t *); -extern int machine_at_603tcf_init(const machine_t *); extern int machine_at_trinity371_init(const machine_t *); extern int machine_at_p6bap_init(const machine_t *); @@ -649,10 +654,6 @@ extern int machine_xt_pc700_init(const machine_t *); extern int machine_xt_iskra3104_init(const machine_t *); -#if defined(DEV_BRANCH) && defined(USE_HEDAKA) -extern int machine_xt_hed919_init(const machine_t *); -#endif - /* m_xt_compaq.c */ extern int machine_xt_compaq_deskpro_init(const machine_t *); extern int machine_xt_compaq_portable_init(const machine_t *); diff --git a/src/include/86box/pci.h b/src/include/86box/pci.h index 210ff1d4e..8e28fbbdf 100644 --- a/src/include/86box/pci.h +++ b/src/include/86box/pci.h @@ -45,6 +45,10 @@ #define PCI_MIRQ1 1 #define PCI_MIRQ2 2 #define PCI_MIRQ3 3 +#define PCI_MIRQ4 4 +#define PCI_MIRQ5 5 +#define PCI_MIRQ6 6 +#define PCI_MIRQ7 7 #define PCI_IRQ_DISABLED -1 diff --git a/src/include/86box/pic.h b/src/include/86box/pic.h index 50ed0914e..139aa5195 100644 --- a/src/include/86box/pic.h +++ b/src/include/86box/pic.h @@ -33,6 +33,11 @@ typedef struct pic { extern pic_t pic, pic2; +extern void pic_reset_smi_irq_mask(void); +extern void pic_set_smi_irq_mask(int irq, int set); +extern uint16_t pic_get_smi_irq_status(void); +extern void pic_clear_smi_irq_status(int irq); + extern int pic_elcr_get_enabled(void); extern void pic_elcr_set_enabled(int enabled); extern void pic_elcr_io_handler(int set); diff --git a/src/include/86box/pit.h b/src/include/86box/pit.h index bf8d71048..93f6c594e 100644 --- a/src/include/86box/pit.h +++ b/src/include/86box/pit.h @@ -18,33 +18,34 @@ # define EMU_PIT_H -typedef struct { +typedef struct ctr_s { uint8_t m, ctrl, read_status, latch, s1_det, l_det, - bcd, pad; + bcd, flag_64k; - uint16_t rl; - - int rm, wm, gate, out, - newcount, clock, using_timer, latched, - state, null_count, do_read_status; + uint16_t l, rl; union { - int count; + uint16_t count; struct { - int units :4; - int tens :4; - int hundreds :4; - int thousands :4; - int myriads :4; + uint16_t units :4; + uint16_t tens :4; + uint16_t hundreds :4; + uint16_t thousands :4; + uint16_t myriads :4; }; }; - uint32_t l; + int rm, wm, gate, out, + newcount, clock, using_timer, latched, + state, null_count, do_read_status, do_load; + void (*tick_func)(struct ctr_s *ctr); void (*load_func)(uint8_t new_m, int new_count); void (*out_func)(int new_out, int old_out); + + struct PIT *pit; } ctr_t; diff --git a/src/include/86box/port_6x.h b/src/include/86box/port_6x.h new file mode 100644 index 000000000..74172728a --- /dev/null +++ b/src/include/86box/port_6x.h @@ -0,0 +1,38 @@ +/* + * 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 Port 6x used by various + * machines. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2021 Miran Grca. + */ +#ifndef EMU_PORT_6X_H +# define EMU_PORT_6X_H + + +#ifdef _TIMER_H_ +typedef struct +{ + uint8_t refresh, flags; + + pc_timer_t refresh_timer; +} port_6x_t; +#endif + + +extern const device_t port_6x_device; +extern const device_t port_6x_xi8088_device; +extern const device_t port_6x_ps2_device; +extern const device_t port_6x_olivetti_device; + + +#endif /*EMU_PORT_6X_H*/ diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index bf9f5526c..1786a9569 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -27,6 +27,7 @@ extern const device_t fdc37c663_ide_device; extern const device_t fdc37c665_device; extern const device_t fdc37c665_ide_device; extern const device_t fdc37c666_device; +extern const device_t fdc37c67x_device; extern const device_t fdc37c669_device; extern const device_t fdc37c669_370_device; extern const device_t fdc37c931apm_device; @@ -53,6 +54,7 @@ extern const device_t pc87311_ide_device; extern const device_t pc87332_device; extern const device_t pc87332_398_device; extern const device_t pc87332_398_ide_device; +extern const device_t pc87332_398_ide_sec_device; extern const device_t pc87332_398_ide_fdcon_device; extern const device_t pc97307_device; extern const device_t prime3b_device; diff --git a/src/include/86box/spd.h b/src/include/86box/spd.h index 53492d0e8..db283cc87 100644 --- a/src/include/86box/spd.h +++ b/src/include/86box/spd.h @@ -106,6 +106,7 @@ typedef struct { extern void spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size); extern void spd_write_drbs(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit); +extern void spd_write_drbs_interleaved(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit); #endif /*EMU_SPD_H*/ diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 73c176742..78a13b346 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -23,8 +23,9 @@ #define FLAG_EXT_WRITE 4 #define FLAG_LATCH8 8 #define FLAG_NOSKEW 16 -#define FLAG_ADDR_BY16 32 +#define FLAG_ADDR_BY16 32 +#define FLAG_128K_MASK 64 typedef struct { int ena, @@ -49,7 +50,8 @@ typedef struct svga_t lowres, interlace, linedbl, rowcount, set_reset_disabled, bpp, ramdac_type, fb_only, readmode, writemode, readplane, - hwcursor_oddeven, dac_hwcursor_oddeven, overlay_oddeven; + hwcursor_oddeven, dac_hwcursor_oddeven, overlay_oddeven, + fcr, hblank_overscan; int dac_addr, dac_pos, dac_r, dac_g, vtotal, dispend, vsyncstart, split, vblankstart, @@ -59,8 +61,9 @@ typedef struct svga_t con, cursoron, blink, scrollcache, char_width, firstline, lastline, firstline_draw, lastline_draw, displine, fullchange, x_add, y_add, pan, - vram_display_mask, vidclock, - hwcursor_on, dac_hwcursor_on, overlay_on, set_override; + vram_display_mask, vidclock, dots_per_clock, hblank_ext, + hwcursor_on, dac_hwcursor_on, overlay_on, set_override, + hblankstart, hblankend, hblank_sub, hblank_end_val, hblank_end_len; /*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 : 0MB-1MB - VRAM diff --git a/src/include/86box/vid_svga_render.h b/src/include/86box/vid_svga_render.h index 46c37f655..1bae05385 100644 --- a/src/include/86box/vid_svga_render.h +++ b/src/include/86box/vid_svga_render.h @@ -44,6 +44,8 @@ void svga_render_4bpp_lowres(svga_t *svga); void svga_render_4bpp_highres(svga_t *svga); void svga_render_8bpp_lowres(svga_t *svga); void svga_render_8bpp_highres(svga_t *svga); +void svga_render_8bpp_tseng_lowres(svga_t *svga); +void svga_render_8bpp_tseng_highres(svga_t *svga); void svga_render_8bpp_gs_lowres(svga_t *svga); void svga_render_8bpp_gs_highres(svga_t *svga); void svga_render_8bpp_rgb_lowres(svga_t *svga); diff --git a/src/include/86box/video.h b/src/include/86box/video.h index a28aecffb..d2cfec0dd 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -252,7 +252,11 @@ extern const device_t ogc_m24_device; /* NCR NGA */ extern const device_t nga_device; +/* Tseng ET3000AX */ +extern const device_t et3000_isa_device; + /* Tseng ET4000AX */ +extern const device_t et4000_tc6058af_isa_device; extern const device_t et4000_isa_device; extern const device_t et4000k_isa_device; extern const device_t et4000k_tg286_isa_device; @@ -304,7 +308,6 @@ extern const device_t oti037c_device; extern const device_t oti067_device; extern const device_t oti067_acer386_device; extern const device_t oti067_ama932j_device; -extern const device_t oti067_m300_device; extern const device_t oti077_device; /* Paradise/WD (S)VGA */ diff --git a/src/log.c b/src/log.c index a20a8d520..99bab97a5 100644 --- a/src/log.c +++ b/src/log.c @@ -43,6 +43,9 @@ typedef struct } log_t; +extern FILE *stdlog; /* file to log output to */ + + void log_set_suppr_seen(void *priv, int suppr_seen) { diff --git a/src/machine/CMakeLists.txt b/src/machine/CMakeLists.txt index 9b16413f6..f7b276ba7 100644 --- a/src/machine/CMakeLists.txt +++ b/src/machine/CMakeLists.txt @@ -19,8 +19,9 @@ add_library(mch OBJECT machine.c machine_table.c m_xt.c m_xt_compaq.c m_amstrad.c m_europc.c m_xt_olivetti.c m_tandy.c m_at.c m_at_commodore.c m_at_t3100e.c m_at_t3100e_vid.c m_ps1.c m_ps1_hdc.c m_ps2_isa.c m_ps2_mca.c m_at_compaq.c m_at_286_386sx.c m_at_386dx_486.c - m_at_socket4_5.c m_at_socket7.c m_at_sockets7.c m_at_socket8.c - m_at_slot1.c m_at_slot2.c m_at_socket370.c m_at_misc.c) + m_at_socket4.c m_at_socket5.c m_at_socket7_3v.c m_at_socket7.c + m_at_sockets7.c m_at_socket8.c m_at_slot1.c m_at_slot2.c m_at_socket370.c + m_at_misc.c) if(HEDAKA) target_compile_definitions(mch PRIVATE USE_HEDAKA) diff --git a/src/machine/m_at.c b/src/machine/m_at.c index 0e5589927..dc47b6207 100644 --- a/src/machine/m_at.c +++ b/src/machine/m_at.c @@ -56,6 +56,7 @@ #include <86box/lpt.h> #include <86box/rom.h> #include <86box/hdc.h> +#include <86box/port_6x.h> #include <86box/machine.h> @@ -69,6 +70,10 @@ machine_at_common_init_ex(const machine_t *model, int type) pic2_init(); dma16_init(); + if (!(type & 4)) + device_add(&port_6x_device); + type &= 3; + if (type == 1) device_add(&ibmat_nvr_device); else if (type == 0) diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 3d691c159..7c9bea86b 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -37,6 +37,7 @@ #include <86box/fdc.h> #include <86box/fdc_ext.h> #include <86box/hdc.h> +#include <86box/port_6x.h> #include <86box/sio.h> #include <86box/serial.h> #include <86box/video.h> @@ -141,7 +142,7 @@ machine_at_quadt286_init(const machine_t *model) return ret; machine_at_common_init(model); - device_add(&keyboard_at_device); + device_add(&keyboard_at_device); if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); @@ -152,6 +153,30 @@ machine_at_quadt286_init(const machine_t *model) } +int +machine_at_quadt386sx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved("roms/machines/quadt386sx/QTC-SXM-EVEN-U3-05-07.BIN", + "roms/machines/quadt386sx/QTC-SXM-ODD-U3-05-07.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&keyboard_at_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + device_add(&headland_gc10x_device); + + return ret; +} + + int machine_at_neat_init(const machine_t *model) { @@ -723,6 +748,7 @@ machine_at_pja511m_init(const machine_t *model) return ret; } + #endif /* @@ -750,6 +776,7 @@ machine_at_pc8_init(const machine_t *model) return ret; } + /* * Current bugs: * - ctrl-alt-del produces an 8042 error @@ -783,6 +810,7 @@ machine_at_3302_init(const machine_t *model) return ret; } + /* * Current bugs: * - soft-reboot after saving CMOS settings/pressing ctrl-alt-del produces an 8042 error @@ -810,6 +838,7 @@ machine_at_pc916sx_init(const machine_t *model) return ret; } + #if defined(DEV_BRANCH) && defined(USE_OLIVETTI) int machine_at_m290_init(const machine_t *model) @@ -822,9 +851,10 @@ machine_at_m290_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 4); device_add(&keyboard_at_olivetti_device); - + device_add(&port_6x_olivetti_device); + if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); @@ -833,58 +863,3 @@ machine_at_m290_init(const machine_t *model) return ret; } #endif - -const device_t * -at_m30008_get_device(void) -{ - return &oti067_m300_device; -} - -int -machine_at_m30008_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/m30008/BIOS.ROM", - 0x000f0000, 65536, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init(model); - - device_add(&opti283_device); - device_add(&keyboard_ps2_olivetti_device); - device_add(&pc87310_ide_device); - - if (gfxcard == VID_INTERNAL) - device_add(&oti067_m300_device); - - return ret; -} - -/* Almost identical to M300-08, save for CPU speed, VRAM, and BIOS identification string */ -int -machine_at_m30015_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/m30015/BIOS.ROM", - 0x000f0000, 65536, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init(model); - - device_add(&opti283_device); - device_add(&keyboard_ps2_olivetti_device); - device_add(&pc87310_ide_device); - - /* Stock VRAM is maxed out, so no need to expose video card config */ - if (gfxcard == VID_INTERNAL) - device_add(&oti067_m300_device); - - return ret; -} - diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index aebfa45ee..eb6efeb96 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -32,12 +32,17 @@ #include <86box/mem.h> #include <86box/nvr.h> #include <86box/pci.h> +#include <86box/dma.h> #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/fdc_ext.h> +#include <86box/gameport.h> +#include <86box/pic.h> +#include <86box/pit.h> #include <86box/rom.h> #include <86box/sio.h> #include <86box/hdc.h> +#include <86box/port_6x.h> #include <86box/video.h> #include <86box/flash.h> #include <86box/scsi_ncr53c8xx.h> @@ -229,7 +234,7 @@ machine_at_spc6000a_init(const machine_t *model) if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); - device_add(&keyboard_at_samsung_device); + device_add(&keyboard_at_ami_device); return ret; } @@ -297,7 +302,7 @@ machine_at_cs4031_init(const machine_t *model) device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } @@ -359,6 +364,7 @@ at_vect486vl_get_device(void) return &gd5428_onboard_device; } + int machine_at_d824_init(const machine_t *model) { @@ -382,39 +388,13 @@ machine_at_d824_init(const machine_t *model) return ret; } + const device_t * at_d824_get_device(void) { return &gd5428_onboard_device; } -int -machine_at_pcs46c_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/pcs46c/OLIVETTI.BIN", - 0x000e0000, 131072, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_ide_init(model); - - device_add(&et6000_device); - device_add(&keyboard_ps2_device); - - if (gfxcard == VID_INTERNAL) - device_add(&gd5428_onboard_device); - - return ret; -} - -const device_t * -at_pcs46c_get_device(void) -{ - return &gd5428_onboard_device; -} int machine_at_acera1g_init(const machine_t *model) @@ -437,7 +417,7 @@ machine_at_acera1g_init(const machine_t *model) device_add(&ide_isa_2ch_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } @@ -450,6 +430,30 @@ at_acera1g_get_device(void) } +int +machine_at_acerv10_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/acerv10/ALL.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&sis_85c461_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&ide_isa_2ch_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + + static void machine_at_ali1429_common_init(const machine_t *model) { @@ -569,6 +573,25 @@ machine_at_opti495_mr_init(const machine_t *model) return ret; } + +static void +machine_at_403tg_common_init(const machine_t *model, int nvr_hack) +{ + if (nvr_hack) { + machine_at_common_init_ex(model, 2); + device_add(&ls486e_nvr_device); + } else + machine_at_common_init(model); + + device_add(&opti895_device); + + device_add(&keyboard_at_ami_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); +} + + int machine_at_403tg_init(const machine_t *model) { @@ -580,14 +603,41 @@ machine_at_403tg_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_403tg_common_init(model, 0); - device_add(&opti895_device); + return ret; +} - device_add(&keyboard_at_device); - if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); +int +machine_at_403tg_rev_d_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/403tg_rev_d/J403TGRevD.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_403tg_common_init(model, 1); + + return ret; +} + + +int +machine_at_403tg_rev_d_mr_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/403tg_rev_d/MRBiosOPT895.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_403tg_common_init(model, 0); return ret; } @@ -685,7 +735,7 @@ machine_at_vli486sv2g_init(const machine_t *model) machine_at_sis_85c471_common_init(model); device_add(&ide_vlb_2ch_device); - device_add(&keyboard_at_device); + device_add(&keyboard_ps2_ami_device); return ret; } @@ -884,7 +934,7 @@ machine_at_4dps_init(const machine_t *model) pci_register_slot(0x07, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&w83787f_device); - device_add(&keyboard_ps2_pci_device); + device_add(&keyboard_at_ami_device); device_add(&intel_flash_bxt_device); @@ -940,10 +990,13 @@ machine_at_4sa2_init(const machine_t *model) pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); - device_add(&w83787f_device); - device_add(&keyboard_ps2_pci_device); + // device_add(&w83787f_device); + device_add(&prime3b_device); + // device_add(&keyboard_ps2_pci_device); + device_add(&keyboard_ps2_ami_pci_device); - device_add(&intel_flash_bxt_device); + // device_add(&intel_flash_bxt_device); + device_add(&sst_flash_29ee010_device); return ret; } @@ -970,7 +1023,7 @@ machine_at_alfredo_init(const machine_t *model) pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - device_add(&keyboard_ps2_ami_pci_device); + device_add(&keyboard_ps2_pci_device); device_add(&sio_device); device_add(&fdc37c663_device); device_add(&intel_flash_bxt_ami_device); @@ -981,6 +1034,34 @@ machine_at_alfredo_init(const machine_t *model) } +int +machine_at_ninja_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined("roms/machines/ninja/1008AY0_.BIO", + "roms/machines/ninja/1008AY0_.BI1", 0x1c000, 128); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1 | PCI_NO_IRQ_STEERING); + 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); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 1, 2, 1); + device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&intel_flash_bxt_ami_device); + + device_add(&i420ex_device); + device_add(&i82091aa_device); + + return ret; +} + + int machine_at_486sp3_init(const machine_t *model) { @@ -1071,7 +1152,7 @@ machine_at_486ap4_init(const machine_t *model) device_add(&keyboard_ps2_ami_pci_device); /* Uses the AMIKEY KBC */ if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); device_add(&i420ex_device); @@ -1079,6 +1160,36 @@ machine_at_486ap4_init(const machine_t *model) } +int +machine_at_g486vpa_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/g486vpa/3.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); + + device_add(&via_vt82c49x_pci_ide_device); + device_add(&via_vt82c505_device); + device_add(&pc87332_398_ide_sec_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + + int machine_at_486vipio2_init(const machine_t *model) { @@ -1165,99 +1276,6 @@ machine_at_win486pci_init(const machine_t *model) } -int -machine_at_atc1415_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/atc1415/1415V330.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(0x0c, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); - - device_add(&umc_hb4_device); - device_add(&umc_8886af_device); - device_add(&keyboard_at_ami_device); - - if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); - - return ret; -} - - -int -machine_at_ecs486_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/ecs486/8810AIO.32J", - 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(0x0c, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0d, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0e, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0f, PCI_CARD_IDE, 0, 0, 0, 0); - - device_add(&umc_hb4_device); - device_add(&umc_8886f_device); - device_add(&ide_cmd640_pci_legacy_only_device); - device_add(&fdc37c665_device); - device_add(&keyboard_at_ami_device); - - return ret; -} - - -int -machine_at_hot433_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/hot433/433AUS33.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(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(&intel_flash_bxt_device); - device_add(&keyboard_at_ami_device); - - return ret; -} - - int machine_at_itoxstar_init(const machine_t *model) { diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index 1ab48f7b4..abc6a6a85 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -486,37 +486,6 @@ at_tsunamiatx_get_device(void) return &es1371_onboard_device; } -#if defined(DEV_BRANCH) && defined(NO_SIO) -int -machine_at_ergox365_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/ergox365/M63v115.rom", - 0x00080000, 524288, 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); - pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x08, PCI_CARD_VIDEO, 3, 0, 0, 0); - device_add(&i440bx_device); - device_add(&piix4e_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&fdc37c665_device); /* Placeholder for the SM(S)C FDC37C675 */ - device_add(&sst_flash_39sf040_device); /* Placeholder for the Intel 28F004 flash chip */ - spd_register(SPD_TYPE_SDRAM, 0xF, 256); - - return ret; -} -#endif int machine_at_ficka6130_init(const machine_t *model) @@ -648,8 +617,10 @@ machine_at_vei8_init(const machine_t *model) device_add(&piix4e_device); device_add(&fdc37m60x_370_device); device_add(&keyboard_ps2_ami_pci_device); + device_add(ics9xxx_get(ICS9250_08)); device_add(&sst_flash_39sf020_device); spd_register(SPD_TYPE_SDRAM, 0x3, 512); + device_add(&as99127f_device); /* fans: Chassis, CPU, Power; temperatures: MB, JTPWR, CPU */ return ret; } diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index b7a83befb..a6d8a9a09 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -100,7 +100,7 @@ machine_at_trinity371_init(const machine_t *model) device_add(&i440bx_device); device_add(&piix4e_device); device_add(&keyboard_ps2_ami_pci_device); - device_add(&w83977f_370_device); + device_add(&w83977ef_370_device); device_add(&intel_flash_bxt_device); return ret; @@ -453,39 +453,3 @@ machine_at_6via90ap_init(const machine_t *model) return ret; } - - -int -machine_at_603tcf_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/603tcf/603tcfA4.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(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 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(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); - device_add(&via_vt8601_device); - device_add(&via_vt82c686b_device); - device_add(&via_vt82c686_sio_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&sst_flash_39sf020_device); - spd_register(SPD_TYPE_SDRAM, 0x3, 512); - device_add(&via_vt82c686_hwm_device); /* fans: 1, 2; temperatures: CPU, System, unused */ - hwm_values.temperatures[0] += 2; /* CPU offset */ - hwm_values.temperatures[1] += 2; /* System offset */ - hwm_values.temperatures[2] = 0; /* unused */ - - return ret; -} diff --git a/src/machine/m_at_socket4.c b/src/machine/m_at_socket4.c new file mode 100644 index 000000000..16673b22f --- /dev/null +++ b/src/machine/m_at_socket4.c @@ -0,0 +1,406 @@ +/* + * 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 Socket 4 machines. + * + * + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2010-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/mem.h> +#include <86box/io.h> +#include <86box/rom.h> +#include <86box/pci.h> +#include <86box/device.h> +#include <86box/chipset.h> +#include <86box/fdc_ext.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/timer.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/keyboard.h> +#include <86box/flash.h> +#include <86box/nvr.h> +#include <86box/scsi_ncr53c8xx.h> +#include <86box/sio.h> +#include <86box/video.h> +#include <86box/machine.h> + + +void +machine_at_premiere_common_init(const machine_t *model, int pci_switch) +{ + machine_at_common_init(model); + device_add(&ide_pci_2ch_device); + + pci_init(PCI_CONFIG_TYPE_2 | pci_switch); + 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(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&sio_zb_device); + device_add(&fdc37c665_device); + 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); + + // device_add(&keyboard_ps2_pci_device); + device_add(&keyboard_ps2_ami_pci_device); +} + + +void +machine_at_sp4_common_init(const machine_t *model) +{ + 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(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + /* Excluded: 02, 03, 04, 05, 06, 07, 08, 09, 0A, 0B, 0C, 0D, 0E, 0F, 10, 11, 12, 13, 14 */ + pci_register_slot(0x0D, PCI_CARD_IDE, 1, 2, 3, 4); + /* Excluded: 02, 03*, 04*, 05*, 06*, 07*, 08* */ + /* Slots: 09 (04), 0A (03), 0B (02), 0C (07) */ + 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); + device_add(&sis_85c50x_device); + device_add(&ide_cmd640_pci_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&fdc37c665_device); + device_add(&intel_flash_bxt_device); +} + + +int +machine_at_p5mp3_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/p5mp3/0205.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + 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); + pci_register_slot(0x05, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 05 = Slot 1 */ + pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 04 = Slot 2 */ + pci_register_slot(0x03, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 03 = Slot 3 */ + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&fdc_at_device); + device_add(&keyboard_ps2_pci_device); + + device_add(&sio_zb_device); + device_add(&catalyst_flash_device); + device_add(&i430lx_device); + + return ret; +} + + +int +machine_at_dellxp60_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_inverted("roms/machines/dellxp60/XP60-A08.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&ide_pci_2ch_device); + + pci_init(PCI_CONFIG_TYPE_2); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + /* Not: 00, 02, 03, 04, 05, 06, 07, 08, 09, 0A, 0B, 0C, 0D, 0E, 0F. */ + /* Yes: 01, 10, 11, 12, 13, 14. */ + pci_register_slot(0x01, PCI_CARD_NORMAL, 1, 3, 2, 4); + pci_register_slot(0x04, PCI_CARD_NORMAL, 4, 4, 3, 3); + pci_register_slot(0x05, PCI_CARD_NORMAL, 1, 4, 3, 2); + pci_register_slot(0x06, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&i430lx_device); + device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&sio_zb_device); + device_add(&fdc37c665_device); + device_add(&intel_flash_bxt_ami_device); + + return ret; +} + + +int +machine_at_opti560l_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_inverted("roms/machines/opti560l/560L_A06.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&ide_pci_2ch_device); + + pci_init(PCI_CONFIG_TYPE_2); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x03, PCI_CARD_NORMAL, 4, 4, 3, 3); + pci_register_slot(0x07, PCI_CARD_NORMAL, 1, 4, 3, 2); + pci_register_slot(0x08, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&i430lx_device); + device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&sio_zb_device); + device_add(&i82091aa_device); + device_add(&intel_flash_bxt_ami_device); + + return ret; +} + + +int +machine_at_ambradp60_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined("roms/machines/ambradp60/1004AF1P.BIO", + "roms/machines/ambradp60/1004AF1P.BI1", 0x1c000, 128); + + if (bios_only || !ret) + return ret; + + machine_at_premiere_common_init(model, 0); + + device_add(&i430lx_device); + + return ret; +} + + +int +machine_at_valuepointp60_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined("roms/machines/valuepointp60/1006AV0M.BIO", + "roms/machines/valuepointp60/1006AV0M.BI1", 0x1d000, 128); + + if (bios_only || !ret) + return ret; + + 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(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&keyboard_ps2_ps1_pci_device); + device_add(&sio_device); + device_add(&fdc37c665_device); + device_add(&intel_flash_bxt_ami_device); + + device_add(&i430lx_device); + + return ret; +} + + +int +machine_at_revenge_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined("roms/machines/revenge/1009af2_.bio", + "roms/machines/revenge/1009af2_.bi1", 0x1c000, 128); + + if (bios_only || !ret) + return ret; + + machine_at_premiere_common_init(model, 0); + + device_add(&i430lx_device); + + return ret; +} + + +int +machine_at_586mc1_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/586mc1/IS.34", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_award_common_init(model); + + device_add(&sio_device); + device_add(&intel_flash_bxt_device); + device_add(&i430lx_device); + + return ret; +} + + +int +machine_at_pb520r_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined("roms/machines/pb520r/1009bc0r.bio", + "roms/machines/pb520r/1009bc0r.bi1", 0x1c000, 128); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_2); + 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_VIDEO, 3, 3, 3, 3); + pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&i430lx_device); + device_add(&ide_cmd640_pci_single_channel_device); + + if (gfxcard == VID_INTERNAL) + device_add(&gd5434_onboard_pci_device); + + device_add(&keyboard_ps2_pci_device); + device_add(&sio_zb_device); + device_add(&i82091aa_ide_device); + device_add(&intel_flash_bxt_ami_device); + + return ret; +} + +const device_t * +at_pb520r_get_device(void) +{ + return &gd5434_onboard_pci_device; +} + + +int +machine_at_excalibur_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_inverted("roms/machines/excalibur/S75P.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&opti5x7_device); + device_add(&ide_opti611_vlb_device); + device_add(&fdc37c661_device); + device_add(&keyboard_ps2_intel_ami_pci_device); + + return ret; +} + + +int +machine_at_p5vl_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/p5vl/SM507.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(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_device); + device_add(&opti822_device); + device_add(&sst_flash_29ee010_device); + device_add(&keyboard_at_ami_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + + +int +machine_at_p5sp4_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/p5sp4/0106.001", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_sp4_common_init(model); + + return ret; +} diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c new file mode 100644 index 000000000..2748210e0 --- /dev/null +++ b/src/machine/m_at_socket5.c @@ -0,0 +1,446 @@ +/* + * 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 Socket 5 machines. + * + * + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2010-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/mem.h> +#include <86box/io.h> +#include <86box/rom.h> +#include <86box/pci.h> +#include <86box/device.h> +#include <86box/chipset.h> +#include <86box/fdc_ext.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/timer.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/keyboard.h> +#include <86box/flash.h> +#include <86box/nvr.h> +#include <86box/scsi_ncr53c8xx.h> +#include <86box/sio.h> +#include <86box/video.h> +#include <86box/machine.h> + + +int +machine_at_plato_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined("roms/machines/plato/1016ax1_.bio", + "roms/machines/plato/1016ax1_.bi1", 0x1d000, 128); + + if (bios_only || !ret) + return ret; + + machine_at_premiere_common_init(model, PCI_CAN_SWITCH_TYPE); + + device_add(&i430nx_device); + + return ret; +} + + +int +machine_at_ambradp90_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined("roms/machines/ambradp90/1002AX1P.BIO", + "roms/machines/ambradp90/1002AX1P.BI1", 0x1d000, 128); + + if (bios_only || !ret) + return ret; + + machine_at_premiere_common_init(model, PCI_CAN_SWITCH_TYPE); + + device_add(&i430nx_device); + + return ret; +} + + +int +machine_at_430nx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/430nx/IP.20", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + 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_acerv30_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/acerv30/V30R01N9.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(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); + device_add(&i430fx_device); + device_add(&piix_device); + device_add(&keyboard_ps2_acer_pci_device); + device_add(&fdc37c665_device); + + device_add(&sst_flash_29ee010_device); + + return ret; +} + + +int +machine_at_apollo_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/apollo/S728P.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + device_add(&ami_apollo_nvr_device); + + 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_exp8551_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/exp8551/AMI20.BIO", + 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(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x11, 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(&w83787f_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + + +int +machine_at_vectra54_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/vectra54/GT0724.22", + 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(0x0F, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_VIDEO, 0, 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); + + if (gfxcard == VID_INTERNAL) + device_add(&s3_phoenix_trio64_onboard_pci_device); + + device_add(&keyboard_ps2_ami_pci_device); + device_add(&i430fx_device); + device_add(&piix_device); + device_add(&fdc37c931apm_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + + +int +machine_at_zappa_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined("roms/machines/zappa/1006bs0_.bio", + "roms/machines/zappa/1006bs0_.bi1", 0x20000, 128); + + 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, 3, 4, 1, 2); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&i430fx_device); + device_add(&piix_device); + device_add(&pc87306_device); + device_add(&intel_flash_bxt_ami_device); + + return ret; +} + + +int +machine_at_powermatev_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/powermatev/BIOS.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(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_NORMAL, 0, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&i430fx_device); + device_add(&piix_device); + device_add(&fdc37c665_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + + +int +machine_at_mb500n_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/mb500n/031396s.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(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&keyboard_ps2_pci_device); + device_add(&i430fx_device); + device_add(&piix_device); + device_add(&fdc37c665_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + + +int +machine_at_hawk_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/hawk/HAWK.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(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + 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(&fdc37c665_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + + +int +machine_at_pat54pv_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/pat54pv/pat54pv.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&opti5x7_device); + device_add(&keyboard_ps2_intel_ami_pci_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + + +int +machine_at_hot543_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/hot543/543_R21.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_device); + device_add(&opti822_device); + device_add(&sst_flash_29ee010_device); + device_add(&keyboard_at_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + + +int +machine_at_p54sp4_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/p54sp4/SI5I0204.AWD", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_sp4_common_init(model); + + return ret; +} + + +int +machine_at_sq588_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/sq588/sq588b03.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(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + /* Correct: 0D (01), 0F (02), 11 (03), 13 (04) */ + pci_register_slot(0x02, PCI_CARD_IDE, 1, 2, 3, 4); + 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); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); + device_add(&sis_85c50x_device); + device_add(&ide_cmd640_pci_single_channel_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&fdc37c665_ide_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} \ No newline at end of file diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index 5ba8a69a3..112be1c60 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -6,7 +6,7 @@ * * This file is part of the 86Box distribution. * - * Implementation of Socket 7 machines. + * Implementation of Socket 7 (Dual Voltage) machines. * * * @@ -45,239 +45,6 @@ #include <86box/fdc.h> #include <86box/nvr.h> -int -machine_at_ap5s_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/ap5s/AP5S150.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(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, 2, 1); - pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 3, 2, 1); - - device_add(&sis_5511_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&fdc37c665_device); - device_add(&sst_flash_29ee010_device); - - return ret; -} - -int -machine_at_chariot_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/chariot/P5IV183.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(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 2, 1); - pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 3, 2, 1); - - device_add(&i430fx_device); - device_add(&piix_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&pc87306_device); - device_add(&intel_flash_bxt_device); - - return ret; -} - -int -machine_at_mr586_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/mr586/TRITON.BIO", - 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(0x07, 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); - - device_add(&i430fx_device); - device_add(&piix_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&fdc37c665_device); - device_add(&intel_flash_bxt_device); - - return ret; -} - -static void -machine_at_thor_common_init(const machine_t *model, int mr) -{ - machine_at_common_init_ex(model, mr); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 2, 1); - pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 3, 2, 1); - 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(&pc87306_device); - device_add(&intel_flash_bxt_ami_device); -} - - -int -machine_at_thor_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear_combined("roms/machines/thor/1006cn0_.bio", - "roms/machines/thor/1006cn0_.bi1", 0x20000, 128); - - if (bios_only || !ret) - return ret; - - machine_at_thor_common_init(model, 0); - - return ret; -} - - -int -machine_at_gw2katx_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear_combined("roms/machines/gw2katx/1003cn0t.bio", - "roms/machines/gw2katx/1003cn0t.bi1", 0x20000, 128); - - if (bios_only || !ret) - return ret; - - machine_at_thor_common_init(model, 0); - - return ret; -} - - -int -machine_at_mrthor_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/mrthor/mr_atx.bio", - 0x000e0000, 131072, 0); - - if (bios_only || !ret) - return ret; - - machine_at_thor_common_init(model, 1); - - return ret; -} - - -int -machine_at_pb640_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear_combined("roms/machines/pb640/1007CP0R.BIO", - "roms/machines/pb640/1007CP0R.BI1", 0x1d000, 128); - - 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_VIDEO, 4, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 2, 1, 4); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - device_add(&i430fx_rev02_device); - device_add(&piix_rev02_device); - - if (gfxcard == VID_INTERNAL) - device_add(&gd5440_onboard_pci_device); - - device_add(&keyboard_ps2_intel_ami_pci_device); - device_add(&pc87306_device); - device_add(&intel_flash_bxt_ami_device); - - return ret; -} - -const device_t * -at_pb640_get_device(void) -{ - return &gd5440_onboard_pci_device; -} - - -int -machine_at_acerm3a_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/acerm3a/r01-b3.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(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0D, 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); - pci_register_slot(0x10, PCI_CARD_VIDEO, 4, 0, 0, 0); - device_add(&i430hx_device); - device_add(&piix3_device); - device_add(&keyboard_ps2_pci_device); - device_add(&fdc37c932fr_device); - - device_add(&sst_flash_29ee010_device); - - return ret; -} - int machine_at_acerv35n_init(const machine_t *model) @@ -311,37 +78,6 @@ machine_at_acerv35n_init(const machine_t *model) } -int -machine_at_ap53_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/ap53/ap53r2c0.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(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); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x06, PCI_CARD_VIDEO, 1, 2, 3, 4); - device_add(&i430hx_device); - device_add(&piix3_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&fdc37c669_device); - device_add(&intel_flash_bxt_device); - - return ret; -} - - int machine_at_p55t2p4_init(const machine_t *model) { @@ -372,66 +108,6 @@ machine_at_p55t2p4_init(const machine_t *model) } -int -machine_at_p55t2s_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/p55t2s/s6y08t.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_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x11, 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_ami_pci_device); - device_add(&pc87306_device); - device_add(&intel_flash_bxt_device); - - return ret; -} - - -int -machine_at_8500tuc_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/8500tuc/Tuc0221b.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(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, 1, 2, 3, 4); - device_add(&i430hx_device); - device_add(&piix3_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&um8669f_device); - device_add(&intel_flash_bxt_device); - - return ret; -} - - int machine_at_m7shi_init(const machine_t *model) { @@ -461,6 +137,7 @@ machine_at_m7shi_init(const machine_t *model) return ret; } + int machine_at_tc430hx_init(const machine_t *model) { @@ -496,8 +173,9 @@ machine_at_tc430hx_init(const machine_t *model) } +/* Information about that machine on machine.h */ int -machine_at_equium5200_init(const machine_t *model) // Information about that machine on machine.h +machine_at_equium5200_init(const machine_t *model) { int ret; @@ -530,6 +208,7 @@ machine_at_equium5200_init(const machine_t *model) // Information about that mac return ret; } + int machine_at_pcv240_init(const machine_t *model) { @@ -564,6 +243,7 @@ machine_at_pcv240_init(const machine_t *model) return ret; } + int machine_at_p65up5_cp55t2d_init(const machine_t *model) { @@ -581,36 +261,6 @@ machine_at_p65up5_cp55t2d_init(const machine_t *model) } -int -machine_at_mb520n_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/mb520n/520n503s.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(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - device_add(&i430vx_device); - device_add(&piix3_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&fdc37c669_device); - device_add(&intel_flash_bxt_device); - - return ret; -} - - int machine_at_p55tvp4_init(const machine_t *model) { @@ -640,6 +290,7 @@ machine_at_p55tvp4_init(const machine_t *model) return ret; } + int machine_at_5ivg_init(const machine_t *model) { @@ -668,92 +319,6 @@ machine_at_5ivg_init(const machine_t *model) return ret; } -int -machine_at_i430vx_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/430vx/55xwuq0e.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(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - device_add(&i430vx_device); - device_add(&piix3_device); - device_add(&keyboard_ps2_pci_device); - device_add(&um8669f_device); - device_add(&intel_flash_bxt_device); - - return ret; -} - -int -machine_at_p55va_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/p55va/va021297.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(&i430vx_device); - device_add(&piix3_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&fdc37c932fr_device); - device_add(&intel_flash_bxt_device); - - return ret; -} - -int -machine_at_brio80xx_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/brio80xx/Hf0705.rom", - 0x000c0000, 262144, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init(model); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x14, PCI_CARD_VIDEO, 4, 0, 0, 0); - pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - device_add(&i430vx_device); - device_add(&piix3_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&fdc37c935_device); - device_add(&sst_flash_29ee020_device); - - return ret; -} int machine_at_8500tvxa_init(const machine_t *model) @@ -843,6 +408,66 @@ machine_at_presario4500_init(const machine_t *model) } +int +machine_at_p55va_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/p55va/va021297.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(&i430vx_device); + device_add(&piix3_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&fdc37c932fr_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + + +int +machine_at_brio80xx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/brio80xx/Hf0705.rom", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x14, PCI_CARD_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + device_add(&i430vx_device); + device_add(&piix3_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&fdc37c935_device); + device_add(&sst_flash_29ee020_device); + + return ret; +} + + int machine_at_pb680_init(const machine_t *model) { @@ -878,16 +503,12 @@ machine_at_pb680_init(const machine_t *model) int -machine_at_gw2kte_init(const machine_t *model) +machine_at_mb520n_init(const machine_t *model) { int ret; - ret = bios_load_linear_combined2("roms/machines/gw2kte/1008CY1T.BIO", - "roms/machines/gw2kte/1008CY1T.BI1", - "roms/machines/gw2kte/1008CY1T.BI2", - "roms/machines/gw2kte/1008CY1T.BI3", - "roms/machines/gw2kte/1008CY1T.RCV", - 0x3a000, 128); + ret = bios_load_linear("roms/machines/mb520n/520n503s.rom", + 0x000e0000, 131072, 0); if (bios_only || !ret) return ret; @@ -896,17 +517,46 @@ machine_at_gw2kte_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(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x10, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); + pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430vx_device); device_add(&piix3_device); device_add(&keyboard_ps2_ami_pci_device); - device_add(&fdc37c932fr_device); - device_add(&intel_flash_bxt_ami_device); + device_add(&fdc37c669_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + + +int +machine_at_i430vx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/430vx/55xwuq0e.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(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&i430vx_device); + device_add(&piix3_device); + device_add(&keyboard_ps2_pci_device); + device_add(&um8669f_device); + device_add(&intel_flash_bxt_device); return ret; } @@ -949,6 +599,7 @@ machine_at_nupro592_init(const machine_t *model) return ret; } + int machine_at_tx97_init(const machine_t *model) { @@ -989,39 +640,6 @@ machine_at_tx97_init(const machine_t *model) } -int -machine_at_ym430tx_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/ym430tx/YM430TX.003", - 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(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(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); /* PIIX4 */ - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); - device_add(&i430tx_device); - device_add(&piix4_device); - device_add(&keyboard_ps2_pci_device); - device_add(&w83977tf_device); - device_add(&intel_flash_bxt_device); - spd_register(SPD_TYPE_SDRAM, 0x3, 128); - - return ret; -} - - #if defined(DEV_BRANCH) && defined(NO_SIO) int machine_at_an430tx_init(const machine_t *model) @@ -1060,6 +678,39 @@ machine_at_an430tx_init(const machine_t *model) #endif +int +machine_at_ym430tx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ym430tx/YM430TX.003", + 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(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(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); /* PIIX4 */ + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + device_add(&i430tx_device); + device_add(&piix4_device); + device_add(&keyboard_ps2_pci_device); + device_add(&w83977tf_device); + device_add(&intel_flash_bxt_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 128); + + return ret; +} + + int machine_at_mb540n_init(const machine_t *model) { @@ -1123,132 +774,6 @@ machine_at_p5mms98_init(const machine_t *model) return ret; } -#if defined(DEV_BRANCH) && defined(USE_M154X) -int -machine_at_m560_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/m560/5600410s.ami", - 0x000e0000, 131072, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init(model); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0C, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_NORMAL, 1, 2, 3, 4); - device_add(&ali1531_device); - device_add(&ali1543_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&sst_flash_29ee010_device); - spd_register(SPD_TYPE_SDRAM, 0x3, 128); - - return ret; -} - -int -machine_at_ms5164_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/ms5164/W564MS43.005", - 0x000e0000, 131072, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init(model); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0C, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_NORMAL, 1, 2, 3, 4); - - device_add(&ali1531_device); - device_add(&ali1543_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&sst_flash_29ee010_device); - spd_register(SPD_TYPE_SDRAM, 0x3, 128); - - return ret; -} -#endif - -int -machine_at_r534f_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/r534f/r534f008.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(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0B, 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); - pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); - - device_add(&sis_5571_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&w83877f_device); - device_add(&sst_flash_29ee010_device); - - return ret; -} - -int -machine_at_ms5146_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/ms5146/A546MS11.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(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); - - device_add(&sis_5571_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&w83877f_device); - device_add(&sst_flash_29ee010_device); - - return ret; -} int machine_at_ficva502_init(const machine_t *model) @@ -1313,12 +838,73 @@ machine_at_ficpa2012_init(const machine_t *model) return ret; } + int -machine_at_sp97xv_init(const machine_t *model) +machine_at_r534f_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/sp97xv/0109XV.005", + ret = bios_load_linear("roms/machines/r534f/r534f008.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(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0B, 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); + pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); + + device_add(&sis_5571_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83877f_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + + +int +machine_at_ms5146_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ms5146/A546MS11.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(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); + + device_add(&sis_5571_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83877f_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + + +int +machine_at_m560_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/m560/5600410s.ami", 0x000e0000, 131072, 0); if (bios_only || !ret) @@ -1328,22 +914,31 @@ machine_at_sp97xv_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(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - device_add(&sis_5598_device); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0C, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); + device_add(&ali1531_device); + device_add(&ali1543_device); device_add(&keyboard_ps2_ami_pci_device); - device_add(&w83877f_device); device_add(&sst_flash_29ee010_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 128); return ret; } + int -machine_at_m571_init(const machine_t *model) +machine_at_ms5164_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/m571/2k0621s.rom", - 0x000c0000, 262144, 0); + ret = bios_load_linear("roms/machines/ms5164/W564MS43.005", + 0x000e0000, 131072, 0); if (bios_only || !ret) return ret; @@ -1352,15 +947,21 @@ machine_at_m571_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(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - 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); - device_add(&sis_5598_device); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_SOUTHBRIDGE, 5, 6, 0, 0); + pci_register_slot(0x0C, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_NORMAL, 1, 2, 3, 4); + + device_add(&ali1531_device); + device_add(&ali1543_device); device_add(&keyboard_ps2_ami_pci_device); - device_add(&it8661f_device); - device_add(&sst_flash_29ee020_device); + device_add(&sst_flash_29ee010_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 128); return ret; } diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c new file mode 100644 index 000000000..f31aeed33 --- /dev/null +++ b/src/machine/m_at_socket7_3v.c @@ -0,0 +1,514 @@ +/* + * 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 Socket 7 (Single Voltage) machines. + * + * + * + * Authors: Sarah Walker, + * Miran Grca, + * Melissa Goad, + * + * Copyright 2010-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/mem.h> +#include <86box/io.h> +#include <86box/rom.h> +#include <86box/pci.h> +#include <86box/device.h> +#include <86box/chipset.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/keyboard.h> +#include <86box/flash.h> +#include <86box/sio.h> +#include <86box/hwm.h> +#include <86box/video.h> +#include <86box/spd.h> +#include "cpu.h" +#include <86box/machine.h> +#include <86box/timer.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/nvr.h> + + +static void +machine_at_thor_common_init(const machine_t *model, int mr) +{ + machine_at_common_init_ex(model, mr); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 2, 1); + pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 3, 2, 1); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + + // device_add(&keyboard_ps2_ami_pci_device); + device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&i430fx_device); + device_add(&piix_device); + device_add(&pc87306_device); + device_add(&intel_flash_bxt_ami_device); +} + + +int +machine_at_p54tp4xe_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/p54tp4xe/t15i0302.awd", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + /* Award BIOS, SMC FDC37C665. */ + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 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(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&keyboard_ps2_pci_device); + device_add(&i430fx_device); + device_add(&piix_device); + device_add(&fdc37c665_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + + +int +machine_at_mr586_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/mr586/TRITON.BIO", + 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(0x07, 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); + + device_add(&i430fx_device); + device_add(&piix_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&fdc37c665_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + + +int +machine_at_gw2katx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined("roms/machines/gw2katx/1003cn0t.bio", + "roms/machines/gw2katx/1003cn0t.bi1", 0x20000, 128); + + if (bios_only || !ret) + return ret; + + machine_at_thor_common_init(model, 0); + + return ret; +} + + +int +machine_at_thor_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined("roms/machines/thor/1006cn0_.bio", + "roms/machines/thor/1006cn0_.bi1", 0x20000, 128); + + if (bios_only || !ret) + return ret; + + machine_at_thor_common_init(model, 0); + + return ret; +} + + +int +machine_at_mrthor_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/mrthor/mr_atx.bio", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_thor_common_init(model, 1); + + return ret; +} + + +int +machine_at_endeavor_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined("roms/machines/endeavor/1006cb0_.bio", + "roms/machines/endeavor/1006cb0_.bi1", 0x1d000, 128); + + 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_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + + if (gfxcard == VID_INTERNAL) + device_add(&s3_phoenix_trio64_onboard_pci_device); + + device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&i430fx_device); + device_add(&piix_device); + device_add(&pc87306_device); + device_add(&intel_flash_bxt_ami_device); + + return ret; +} + + +const device_t * +at_endeavor_get_device(void) +{ + return &s3_phoenix_trio64_onboard_pci_device; +} + + +int +machine_at_ms5119_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ms5119/A37E.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(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0d, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0e, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0f, PCI_CARD_NORMAL, 3, 4, 1, 2); + + device_add(&i430fx_device); + device_add(&piix_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83787f_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + + +int +machine_at_pb640_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined("roms/machines/pb640/1007CP0R.BIO", + "roms/machines/pb640/1007CP0R.BI1", 0x1d000, 128); + + 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_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 2, 1, 4); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&i430fx_rev02_device); + device_add(&piix_rev02_device); + + if (gfxcard == VID_INTERNAL) + device_add(&gd5440_onboard_pci_device); + + device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&pc87306_device); + device_add(&intel_flash_bxt_ami_device); + + return ret; +} + + +const device_t * +at_pb640_get_device(void) +{ + return &gd5440_onboard_pci_device; +} + + +int +machine_at_fmb_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/fmb/P5IV183.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(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 2, 1); + pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 3, 2, 1); + + device_add(&i430fx_device); + device_add(&piix_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83787f_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + + +int +machine_at_acerm3a_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/acerm3a/r01-b3.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(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, 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); + pci_register_slot(0x10, PCI_CARD_VIDEO, 4, 0, 0, 0); + device_add(&i430hx_device); + device_add(&piix3_device); + device_add(&keyboard_ps2_pci_device); + device_add(&fdc37c932fr_device); + + device_add(&sst_flash_29ee010_device); + + return ret; +} + + +int +machine_at_ap53_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ap53/ap53r2c0.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(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); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_VIDEO, 1, 2, 3, 4); + device_add(&i430hx_device); + device_add(&piix3_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&fdc37c669_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + + +int +machine_at_8500tuc_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/8500tuc/Tuc0221b.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(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, 1, 2, 3, 4); + device_add(&i430hx_device); + device_add(&piix3_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&um8669f_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + + +int +machine_at_p55t2s_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/p55t2s/s6y08t.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_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x11, 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_ami_pci_device); + device_add(&pc87306_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + + +int +machine_at_gw2kte_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined2("roms/machines/gw2kte/1008CY1T.BIO", + "roms/machines/gw2kte/1008CY1T.BI1", + "roms/machines/gw2kte/1008CY1T.BI2", + "roms/machines/gw2kte/1008CY1T.BI3", + "roms/machines/gw2kte/1008CY1T.RCV", + 0x3a000, 128); + + 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_VIDEO, 4, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); + device_add(&i430vx_device); + device_add(&piix3_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&fdc37c932fr_device); + device_add(&intel_flash_bxt_ami_device); + + return ret; +} + + +int +machine_at_ap5s_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ap5s/AP5S150.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(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, 2, 1); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 3, 2, 1); + + device_add(&sis_5511_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&fdc37c665_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 1aa892415..572d6ec48 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -62,6 +62,8 @@ machine_at_p6rp4_init(const machine_t *model) pci_register_slot(0x08, PCI_CARD_IDE, 0, 0, 0, 0); device_add(&i450kx_device); device_add(&sio_zb_device); + // device_add(&keyboard_ps2_ami_pci_device); + /* Input port bit 2 must be 1 or CMOS Setup is disabled. */ device_add(&keyboard_ps2_ami_pci_device); device_add(&fdc37c665_device); device_add(&ide_cmd640_pci_device); diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index 33b67aabe..ca444421c 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -59,6 +59,7 @@ #include <86box/hdc_ide.h> #include <86box/fdd.h> #include <86box/fdc.h> +#include <86box/port_6x.h> #include <86box/sound.h> #include <86box/snd_sn76489.h> #include <86box/video.h> @@ -514,6 +515,7 @@ ps1_common_init(const machine_t *model) pic2_init(); device_add(&keyboard_ps2_ps1_device); + device_add(&port_6x_device); /* Audio uses ports 200h and 202-207h, so only initialize gameport on 201h. */ standalone_gameport_type = &gameport_201_device; diff --git a/src/machine/m_ps2_isa.c b/src/machine/m_ps2_isa.c index 0b9dbaeb4..987b29f2e 100644 --- a/src/machine/m_ps2_isa.c +++ b/src/machine/m_ps2_isa.c @@ -15,6 +15,7 @@ #include <86box/nvr.h> #include <86box/keyboard.h> #include <86box/lpt.h> +#include <86box/port_6x.h> #include <86box/port_92.h> #include <86box/serial.h> #include <86box/hdc.h> @@ -186,7 +187,8 @@ machine_ps2_m30_286_init(const machine_t *model) refresh_at_enable = 1; pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_at); dma16_init(); - device_add(&keyboard_ps2_ps2_device); + device_add(&keyboard_ps2_device); + device_add(&port_6x_ps2_device); device_add(&ps_nvr_device); pic2_init(); ps2board_init(); diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index 59a3fe535..b1b611d94 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -63,6 +63,7 @@ #include <86box/keyboard.h> #include <86box/lpt.h> #include <86box/mouse.h> +#include <86box/port_6x.h> #include <86box/port_92.h> #include <86box/serial.h> #include <86box/video.h> @@ -793,7 +794,8 @@ static void ps2_mca_board_common_init() io_sethandler(0x0096, 0x0001, ps2_mca_read, NULL, NULL, ps2_mca_write, NULL, NULL, NULL); io_sethandler(0x0100, 0x0008, ps2_mca_read, NULL, NULL, ps2_mca_write, NULL, NULL, NULL); - device_add(&port_92_device); + device_add(&port_6x_ps2_device); + device_add(&port_92_device); ps2.setup = 0xff; diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 127495259..e356d1cbb 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -290,28 +290,6 @@ machine_xt_pcxt_init(const machine_t *model) } -#if defined(DEV_BRANCH) && defined(USE_HEDAKA) -int -machine_xt_hed919_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/hed919/Hedaka_HED-919_bios_version_3.28f.bin", - 0x000fe000, 8192, 0); - - if (bios_only || !ret) - return ret; - - machine_xt_clone_init(model); - - if (mem_size > 640) - mem_remap_top(mem_size - 640); - - return ret; -} -#endif - - int machine_xt_pxxt_init(const machine_t *model) { diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index bc9edb672..3a5c6da80 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -44,6 +44,7 @@ #include <86box/fdc.h> #include <86box/fdc_ext.h> #include <86box/gameport.h> +#include <86box/port_6x.h> #include <86box/sound.h> #include <86box/snd_speaker.h> #include <86box/video.h> @@ -765,6 +766,9 @@ machine_xt_m240_init(const machine_t *model) pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + /* Address 66-67 = mainboard dip-switch settings */ + io_sethandler(0x0066, 2, m24_read, NULL, NULL, NULL, NULL, NULL, NULL); + /* * port 60: should return jumper settings only under unknown conditions * SWB on mainboard (off=1) @@ -772,6 +776,7 @@ machine_xt_m240_init(const machine_t *model) * bit 6 - use OCG/CGA display adapter (on) / other display adapter (off) */ device_add(&keyboard_at_olivetti_device); + device_add(&port_6x_olivetti_device); /* FIXME: make sure this is correct?? */ device_add(&at_nvr_device); diff --git a/src/machine/m_xt_xi8088.c b/src/machine/m_xt_xi8088.c index d7a127119..891469cc5 100644 --- a/src/machine/m_xt_xi8088.c +++ b/src/machine/m_xt_xi8088.c @@ -19,6 +19,7 @@ #include <86box/lpt.h> #include <86box/rom.h> #include <86box/hdc.h> +#include <86box/port_6x.h> #include <86box/video.h> #include <86box/machine.h> #include "cpu.h" @@ -178,6 +179,7 @@ machine_xt_xi8088_init(const machine_t *model) device_add(&fdc_at_device); device_add(&keyboard_ps2_xi8088_device); + device_add(&port_6x_xi8088_device); nmi_init(); device_add(&ibmat_nvr_device); pic2_init(); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index a952c2b4e..75dad8e60 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -39,10 +39,12 @@ const machine_type_t machine_types[] = { { "8086", MACHINE_TYPE_8086 }, { "80286", MACHINE_TYPE_286 }, { "i386SX", MACHINE_TYPE_386SX }, + { "486SLC", MACHINE_TYPE_486SLC }, { "i386DX", MACHINE_TYPE_386DX }, { "i386DX/i486", MACHINE_TYPE_386DX_486 }, { "i486 (Socket 168 and 1)", MACHINE_TYPE_486 }, - { "i486 (Socket 2 and 3)", MACHINE_TYPE_486_S3 }, + { "i486 (Socket 2)", MACHINE_TYPE_486_S2 }, + { "i486 (Socket 3)", MACHINE_TYPE_486_S3 }, { "i486 (Miscellaneous)", MACHINE_TYPE_486_MISC }, { "Socket 4", MACHINE_TYPE_SOCKET4 }, { "Socket 5", MACHINE_TYPE_SOCKET5 }, @@ -58,6 +60,49 @@ const machine_type_t machine_types[] = { }; +/* Machines to add before machine freeze: + - Jetway J-403TG MR BIOS v2.02; + - Matsonic MS6260S (AMI Super Socket 7 with Aladdin V chipset); + - PCChips M773 (440BX + SMSC with AMI BIOS); + - Rise R418 (was removed on my end, has to be re-added); + - TMC Mycomp PCI54ST; + - Zeos Quadtel 486. + + NOTE: The AMI MegaKey tests were done on a real Intel Advanced/ATX + (thanks, MrKsoft for running my AMIKEY.COM on it), but the + technical specifications of the other Intel machines confirm + that the other boards also have the MegaKey. + + NOTE: The later (ie. not AMI Color) Intel AMI BIOS'es execute a + sequence of commands (B8, BA, BB) during one of the very first + phases of POST, in a way that is only valid on the AMIKey-3 + KBC firmware, that includes the Classic PCI/ED (Ninja) BIOS + which otherwise does not execute any AMI KBC commands, which + indicates that the sequence is a leftover of whatever AMI + BIOS (likely a laptop one since the AMIKey-3 is a laptop KBC + firmware!) Intel forked. + + NOTE: The VIA VT82C42N returns 0x46 ('F') in command 0xA1 (so it + emulates the AMI KF/AMIKey KBC firmware), and 0x42 ('B') in + command 0xAF. + The version on the VIA VT82C686B southbridge also returns + 'F' in command 0xA1, but 0x45 ('E') in command 0xAF. + + NOTE: The AMI MegaKey commands blanked in the technical reference + are CC and and C4, which are Set P14 High and Set P14 Low, + respectively. Also, AMI KBC command C1, mysteriously missing + from the technical references of AMI MegaKey and earlier, is + Write Input Port, same as on AMIKey-3. + + Machines to remove: + - Hedaka HED-919; + - A-Trend ATC-1415; + - ECS Elite UM8810PAIO; + - Shuttle HOT-433A; + - Azza 5IVG (if a more interesting machine with Prime3C is found). +*/ + + const machine_t machines[] = { /* 8088 Machines */ { "[8088] IBM PC (1981)", "ibmpc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 16, 64, 16, 0, machine_pc_init, NULL }, @@ -69,10 +114,10 @@ const machine_t machines[] = { { "[8088] AMI XT clone", "amixt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_amixt_init, NULL }, { "[8088] Columbia Data Products MPC-1600", "mpc1600", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 512, 64, 0, machine_xt_mpc1600_init, NULL }, { "[8088] Compaq Portable", "portable", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_compaq_portable_init, NULL }, - { "[8088] DTK XT clone", "dtk", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_dtk_init, NULL }, + { "[8088] DTK PIM-TB10-Z", "dtk", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_dtk_init, NULL }, { "[8088] Eagle PC Spirit", "pcspirit", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_pcspirit_init, NULL }, { "[8088] Generic XT clone", "genxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_genxt_init, NULL }, - { "[8088] Juko XT clone", "jukopc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_jukopc_init, NULL }, + { "[8088] Juko ST", "jukopc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_jukopc_init, NULL }, { "[8088] Multitech PC-700", "pc700", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_pc700_init, NULL }, { "[8088] NCR PC4i", "pc4i", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_pc4i_init, NULL }, { "[8088] Olivetti M19", "m19", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 256, 640, 256, 0, machine_xt_m19_init, NULL }, @@ -87,6 +132,7 @@ const machine_t machines[] = { #if defined(DEV_BRANCH) && defined(USE_LASERXT) { "[8088] VTech Laser Turbo XT", "ltxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_laserxt_init, NULL }, #endif + /* Has a standard PS/2 KBC (so, use IBM PS/2 Type 1). */ { "[8088] Xi8088", "xi8088", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2, 64, 1024, 128, 127, machine_xt_xi8088_init, xi8088_get_device }, { "[8088] Zenith Data Systems Z-151/152/161","zdsz151", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_z151_init, NULL }, { "[8088] Zenith Data Systems Z-159", "zdsz159", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_z159_init, NULL }, @@ -102,6 +148,7 @@ const machine_t machines[] = { { "[8086] Amstrad PPC512/640", "ppc512", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO | MACHINE_MOUSE | MACHINE_NONMI, 512, 640, 128, 63, machine_ppc512_init, ppc512_get_device }, { "[8086] Compaq Deskpro", "deskpro", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_compaq_deskpro_init, NULL }, { "[8086] Olivetti M21/24/24SP", "m24", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO | MACHINE_MOUSE, 128, 640, 128, 0, machine_xt_m24_init, m24_get_device }, + /* Has Olivetti KBC firmware. */ { "[8086] Olivetti M240", "m240", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_m240_init, NULL }, { "[8086] Schetmash Iskra-3104", "iskra3104", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_iskra3104_init, NULL }, { "[8086] Tandy 1000 SL/2", "tandy1000sl2", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 512, 768, 128, 0, machine_tandy1000sl2_init, tandy1k_sl_get_device }, @@ -111,360 +158,693 @@ const machine_t machines[] = { { "[8086] VTech Laser XT3", "lxt3", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_lxt3_init, NULL }, #endif - /* 286 XT machines */ -#if defined(DEV_BRANCH) && defined(USE_HEDAKA) - { "[Citygate D30 XT] Hedaka HED-919", "hed919", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 1024, 64, 0, machine_xt_hed919_init, NULL }, -#endif - /* 286 AT machines */ + /* Has IBM AT KBC firmware. */ { "[ISA] IBM AT", "ibmat", MACHINE_TYPE_286, CPU_PKG_286, 0, 6000000, 8000000, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_ibm_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[ISA] IBM PS/1 model 2011", "ibmps1es", MACHINE_TYPE_286, CPU_PKG_286, 0, 10000000, 10000000, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_XTA | MACHINE_VIDEO_FIXED, 512, 16384, 512, 63, machine_ps1_m2011_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[ISA] IBM PS/2 model 30-286", "ibmps2_m30_286", MACHINE_TYPE_286, CPU_PKG_286 | CPU_PKG_486SLC_IBM, 0, 10000000, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_XTA | MACHINE_VIDEO_FIXED, 1024, 16384,1024, 127, machine_ps2_m30_286_init, NULL }, + /* Has IBM AT KBC firmware. */ { "[ISA] IBM XT Model 286", "ibmxt286", MACHINE_TYPE_286, CPU_PKG_286, 0, 6000000, 6000000, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 127, machine_at_ibmxt286_init, NULL }, + /* AMI BIOS for a chipset-less machine, most likely has AMI 'F' KBC firmware. */ { "[ISA] AMI IBM AT", "ibmatami", MACHINE_TYPE_286, CPU_PKG_286, 0, 6000000, 8000000, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_ibmatami_init, NULL }, + /* Uses Commodore (CBM) KBC firmware, to be implemented as identical to the + IBM AT KBC firmware unless evidence emerges of any proprietary commands. */ { "[ISA] Commodore PC 30 III", "cmdpc30", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 640, 16384, 128, 127, machine_at_cmdpc_init, NULL }, + /* Uses Compaq KBC firmware. */ { "[ISA] Compaq Portable II", "portableii", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 640, 16384, 128, 127, machine_at_portableii_init, NULL }, + /* Uses Compaq KBC firmware. */ { "[ISA] Compaq Portable III", "portableiii", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_VIDEO, 640, 16384, 128, 127, machine_at_portableiii_init, at_cpqiii_get_device }, + /* Has IBM AT KBC firmware. */ { "[ISA] MR 286 clone", "mr286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 512, 16384, 128, 127, machine_at_mr286_init, NULL }, + /* Has IBM AT KBC firmware. */ { "[ISA] NCR PC8/810/710/3390/3392", "pc8", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_pc8_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_OLIVETTI) + /* Has Olivetti KBC firmware. */ { "[ISA] Olivetti M290", "m290", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 640, 16384, 128, 127, machine_at_m290_init, NULL }, #endif - #if defined(DEV_BRANCH) && defined(USE_OPEN_AT) +#if defined(DEV_BRANCH) && defined(USE_OPEN_AT) + /* Has IBM AT KBC firmware. */ { "[ISA] OpenAT", "openat", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_openat_init, NULL }, #endif + /* Has IBM AT KBC firmware. */ { "[ISA] Phoenix IBM AT", "ibmatpx", MACHINE_TYPE_286, CPU_PKG_286, 0, 6000000, 8000000, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_ibmatpx_init, NULL }, + /* Has Quadtel KBC firmware. */ { "[ISA] Quadtel IBM AT", "ibmatquadtel", MACHINE_TYPE_286, CPU_PKG_286, 0, 6000000, 8000000, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_ibmatquadtel_init, NULL }, + /* This has a Siemens proprietary KBC which is completely undocumented. */ { "[ISA] Siemens PCD-2L", "siemens", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_siemens_init, NULL }, + /* This has Toshiba's proprietary KBC, which is already implemented. */ { "[ISA] Toshiba T3100e", "t3100e", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_VIDEO_FIXED, 1024, 5120, 256, 63, machine_at_t3100e_init, NULL }, + /* Has Quadtel KBC firmware. */ { "[GC103] Quadtel 286 clone", "quadt286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_quadt286_init, NULL }, + /* Most likely has AMI 'F' KBC firmware. */ { "[GC103] Trigem 286M", "tg286m", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 512, 8192, 128, 127, machine_at_tg286m_init, NULL }, - { "[NEAT] AMI 286 clone", "ami286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_neat_ami_init, NULL }, + /* This has "AMI KEYBOARD BIOS", most likely 'F'. */ + { "[NEAT] Dataexpert 286", "ami286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_neat_ami_init, NULL }, + /* Has IBM AT KBC firmware. */ { "[NEAT] NCR 3302", "3302", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_VIDEO, 512, 16384, 128, 127, machine_at_3302_init, NULL }, + /* Has IBM AT KBC firmware. */ { "[NEAT] Phoenix 286 clone", "px286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_px286_init, NULL }, - { "[SCAT] Award 286 clone", "award286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_award286_init, NULL }, + /* Has Chips & Technologies KBC firmware. */ { "[SCAT] GW-286CT GEAR", "gw286ct", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 512, 16384, 128, 127, machine_at_gw286ct_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[SCAT] Goldstar GDC-212M", "gdc212m", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_BUS_PS2, 512, 4096, 512, 127, machine_at_gdc212m_init, NULL }, + /* Has a VIA VT82C42N KBC. */ + { "[SCAT] Hyundai Solomon 286KP", "award286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_award286_init, NULL }, + /* Has a VIA VT82C42N KBC. */ { "[SCAT] Hyundai Super-286TR", "super286tr", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_super286tr_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[SCAT] Samsung SPC-4200P", "spc4200p", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2, 512, 2048, 128, 127, machine_at_spc4200p_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[SCAT] Samsung SPC-4216P", "spc4216p", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2, 1024, 5120,1024, 127, machine_at_spc4216p_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[SCAT] Samsung SPC-4620P", "spc4620p", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 5120,1024, 127, machine_at_spc4620p_init, NULL }, + /* Has IBM AT KBC firmware. */ { "[SCAT] Samsung Deskmaster 286", "deskmaster286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_deskmaster286_init, NULL }, /* 286 machines that utilize the MCA bus */ + /* Has IBM PS/2 Type 2 KBC firmware. */ { "[MCA] IBM PS/2 model 50", "ibmps2_m50", MACHINE_TYPE_286, CPU_PKG_286 | CPU_PKG_486SLC_IBM, 0, 10000000, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 10240,1024, 63, machine_ps2_model_50_init, NULL }, /* 386SX machines */ - { "[ISA] IBM PS/1 model 2121", "ibmps1_2121", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO_FIXED, 2048, 6144,1024, 63, machine_ps1_m2121_init, NULL }, - { "[ISA] IBM PS/1 m.2121+ISA", "ibmps1_2121_isa", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 6144,1024, 63, machine_ps1_m2121_init, NULL }, - { "[ISA] NCR PC916SX", "pc916sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 128, 127, machine_at_pc916sx_init, NULL }, + /* ISA slots available because an official IBM expansion for that existed. */ + /* Has IBM PS/2 Type 1 KBC firmware. */ + { "[ISA] IBM PS/1 model 2121", "ibmps1_2121", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 6144,1024, 63, machine_ps1_m2121_init, NULL }, + /* Has IBM AT KBC firmware. */ + { "[ISA] NCR PC916SX", "pc916sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 128, 127, machine_at_pc916sx_init, NULL }, + /* Has Quadtel KBC firmware. */ + { "[ISA] QTC-SXM KT X20T02/HI", "quadt386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 128, 127, machine_at_quadt386sx_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_M6117) + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[ALi M6117] Acrosser AR-B1375", "arb1375", MACHINE_TYPE_386SX, CPU_PKG_M6117, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768,1024, 127, machine_at_arb1375_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[ALi M6117] Acrosser PJ-A511M", "pja511m", MACHINE_TYPE_386SX, CPU_PKG_M6117, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768,1024, 127, machine_at_pja511m_init, NULL }, #endif - { "[ALi M1217] Flytech 386", "flytech386", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 16384, 1024, 127, machine_at_flytech386_init, at_flytech386_get_device }, + /* 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. */ + { "[ALi M1217] Flytech 386", "flytech386", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 16384, 1024, 127, machine_at_flytech386_init, at_flytech386_get_device }, + /* 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. */ { "[HT18] AMA-932J", "ama932j", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_VIDEO, 512, 8192, 128, 127, machine_at_ama932j_init, at_ama932j_get_device }, - { "[Intel 82335] ADI 386SX", "adi386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_adi386sx_init, NULL }, + /* Has an unknown KBC firmware with commands B8 and BB in the style of + Phoenix MultiKey and AMIKey-3(!), but also commands E1 and EA with + unknown functions. */ + { "[Intel 82335 ADI 386SX", "adi386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_adi386sx_init, NULL }, + /* Has an AMI Keyboard BIOS PLUS KBC firmware ('8'). */ { "[Intel 82335] Shuttle 386SX", "shuttle386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_shuttle386sx_init, NULL }, + /* Uses Commodore (CBM) KBC firmware, to be implemented as identical to + the IBM PS/2 Type 1 KBC firmware unless evidence emerges of any + proprietary commands. */ { "[NEAT] Commodore SL386SX-16", "cmdsl386sx16", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 8192, 512, 127, machine_at_cmdsl386sx16_init, NULL }, + /* Has IBM AT KBC firmware. */ { "[NEAT] DTK 386SX clone", "dtk386", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_neat_init, NULL }, - { "[OPTi 283] Olivetti M300-08", "m30008", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 20000000, 20000000, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 16384, 2048, 127, machine_at_m30008_init, at_m30008_get_device }, - { "[OPTi 283] Olivetti M300-15", "m30015", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 25000000, 25000000, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 16384, 2048, 127, machine_at_m30015_init, NULL }, + /* Has IBM AT KBC firmware. */ { "[OPTi 291] DTK PPM-3333P", "awardsx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_awardsx_init, NULL }, + /* Uses Commodore (CBM) KBC firmware, to be implemented as identical to + the IBM PS/2 Type 1 KBC firmware unless evidence emerges of any + proprietary commands. */ { "[SCAMP] Commodore SL386SX-25", "cmdsl386sx25", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 8192, 512, 127, machine_at_cmdsl386sx25_init, at_cmdsl386sx25_get_device }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[SCAMP] Samsung SPC-6033P", "spc6033p", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 12288, 2048, 127, machine_at_spc6033p_init, at_spc6033p_get_device }, + /* Has an unknown AMI KBC firmware, I'm going to assume 'F' until a + photo or real hardware BIOS string is found. */ { "[SCAT] KMX-C-02", "kmxc02", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 512, 127, machine_at_kmxc02_init, NULL }, + /* Has Quadtel KBC firmware. */ { "[WD76C10] Amstrad MegaPC", "megapc", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 32768, 1024, 127, machine_at_wd76c10_init, NULL }, /* 386SX machines which utilize the MCA bus */ + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[MCA] IBM PS/2 model 55SX", "ibmps2_m55sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 8192, 1024, 63, machine_ps2_model_55sx_init, NULL }, + /* 486SLC machines */ + /* 486SLC machines with just the ISA slot */ + /* Has AMIKey H KBC firmware. */ + { "[OPTi 283] RYC Leopard LX", "rycleopardlx", MACHINE_TYPE_486SLC, CPU_PKG_486SLC_IBM, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 16384, 1024, 127, machine_at_rycleopardlx_init, NULL }, + /* 386DX machines */ { "[ACC 2168] AMI 386DX clone", "acc386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_acc386_init, NULL }, + /* Has an AMI Keyboard BIOS PLUS KBC firmware ('8'). */ { "[C&T 386] ECS 386/32", "ecs386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_ecs386_init, NULL }, { "[C&T 386] Samsung SPC-6000A", "spc6000a", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_spc6000a_init, NULL }, + /* Uses Compaq KBC firmware. */ { "[ISA] Compaq Portable III (386)", "portableiii386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_VIDEO, 1024, 14336, 1024, 127, machine_at_portableiii386_init, at_cpqiii_get_device }, - { "[ISA] Micronics 386 clone", "micronics386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_micronics386_init, NULL }, - { "[SiS 310] ASUS ISA-386C", "asus386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_asus386_init, NULL }, + /* Has IBM AT KBC firmware. */ + { "[ISA] Micronics 09-00021", "micronics386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_micronics386_init, NULL }, + /* Has AMIKey F KBC firmware. */ + { "[SiS 310] ASUS ISA-386C", "asus386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 32768, 1024, 127, machine_at_asus386_init, NULL }, /* 386DX machines which utilize the MCA bus */ + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[MCA] IBM PS/2 model 70 (type 3)", "ibmps2_m70_type3", MACHINE_TYPE_386DX, CPU_PKG_386DX | CPU_PKG_486BL, 0, 0, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 2048, 16384, 2048, 63, machine_ps2_model_70_type3_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[MCA] IBM PS/2 model 80", "ibmps2_m80", MACHINE_TYPE_386DX, CPU_PKG_386DX | CPU_PKG_486BL, 0, 0, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 12288, 1024, 63, machine_ps2_model_80_init, NULL }, - { "[MCA] IBM PS/2 model 80 (type 3)", "ibmps2_m80_type3", MACHINE_TYPE_386DX, CPU_PKG_386DX | CPU_PKG_486BL, 0, 0, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 2048, 12288, 2048, 63, machine_ps2_model_80_axx_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ + { "[MCA] IBM PS/2 model 80 (type 3)", "ibmps2_m80_type3", MACHINE_TYPE_386DX, CPU_PKG_386DX | CPU_PKG_486BL, 0, 0, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 2048, 12288, 2048, 63, machine_ps2_model_80_axx_init, NULL }, /* 386DX/486 machines */ - { "[OPTi 495] Award 486 clone", "award486", MACHINE_TYPE_386DX_486, CPU_PKG_386DX | CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_init, NULL }, - { "[OPTi 495] Dataexpert SX495 (486)", "ami486", MACHINE_TYPE_386DX_486, CPU_PKG_386DX | CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_ami_init, NULL }, - { "[OPTi 495] MR 486 clone", "mr486", MACHINE_TYPE_386DX_486, CPU_PKG_386DX | CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_mr_init, NULL }, + /* The BIOS sends commands C9 without a parameter and D5, both of which are + Phoenix MultiKey commands. */ + { "[OPTi 495] Award 486 clone", "award495", MACHINE_TYPE_386DX_486, CPU_PKG_386DX | CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_init, NULL }, + /* Has AMIKey F KBC firmware. */ + { "[OPTi 495] Dataexpert SX495", "ami495", MACHINE_TYPE_386DX_486, CPU_PKG_386DX | CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_ami_init, NULL }, + /* Has AMIKey F KBC firmware (it's just the MR BIOS for the above machine). */ + { "[OPTi 495] Dataexpert SX495 (MR BIOS)", "mr495", MACHINE_TYPE_386DX_486, CPU_PKG_386DX | CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_mr_init, NULL }, /* 486 machines - Socket 1 */ + /* Has JetKey 5 KBC Firmware which looks like it is a clone of AMIKey type F. + It also has those Ex commands also seen on the VIA VT82C42N (the BIOS + supposedly sends command EF. + The board was also seen in 2003 with a -H string - perhaps someone swapped + the KBC? */ { "[ALi M1429] Olystar LIL1429", "ali1429", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_ali1429_init, NULL }, + /* Has JetKey 5 KBC Firmware - but the BIOS string ends in a hardcoded -F, and + the BIOS also explicitly expects command A1 to return a 'F', so it looks like + the JetKey 5 is a clone of AMIKey type F. */ { "[CS4031] AMI 486 CS4031", "cs4031", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_cs4031_init, NULL }, - { "[ETEQ ET6000] Olivetti PCS-46C", "pcs46c", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE | MACHINE_VIDEO, 4096, 32768, 4096, 127, machine_at_pcs46c_init, at_pcs46c_get_device }, + /* Uses some variant of Phoenix MultiKey/42 as the Intel 8242 chip has a Phoenix + copyright. */ { "[OPTi 895] Mylex MVI486", "mvi486", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE_DUAL, 1024, 65536, 1024, 127, machine_at_mvi486_init, NULL }, + /* Has AMI KF KBC firmware. */ + { "[SiS 401] ASUS ISA-486", "isa486", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_isa486_init, NULL }, + /* Has AMIKey H KBC firmware, per the screenshot in "How computers & MS-DOS work". */ + { "[SiS 401] Chaintech 433SC", "sis401", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_sis401_init, NULL }, + /* Has AMIKey F KBC firmware, per a photo of a monitor with the BIOS screen on + eBay. */ + { "[SiS 460] ABIT AV4", "av4", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_av4_init, NULL }, + /* Has a MR (!) KBC firmware, which is a clone of the standard IBM PS/2 KBC firmware. */ + { "[SiS 471] SiS VL-BUS 471 REV. A1", "px471", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024,131072, 1024, 127, machine_at_px471_init, NULL }, + /* The chip is a Lance LT38C41, a clone of the Intel 8041, and the BIOS sends + commands BC, BD, and C9 which exist on both AMIKey and Phoenix MultiKey/42, + but it does not write a byte after C9, which is consistent with AMIKey, so + this must have some form of AMIKey. */ { "[VIA VT82C495] FIC 486-VC-HD", "486vchd", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 64512, 1024, 127, machine_at_486vchd_init, 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. */ { "[VLSI 82C480] HP Vectra 486VL", "vect486vl", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 32768, 2048, 127, machine_at_vect486vl_init, at_vect486vl_get_device }, - { "[VLSI 82C481] Siemens Nixdorf D824", "d824", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 32768, 2048, 127, machine_at_d824_init, at_d824_get_device }, + /* Has a standard IBM PS/2 KBC firmware or a clone thereof. */ + { "[VLSI 82C481] Siemens Nixdorf D824", "d824", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 32768, 2048, 127, machine_at_d824_init, at_d824_get_device }, + + /* 486 machines - Socket 2 */ + /* 486 machines with just the ISA slot */ + /* Uses some variant of Phoenix MultiKey/42 as the BIOS sends keyboard controller + command C7 (OR input byte with received data byte). */ + { "[ACC 2168] Packard Bell PB410A", "pb410a", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 4096, 36864, 1024, 127, machine_at_pb410a_init, NULL }, + /* Uses an ACER/NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware (V4.01H). */ + { "[ALi M1429G] Acer A1G", "acera1g", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 4096, 36864, 1024, 127, machine_at_acera1g_init, at_acera1g_get_device }, + /* There are two similar BIOS strings with -H, and one with -U, so I'm going to + give it an AMIKey H KBC firmware. */ + { "[ALi M1429G] AMI WinBIOS 486", "win486", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_winbios1429_init, NULL }, + /* Uses an NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware. */ + { "[SiS 461] Acer V10", "acerv10", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 1024, 32768, 1024, 127, machine_at_acerv10_init, 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. */ + { "[SiS 461] IBM PS/ValuePoint 433DX/Si", "valuepoint433", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 65536, 1024, 127, machine_at_valuepoint433_init, 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. */ + { "[SiS 471] ABit AB-AH4", "win471", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_win471_init, NULL }, /* 486 machines - Socket 3 */ /* 486 machines with just the ISA slot */ - { "[ACC 2168] Packard Bell PB410A", "pb410a", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 4096, 36864, 1024, 127, machine_at_pb410a_init, NULL }, - { "[ALi M1429G] Acer A1G", "acera1g", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 4096, 36864, 1024, 127, machine_at_acera1g_init, at_acera1g_get_device }, - { "[ALi M1429] AMI WinBIOS 486", "win486", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_winbios1429_init, NULL }, + /* Has a VIA VT82C42N KBC. */ { "[OPTi 895] Jetway J-403TG", "403tg", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_403tg_init, NULL }, - { "[SiS 401] AMI 486 Clone", "sis401", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_sis401_init, NULL }, - { "[SiS 401] ASUS ISA-486", "isa486", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_isa486_init, NULL }, - { "[SiS 460] ABIT AV4", "av4", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_av4_init, NULL }, - { "[SiS 461] IBM PS/ValuePoint 433DX/Si", "valuepoint433", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 65536, 1024, 127, machine_at_valuepoint433_init, NULL }, - { "[SiS 471] AMI 486 Clone", "ami471", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_ami471_init, NULL }, - { "[SiS 471] AMI WinBIOS 486 clone", "win471", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_win471_init, NULL }, + /* Has JetKey 5 KBC Firmware which looks like it is a clone of AMIKey type F. */ + { "[OPTi 895] Jetway J-403TG Rev D", "403tg_rev_d", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_403tg_rev_d_init, NULL }, + /* Has JetKey 5 KBC Firmware which looks like it is a clone of AMIKey type F. */ + { "[OPTi 895] Jetway J-403TG Rev D (MR BIOS)","403tg_rev_d_mr", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_403tg_rev_d_mr_init, NULL }, + /* Has AMIKey H keyboard BIOS. */ { "[SiS 471] AOpen Vi15G", "vi15g", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_vi15g_init, NULL }, - { "[SiS 471] ASUS VL/I-486SV2G (GX4)", "vli486sv2g", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE_DUAL, 1024, 65536, 1024, 127, machine_at_vli486sv2g_init, NULL }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ + { "[SiS 471] ASUS VL/I-486SV2G (GX4)", "vli486sv2g", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 65536, 1024, 127, machine_at_vli486sv2g_init, NULL }, + /* Has JetKey 5 KBC Firmware which looks like it is a clone of AMIKey type F. */ { "[SiS 471] DTK PKM-0038S E-2", "dtk486", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_dtk486_init, NULL }, - { "[SiS 471] Phoenix SiS 471", "px471", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024,131072, 1024, 127, machine_at_px471_init, NULL }, + /* Unknown Epox VLB Socket 3 board, has AMIKey F keyboard BIOS. */ + { "[SiS 471] Epox 486SX/DX Green", "ami471", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_ami471_init, NULL }, /* 486 machines which utilize the PCI bus */ + /* Has the ALi M1487/9's on-chip keyboard controller which clones a standard AT + KBC. */ { "[ALi M1489] ABIT AB-PB4", "abpb4", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_abpb4_init, NULL }, + /* Has the ALi M1487/9's on-chip keyboard controller which clones a standard AT + KBC. + The BIOS string always ends in -U, but the BIOS will send AMIKey commands 0xCA + and 0xCB if command 0xA1 returns a letter in the 0x5x or 0x7x ranges, so I'm + going to give it an AMI 'U' KBC. */ { "[ALi M1489] AMI WinBIOS 486 PCI", "win486pci", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_win486pci_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[OPTi 802G] IBM PC 330 (type 6573)", "pc330_6573", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3_PC330, 0, 25000000, 33333333, 0, 0, 2.0, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_pc330_6573_init, NULL }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[i420EX] ASUS PVI-486AP4", "486ap4", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_IDE_DUAL, 1024, 131072, 1024, 127, machine_at_486ap4_init, NULL }, + /* This has the Phoenix MultiKey KBC firmware. */ + { "[i420EX] Intel Classic/PCI ED", "ninja", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 131072, 1024, 127, machine_at_ninja_init, NULL }, + /* This has an AMIKey-2, which is an updated version of type 'H'. Also has a + SST 29EE010 Flash chip. */ { "[i420ZX] ASUS PCI/I-486SP3G", "486sp3g", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL | MACHINE_SCSI, 1024, 131072, 1024, 127, machine_at_486sp3g_init, NULL }, + /* I'm going to assume this as an AMIKey-2 like the other two 486SP3's. */ { "[i420TX] ASUS PCI/I-486SP3", "486sp3", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL | MACHINE_SCSI, 1024, 131072, 1024, 127, machine_at_486sp3_init, NULL }, + /* This has the Phoenix MultiKey KBC firmware. */ { "[i420TX] Intel Classic/PCI", "alfredo", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_alfredo_init, NULL }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[SiS 496] ASUS PVI-486SP3C", "486sp3c", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_IDE_DUAL, 1024, 261120, 1024, 255, machine_at_486sp3c_init, NULL }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[SiS 496] Lucky Star LS-486E", "ls486e", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_ls486e_init, NULL }, + /* The BIOS does not send a single non-standard KBC command, so it has a standard PS/2 KBC. */ { "[SiS 496] Micronics M4Li", "m4li", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 131072, 1024, 127, machine_at_m4li_init, NULL }, + /* Has a BestKey KBC which clones AMI type 'H'. */ { "[SiS 496] Rise Computer R418", "r418", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 261120, 1024, 255, machine_at_r418_init, NULL }, + /* This has a Holtek 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. */ { "[SiS 496] Soyo 4SA2", "4sa2", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, CPU_BLOCK(CPU_i486SX, CPU_i486DX, CPU_Am486SX, CPU_Am486DX), 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 261120, 1024, 255, machine_at_4sa2_init, NULL }, + /* According to MrKsoft, his real 4DPS has an AMIKey-2, which is an updated version + of type 'H'. */ { "[SiS 496] Zida Tomato 4DP", "4dps", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 261120, 1024, 255, machine_at_4dps_init, NULL }, - { "[UMC 8881] A-Trend ATC-1415", "atc1415", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_atc1415_init, NULL }, - { "[UMC 8881] ECS Elite UM8810PAIO", "ecs486", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_ecs486_init, NULL }, - { "[UMC 8881] Shuttle HOT-433A", "hot433", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 262144, 1024, 255, machine_at_hot433_init, NULL }, + /* Has a VIA VT82C406 KBC+RTC that likely has identical commands to the VT82C42N. */ + { "[VIA VT82C496G] DFI G486VPA", "g486vpa", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_g486vpa_init, NULL }, + /* Has a VIA VT82C42N KBC. */ { "[VIA VT82C496G] FIC VIP-IO2", "486vipio2", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_486vipio2_init, NULL }, /* 486 machines - Miscellaneous */ - /* 486 machines with just the ISA slot */ - { "[OPTi 283] RYC Leopard LX", "rycleopardlx", MACHINE_TYPE_486_MISC, CPU_PKG_486SLC_IBM, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 16384, 1024, 127, machine_at_rycleopardlx_init, NULL }, - /* 486 machines which utilize the PCI bus */ + /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[STPC Client] ITOX STAR", "itoxstar", MACHINE_TYPE_486_MISC, CPU_PKG_STPC, 0, 66666667, 75000000, 0, 0, 1.0, 1.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 255, machine_at_itoxstar_init, NULL }, + /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[STPC Consumer-II] Acrosser AR-B1479", "arb1479", MACHINE_TYPE_486_MISC, CPU_PKG_STPC, 0, 66666667, 66666667, 0, 0, 2.0, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 32768, 163840, 8192, 255, machine_at_arb1479_init, NULL }, + /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[STPC Elite] Advantech PCM-9340", "pcm9340", MACHINE_TYPE_486_MISC, CPU_PKG_STPC, 0, 66666667, 66666667, 0, 0, 2.0, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 32768, 98304, 8192, 255, machine_at_pcm9340_init, NULL }, + /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[STPC Atlas] AAEON PCM-5330", "pcm5330", MACHINE_TYPE_486_MISC, CPU_PKG_STPC, 0, 66666667, 66666667, 0, 0, 2.0, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 32768, 131072,32768, 255, machine_at_pcm5330_init, NULL }, /* Socket 4 machines */ /* 430LX */ + /* Has AMIKey F KBC firmware (AMIKey). */ { "[i430LX] ASUS P/I-P5MP3", "p5mp3", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE, 2048, 196608, 2048, 127, machine_at_p5mp3_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[i430LX] Dell Dimension XPS P60", "dellxp60", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE, 2048, 131072, 2048, 127, machine_at_dellxp60_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[i430LX] Dell OptiPlex 560/L", "opti560l", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_opti560l_init, NULL }, + /* This has the Phoenix MultiKey KBC firmware. + This is basically an Intel Batman (*NOT* Batman's Revenge) with a fancier + POST screen */ { "[i430LX] AMBRA DP60 PCI", "ambradp60", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_ambradp60_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[i430LX] IBM PS/ValuePoint P60", "valuepointp60", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_valuepointp60_init, NULL }, - { "[i430LX] Intel Premiere/PCI", "revenge", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_batman_init, NULL }, + /* This has the Phoenix MultiKey KBC firmware. */ + { "[i430LX] Intel Premiere/PCI", "revenge", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_revenge_init, NULL }, + /* Has AMI MegaKey KBC firmware. */ { "[i430LX] Micro Star 586MC1", "586mc1", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_586mc1_init, NULL }, + /* This has the Phoenix MultiKey KBC firmware. */ { "[i430LX] Packard Bell PB520R", "pb520r", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 139264, 2048, 127, machine_at_pb520r_init, at_pb520r_get_device }, /* OPTi 596/597 */ + /* This uses an AMI KBC firmware in PS/2 mode (it sends command A5 with the + PS/2 "Load Security" meaning), most likely MegaKey as it sends command AF + (Set Extended Controller RAM) just like the later Intel AMI BIOS'es. */ { "[OPTi 597] AMI Excalibur VLB", "excalibur", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_VLB | MACHINE_IDE, 2048, 65536, 2048, 127, machine_at_excalibur_init, NULL }, + /* OPTi 596/597/822 */ + /* This has AMIKey 'F' KBC firmware. */ + { "[OPTi 597] Supermicro P5VL-PCI", "p5vl", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_VLB, 8192, 131072, 8192, 127, machine_at_p5vl_init, NULL }, + /* SiS 85C50x */ + /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[SiS 85C50x] ASUS PCI/I-P5SP4", "p5sp4", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p5sp4_init, NULL }, /* Socket 5 machines */ /* 430NX */ + /* This has the Phoenix MultiKey KBC firmware. */ { "[i430NX] Intel Premiere/PCI II", "plato", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_plato_init, NULL }, + /* This has the Phoenix MultiKey KBC firmware. + This is basically an Intel Premiere/PCI II with a fancier POST screen. */ { "[i430NX] AMBRA DP90 PCI", "ambradp90", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_ambradp90_init, NULL }, + /* Has AMI MegaKey KBC firmware. */ { "[i430NX] Gigabyte GA-586IP", "430nx", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_430nx_init, NULL }, /* 430FX */ + /* Uses an ACER/NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware (V5.0). */ { "[i430FX] Acer V30", "acerv30", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_acerv30_init, NULL }, + /* Has AMIKey F KBC firmware. */ { "[i430FX] AMI Apollo", "apollo", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_apollo_init, NULL }, + /* Has AMIKey H KBC firmware. */ + { "[i430FX] Dataexpert EXP8551", "exp8551", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_exp8551_init, NULL }, + /* The BIOS does not send a single non-standard KBC command, but the board has a SMC Super I/O + chip with on-chip KBC and AMI MegaKey KBC firmware. */ { "[i430FX] HP Vectra VL 5 Series 4", "vectra54", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 511, machine_at_vectra54_init, at_vectra54_get_device }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430FX] Intel Advanced/ZP", "zappa", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_zappa_init, NULL }, + /* The BIOS sends KBC command B3 which indicates an AMI (or VIA VT82C42N) KBC. */ { "[i430FX] NEC PowerMate V", "powermatev", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_powermatev_init, NULL }, + /* Has a VIA VT82C42N KBC. */ { "[i430FX] PC Partner MB500N", "mb500n", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_mb500n_init, NULL }, + /* Has AMIKey Z(!) KBC firmware. */ + { "[i430FX] Trigem Hawk", "hawk", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_hawk_init, NULL }, /* OPTi 596/597 */ + /* This uses an AMI KBC firmware in PS/2 mode (it sends command A5 with the + PS/2 "Load Security" meaning), most likely MegaKey as it sends command AF + (Set Extended Controller RAM) just like the later Intel AMI BIOS'es. */ { "[OPTi 597] TMC PAT54PV", "pat54pv", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_K5, CPU_5K86), 50000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_VLB, 2048, 65536, 2048, 127, machine_at_pat54pv_init, NULL }, /* OPTi 596/597/822 */ { "[OPTi 597] Shuttle HOT-543", "hot543", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_VLB, 8192, 131072, 8192, 127, machine_at_hot543_init, NULL }, - { "[OPTi 597] Supermicro P54VL-PCI", "p54vl", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_VLB, 8192, 131072, 8192, 127, machine_at_p54vl_init, NULL }, /* SiS 85C50x */ + /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[SiS 85C50x] ASUS PCI/I-P54SP4", "p54sp4", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_K5, CPU_5K86), 40000000, 66666667, 3380, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p54sp4_init, NULL }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[SiS 85C50x] BCM SQ-588", "sq588", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_PENTIUMMMX), 50000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_sq588_init, NULL }, - /* UMC 889x */ - { "[UMC 889x] Shuttle HOT-539", "hot539", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_K5, CPU_5K86), 40000000, 66666667, 3380, 3600, 1.5, 2.0, MACHINE_PCI | MACHINE_IDE_DUAL, 8192, 262144, 8192, 127, machine_at_hot539_init, NULL }, - /* Socket 7 (Single Voltage) machines */ /* 430FX */ + /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[i430FX] ASUS P/I-P54TP4XE", "p54tp4xe", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3600, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p54tp4xe_init, NULL }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[i430FX] ASUS P/I-P54TP4XE (MR BIOS)", "mr586", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3600, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_mr586_init, NULL }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430FX] Gateway 2000 Thor", "gw2katx", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_gw2katx_init, NULL }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430FX] Intel Advanced/ATX", "thor", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_thor_init, NULL }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430FX] Intel Advanced/ATX (MR BIOS)", "mrthor", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_mrthor_init, NULL }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430FX] Intel Advanced/EV", "endeavor", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_endeavor_init, at_endeavor_get_device }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ + { "[i430FX] MSI MS-5119", "ms5119", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_ms5119_init, NULL }, + /* This most likely uses AMI MegaKey KBC firmware as well due to having the same + Super I/O chip (that has the KBC firmware on it) as eg. the Advanced/EV. */ { "[i430FX] Packard Bell PB640", "pb640", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_pb640_init, at_pb640_get_device }, - { "[i430FX] QDI Chariot", "chariot", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_WINCHIP, CPU_WINCHIP2, CPU_Cx6x86, CPU_Cx6x86L, CPU_Cx6x86MX), 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_chariot_init, NULL }, + /* Has an AMI 'H' KBC firmware (1992). */ + { "[i430FX] QDI FMB", "fmb", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_WINCHIP, CPU_WINCHIP2, CPU_Cx6x86, CPU_Cx6x86L, CPU_Cx6x86MX), 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_fmb_init, NULL }, /* 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. */ { "[i430HX] Acer M3A", "acerm3a", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3300, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 196608, 8192, 127, machine_at_acerm3a_init, NULL }, + /* Has AMIKey F KBC firmware. */ { "[i430HX] AOpen AP53", "ap53", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3450, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_ap53_init, NULL }, + /* [TEST] Has a VIA 82C42N KBC, with AMIKey F KBC firmware. */ { "[i430HX] Biostar MB-8500TUC", "8500tuc", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_8500tuc_init, 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. */ { "[i430HX] SuperMicro Super P55T2S", "p55t2s", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3300, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 127, machine_at_p55t2s_init, NULL }, /* 430VX */ + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430VX] Gateway 2000 Tigereye", "gw2kte", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_gw2kte_init, NULL }, /* SiS 5511 */ - { "[SiS 5511] AOpen AP5S", "ap5s", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_ap5s_init, NULL }, + /* Has AMIKey H KBC firmware (AMIKey-2). */ + { "[SiS 5511] AOpen AP5S", "ap5s", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_ap5s_init, NULL }, /* Socket 7 (Dual Voltage) machines */ /* 430HX */ + /* Has SST flash and the SMC FDC73C935's on-chip KBC with Phoenix MultiKey firmware. */ { "[i430HX] Acer V35N", "acerv35n", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_Cx6x86MX), 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 196608, 8192, 127, machine_at_acerv35n_init, NULL }, + /* Has AMIKey H KBC firmware (AMIKey-2). */ { "[i430HX] ASUS P/I-P55T2P4", "p55t2p4", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 83333333, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 127, machine_at_p55t2p4_init, NULL }, + /* Has the SMC FDC73C935's on-chip KBC with Phoenix MultiKey firmware. */ { "[i430HX] Micronics M7S-Hi", "m7shi", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 511, machine_at_m7shi_init, NULL }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430HX] Intel TC430HX", "tc430hx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 255, machine_at_tc430hx_init, NULL }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430HX] Toshiba Equium 5200D", "equium5200", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 196608, 8192, 127, machine_at_equium5200_init, NULL }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . + Yes, this is an Intel AMI BIOS with a fancy splash screen. */ { "[i430HX] Sony Vaio PCV-240", "pcv240", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 196608, 8192, 127, machine_at_pcv240_init, NULL }, + /* The base board has AMIKey-2 (updated 'H') KBC firmware. */ { "[i430HX] ASUS P/I-P65UP5 (C-P55T2D)", "p65up5_cp55t2d", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_p65up5_cp55t2d_init, NULL }, /* 430VX */ + /* Has AMIKey H KBC firmware (AMIKey-2). */ { "[i430VX] ASUS P/I-P55TVP4", "p55tvp4", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p55tvp4_init, NULL }, + /* The BIOS does not send a single non-standard KBC command, so it must have a standard IBM + PS/2 KBC firmware or a clone thereof. */ { "[i430VX] Azza 5IVG", "5ivg", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_5ivg_init, NULL }, + /* [TEST] Has AMIKey 'F' KBC firmware. */ { "[i430VX] Biostar MB-8500TVX-A", "8500tvxa", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2600, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_8500tvxa_init, NULL }, + /* The BIOS does not send a single non-standard KBC command, but the board has a SMC Super I/O + chip with on-chip KBC and AMI MegaKey KBC firmware. */ { "[i430VX] Compaq Presario 2240", "presario2240", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_presario2240_init, NULL }, + /* This most likely has AMI MegaKey as above. */ { "[i430VX] Compaq Presario 4500", "presario4500", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_presario4500_init, NULL }, + /* The BIOS sends KBC command CB which is an AMI KBC command, so it has an AMI KBC firmware. */ { "[i430VX] Epox P55-VA", "p55va", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p55va_init, NULL }, + /* The BIOS does not send a single non-standard KBC command. */ { "[i430VX] HP Brio 80xx", "brio80xx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 66666667, 66666667, 2200, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_brio80xx_init, NULL }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430VX] Packard Bell PB680", "pb680", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_pb680_init, NULL }, + /* This has the AMIKey 'H' firmware, possibly AMIKey-2. Photos show it with a BestKey, so it + likely clones the behavior of AMIKey 'H'. */ { "[i430VX] PC Partner MB520N", "mb520n", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2600, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_mb520n_init, NULL }, + /* This has a Holtek 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. */ { "[i430VX] Shuttle HOT-557", "430vx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_GAMEPORT, 8192, 131072, 8192, 127, machine_at_i430vx_init, NULL }, /* 430TX */ + /* The BIOS sends KBC command B8, CA, and CB, so it has an AMI KBC firmware. */ { "[i430TX] ADLink NuPRO-592", "nupro592", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 66666667, 66666667, 1900, 2800, 1.5, 5.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_nupro592_init, NULL }, + /* This has the AMIKey KBC firmware, which is an updated 'F' type (YM430TX is based on the TX97). */ { "[i430TX] ASUS TX97", "tx97", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 75000000, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_tx97_init, NULL }, #if defined(DEV_BRANCH) && defined(NO_SIO) + /* This has the Phoenix MultiKey KBC firmware. */ { "[i430TX] Intel AN430TX", "an430tx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_an430tx_init, NULL }, #endif + /* This has the AMIKey KBC firmware, which is an updated 'F' type. */ { "[i430TX] Intel YM430TX", "ym430tx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_ym430tx_init, NULL }, + /* The BIOS sends KBC command BB and expects it to output a byte, which is AMI KBC behavior. */ { "[i430TX] PC Partner MB540N", "mb540n", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2700, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_mb540n_init, NULL }, + /* [TEST] Has AMIKey 'H' KBC firmware. */ { "[i430TX] SuperMicro Super P5MMS98", "p5mms98", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2100, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_p5mms98_init, NULL }, /* Apollo VPX */ + /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA + VT82C42N. */ { "[VIA VPX] FIC VA-502", "ficva502", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 75000000, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_ficva502_init, NULL }, /* Apollo VP3 */ + /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA + VT82C42N. */ { "[VIA VP3] FIC PA-2012", "ficpa2012", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 55000000, 75000000, 2100, 3520, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 127, machine_at_ficpa2012_init, NULL }, /* SiS 5571 */ + /* Has the SiS 5571 chipset with on-chip KBC. */ { "[SiS 5571] Rise R534F", "r534f", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 393216, 8192, 127, machine_at_r534f_init, NULL }, + /* Has the SiS 5571 chipset with on-chip KBC. */ { "[SiS 5571] MSI MS-5146", "ms5146", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 127, machine_at_ms5146_init, NULL }, - /* SiS 5598 */ - { "[SiS 5598] ASUS SP97-XV", "sp97xv", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2100, 3200, 1.5, 2.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_sp97xv_init, NULL }, - { "[SiS 5598] PC Chips M571", "m571", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 75000000, 2500, 3500, 1.5, 3.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_m571_init, NULL }, - /* ALi ALADDiN IV */ -#if defined(DEV_BRANCH) && defined(USE_M154X) + /* Has the ALi M1543 southbridge with on-chip KBC. */ { "[ALi ALADDiN IV] PC Chips M560", "m560", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 83333333, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_m560_init, NULL }, + /* Has the ALi M1543 southbridge with on-chip KBC. */ { "[ALi ALADDiN IV] MSI MS-5164", "ms5164", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2100, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_ms5164_init, NULL }, -#endif /* Super Socket 7 machines */ /* Apollo MVP3 */ + /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA + VT82C42N. */ { "[VIA MVP3] AOpen AX59 Pro", "ax59pro", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 1300, 3520, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_ax59pro_init, NULL }, + /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA + VT82C42N. */ { "[VIA MVP3] FIC VA-503+", "ficva503p", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 2000, 3200, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_mvp3_init, NULL }, + /* Has the VIA VT82C686A southbridge with on-chip KBC identical to the VIA + VT82C42N. */ { "[VIA MVP3] FIC VA-503A", "ficva503a", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 1800, 3100, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_ficva503a_init, NULL }, /* Socket 8 machines */ /* 450KX */ #if defined(DEV_BRANCH) && defined(USE_I450KX) + /* This has an AMIKey, which is an updated version of type 'F'. */ { "[i450KX] ASUS P/I-P6RP4", "p6rp4", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_p6rp4_init, NULL }, #endif /* 440FX */ + /* Has the SMC FDC73C935's on-chip KBC with Phoenix MultiKey firmware. */ { "[i440FX] Acer V60N", "v60n", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2500, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_v60n_init, NULL }, + /* The base board has AMIKey-2 (updated 'H') KBC firmware. */ { "[i440FX] ASUS P/I-P65UP5 (C-P6ND)", "p65up5_cp6nd", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 127, machine_at_p65up5_cp6nd_init, 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. */ { "[i440FX] Biostar MB-8600TTC", "8600ttc", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 50000000, 66666667, 2900, 3300, 2.0, 5.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 127, machine_at_8500ttc_init, NULL }, { "[i440FX] Gigabyte GA-686NX", "686nx", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 2.0, 5.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_686nx_init, NULL }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i440FX] Intel AP440FX", "ap440fx", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 2.0, 3.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_ap440fx_init, NULL }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i440FX] Intel VS440FX", "vs440fx", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 2.0, 3.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_vs440fx_init, NULL }, + /* Has the SMC FDC73C935's on-chip KBC with Phoenix MultiKey firmware. */ { "[i440FX] Micronics M6Mi", "m6mi", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2900, 3300, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 127, machine_at_m6mi_init, 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. */ { "[i440FX] PC Partner MB600N", "mb600n", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_mb600n_init, NULL }, /* Slot 1 machines */ /* 440FX */ + /* The base board has AMIKey-2 (updated 'H') KBC firmware. */ { "[i440FX] ASUS P/I-P65UP5 (C-PKND)", "p65up5_cpknd", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 50000000, 66666667, 1800, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 127, machine_at_p65up5_cpknd_init, NULL }, + /* This has a Holtek 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. */ { "[i440FX] ASUS KN97", "kn97", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 60000000, 83333333, 1800, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 127, machine_at_kn97_init, NULL }, /* 440LX */ + /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440LX] ABIT LX6", "lx6", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 60000000, 100000000, 1500, 3500, 2.0, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_lx6_init, NULL }, + /* Has a SM(S)C FDC37C935 Super I/O chip with on-chip KBC with Phoenix + MultiKey KBC firmware. */ { "[i440LX] Micronics Spitfire", "spitfire", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 66666667, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_spitfire_init, NULL }, /* 440EX */ + /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440EX] QDI EXCELLENT II", "p6i440e2", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 83333333, 1800, 3500, 3.0, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 255, machine_at_p6i440e2_init, NULL }, /* 440BX */ + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] ASUS P2B-LS", "p2bls", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 50000000, 112121212, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_p2bls_init, NULL }, + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] ASUS P3B-F", "p3bf", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_p3bf_init, NULL }, + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] ABIT BF6", "bf6", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 133333333, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_bf6_init, NULL }, + /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] AOpen AX6BC", "ax6bc", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 112121212, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_ax6bc_init, NULL }, + /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] Gigabyte GA-686BX", "686bx", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_686bx_init, NULL }, + /* Has a SM(S)C FDC37M60x Super I/O chip with on-chip KBC with most likely + AMIKey-2 KBC firmware. */ { "[i440BX] HP Vectra VEi 8", "vei8", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_vei8_init, NULL }, + /* Has a National Semiconductors PC87309 Super I/O chip with on-chip KBC + with most likely AMIKey-2 KBC firmware. */ { "[i440BX] Tyan Tsunami ATX", "tsunamiatx", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 112121212, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_SOUND, 8192,1048576, 8192, 255, machine_at_tsunamiatx_init, at_tsunamiatx_get_device }, + /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] SuperMicro Super P6SBA", "p6sba", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_p6sba_init, NULL }, -#if defined(DEV_BRANCH) && defined(NO_SIO) - { "[i440BX] Fujitsu ErgoPro x365", "ergox365", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 393216, 8192, 511, machine_at_ergox365_init, NULL }, -#endif /* 440ZX */ + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440ZX] MSI MS-6168", "ms6168", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_SOUND,8192, 524288, 8192, 255, machine_at_ms6168_init, NULL }, + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440ZX] Packard Bell Bora Pro", "borapro", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 66666667, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_SOUND,8192, 524288, 8192, 255, machine_at_borapro_init, NULL }, /* SMSC VictoryBX-66 */ + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[SMSC VictoryBX-66] A-Trend ATC6310BXII","atc6310bxii", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_atc6310bxii_init, NULL }, /* VIA Apollo Pro */ + /* Has the VIA VT82C596B southbridge with on-chip KBC identical to the VIA + VT82C42N. */ { "[VIA Apollo Pro] FIC KA-6130", "ficka6130", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 255, machine_at_ficka6130_init, NULL }, + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[VIA Apollo Pro133] ASUS P3V133", "p3v133", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1572864, 8192, 255, machine_at_p3v133_init, NULL }, + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[VIA Apollo Pro133A] ASUS P3V4X", "p3v4x", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,2097152, 8192, 255, machine_at_p3v4x_init, NULL }, /* Slot 1/2 machines */ /* 440GX */ + /* Has a National Semiconductors PC87309 Super I/O chip with on-chip KBC + with most likely AMIKey-2 KBC firmware. */ { "[i440GX] Freeway FW-6400GX", "fw6400gx", MACHINE_TYPE_SLOT1_2, CPU_PKG_SLOT1 | CPU_PKG_SLOT2, 0, 100000000, 150000000, 1800, 3500, 3.0, 8.0, (MACHINE_AGP & ~MACHINE_AT) | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 16384,2080768,16384, 511, machine_at_fw6400gx_init, NULL }, /* Slot 2 machines */ /* 440GX */ + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440GX] Gigabyte GA-6GXU", "6gxu", MACHINE_TYPE_SLOT2, CPU_PKG_SLOT2, 0, 100000000, 133333333, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 16384,2097152,16384, 511, machine_at_6gxu_init, NULL }, + /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440GX] SuperMicro Super S2DGE", "s2dge", MACHINE_TYPE_SLOT2, CPU_PKG_SLOT2, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 16384,2097152,16384, 511, machine_at_s2dge_init, NULL }, /* PGA370 machines */ /* 440LX */ + /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440LX] SuperMicro Super 370SLM", "s370slm", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 100000000, 1800, 3500, MACHINE_MULTIPLIER_FIXED, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_s370slm_init, NULL }, /* 440BX */ + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] AEWIN AW-O671R", "awo671r", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, /* limits assumed */ MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 255, machine_at_awo671r_init, NULL }, + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] ASUS CUBX", "cubx", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_cubx_init, NULL }, + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] AmazePC AM-BX133", "ambx133", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, /* limits assumed */ MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_ambx133_init, NULL }, + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] Tyan Trinity 371", "trinity371", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_trinity371_init, NULL }, /* 440ZX */ + /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440ZX] Soltek SL-63A1", "63a", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 255, machine_at_63a_init, NULL }, /* SMSC VictoryBX-66 */ + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[SMSC VictoryBX-66] A-Trend ATC7020BXII","atc7020bxii", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_atc7020bxii_init, NULL }, /* VIA Apollo Pro */ + /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA + VT82C42N. */ { "[VIA Apollo Pro] PC Partner APAS3", "apas3", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_apas3_init, NULL }, + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[VIA Apollo Pro133] ECS P6BAP", "p6bap", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1572864, 8192, 255, machine_at_p6bap_init, NULL }, + /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[VIA Apollo Pro133A] AEWIN WCF-681", "wcf681", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, /* limits assumed */ MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_wcf681_init, NULL }, + /* Has the VIA VT82C686B southbridge with on-chip KBC identical to the VIA + VT82C42N. */ { "[VIA Apollo Pro133A] ASUS CUV4X-LS", "cuv4xls", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, (MACHINE_AGP & ~MACHINE_AT) | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 16384,1572864, 8192, 255, machine_at_cuv4xls_init, NULL }, + /* Has the VIA VT82C686B southbridge with on-chip KBC identical to the VIA + VT82C42N. */ { "[VIA Apollo Pro133A] Acorp 6VIA90AP", "6via90ap", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, MACHINE_MULTIPLIER_FIXED, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1572864, 8192, 255, machine_at_6via90ap_init, NULL }, - { "[VIA Apollo ProMedia] Jetway 603TCF", "603tcf", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_603tcf_init, NULL }, /* Miscellaneous/Fake/Hypervisor machines */ + /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] Microsoft Virtual PC 2007", "vpc2007", MACHINE_TYPE_MISC, CPU_PKG_SLOT1, CPU_BLOCK(CPU_PENTIUM2, CPU_CYRIX3S), 0, 0, 0, 0, 0, 0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_vpc2007_init, NULL }, { NULL, NULL, MACHINE_TYPE_NONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL } diff --git a/src/mem/mem.c b/src/mem/mem.c index cac528a59..79e27f011 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -1794,7 +1794,7 @@ mem_read_ram(uint32_t addr, void *priv) mem_log("Read B %02X from %08X\n", ram[addr], addr); #endif - if (AT) + if (is286 || AT) addreadlookup(mem_logical_addr, addr); return ram[addr]; @@ -1809,7 +1809,7 @@ mem_read_ramw(uint32_t addr, void *priv) mem_log("Read W %04X from %08X\n", *(uint16_t *)&ram[addr], addr); #endif - if (AT) + if (is286 || AT) addreadlookup(mem_logical_addr, addr); return *(uint16_t *)&ram[addr]; @@ -1824,7 +1824,7 @@ mem_read_raml(uint32_t addr, void *priv) mem_log("Read L %08X from %08X\n", *(uint32_t *)&ram[addr], addr); #endif - if (AT) + if (is286 || AT) addreadlookup(mem_logical_addr, addr); return *(uint32_t *)&ram[addr]; @@ -2068,7 +2068,7 @@ mem_write_ram(uint32_t addr, uint8_t val, void *priv) if ((addr >= 0xa0000) && (addr <= 0xbffff)) mem_log("Write B %02X to %08X\n", val, addr); #endif - if (AT) { + if (is286 || AT) { addwritelookup(mem_logical_addr, addr); mem_write_ramb_page(addr, val, &pages[addr >> 12]); } else @@ -2083,7 +2083,7 @@ mem_write_ramw(uint32_t addr, uint16_t val, void *priv) if ((addr >= 0xa0000) && (addr <= 0xbffff)) mem_log("Write W %04X to %08X\n", val, addr); #endif - if (AT) { + if (is286 || AT) { addwritelookup(mem_logical_addr, addr); mem_write_ramw_page(addr, val, &pages[addr >> 12]); } else @@ -2098,7 +2098,7 @@ mem_write_raml(uint32_t addr, uint32_t val, void *priv) if ((addr >= 0xa0000) && (addr <= 0xbffff)) mem_log("Write L %08X to %08X\n", val, addr); #endif - if (AT) { + if (is286 || AT) { addwritelookup(mem_logical_addr, addr); mem_write_raml_page(addr, val, &pages[addr >> 12]); } else @@ -2110,7 +2110,7 @@ static uint8_t mem_read_remapped(uint32_t addr, void *priv) { addr = 0xA0000 + (addr - remap_start_addr); - if (AT) + if (is286 || AT) addreadlookup(mem_logical_addr, addr); return ram[addr]; } @@ -2120,7 +2120,7 @@ static uint16_t mem_read_remappedw(uint32_t addr, void *priv) { addr = 0xA0000 + (addr - remap_start_addr); - if (AT) + if (is286 || AT) addreadlookup(mem_logical_addr, addr); return *(uint16_t *)&ram[addr]; } @@ -2130,7 +2130,7 @@ static uint32_t mem_read_remappedl(uint32_t addr, void *priv) { addr = 0xA0000 + (addr - remap_start_addr); - if (AT) + if (is286 || AT) addreadlookup(mem_logical_addr, addr); return *(uint32_t *)&ram[addr]; } @@ -2141,7 +2141,7 @@ mem_write_remapped(uint32_t addr, uint8_t val, void *priv) { uint32_t oldaddr = addr; addr = 0xA0000 + (addr - remap_start_addr); - if (AT) { + if (is286 || AT) { addwritelookup(mem_logical_addr, addr); mem_write_ramb_page(addr, val, &pages[oldaddr >> 12]); } else @@ -2154,7 +2154,7 @@ mem_write_remappedw(uint32_t addr, uint16_t val, void *priv) { uint32_t oldaddr = addr; addr = 0xA0000 + (addr - remap_start_addr); - if (AT) { + if (is286 || AT) { addwritelookup(mem_logical_addr, addr); mem_write_ramw_page(addr, val, &pages[oldaddr >> 12]); } else @@ -2167,7 +2167,7 @@ mem_write_remappedl(uint32_t addr, uint32_t val, void *priv) { uint32_t oldaddr = addr; addr = 0xA0000 + (addr - remap_start_addr); - if (AT) { + if (is286 || AT) { addwritelookup(mem_logical_addr, addr); mem_write_raml_page(addr, val, &pages[oldaddr >> 12]); } else @@ -2536,7 +2536,7 @@ mem_a20_init(void) flushmmucache(); mem_a20_state = mem_a20_key | mem_a20_alt; } else { - rammask = 0xfffff; + rammask = is286 ? 0xffffff : 0xfffff; flushmmucache(); mem_a20_key = mem_a20_alt = mem_a20_state = 0; } @@ -2662,15 +2662,20 @@ mem_reset(void) */ if (AT) { if (cpu_16bitbus) { - /* 80186/286; maximum address space is 16MB. */ + /* 80286/386SX; maximum address space is 16MB. */ m = 4096; } else { - /* 80386+; maximum address space is 4GB. */ + /* 80386DX+; maximum address space is 4GB. */ m = 1048576; } } else { - /* 8088/86; maximum address space is 1MB. */ - m = 256; + if (is286) { + /* 80286; maximum address space is 16MB. */ + m = 4096; + } else { + /* 8088/86; maximum address space is 1MB. */ + m = 256; + } } /* @@ -2864,7 +2869,7 @@ mem_a20_recalc(void) int state; if (! AT) { - rammask = 0xfffff; + rammask = is286 ? 0xffffff : 0xfffff; flushmmucache(); mem_a20_key = mem_a20_alt = mem_a20_state = 0; diff --git a/src/mem/rom.c b/src/mem/rom.c index efb173d0b..2f81957bf 100644 --- a/src/mem/rom.c +++ b/src/mem/rom.c @@ -392,10 +392,12 @@ static void bios_add(void) { int temp_cpu_type, temp_cpu_16bitbus = 1; + int temp_is286 = 0; - if (AT && cpu_s) { + if (/*AT && */cpu_s) { temp_cpu_type = cpu_s->cpu_type; temp_cpu_16bitbus = (temp_cpu_type == CPU_286 || temp_cpu_type == CPU_386SX || temp_cpu_type == CPU_486SLC || temp_cpu_type == CPU_IBM386SLC || temp_cpu_type == CPU_IBM486SLC ); + temp_is286 = (temp_cpu_type == CPU_286); } if (biosmask > 0x1ffff) { @@ -417,7 +419,7 @@ bios_add(void) MEM_READ_ROMCS | MEM_WRITE_ROMCS); } - if (AT) { + if (temp_is286 || AT) { mem_mapping_add(&bios_high_mapping, biosaddr | (temp_cpu_16bitbus ? 0x00f00000 : 0xfff00000), biosmask + 1, bios_read,bios_readw,bios_readl, NULL,NULL,NULL, diff --git a/src/mem/spd.c b/src/mem/spd.c index 32b49a101..821f88e71 100644 --- a/src/mem/spd.c +++ b/src/mem/spd.c @@ -384,6 +384,62 @@ spd_write_drbs(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit } +void +spd_write_drbs_interleaved(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit) +{ + uint8_t row, dimm, drb, apollo = 0; + uint16_t size, rows[SPD_MAX_SLOTS]; + + /* Special case for VIA Apollo Pro family, which jumps from 5F to 56. */ + if (reg_max < reg_min) { + apollo = reg_max; + reg_max = reg_min + 7; + } + + /* No SPD: split SIMMs into pairs as if they were "DIMM"s. */ + if (!spd_present) { + dimm = ((reg_max - reg_min) + 1) >> 2; /* amount of "DIMM"s, also used to determine the maximum "DIMM" size */ + spd_populate(rows, dimm, mem_size >> 10, drb_unit, 1 << (log2i((machines[machine].max_ram >> 10) / dimm)), 0); + } + + /* Write DRBs for each row. */ + spd_log("SPD: Writing DRBs... regs=[%02X:%02X] unit=%d\n", reg_min, reg_max, drb_unit); + for (row = 0; row <= (reg_max - reg_min); row += 2) { + dimm = (row >> 2); + size = 0; + + if (spd_present) { + /* SPD enabled: use SPD info for this slot, if present. */ + if (spd_modules[dimm]) { + if (spd_modules[dimm]->row1 < drb_unit) /* hack within a hack: turn a double-sided DIMM that is too small into a single-sided one */ + size = ((row >> 1) & 1) ? 0 : drb_unit; + else + size = ((row >> 1) & 1) ? spd_modules[dimm]->row2 : spd_modules[dimm]->row1; + } + } else { + /* No SPD: use the values calculated above. */ + size = (rows[dimm] >> 1); + } + + /* Determine the DRB register to write. */ + drb = reg_min + row; + if (apollo && ((drb & 0xf) < 0xa)) + drb = apollo + (drb & 0xf); + + /* Write DRB register, adding the previous DRB's value. */ + if (row == 0) + regs[drb] = 0; + else if ((apollo) && (drb == apollo)) + regs[drb] = regs[drb | 0xf]; /* 5F comes before 56 */ + else + regs[drb] = regs[drb - 1]; + if (size) + regs[drb] += size / drb_unit; /* this will intentionally overflow on 440GX with 2 GB */ + spd_log("SPD: DRB[%d] = %d MB (%02Xh raw)\n", row >> 1, size, regs[drb]); + } +} + + static const device_t spd_device = { "Serial Presence Detect ROMs", DEVICE_ISA, diff --git a/src/pci.c b/src/pci.c index 5f1c48f50..387366a39 100644 --- a/src/pci.c +++ b/src/pci.c @@ -59,7 +59,7 @@ static uint8_t pci_pmc = 0, last_pci_card = 0, last_normal_pci_card = 0, last_p static uint8_t pci_card_to_slot_mapping[256][32], pci_bus_number_to_index_mapping[256]; static uint8_t pci_irqs[16], pci_irq_level[16]; static uint64_t pci_irq_hold[16]; -static pci_mirq_t pci_mirqs[4]; +static pci_mirq_t pci_mirqs[8]; static int pci_type, pci_switch, pci_index, @@ -74,6 +74,7 @@ static int trc_reg = 0; static void pci_reset_regs(void); +// #define ENABLE_PCI_LOG 1 #ifdef ENABLE_PCI_LOG int pci_do_log = ENABLE_PCI_LOG; diff --git a/src/pic.c b/src/pic.c index ad165ee5c..36bd4b0e2 100644 --- a/src/pic.c +++ b/src/pic.c @@ -54,6 +54,8 @@ static pc_timer_t pic_timer; static int shadow = 0, elcr_enabled = 0, tmr_inited = 0, latched = 0; +static uint16_t smi_irq_mask = 0x0000, + smi_irq_status = 0x0000; static void (*update_pending)(void); @@ -79,6 +81,39 @@ pic_log(const char *fmt, ...) #endif +void +pic_reset_smi_irq_mask(void) +{ + smi_irq_mask = 0x0000; +} + + +void +pic_set_smi_irq_mask(int irq, int set) +{ + if ((irq >= 0) && (irq <= 15)) { + if (set) + smi_irq_mask |= (1 << irq); + else + smi_irq_mask &= ~(1 << irq); + } +} + +uint16_t +pic_get_smi_irq_status(void) +{ + return smi_irq_status; +} + + +void +pic_clear_smi_irq_status(int irq) +{ + if ((irq >= 0) && (irq <= 15)) + smi_irq_status &= ~(1 << irq); +} + + void pic_elcr_write(uint16_t port, uint8_t val, void *priv) { @@ -255,6 +290,8 @@ pic_reset() update_pending = is_at ? pic_update_pending_at : pic_update_pending_xt; pic.at = pic2.at = is_at; + + smi_irq_mask = smi_irq_status = 0x0000; } @@ -541,6 +578,11 @@ picint_common(uint16_t num, int level, int set) acpi_rtc_status = !!set; if (set) { + if (smi_irq_mask & num) { + smi_line = 1; + smi_irq_status |= num; + } + if (num & 0xff00) { if (level) pic2.lines |= (num >> 8); @@ -555,6 +597,8 @@ picint_common(uint16_t num, int level, int set) pic.irr |= num; } } else { + smi_irq_status &= ~num; + if (num & 0xff00) { pic2.lines &= ~(num >> 8); pic2.irr &= ~(num >> 8); diff --git a/src/pit.c b/src/pit.c index 9db4c45dd..fc1e91927 100644 --- a/src/pit.c +++ b/src/pit.c @@ -64,6 +64,7 @@ int64_t firsttime = 1; #define PIT_EXT_IO 32 /* The PIT has externally specified port I/O. */ #define PIT_CUSTOM_CLOCK 64 /* The PIT uses custom clock inputs provided by another provider. */ #define PIT_SECONDARY 128 /* The PIT is secondary (ports 0048-004B). */ +#define PIT_OLIVETTI 256 /* The PIT is that of the Olivetti 486 (has slight timing differences). */ enum { @@ -92,67 +93,214 @@ pit_log(const char *fmt, ...) #endif +#define NEW_PIT_CODE 1 + + +#ifdef NEW_PIT_CODE +typedef void (*tf_t)(ctr_t *ctr); + + +static void ctr_tick_mode_0(ctr_t *ctr); +static void ctr_tick_mode_1(ctr_t *ctr); +static void ctr_tick_mode_2_and_6(ctr_t *ctr); +static void ctr_tick_mode_3_and_7(ctr_t *ctr); +static void ctr_tick_mode_4_and_5(ctr_t *ctr); + + +static tf_t ctr_tick_funcs[8] = { ctr_tick_mode_0, ctr_tick_mode_1, ctr_tick_mode_2_and_6, + ctr_tick_mode_3_and_7, ctr_tick_mode_4_and_5, ctr_tick_mode_4_and_5, + ctr_tick_mode_2_and_6, ctr_tick_mode_3_and_7 }; + + +/* MODE 0: Interrupt on Terminal Count. */ static void -ctr_set_out(ctr_t *ctr, int out) +ctr_tick_mode_0(ctr_t *ctr) { - if (ctr == NULL) - return; + uint8_t state = ctr->state; - if (ctr->out_func != NULL) - ctr->out_func(out, ctr->out); - ctr->out = out; -} - - -static void -ctr_decrease_count(ctr_t *ctr) -{ - if (ctr->bcd) { - ctr->units--; - if (ctr->units == 0xff) { - ctr->units = 9; - ctr->tens--; - if (ctr->tens == 0xff) { - ctr->tens = 9; - ctr->hundreds--; - if (ctr->hundreds == 0xff) { - ctr->hundreds = 9; - ctr->thousands--; - if (ctr->thousands == 0xff) { - ctr->thousands = 9; - ctr->myriads--; - if (ctr->myriads == 0xff) - ctr->myriads = 0; /* 0 - 1 should wrap around to 9999. */ - } + switch (state) { + case 1: + /* Load count. */ + ctr->count = ctr->l; + ctr->null_count = 0; + /* Switch to next state. */ + ctr->state++; + case 2: case 3: + if (ctr->gate) { + /* Decrease counter. */ + if ((state == 3) || ctr->gate) + ctr->count--; + if ((state == 2) && ctr->gate && (ctr->count == 0)) { + /* Terminal count reached, switch to next state. */ + ctr->state++; + /* Set output high. */ + if (ctr->out_func != NULL) + ctr->out_func(1, ctr->out); + ctr->out = 1; } } - } - } else - ctr->count = (ctr->count - 1) & 0xffff; + break; + } +} + + +/* MODE 1: Programmale One-Shoft. */ +static void +ctr_tick_mode_1(ctr_t *ctr) +{ + uint8_t state = ctr->state; + + switch (state) { + case 1: + /* Load count. */ + ctr->count = ctr->l; + ctr->null_count = 0; + /* Switch to next state. */ + ctr->state++; + /* Set output low. */ + if (ctr->out_func != NULL) + ctr->out_func(0, ctr->out); + ctr->out = 0; + break; + case 2: case 3: + /* Decrease counter. */ + ctr->count--; + if ((state == 2) && (ctr->count == 0)) { + /* Terminal count reached, switch to next state. */ + ctr->state++; + /* Set output high. */ + if (ctr->out_func != NULL) + ctr->out_func(1, ctr->out); + ctr->out = 1; + } + break; + } } static void -ctr_load_count(ctr_t *ctr) +ctr_tick_mode_2_and_6(ctr_t *ctr) { - int l = ctr->l ? ctr->l : 0x10000; + uint8_t state = ctr->state; - ctr->count = l; - pit_log("ctr->count = %i\n", l); - ctr->null_count = 0; - ctr->newcount = !!(l & 1); + switch (state) { + case 1: case 3: + /* Load count. */ + ctr->count = ctr->l; + ctr->null_count = 0; + if (ctr->state == 3) { + /* Set output high. */ + if (ctr->out_func != NULL) + ctr->out_func(1, ctr->out); + ctr->out = 1; + } + /* Switch to next state. */ + ctr->state = 2; + break; + case 2: + /* Decrease counter. */ + if (ctr->gate) { + ctr->count--; + if (ctr->count == 1) { + /* Terminal count reached, switch to previous state. */ + ctr->state = 3; + /* Set output low. */ + if (ctr->out_func != NULL) + ctr->out_func(0, ctr->out); + ctr->out = 0; + } + } + break; + } } +static void +ctr_tick_mode_3_and_7(ctr_t *ctr) +{ + uint8_t state = ctr->state; + uint16_t old_count = ctr->count; + + switch (state) { + case 1: + /* Load count. */ + ctr->count = ctr->l; + ctr->flag_64k = !ctr->count; + ctr->null_count = 0; + ctr->newcount = ctr->count & 1; + /* Switch to next state. */ + ctr->state = 2; + case 2: case 3: + if (ctr->gate) { + ctr->count -= (ctr->newcount ? ((ctr->state == 3) ? 3 : 1) : 2); + if (!ctr->flag_64k && (ctr->count > old_count)) { + /* Load count. */ + ctr->count = ctr->l; + ctr->flag_64k = !ctr->count; + ctr->null_count = 0; + ctr->newcount = ctr->count & 1; + /* Switch to next state. */ + ctr->state ^= 1; + /* Set output low. */ + if (ctr->out_func != NULL) + ctr->out_func(state & 1, ctr->out); + ctr->out = state & 1; + } else { + if (ctr->newcount) + ctr->newcount = 0; + ctr->flag_64k = 0; + } + } + break; + } +} + + +static void +ctr_tick_mode_4_and_5(ctr_t *ctr) +{ + uint8_t state = ctr->state; + + /* Software triggered strobe */ + /* Hardware triggered strobe */ + if (ctr->gate || (ctr->m != 4)) { + switch(state) { + case 0: case 2: + ctr->count--; + if ((state == 2) && (ctr->count < 1)) { + ctr->state++; + if (ctr->out_func != NULL) + ctr->out_func(0, ctr->out); + ctr->out = 0; + } + break; + case 3: + ctr->state = 0; + if (ctr->out_func != NULL) + ctr->out_func(1, ctr->out); + ctr->out = 1; + break; + } + } +} +#else static void ctr_tick(ctr_t *ctr) { uint8_t state = ctr->state; + uint16_t old_count = ctr->count; if (state == 1) { /* This is true for all modes */ - ctr_load_count(ctr); - ctr->state = 2; + ctr->count = ctr->l; + ctr->null_count = 0; + ctr->newcount = !!(ctr->count & 1); + ctr->state++; + if ((ctr->m & 0x07) == 1) { + if (ctr->out_func != NULL) + ctr->out_func(0, ctr->out); + ctr->out = 0; + } return; } @@ -161,38 +309,35 @@ ctr_tick(ctr_t *ctr) /* Interrupt on terminal count */ switch (state) { case 2: - if (ctr->gate && (ctr->count >= 1)) { - ctr_decrease_count(ctr); + if (ctr->gate) { + ctr->count--; if (ctr->count < 1) { - ctr->state = 3; - ctr_set_out(ctr, 1); + ctr->state++; + if (ctr->out_func != NULL) + ctr->out_func(1, ctr->out); + ctr->out = 1; } } break; case 3: - ctr_decrease_count(ctr); + ctr->count--; break; } break; case 1: /* Hardware retriggerable one-shot */ switch (state) { - case 1: - ctr_load_count(ctr); - ctr->state = 2; - ctr_set_out(ctr, 0); - break; case 2: - if (ctr->count >= 1) { - ctr_decrease_count(ctr); - if (ctr->count < 1) { - ctr->state = 3; - ctr_set_out(ctr, 1); - } + ctr->count--; + if (ctr->count < 1) { + ctr->state++; + if (ctr->out_func != NULL) + ctr->out_func(1, ctr->out); + ctr->out = 1; } break; case 3: - ctr_decrease_count(ctr); + ctr->count--; break; } break; @@ -200,59 +345,40 @@ ctr_tick(ctr_t *ctr) /* Rate generator */ switch (state) { case 3: - ctr_load_count(ctr); - ctr->state = 2; - ctr_set_out(ctr, 1); + ctr->count = ctr->l; + ctr->null_count = 0; + ctr->state ^= 1; + if (ctr->out_func != NULL) + ctr->out_func(1, ctr->out); + ctr->out = 1; break; case 2: - if (ctr->gate == 0) - break; - else if (ctr->count >= 2) { - ctr_decrease_count(ctr); + // if (ctr->gate) { + ctr->count--; if (ctr->count < 2) { - ctr->state = 3; - ctr_set_out(ctr, 0); + ctr->state ^= 1; + if (ctr->out_func != NULL) + ctr->out_func(0, ctr->out); + ctr->out = 0; } - } + // } break; } break; case 3: case 7: /* Square wave mode */ switch (state) { - case 2: - if (ctr->gate == 0) - break; - else if (ctr->count >= 0) { - if (ctr->bcd) { - ctr_decrease_count(ctr); - if (!ctr->newcount) - ctr_decrease_count(ctr); - } else - ctr->count -= (ctr->newcount ? 1 : 2); - if (ctr->count < 0) { - ctr_load_count(ctr); - ctr->state = 3; - ctr_set_out(ctr, 0); - } else if (ctr->newcount) - ctr->newcount = 0; - } - break; - case 3: - if (ctr->gate == 0) - break; - else if (ctr->count >= 0) { - if (ctr->bcd) { - ctr_decrease_count(ctr); - ctr_decrease_count(ctr); - if (ctr->newcount) - ctr_decrease_count(ctr); - } else - ctr->count -= (ctr->newcount ? 3 : 2); - if (ctr->count < 0) { - ctr_load_count(ctr); - ctr->state = 2; - ctr_set_out(ctr, 1); + case 2: case 3: + if (ctr->gate != 0) { + ctr->count -= (ctr->newcount ? ((state & 1) ? 3 : 1) : 2); + if (ctr->count > old_count) { + ctr->count = ctr->l; + ctr->null_count = 0; + ctr->newcount = !!(ctr->count & 1); + ctr->state ^= 1; + if (ctr->out_func != NULL) + ctr->out_func(0, ctr->out); + ctr->out = 0; } else if (ctr->newcount) ctr->newcount = 0; } @@ -264,21 +390,20 @@ ctr_tick(ctr_t *ctr) /* Hardware triggered strobe */ if ((ctr->gate != 0) || (ctr->m != 4)) { switch(state) { - case 0: - ctr_decrease_count(ctr); - break; - case 2: - if (ctr->count >= 1) { - ctr_decrease_count(ctr); - if (ctr->count < 1) { - ctr->state = 3; - ctr_set_out(ctr, 0); - } + case 0: case 2: + ctr->count--; + if ((state == 2) && (ctr->count < 1)) { + ctr->state++; + if (ctr->out_func != NULL) + ctr->out_func(0, ctr->out); + ctr->out = 0; } break; case 3: ctr->state = 0; - ctr_set_out(ctr, 1); + if (ctr->out_func != NULL) + ctr->out_func(1, ctr->out); + ctr->out = 1; break; } } @@ -287,19 +412,24 @@ ctr_tick(ctr_t *ctr) break; } } +#endif static void ctr_clock(ctr_t *ctr) { - /* FIXME: Is this even needed? */ + /* FIXME: Is this even needed? */ if ((ctr->state == 3) && (ctr->m != 2) && (ctr->m != 3)) return; if (ctr->using_timer) return; +#ifdef NEW_PIT_CODE + ctr->tick_func(ctr); +#else ctr_tick(ctr); +#endif } @@ -350,6 +480,11 @@ ctr_latch_count(ctr_t *ctr) { int count = (ctr->latch || (ctr->state == 1)) ? ctr->l : ctr->count; + // if ((ctr->pit->flags & PIT_OLIVETTI) && (ctr->state == 0)) + // count--; + + pit_log("PIT latch count with state %i (%i)\n", ctr->state, ctr->latch); + switch (ctr->rm & 0x03) { case 0x00: /* This should never happen. */ @@ -415,15 +550,21 @@ pit_ctr_set_gate(ctr_t *ctr, int gate) if (!old && gate) { /* Here we handle the rising edges. */ if (mode & 1) { - if (mode != 1) - ctr_set_out(ctr, 1); + if (mode != 1) { + if (ctr->out_func != NULL) + ctr->out_func(1, ctr->out); + ctr->out = 1; + } ctr->state = 1; } else if (mode == 2) ctr->state = 3; } else if (old && !gate) { /* Here we handle the lowering edges. */ - if (mode & 2) - ctr_set_out(ctr, 1); + if (mode & 2) { + if (ctr->out_func != NULL) + ctr->out_func(1, ctr->out); + ctr->out = 1; + } } break; } @@ -437,12 +578,27 @@ pit_ctr_set_clock_common(ctr_t *ctr, int clock) ctr->clock = clock; - if (ctr->using_timer && ctr->latch) { + if (!ctr->using_timer) + return; + +#if 0 + if ((ctr->pit->flags & PIT_OLIVETTI) && !old && ctr->clock) { + if (ctr->do_load) { + if (ctr->do_load == 3) + ctr_load(ctr); + ctr->do_load++; + if (ctr->do_load == 4) + ctr->do_load = 0; + } + } +#endif + + if (ctr->latch) { if (old && !ctr->clock) { ctr_set_state_1(ctr); ctr->latch = 0; } - } else if (ctr->using_timer && !ctr->latch) { + } else if (!ctr->latch) { if (ctr->state == 1) { if (!old && ctr->clock) ctr->s1_det = 1; /* Rising edge. */ @@ -450,11 +606,19 @@ pit_ctr_set_clock_common(ctr_t *ctr, int clock) ctr->s1_det++; /* Falling edge. */ if (ctr->s1_det >= 2) { ctr->s1_det = 0; +#ifdef NEW_PIT_CODE + ctr->tick_func(ctr); +#else ctr_tick(ctr); +#endif } } } else if (old && !ctr->clock) +#ifdef NEW_PIT_CODE + ctr->tick_func(ctr); +#else ctr_tick(ctr); +#endif } } @@ -538,9 +702,14 @@ pit_write(uint16_t addr, uint8_t val, void *priv) ctr->m = (val >> 1) & 7; if (ctr->m > 5) ctr->m &= 3; +#ifdef NEW_PIT_CODE + ctr->tick_func = ctr_tick_funcs[ctr->m]; +#endif ctr->null_count = 1; ctr->bcd = (ctr->ctrl & 0x01); - ctr_set_out(ctr, !!ctr->m); + if (ctr->out_func != NULL) + ctr->out_func(!!ctr->m, ctr->out); + ctr->out = !!ctr->m; ctr->state = 0; if (ctr->latched) { pit_log("PIT %i: Reload while counter is latched\n", t); @@ -563,27 +732,44 @@ pit_write(uint16_t addr, uint8_t val, void *priv) break; case 1: ctr->l = val; - if (ctr->m == 0) - ctr_set_out(ctr, 0); - ctr_load(ctr); + if (ctr->m == 0) { + if (ctr->out_func != NULL) + ctr->out_func(0, ctr->out); + ctr->out = 0; + } + if (dev->flags & PIT_OLIVETTI) + ctr->do_load = 1; + else + ctr_load(ctr); break; case 2: ctr->l = (val << 8); - if (ctr->m == 0) - ctr_set_out(ctr, 0); - ctr_load(ctr); + if (ctr->m == 0) { + if (ctr->out_func != NULL) + ctr->out_func(0, ctr->out); + ctr->out = 0; + } + if (dev->flags & PIT_OLIVETTI) + ctr->do_load = 1; + else + ctr_load(ctr); break; case 3: case 0x83: if (ctr->wm & 0x80) { ctr->l = (ctr->l & 0x00ff) | (val << 8); pit_log("PIT %i: Written high byte %02X, latch now %04X\n", t, val, ctr->l); - ctr_load(ctr); + if (dev->flags & PIT_OLIVETTI) + ctr->do_load = 1; + else + ctr_load(ctr); } else { ctr->l = (ctr->l & 0xff00) | val; pit_log("PIT %i: Written low byte %02X, latch now %04X\n", t, val, ctr->l); if (ctr->m == 0) { ctr->state = 0; - ctr_set_out(ctr, 0); + if (ctr->out_func != NULL) + ctr->out_func(0, ctr->out); + ctr->out = 0; } } @@ -757,7 +943,7 @@ pit_nmi_timer_ps2(int new_out, int old_out) static void -ctr_reset(ctr_t *ctr) +ctr_reset(pit_t *dev, ctr_t *ctr) { ctr->ctrl = 0; ctr->m = 0; @@ -771,6 +957,8 @@ ctr_reset(ctr_t *ctr) ctr->s1_det = 0; ctr->l_det = 0; + + ctr->pit = dev; } @@ -784,10 +972,15 @@ pit_reset(pit_t *dev) dev->clock = 0; for (i = 0; i < 3; i++) - ctr_reset(&dev->counters[i]); + ctr_reset(dev, &dev->counters[i]); /* Disable speaker gate. */ dev->counters[2].gate = 0; + +#ifdef NEW_PIT_CODE + dev->counters[0].tick_func = dev->counters[1].tick_func = + dev->counters[2].tick_func = ctr_tick_funcs[0]; +#endif } @@ -858,6 +1051,17 @@ const device_t i8254_device = }; +const device_t i8254_olivetti_device = +{ + "Intel 8254 Programmable Interval Timer (Olivetti)", + DEVICE_ISA, + PIT_8254 | PIT_OLIVETTI, + pit_init, pit_close, NULL, + { NULL }, NULL, NULL, + NULL +}; + + const device_t i8254_sec_device = { "Intel 8254 Programmable Interval Timer (Secondary)", @@ -904,6 +1108,9 @@ pit_common_init(int type, void (*out0)(int new_out, int old_out), void (*out1)(i case PIT_8254: pit = device_add(&i8254_device); break; + case (PIT_8254 | PIT_OLIVETTI): + pit = device_add(&i8254_olivetti_device); + break; } for (i = 0; i < 3; i++) { diff --git a/src/port_6x.c b/src/port_6x.c new file mode 100644 index 000000000..98cd4350d --- /dev/null +++ b/src/port_6x.c @@ -0,0 +1,214 @@ +/* + * 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 Ports 61, 62, and 63 used by various + * machines. + * + * Authors: Miran Grca, + * + * Copyright 2021 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/device.h> +#include "cpu.h" +#include <86box/timer.h> +#include <86box/io.h> +#include <86box/keyboard.h> +#include <86box/mem.h> +#include <86box/m_xt_xi8088.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/sound.h> +#include <86box/snd_speaker.h> +#include <86box/pit.h> +#include <86box/ppi.h> +#include <86box/video.h> +#include <86box/port_6x.h> + + +#define PS2_REFRESH_TIME (16 * TIMER_USEC) + +#define PORT_6X_TURBO 1 +#define PORT_6X_EXT_REF 2 +#define PORT_6X_MIRROR 4 +#define PORT_6X_SWA 8 + + +static void +port_6x_write(uint16_t port, uint8_t val, void *priv) +{ + port_6x_t *dev = (port_6x_t *) priv; + + port &= 3; + + if ((port == 3) && (dev->flags & PORT_6X_MIRROR)) + port = 1; + + switch (port) { + case 1: + ppi.pb = (ppi.pb & 0x10) | (val & 0x0f); + + speaker_update(); + speaker_gated = val & 1; + speaker_enable = val & 2; + if (speaker_enable) + was_speaker_enable = 1; + pit_ctr_set_gate(&pit->counters[2], val & 1); + + if (dev->flags & PORT_6X_TURBO) + xi8088_turbo_set(!!(val & 0x04)); + break; + } +} + + +static uint8_t +port_6x_read(uint16_t port, void *priv) +{ + port_6x_t *dev = (port_6x_t *) priv; + uint8_t ret = 0xff; + + port &= 3; + + if ((port == 3) && (dev->flags & PORT_6X_MIRROR)) + port = 1; + + switch (port) { + case 1: + if (dev->flags & PORT_6X_EXT_REF) { + ret = ppi.pb & 0x0f; + + if (dev->refresh) + ret |= 0x10; + } else + ret = ppi.pb & 0x1f; + + if (ppispeakon) + ret |= 0x20; + + if (dev->flags & PORT_6X_TURBO) + ret = (ret & 0xfb) | (xi8088_turbo_get() ? 0x04 : 0x00); + break; + case 2: + if (dev->flags & PORT_6X_SWA) { + /* SWA on Olivetti M240 mainboard (off=1) */ + ret = 0x00; + if (ppi.pb & 0x8) { + /* Switches 4, 5 - floppy drives (number) */ + int i, fdd_count = 0; + for (i = 0; i < FDD_NUM; i++) { + if (fdd_get_flags(i)) + fdd_count++; + } + if (!fdd_count) + ret |= 0x00; + else + ret |= ((fdd_count - 1) << 2); + /* Switches 6, 7 - monitor type */ + if (video_is_mda()) + ret |= 0x3; + else if (video_is_cga()) + ret |= 0x2; /* 0x10 would be 40x25 */ + else + ret |= 0x0; + } else { + /* bit 2 always on */ + ret |= 0x4; + /* Switch 8 - 8087 FPU. */ + if (hasfpu) + ret |= 0x02; + } + } + break; + } + + return(ret); +} + + +static void +port_6x_refresh(void *priv) +{ + port_6x_t *dev = (port_6x_t *) priv; + + dev->refresh = !dev->refresh; + timer_advance_u64(&dev->refresh_timer, PS2_REFRESH_TIME); +} + + +static void +port_6x_close(void *priv) +{ + port_6x_t *dev = (port_6x_t *) priv; + + timer_disable(&dev->refresh_timer); + + free(dev); +} + + +void * +port_6x_init(const device_t *info) +{ + port_6x_t *dev = (port_6x_t *) malloc(sizeof(port_6x_t)); + memset(dev, 0, sizeof(port_6x_t)); + + dev->flags = info->local & 0xff; + + io_sethandler(0x0061, 3, port_6x_read, NULL, NULL, port_6x_write, NULL, NULL, dev); + + if (dev->flags & PORT_6X_EXT_REF) + timer_add(&dev->refresh_timer, port_6x_refresh, dev, 1); + + return dev; +} + + +const device_t port_6x_device = { + "Port 6x Registers", + 0, + 0, + port_6x_init, port_6x_close, NULL, + { NULL }, NULL, NULL, + NULL +}; + + +const device_t port_6x_xi8088_device = { + "Port 6x Registers (Xi8088)", + 0, + PORT_6X_TURBO | PORT_6X_EXT_REF | PORT_6X_MIRROR, + port_6x_init, port_6x_close, NULL, + { NULL }, NULL, NULL, + NULL +}; + + +const device_t port_6x_ps2_device = { + "Port 6x Registers (IBM PS/2)", + 0, + PORT_6X_EXT_REF, + port_6x_init, port_6x_close, NULL, + { NULL }, NULL, NULL, + NULL +}; + + +const device_t port_6x_olivetti_device = { + "Port 6x Registers (Olivetti)", + 0, + PORT_6X_SWA, + port_6x_init, port_6x_close, NULL, + { NULL }, NULL, NULL, + NULL +}; diff --git a/src/sio/CMakeLists.txt b/src/sio/CMakeLists.txt index 9eff04f30..902f8b231 100644 --- a/src/sio/CMakeLists.txt +++ b/src/sio/CMakeLists.txt @@ -14,7 +14,7 @@ # add_library(sio OBJECT sio_acc3221.c sio_f82c710.c sio_82091aa.c sio_fdc37c651.c sio_fdc37c661.c - sio_fdc37c66x.c sio_fdc37c669.c sio_fdc37c93x.c sio_fdc37m60x.c + sio_fdc37c66x.c sio_fdc37c67x.c sio_fdc37c669.c sio_fdc37c93x.c sio_fdc37m60x.c sio_it8661f.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 diff --git a/src/sio/sio_fdc37c67x.c b/src/sio/sio_fdc37c67x.c new file mode 100644 index 000000000..d6905a72d --- /dev/null +++ b/src/sio/sio_fdc37c67x.c @@ -0,0 +1,613 @@ +/* + * 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 SMC FDC37C67X Super I/O Chip. + * + * + * + * Author: Miran Grca, + * Copyright 2016-2018 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/timer.h> +#include <86box/device.h> +#include <86box/pic.h> +#include <86box/pci.h> +#include <86box/lpt.h> +#include <86box/serial.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include "cpu.h" +#include <86box/sio.h> + + +#define AB_RST 0x80 + + +typedef struct { + uint8_t chip_id, is_apm, + tries, + gpio_regs[2], auxio_reg, + regs[48], + ld_regs[11][256]; + uint16_t gpio_base, /* Set to EA */ + auxio_base, sio_base; + int locked, + cur_reg; + fdc_t *fdc; + serial_t *uart[2]; +} fdc37c67x_t; + + +static void fdc37c67x_write(uint16_t port, uint8_t val, void *priv); +static uint8_t fdc37c67x_read(uint16_t port, void *priv); + + +static uint16_t +make_port(fdc37c67x_t *dev, uint8_t ld) +{ + uint16_t r0 = dev->ld_regs[ld][0x60]; + uint16_t r1 = dev->ld_regs[ld][0x61]; + + uint16_t p = (r0 << 8) + r1; + + return p; +} + + +static uint8_t +fdc37c67x_auxio_read(uint16_t port, void *priv) +{ + fdc37c67x_t *dev = (fdc37c67x_t *) priv; + + return dev->auxio_reg; +} + + +static void +fdc37c67x_auxio_write(uint16_t port, uint8_t val, void *priv) +{ + fdc37c67x_t *dev = (fdc37c67x_t *) priv; + + dev->auxio_reg = val; +} + + +static uint8_t +fdc37c67x_gpio_read(uint16_t port, void *priv) +{ + fdc37c67x_t *dev = (fdc37c67x_t *) priv; + uint8_t ret = 0xff; + + ret = dev->gpio_regs[port & 1]; + + return ret; +} + + +static void +fdc37c67x_gpio_write(uint16_t port, uint8_t val, void *priv) +{ + fdc37c67x_t *dev = (fdc37c67x_t *) priv; + + if (!(port & 1)) + dev->gpio_regs[0] = (dev->gpio_regs[0] & 0xfc) | (val & 0x03); +} + + +static void +fdc37c67x_fdc_handler(fdc37c67x_t *dev) +{ + uint16_t ld_port = 0; + uint8_t global_enable = !!(dev->regs[0x22] & (1 << 0)); + uint8_t local_enable = !!dev->ld_regs[0][0x30]; + + fdc_remove(dev->fdc); + if (global_enable && local_enable) { + ld_port = make_port(dev, 0) & 0xFFF8; + if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) + fdc_set_base(dev->fdc, ld_port); + } +} + + +static void +fdc37c67x_lpt_handler(fdc37c67x_t *dev) +{ + uint16_t ld_port = 0; + uint8_t global_enable = !!(dev->regs[0x22] & (1 << 3)); + uint8_t local_enable = !!dev->ld_regs[3][0x30]; + uint8_t lpt_irq = dev->ld_regs[3][0x70]; + + if (lpt_irq > 15) + lpt_irq = 0xff; + + lpt1_remove(); + if (global_enable && local_enable) { + ld_port = make_port(dev, 3) & 0xFFFC; + if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) + lpt1_init(ld_port); + } + lpt1_irq(lpt_irq); +} + + +static void +fdc37c67x_serial_handler(fdc37c67x_t *dev, int uart) +{ + uint16_t ld_port = 0; + uint8_t uart_no = 4 + uart; + uint8_t global_enable = !!(dev->regs[0x22] & (1 << uart_no)); + uint8_t local_enable = !!dev->ld_regs[uart_no][0x30]; + + serial_remove(dev->uart[uart]); + if (global_enable && local_enable) { + ld_port = make_port(dev, uart_no) & 0xFFF8; + if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) + serial_setup(dev->uart[uart], ld_port, dev->ld_regs[uart_no][0x70]); + } +} + + +static void +fdc37c67x_auxio_handler(fdc37c67x_t *dev) +{ + uint16_t ld_port = 0; + uint8_t local_enable = !!dev->ld_regs[8][0x30]; + + io_removehandler(dev->auxio_base, 0x0001, + fdc37c67x_auxio_read, NULL, NULL, fdc37c67x_auxio_write, NULL, NULL, dev); + if (local_enable) { + dev->auxio_base = ld_port = make_port(dev, 8); + if ((ld_port >= 0x0100) && (ld_port <= 0x0FFF)) + io_sethandler(dev->auxio_base, 0x0001, + fdc37c67x_auxio_read, NULL, NULL, fdc37c67x_auxio_write, NULL, NULL, dev); + } +} + + +static void +fdc37c67x_sio_handler(fdc37c67x_t *dev) +{ +#if 0 + if (dev->sio_base) { + io_removehandler(dev->sio_base, 0x0002, + fdc37c67x_read, NULL, NULL, fdc37c67x_write, NULL, NULL, dev); + } + dev->sio_base = (((uint16_t) dev->regs[0x27]) << 8) | dev->regs[0x26]; + if (dev->sio_base) { + io_sethandler(dev->sio_base, 0x0002, + fdc37c67x_read, NULL, NULL, fdc37c67x_write, NULL, NULL, dev); + } +#endif +} + + +static void +fdc37c67x_gpio_handler(fdc37c67x_t *dev) +{ + uint16_t ld_port = 0; + uint8_t local_enable; + + local_enable = !!(dev->regs[0x03] & 0x80); + + io_removehandler(dev->gpio_base, 0x0002, + fdc37c67x_gpio_read, NULL, NULL, fdc37c67x_gpio_write, NULL, NULL, dev); + if (local_enable) { + switch (dev->regs[0x03] & 0x03) { + case 0: + ld_port = 0xe0; + break; + case 1: + ld_port = 0xe2; + break; + case 2: + ld_port = 0xe4; + break; + case 3: + ld_port = 0xea; /* Default */ + break; + } + dev->gpio_base = ld_port; + if (ld_port > 0x0000) + io_sethandler(dev->gpio_base, 0x0002, + fdc37c67x_gpio_read, NULL, NULL, fdc37c67x_gpio_write, NULL, NULL, dev); + } +} + + +static void +fdc37c67x_smi_handler(fdc37c67x_t *dev) +{ + /* TODO: 8042 P1.2 SMI#. */ + pic_reset_smi_irq_mask(); + pic_set_smi_irq_mask(dev->ld_regs[3][0x70], dev->ld_regs[8][0xb4] & 0x02); + pic_set_smi_irq_mask(dev->ld_regs[5][0x70], dev->ld_regs[8][0xb4] & 0x04); + pic_set_smi_irq_mask(dev->ld_regs[4][0x70], dev->ld_regs[8][0xb4] & 0x08); + pic_set_smi_irq_mask(dev->ld_regs[0][0x70], dev->ld_regs[8][0xb4] & 0x10); + pic_set_smi_irq_mask(12, dev->ld_regs[8][0xb5] & 0x01); + pic_set_smi_irq_mask(1, dev->ld_regs[8][0xb5] & 0x02); + pic_set_smi_irq_mask(10, dev->ld_regs[8][0xb5] & 0x80); +} + + +static void +fdc37c67x_write(uint16_t port, uint8_t val, void *priv) +{ + fdc37c67x_t *dev = (fdc37c67x_t *) priv; + uint8_t index = (port & 1) ? 0 : 1; + uint8_t valxor = 0x00, keep = 0x00; + + if (index) { + if ((val == 0x55) && !dev->locked) { + if (dev->tries) { + dev->locked = 1; + fdc_3f1_enable(dev->fdc, 0); + dev->tries = 0; + } else + dev->tries++; + } else { + if (dev->locked) { + if (val == 0xaa) { + dev->locked = 0; + fdc_3f1_enable(dev->fdc, 1); + return; + } + dev->cur_reg = val; + } else { + if (dev->tries) + dev->tries = 0; + } + } + return; + } else { + if (dev->locked) { + if (dev->cur_reg < 48) { + valxor = val ^ dev->regs[dev->cur_reg]; + if ((val == 0x20) || (val == 0x21)) + return; + dev->regs[dev->cur_reg] = val; + } else { + valxor = val ^ dev->ld_regs[dev->regs[7]][dev->cur_reg]; + if (((dev->cur_reg & 0xF0) == 0x70) && (dev->regs[7] < 4)) + return; + /* Block writes to some logical devices. */ + if (dev->regs[7] > 0x0a) + return; + else switch (dev->regs[7]) { + case 0x01: + case 0x02: + case 0x07: + return; + } + dev->ld_regs[dev->regs[7]][dev->cur_reg] = val | keep; + } + } else + return; + } + + if (dev->cur_reg < 48) { + switch(dev->cur_reg) { + case 0x03: + if (valxor & 0x83) + fdc37c67x_gpio_handler(dev); + dev->regs[0x03] &= 0x83; + break; + case 0x22: + if (valxor & 0x01) + fdc37c67x_fdc_handler(dev); + if (valxor & 0x08) + fdc37c67x_lpt_handler(dev); + if (valxor & 0x10) + fdc37c67x_serial_handler(dev, 0); + if (valxor & 0x20) + fdc37c67x_serial_handler(dev, 1); + break; + case 0x26: case 0x27: + fdc37c67x_sio_handler(dev); + } + + return; + } + + switch(dev->regs[7]) { + case 0: + /* FDD */ + switch(dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] |= 0x01; + if (valxor) + fdc37c67x_fdc_handler(dev); + break; + case 0xF0: + if (valxor & 0x01) + fdc_update_enh_mode(dev->fdc, val & 0x01); + if (valxor & 0x10) + fdc_set_swap(dev->fdc, (val & 0x10) >> 4); + break; + case 0xF1: + if (valxor & 0xC) + fdc_update_densel_force(dev->fdc, (val & 0xc) >> 2); + break; + case 0xF2: + if (valxor & 0xC0) + fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6); + if (valxor & 0x30) + fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4); + if (valxor & 0x0C) + fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2); + if (valxor & 0x03) + fdc_update_rwc(dev->fdc, 0, (val & 0x03)); + break; + case 0xF4: + if (valxor & 0x18) + fdc_update_drvrate(dev->fdc, 0, (val & 0x18) >> 3); + break; + case 0xF5: + if (valxor & 0x18) + fdc_update_drvrate(dev->fdc, 1, (val & 0x18) >> 3); + break; + case 0xF6: + if (valxor & 0x18) + fdc_update_drvrate(dev->fdc, 2, (val & 0x18) >> 3); + break; + case 0xF7: + if (valxor & 0x18) + fdc_update_drvrate(dev->fdc, 3, (val & 0x18) >> 3); + break; + } + break; + case 3: + /* Parallel port */ + switch(dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + case 0x70: + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] |= 0x08; + if (valxor) + fdc37c67x_lpt_handler(dev); + if (dev->cur_reg == 0x70) + fdc37c67x_smi_handler(dev); + break; + } + break; + case 4: + /* Serial port 1 */ + switch(dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + case 0x70: + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] |= 0x10; + if (valxor) + fdc37c67x_serial_handler(dev, 0); + if (dev->cur_reg == 0x70) + fdc37c67x_smi_handler(dev); + break; + } + break; + case 5: + /* Serial port 2 */ + switch(dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + case 0x70: + if ((dev->cur_reg == 0x30) && (val & 0x01)) + dev->regs[0x22] |= 0x20; + if (valxor) + fdc37c67x_serial_handler(dev, 1); + if (dev->cur_reg == 0x70) + fdc37c67x_smi_handler(dev); + break; + } + break; + case 8: + /* Auxiliary I/O */ + switch(dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + case 0x70: + if (valxor) + fdc37c67x_auxio_handler(dev); + break; + case 0xb4: + case 0xb5: + fdc37c67x_smi_handler(dev); + break; + } + break; + } +} + + +static uint8_t +fdc37c67x_read(uint16_t port, void *priv) +{ + fdc37c67x_t *dev = (fdc37c67x_t *) priv; + uint8_t index = (port & 1) ? 0 : 1; + uint8_t ret = 0xff; + uint16_t smi_stat = pic_get_smi_irq_status(); + int f_irq = dev->ld_regs[0][0x70]; + int p_irq = dev->ld_regs[3][0x70]; + int s1_irq = dev->ld_regs[4][0x70]; + int s2_irq = dev->ld_regs[5][0x70]; + + if (dev->locked) { + if (index) + ret = dev->cur_reg; + else { + if (dev->cur_reg < 0x30) { + if (dev->cur_reg == 0x20) + ret = dev->chip_id; + else + ret = dev->regs[dev->cur_reg]; + } else { + if ((dev->regs[7] == 0) && (dev->cur_reg == 0xF2)) { + ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | + (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6)); + } else + ret = dev->ld_regs[dev->regs[7]][dev->cur_reg]; + + /* TODO: 8042 P1.2 SMI#. */ + if ((dev->regs[7] == 8) && (dev->cur_reg == 0xb6)) { + ret = dev->regs[dev->cur_reg] & 0xe1; + ret |= ((!!(smi_stat & (1 << p_irq))) << 1); + ret |= ((!!(smi_stat & (1 << s2_irq))) << 2); + ret |= ((!!(smi_stat & (1 << s1_irq))) << 3); + ret |= ((!!(smi_stat & (1 << f_irq))) << 4); + } else if ((dev->regs[7] == 8) && (dev->cur_reg == 0xb7)) { + ret = dev->regs[dev->cur_reg] & 0xec; + ret |= ((!!(smi_stat & (1 << 12))) << 0); + ret |= ((!!(smi_stat & (1 << 1))) << 1); + ret |= ((!!(smi_stat & (1 << 10))) << 4); + } + } + } + } + + return ret; +} + + +static void +fdc37c67x_reset(fdc37c67x_t *dev) +{ + int i = 0; + + memset(dev->regs, 0, 48); + + dev->regs[0x03] = 0x03; + dev->regs[0x20] = dev->chip_id; + dev->regs[0x22] = 0x39; + dev->regs[0x24] = 0x04; + dev->regs[0x26] = 0xf0; + dev->regs[0x27] = 0x03; + + for (i = 0; i < 11; i++) + memset(dev->ld_regs[i], 0, 256); + + /* Logical device 0: FDD */ + dev->ld_regs[0][0x30] = 1; + dev->ld_regs[0][0x60] = 3; + dev->ld_regs[0][0x61] = 0xf0; + dev->ld_regs[0][0x70] = 6; + dev->ld_regs[0][0x74] = 2; + dev->ld_regs[0][0xf0] = 0x0e; + dev->ld_regs[0][0xf2] = 0xff; + + /* Logical device 3: Parallel Port */ + dev->ld_regs[3][0x30] = 1; + dev->ld_regs[3][0x60] = 3; + dev->ld_regs[3][0x61] = 0x78; + dev->ld_regs[3][0x70] = 7; + dev->ld_regs[3][0x74] = 4; + dev->ld_regs[3][0xf0] = 0x3c; + + /* Logical device 4: Serial Port 1 */ + dev->ld_regs[4][0x30] = 1; + dev->ld_regs[4][0x60] = 3; + dev->ld_regs[4][0x61] = 0xf8; + dev->ld_regs[4][0x70] = 4; + dev->ld_regs[4][0xf0] = 3; + serial_setup(dev->uart[0], 0x3f8, dev->ld_regs[4][0x70]); + + /* Logical device 5: Serial Port 2 */ + dev->ld_regs[5][0x30] = 1; + dev->ld_regs[5][0x60] = 2; + dev->ld_regs[5][0x61] = 0xf8; + dev->ld_regs[5][0x70] = 3; + dev->ld_regs[5][0x74] = 4; + dev->ld_regs[5][0xf1] = 2; + dev->ld_regs[5][0xf2] = 3; + serial_setup(dev->uart[1], 0x2f8, dev->ld_regs[5][0x70]); + + /* Logical device 7: Keyboard */ + dev->ld_regs[7][0x30] = 1; + dev->ld_regs[7][0x61] = 0x60; + dev->ld_regs[7][0x70] = 1; + dev->ld_regs[7][0x72] = 12; + + /* Logical device 8: Auxiliary I/O */ + dev->ld_regs[8][0xc0] = 6; + dev->ld_regs[8][0xc1] = 3; + + fdc37c67x_gpio_handler(dev); + fdc37c67x_lpt_handler(dev); + fdc37c67x_serial_handler(dev, 0); + fdc37c67x_serial_handler(dev, 1); + fdc37c67x_auxio_handler(dev); + fdc37c67x_sio_handler(dev); + + fdc_reset(dev->fdc); + fdc37c67x_fdc_handler(dev); + + dev->locked = 0; +} + + +static void +fdc37c67x_close(void *priv) +{ + fdc37c67x_t *dev = (fdc37c67x_t *) priv; + + free(dev); +} + + +static void * +fdc37c67x_init(const device_t *info) +{ + fdc37c67x_t *dev = (fdc37c67x_t *) malloc(sizeof(fdc37c67x_t)); + memset(dev, 0, sizeof(fdc37c67x_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->chip_id = info->local & 0xff; + + dev->gpio_regs[0] = 0xff; + // dev->gpio_regs[1] = (info->local == 0x0030) ? 0xff : 0xfd; + dev->gpio_regs[1] = (dev->chip_id == 0x30) ? 0xff : 0xfd; + + fdc37c67x_reset(dev); + + io_sethandler(0x370, 0x0002, + fdc37c67x_read, NULL, NULL, fdc37c67x_write, NULL, NULL, dev); + io_sethandler(0x3f0, 0x0002, + fdc37c67x_read, NULL, NULL, fdc37c67x_write, NULL, NULL, dev); + + return dev; +} + + +const device_t fdc37c67x_device = { + "SMC FDC37C67X Super I/O", + 0, + 0x40, + fdc37c67x_init, fdc37c67x_close, NULL, + { NULL }, NULL, NULL, + NULL +}; diff --git a/src/sio/sio_pc87332.c b/src/sio/sio_pc87332.c index 267de0543..c5eb40e60 100644 --- a/src/sio/sio_pc87332.c +++ b/src/sio/sio_pc87332.c @@ -366,6 +366,16 @@ const device_t pc87332_398_ide_device = { }; +const device_t pc87332_398_ide_sec_device = { + "National Semiconductor PC87332 Super I/O (Port 398h) (With Secondary IDE)", + 0, + 0x201, + pc87332_init, pc87332_close, NULL, + { NULL }, NULL, NULL, + NULL +}; + + const device_t pc87332_398_ide_fdcon_device = { "National Semiconductor PC87332 Super I/O (Port 398h) (With IDE and FDC on)", 0, diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 8e1ea61a4..d045bc082 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -1026,8 +1026,9 @@ sb_ct1745_mixer_read(uint16_t addr, void *p) /* 0 = none, 1 = digital 8bit or SBMIDI, 2 = digital 16bit, 4 = MPU-401 */ /* 0x02000 DSP v4.04, 0x4000 DSP v4.05, 0x8000 DSP v4.12. I haven't seen this making any difference, but I'm keeping it for now. */ + /* If QEMU is any indication, then the values are actually 0x20, 0x40, and 0x80. */ temp = ((sb->dsp.sb_irq8) ? 1 : 0) | ((sb->dsp.sb_irq16) ? 2 : 0) | - ((sb->dsp.sb_irq401) ? 4 : 0) | 0x4000; + ((sb->dsp.sb_irq401) ? 4 : 0) | 0x40; ret = temp; break; diff --git a/src/usb.c b/src/usb.c index 9692068b2..dce1a31af 100644 --- a/src/usb.c +++ b/src/usb.c @@ -146,6 +146,9 @@ ohci_mmio_read(uint32_t addr, void *p) ret = dev->ohci_mmio[addr]; + if (addr == 0x101) + ret = (ret & 0xfe) | (!!mem_a20_key); + return ret; } diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index 03436ba32..7bf5933a1 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -20,8 +20,8 @@ add_library(vid OBJECT video.c vid_table.c vid_cga.c vid_cga_comp.c vid_svga_render.c vid_ddc.c vid_vga.c vid_ati_eeprom.c vid_ati18800.c vid_ati28800.c vid_ati_mach64.c vid_ati68860_ramdac.c vid_bt48x_ramdac.c vid_av9194.c vid_icd2061.c vid_ics2494.c vid_ics2595.c vid_cl54xx.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 vid_rtg310x.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 vid_rtg310x.c vid_ti_cf62011.c vid_tvga.c vid_tgui9440.c vid_tkd8001_ramdac.c vid_att20c49x_ramdac.c vid_s3.c vid_s3_virge.c vid_ibm_rgb528_ramdac.c vid_sdac_ramdac.c vid_ogc.c vid_nga.c) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 155253610..62a484891 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -1597,7 +1597,7 @@ gd54xx_recalctimings(svga_t *svga) uint8_t clocksel, rdmask; uint8_t linedbl = svga->dispend * 9 / 10 >= svga->hdisp; - svga->rowoffset = (svga->crtc[0x13]) | ((svga->crtc[0x1b] & 0x10) << 4); + svga->rowoffset = (svga->crtc[0x13]) | (((int) (uint32_t) (svga->crtc[0x1b] & 0x10)) << 4); svga->interlace = (svga->crtc[0x1a] & 0x01); @@ -1774,6 +1774,28 @@ gd54xx_recalctimings(svga_t *svga) } svga->vram_display_mask = (svga->crtc[0x1b] & 2) ? gd54xx->vram_mask : 0x3ffff; + + pclog("svga->crtc[0x1a] = %02X\n", svga->crtc[0x1a]); + pclog("svga->crtc[0x1b] = %02X\n", svga->crtc[0x1b]); + pclog("svga->crtc[0x1c] = %02X\n", svga->crtc[0x1c]); + + if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430) + svga->htotal += ((svga->crtc[0x1c] >> 3) & 0x07); + + 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, + and the actual blanking comes from the display enable signal. */ + /* Start blanking at the first character clock after the last active one. */ + svga->hblankstart = svga->crtc[1] + 1; + svga->hblank_end_val = (svga->htotal + 6) & 0x3f; + /* 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; + /* Also make sure vertical blanking starts on display end. */ + svga->vblankstart = svga->dispend; + } } diff --git a/src/video/vid_et3000.c b/src/video/vid_et3000.c new file mode 100644 index 000000000..70a383bfa --- /dev/null +++ b/src/video/vid_et3000.c @@ -0,0 +1,308 @@ +/* + * 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 Tseng Labs ET3000. + * + * Authors: Miran Grca, + * + * Copyright 2016-2018 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/mca.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> + + +#define BIOS_ROM_PATH "roms/video/et3000/Tseng ET3000AX ISA VGA-VGA ULTRA.bin" + +typedef struct { + const char *name; + int type; + + svga_t svga; + + rom_t bios_rom; + + uint8_t banking; +} et3000_t; + + +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); + + +static uint8_t +et3000_in(uint16_t addr, void *priv) +{ + et3000_t *dev = (et3000_t *)priv; + svga_t *svga = &dev->svga; + + if (((addr & 0xfff0) == 0x3d0 || + (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; + + switch (addr) { + case 0x3cd: /*Banking*/ + return dev->banking; + + case 0x3d4: + return svga->crtcreg; + + case 0x3d5: + return svga->crtc[svga->crtcreg]; + } + + return svga_in(addr, svga); +} + +static void +et3000_out(uint16_t addr, uint8_t val, void *priv) +{ + et3000_t *dev = (et3000_t *)priv; + svga_t *svga = &dev->svga; + uint8_t old; + + if (((addr & 0xfff0) == 0x3d0 || + (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; + + switch (addr) { + case 0x3c0: + case 0x3c1: + 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); + } + break; + + case 0x3c5: + 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); + return; + } + break; + + case 0x3cf: + if ((svga->gdcaddr & 15) == 5) { + svga->chain4 &= ~0x10; + if (val & 0x40) + svga->chain4 |= (svga->attrregs[0x16] & 0x10); + } + break; + + case 0x3cd: /*Banking*/ + dev->banking = 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->read_bank = ((val >> 3) & 7) << 17; + break; + case 1: /*64K segments*/ + svga->write_bank = (val & 7) << 16; + svga->read_bank = ((val >> 3) & 7) << 16; + break; + } + } + return; + + case 0x3d4: + svga->crtcreg = val & 0x3f; + 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 < 0x0e || svga->crtcreg > 0x10) { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + break; + } + + svga_out(addr, val, svga); +} + + +static void +et3000_recalctimings(svga_t *svga) +{ + svga->ma_latch |= (svga->crtc[0x23] & 2) << 15; + if (svga->crtc[0x25] & 1) svga->vblankstart |= 0x400; + if (svga->crtc[0x25] & 2) svga->vtotal |= 0x400; + if (svga->crtc[0x25] & 4) svga->dispend |= 0x400; + if (svga->crtc[0x25] & 8) svga->vsyncstart |= 0x400; + if (svga->crtc[0x25] & 0x10) svga->split |= 0x400; + + svga->interlace = !!(svga->crtc[0x25] & 0x80); + + if (svga->attrregs[0x16] & 0x10) { + svga->ma_latch <<= (1 << 0); + svga->rowoffset <<= (1 << 0); + switch (svga->gdcreg[5] & 0x60) { + case 0x00: + svga->render = svga_render_4bpp_highres; + svga->hdisp *= 2; + break; + case 0x20: + svga->render = svga_render_2bpp_highres; + break; + case 0x40: case 0x60: + svga->render = svga_render_8bpp_highres; + break; + } + } + + /* pclog("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: + case 1: + break; + case 3: + svga->clock = (cpuclock * (double)(1ull << 32)) / 40000000.0; + break; + case 5: + svga->clock = (cpuclock * (double)(1ull << 32)) / 65000000.0; + break; + default: + svga->clock = (cpuclock * (double)(1ull << 32)) / 36000000.0; + break; + } +} + + +static void * +et3000_init(const device_t *info) +{ + const char *fn; + et3000_t *dev; + + dev = (et3000_t *)malloc(sizeof(et3000_t)); + memset(dev, 0x00, sizeof(et3000_t)); + dev->name = info->name; + dev->type = info->local; + fn = BIOS_ROM_PATH; + + switch(dev->type) { + case 0: /* ISA ET3000AX */ + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et3000_isa); + svga_init(info, &dev->svga, dev, device_get_config_int("memory") << 10, + et3000_recalctimings, et3000_in, et3000_out, + NULL, NULL); + io_sethandler(0x03c0, 32, + et3000_in,NULL,NULL, et3000_out,NULL,NULL, dev); + break; + } + + rom_init(&dev->bios_rom, (char *) fn, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + dev->svga.bpp = 8; + dev->svga.miscout = 1; + + return(dev); +} + + +static void +et3000_close(void *priv) +{ + et3000_t *dev = (et3000_t *)priv; + + svga_close(&dev->svga); + + free(dev); +} + + +static void +et3000_speed_changed(void *priv) +{ + et3000_t *dev = (et3000_t *)priv; + + svga_recalctimings(&dev->svga); +} + + +static void +et3000_force_redraw(void *priv) +{ + et3000_t *dev = (et3000_t *)priv; + + dev->svga.fullchange = changeframecount; +} + + +static int +et3000_available(void) +{ + return rom_present(BIOS_ROM_PATH); +} + +static const device_config_t et3000_config[] = +{ + { + "memory", "Memory size", CONFIG_SELECTION, "", 512, "", { 0 }, + { + { + "256 KB", 256 + }, + { + "512 KB", 512 + }, + { + "1 MB", 1024 + }, + { + "" + } + } + }, + { + "", "", -1 + } +}; + +const device_t et3000_isa_device = { + "Tseng Labs ET3000AX (ISA)", + DEVICE_ISA, + 0, + et3000_init, et3000_close, NULL, + { et3000_available }, + et3000_speed_changed, + et3000_force_redraw, + et3000_config +}; diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index d22a6e6af..3bce65159 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -55,6 +55,7 @@ #define BIOS_ROM_PATH "roms/video/et4000/et4000.bin" +#define TC6058AF_BIOS_ROM_PATH "roms/video/et4000/Tseng_Labs_VGA-4000_BIOS_V1.1.bin" #define KOREAN_BIOS_ROM_PATH "roms/video/et4000/tgkorvga.bin" #define KOREAN_FONT_ROM_PATH "roms/video/et4000/tg_ksc5601.rom" #define KASAN_BIOS_ROM_PATH "roms/video/et4000/et4000_kasan16.bin" @@ -109,13 +110,14 @@ et4000_in(uint16_t addr, void *priv) { et4000_t *dev = (et4000_t *)priv; svga_t *svga = &dev->svga; + uint8_t ret; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; switch (addr) { case 0x3c2: - if (dev->type == 1) { + if (dev->type == 2) { if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x4e) return 0; else @@ -132,7 +134,9 @@ et4000_in(uint16_t addr, void *priv) case 0x3c7: case 0x3c8: case 0x3c9: - return sc1502x_ramdac_in(addr, svga->ramdac, svga); + if (dev->type >= 1) + return sc1502x_ramdac_in(addr, svga->ramdac, svga); + break; case 0x3cd: /*Banking*/ return dev->banking; @@ -142,6 +146,26 @@ et4000_in(uint16_t addr, void *priv) case 0x3d5: return svga->crtc[svga->crtcreg]; + + 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; + + if (ret & 0x08) + ret &= 0x7f; + else + ret |= 0x80; + + return ret; } return svga_in(addr, svga); @@ -223,12 +247,34 @@ et4000_out(uint16_t addr, uint8_t val, void *priv) (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; switch (addr) { + case 0x3c5: + 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); + return; + } else if (svga->seqaddr == 0x0e) { + svga->seqregs[0x0e] = val; + svga->chain4 &= ~0x02; + if (svga->gdcreg[5] & 0x40) + svga->chain4 |= (svga->seqregs[0x0e] & 0x02); + svga_recalctimings(svga); + return; + } + break; + case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: - sc1502x_ramdac_out(addr, val, svga->ramdac, svga); - return; + if (dev->type >= 1) { + sc1502x_ramdac_out(addr, val, svga->ramdac, svga); + return; + } + break; case 0x3cd: /*Banking*/ if (!(svga->crtc[0x36] & 0x10) && !(svga->gdcreg[6] & 0x08)) { @@ -239,7 +285,11 @@ et4000_out(uint16_t addr, uint8_t val, void *priv) return; case 0x3cf: - if ((svga->gdcaddr & 15) == 6) { + if ((svga->gdcaddr & 15) == 5) { + svga->chain4 &= ~0x02; + if (val & 0x40) + svga->chain4 |= (svga->seqregs[0x0e] & 0x02); + } else if ((svga->gdcaddr & 15) == 6) { if (!(svga->crtc[0x36] & 0x10) && !(val & 0x08)) { svga->write_bank = (dev->banking & 0x0f) * 0x10000; svga->read_bank = ((dev->banking >> 4) & 0x0f) * 0x10000; @@ -542,13 +592,13 @@ et4000_recalctimings(svga_t *svga) et4000_t *dev = (et4000_t *)svga->p; svga->ma_latch |= (svga->crtc[0x33] & 3) << 16; - if (svga->crtc[0x35] & 1) svga->vblankstart += 0x400; - if (svga->crtc[0x35] & 2) svga->vtotal += 0x400; - if (svga->crtc[0x35] & 4) svga->dispend += 0x400; - if (svga->crtc[0x35] & 8) svga->vsyncstart += 0x400; - if (svga->crtc[0x35] & 0x10) svga->split += 0x400; + if (svga->crtc[0x35] & 1) svga->vblankstart |= 0x400; + if (svga->crtc[0x35] & 2) svga->vtotal |= 0x400; + if (svga->crtc[0x35] & 4) svga->dispend |= 0x400; + if (svga->crtc[0x35] & 8) svga->vsyncstart |= 0x400; + if (svga->crtc[0x35] & 0x10) svga->split |= 0x400; if (!svga->rowoffset) svga->rowoffset = 0x100; - if (svga->crtc[0x3f] & 1) svga->htotal += 256; + if (svga->crtc[0x3f] & 1) svga->htotal |= 0x100; if (svga->attrregs[0x16] & 0x20) svga->hdisp <<= 1; switch (((svga->miscout >> 2) & 3) | ((svga->crtc[0x34] << 1) & 4)) { @@ -577,7 +627,7 @@ et4000_recalctimings(svga_t *svga) break; } - if (dev->type == 2 || dev->type == 3 || dev->type == 4) { + if (dev->type == 3 || dev->type == 4 || dev->type == 5) { if ((svga->render == svga_render_text_80) && ((svga->crtc[0x37] & 0x0A) == 0x0A)) { if (dev->port_32cb_val & 0x80) { svga->ma_latch -= 2; @@ -588,6 +638,19 @@ et4000_recalctimings(svga_t *svga) } } } + + if ((svga->seqregs[0x0e] & 0x02) && ((svga->gdcreg[5] & 0x60) >= 0x40)) { + svga->ma_latch <<= (1 << 0); + svga->rowoffset <<= (1 << 0); + svga->render = svga_render_8bpp_highres; + } + + if (dev->type == 0) { + if (svga->render == svga_render_8bpp_lowres) + svga->render = svga_render_8bpp_tseng_lowres; + else if (svga->render == svga_render_8bpp_highres) + svga->render = svga_render_8bpp_tseng_highres; + } } static void @@ -601,6 +664,7 @@ et4000_kasan_recalctimings(svga_t *svga) svga->ma_latch -= 3; svga->ca_adj = (et4000->kasan_cfg_regs[0] >> 6) - 3; svga->ksc5601_sbyte_mask = (et4000->kasan_cfg_regs[0] & 4) << 5; + /* TODO: Are we sure this doesn't use Attribute register 16h bit 6 (two-byte character code enable)? */ if((et4000->kasan_cfg_regs[0] & 0x23) == 0x20 && (et4000->kasan_cfg_regs[4] & 0x80) && ((svga->crtc[0x37] & 0x0B) == 0x0A)) svga->render = svga_render_text_80_ksc5601; } @@ -649,7 +713,8 @@ et4000_init(const device_t *info) fn = BIOS_ROM_PATH; switch(dev->type) { - case 0: /* ISA ET4000AX */ + case 0: /* ISA ET4000AX (TC6058AF) */ + case 1: /* ISA ET4000AX */ dev->vram_size = device_get_config_int("memory") << 10; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000_isa); svga_init(info, &dev->svga, dev, dev->vram_size, @@ -657,9 +722,11 @@ et4000_init(const device_t *info) NULL, NULL); io_sethandler(0x03c0, 32, et4000_in,NULL,NULL, et4000_out,NULL,NULL, dev); + if (dev->type == 0) + fn = TC6058AF_BIOS_ROM_PATH; break; - case 1: /* MCA ET4000AX */ + case 2: /* MCA ET4000AX */ dev->vram_size = 1024 << 10; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000_mca); svga_init(info, &dev->svga, dev, dev->vram_size, @@ -672,8 +739,8 @@ et4000_init(const device_t *info) mca_add(et4000_mca_read, et4000_mca_write, et4000_mca_feedb, NULL, dev); break; - case 2: /* Korean ET4000 */ - case 3: /* Trigem 286M ET4000 */ + case 3: /* Korean ET4000 */ + case 4: /* Trigem 286M ET4000 */ dev->vram_size = device_get_config_int("memory") << 10; dev->port_22cb_val = 0x60; dev->port_32cb_val = 0; @@ -697,7 +764,7 @@ et4000_init(const device_t *info) loadfont(KOREAN_FONT_ROM_PATH, 6); fn = KOREAN_BIOS_ROM_PATH; break; - case 4: /* Kasan ET4000 */ + case 5: /* Kasan ET4000 */ dev->vram_size = device_get_config_int("memory") << 10; dev->svga.ksc5601_sbyte_mask = 0; dev->svga.ksc5601_udc_area_msb[0] = 0xC9; @@ -733,7 +800,8 @@ et4000_init(const device_t *info) } - dev->svga.ramdac = device_add(&sc1502x_ramdac_device); + if (dev->type >= 1) + dev->svga.ramdac = device_add(&sc1502x_ramdac_device); dev->vram_mask = dev->vram_size - 1; @@ -777,6 +845,13 @@ et4000_force_redraw(void *priv) } +static int +et4000_tc6058af_available(void) +{ + return rom_present(TC6058AF_BIOS_ROM_PATH); +} + + static int et4000_available(void) { @@ -798,6 +873,27 @@ et4000_kasan_available(void) rom_present(KASAN_FONT_ROM_PATH); } +static const device_config_t et4000_tc6058af_config[] = +{ + { + "memory", "Memory size", CONFIG_SELECTION, "", 1024, "", { 0 }, + { + { + "256 KB", 256 + }, + { + "512 KB", 512 + }, + { + "" + } + } + }, + { + "", "", -1 + } +}; + static const device_config_t et4000_config[] = { { @@ -822,10 +918,21 @@ static const device_config_t et4000_config[] = } }; +const device_t et4000_tc6058af_isa_device = { + "Tseng Labs ET4000AX (TC6058AF) (ISA)", + DEVICE_ISA, + 0, + et4000_init, et4000_close, NULL, + { et4000_tc6058af_available }, + et4000_speed_changed, + et4000_force_redraw, + et4000_tc6058af_config +}; + const device_t et4000_isa_device = { "Tseng Labs ET4000AX (ISA)", DEVICE_ISA, - 0, + 1, et4000_init, et4000_close, NULL, { et4000_available }, et4000_speed_changed, @@ -836,7 +943,7 @@ const device_t et4000_isa_device = { const device_t et4000_mca_device = { "Tseng Labs ET4000AX (MCA)", DEVICE_MCA, - 1, + 2, et4000_init, et4000_close, NULL, { et4000_available }, et4000_speed_changed, @@ -847,7 +954,7 @@ const device_t et4000_mca_device = { const device_t et4000k_isa_device = { "Trigem Korean VGA (Tseng Labs ET4000AX Korean)", DEVICE_ISA, - 2, + 3, et4000_init, et4000_close, NULL, { et4000k_available }, et4000_speed_changed, @@ -858,7 +965,7 @@ const device_t et4000k_isa_device = { const device_t et4000k_tg286_isa_device = { "Trigem Korean VGA (Trigem 286M)", DEVICE_ISA, - 3, + 4, et4000_init, et4000_close, NULL, { et4000k_available }, et4000_speed_changed, @@ -869,7 +976,7 @@ const device_t et4000k_tg286_isa_device = { const device_t et4000_kasan_isa_device = { "Kasan Hangulmadang-16 VGA (Tseng Labs ET4000AX Korean)", DEVICE_ISA, - 4, + 5, et4000_init, et4000_close, NULL, { et4000_kasan_available }, et4000_speed_changed, diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 1652615af..e2cbab980 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -363,6 +363,7 @@ et4000w32p_recalctimings(svga_t *svga) svga->clock = (cpuclock * (double)(1ull << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen); +#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 */ @@ -379,10 +380,10 @@ et4000w32p_recalctimings(svga_t *svga) 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; + } } } +#endif if (et4000->type == ET4000W32) { if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { @@ -421,8 +422,10 @@ et4000w32p_recalctimings(svga_t *svga) else svga->render = svga_render_text_80; } else { +#if 0 if (svga->adv_flags & FLAG_NOSKEW) svga->ma_latch--; +#endif switch (svga->gdcreg[5] & 0x60) { case 0x00: diff --git a/src/video/vid_oak_oti.c b/src/video/vid_oak_oti.c index cd7d4e26e..771ed1f05 100644 --- a/src/video/vid_oak_oti.c +++ b/src/video/vid_oak_oti.c @@ -30,9 +30,7 @@ #include <86box/vid_svga.h> #define BIOS_037C_PATH "roms/video/oti/bios.bin" -#define BIOS_067_AMA932J_PATH "roms/machines/ama932j/oti067.bin" -#define BIOS_067_M300_08_PATH "roms/machines/olivetti_m300_08/EVC_BIOS.ROM" -#define BIOS_067_M300_15_PATH "roms/machines/olivetti_m300_15/EVC_BIOS.ROM" +#define BIOS_067_AMA932J_PATH "roms/machines/ama932j/oti067.bin" #define BIOS_077_PATH "roms/video/oti/oti077.vbi" @@ -40,7 +38,6 @@ enum { OTI_037C, OTI_067 = 2, OTI_067_AMA932J, - OTI_067_M300 = 4, OTI_077 = 5 }; @@ -370,16 +367,6 @@ oti_init(const device_t *info) io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti); break; - case OTI_067_M300: - if (rom_present(BIOS_067_M300_15_PATH)) - romfn = BIOS_067_M300_15_PATH; - else - romfn = BIOS_067_M300_08_PATH; - oti->vram_size = device_get_config_int("memory"); - oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */ - io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti); - break; - case OTI_067: case OTI_077: romfn = BIOS_077_PATH; @@ -446,27 +433,20 @@ oti037c_available(void) return(rom_present(BIOS_037C_PATH)); } + static int oti067_ama932j_available(void) { return(rom_present(BIOS_067_AMA932J_PATH)); } + static int oti067_077_available(void) { return(rom_present(BIOS_077_PATH)); } -static int -oti067_m300_available(void) -{ - if (rom_present(BIOS_067_M300_15_PATH)) - return(rom_present(BIOS_067_M300_15_PATH)); - else - return(rom_present(BIOS_067_M300_08_PATH)); -} - static const device_config_t oti067_config[] = { @@ -559,18 +539,6 @@ const device_t oti067_device = oti067_config }; -const device_t oti067_m300_device = -{ - "Oak OTI-067 (Olivetti M300-08/15)", - DEVICE_ISA, - 4, - oti_init, oti_close, NULL, - { oti067_m300_available }, - oti_speed_changed, - oti_force_redraw, - oti067_config -}; - const device_t oti067_ama932j_device = { "Oak OTI-067 (AMA-932J)", diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index ed2d4b648..0822c9148 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -2531,14 +2531,14 @@ static void s3_recalctimings(svga_t *svga) s3_t *s3 = (s3_t *)svga->p; int clk_sel = (svga->miscout >> 2) & 3; + svga->hdisp = svga->hdisp_old; svga->ma_latch |= (s3->ma_ext << 16); - if (s3->chip >= S3_86C928) { - svga->hdisp = svga->hdisp_old; + if (s3->chip >= S3_86C928) { if (svga->crtc[0x5d] & 0x01) svga->htotal |= 0x100; if (svga->crtc[0x5d] & 0x02) { svga->hdisp_time |= 0x100; - svga->hdisp |= 0x100 * ((svga->seqregs[1] & 8) ? 16 : 8); + svga->hdisp |= 0x100 * svga->dots_per_clock; } if (svga->crtc[0x5e] & 0x01) svga->vtotal |= 0x400; if (svga->crtc[0x5e] & 0x02) svga->dispend |= 0x400; @@ -2547,7 +2547,7 @@ static void s3_recalctimings(svga_t *svga) if (svga->crtc[0x5e] & 0x40) svga->split |= 0x400; if (svga->crtc[0x51] & 0x30) svga->rowoffset |= (svga->crtc[0x51] & 0x30) << 4; else if (svga->crtc[0x43] & 0x04) svga->rowoffset |= 0x100; - } + } else if (svga->crtc[0x43] & 0x04) svga->rowoffset |= 0x100; if (!svga->rowoffset) svga->rowoffset = 256; if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { @@ -2649,6 +2649,28 @@ static void s3_recalctimings(svga_t *svga) svga->rowoffset <<= 1; } } + + 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); + } + + 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. */ + // pclog("svga->crtc[0x5d] = %02X\n", svga->crtc[0x5d]); + if (svga->crtc[0x5d] & 0x08) + svga->hblank_ext = 0x40; + svga->hblank_end_len = 0x00000040; + } + } + + svga->hblank_overscan = !(svga->crtc[0x33] & 0x20); } static void s3_trio64v_recalctimings(svga_t *svga) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 07f6f3823..01afc2123 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -20,11 +20,13 @@ * Copyright 2016-2019 Miran Grca. */ #include +#include #include #include -#include #include +#include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/device.h> @@ -53,6 +55,27 @@ uint8_t svga_rotate[8][256]; static svga_t *svga_pri; +// #define ENABLE_SVGA_LOG 1 +#ifdef ENABLE_SVGA_LOG +int svga_do_log = ENABLE_SVGA_LOG; + + +static void +svga_log(const char *fmt, ...) +{ + va_list ap; + + if (svga_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define svga_log(fmt, ...) +#endif + + svga_t *svga_get_pri() { @@ -176,7 +199,7 @@ svga_out(uint16_t addr, uint8_t val, void *p) break; case 4: svga->chain2_write = !(val & 4); - svga->chain4 = val & 8; + svga->chain4 = (svga->chain4 & ~8) | (val & 8); svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && ((svga->chain4 && svga->packed_chain4) || svga->fb_only) && !(svga->adv_flags & FLAG_ADDR_BY8); break; @@ -235,7 +258,7 @@ svga_out(uint16_t addr, uint8_t val, void *p) break; case 6: if ((svga->gdcreg[6] & 0xc) != (val & 0xc)) { - switch (val&0xC) { + switch (val & 0xc) { case 0x0: /*128k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); svga->banked_mask = 0xffff; @@ -266,6 +289,9 @@ svga_out(uint16_t addr, uint8_t val, void *p) ((svga->gdcaddr & 15) == 6 && (val ^ o) & 1)) svga_recalctimings(svga); break; + case 0x3da: + svga->fcr = val; + break; } } @@ -331,6 +357,9 @@ svga_in(uint16_t addr, void *p) break; } break; + case 0x3ca: + ret = svga->fcr; + break; case 0x3cc: ret = svga->miscout; break; @@ -364,7 +393,11 @@ svga_in(uint16_t addr, void *p) svga->cgastat &= ~0x30; else svga->cgastat ^= 0x30; + ret = svga->cgastat; + + if ((svga->fcr & 0x08) && svga->dispon) + ret |= 0x08; break; } @@ -396,6 +429,10 @@ void svga_recalctimings(svga_t *svga) { double crtcconst, _dispontime, _dispofftime, disptime; +#ifdef ENABLE_SVGA_LOG + int vsyncend, vblankend; + int hdispstart, hdispend, hsyncstart, hsyncend; +#endif svga->vtotal = svga->crtc[6]; svga->dispend = svga->crtc[0x12]; @@ -433,12 +470,9 @@ svga_recalctimings(svga_t *svga) svga->vblankstart |= 0x200; svga->vblankstart++; - svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5); + svga->hdisp = svga->crtc[1] - ((svga->crtc[3] & 0x60) >> 5); svga->hdisp++; - svga->htotal = svga->crtc[0]; - svga->htotal += 6; /*+6 is required for Tyrian*/ - svga->rowoffset = svga->crtc[0x13]; svga->clock = (svga->vidclock) ? VGACONST2 : VGACONST1; @@ -455,20 +489,19 @@ svga_recalctimings(svga_t *svga) svga->hdisp_time = svga->hdisp; svga->render = svga_render_blank; 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->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)) { /*Text mode*/ - if (svga->seqregs[1] & 8) /*40 column*/ { + if (svga->seqregs[1] & 8) /*40 column*/ svga->render = svga_render_text_40; - svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; - /* Character clock is off by 1 now in 40-line modes, on all cards. */ - svga->ma_latch--; - svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18; - } else { + else svga->render = svga_render_text_80; - svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9; - } svga->hdisp_old = svga->hdisp; } else { - svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; svga->hdisp_old = svga->hdisp; switch (svga->gdcreg[5] & 0x60) { @@ -530,7 +563,7 @@ svga_recalctimings(svga_t *svga) } svga->linedbl = svga->crtc[9] & 0x80; - svga->char_width = (svga->seqregs[1] & 1) ? 8 : 9; + svga->char_width = (svga->seqregs[1] & 1) ? 8 : 9; if (enable_overscan) { overscan_y = (svga->rowcount + 1) << 1; @@ -547,9 +580,41 @@ svga_recalctimings(svga_t *svga) } else overscan_x = 16; + svga->htotal = svga->crtc[0]; + svga->hblankstart = svga->crtc[4] + 1; + svga->hblank_end_val = (svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00); + // pclog("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); + } else + svga->dots_per_clock = 1; + + /* Do svga->recalctimings_ex() here so that the above five variables can be + updated by said function. */ if (svga->recalctimings_ex) svga->recalctimings_ex(svga); + svga->htotal += 6; /*+6 is required for Tyrian*/ + 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; + + 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->y_add = (overscan_y >> 1) - (svga->crtc[8] & 0x1f); svga->x_add = (overscan_x >> 1); @@ -558,6 +623,44 @@ svga_recalctimings(svga_t *svga) crtcconst = svga->clock * svga->char_width; +#ifdef ENABLE_SVGA_LOG + vsyncend = (svga->vsyncstart & 0xfffffff0) | (svga->crtc[0x11] & 0x0f); + if (vsyncend <= svga->vsyncstart) + vsyncend += 0x00000010; + vblankend = (svga->vblankstart & 0xffffff80) | (svga->crtc[0x16] & 0x7f); + if (vblankend <= svga->vblankstart) + vblankend += 0x00000080; + + hdispstart = ((svga->crtc[3] >> 5) & 3); + hdispend = svga->crtc[1] + 1; + hsyncstart = svga->crtc[4] + ((svga->crtc[5] >> 5) & 3) + 1; + hsyncend = (hsyncstart & 0xffffffe0) | (svga->crtc[5] & 0x1f); + if (hsyncend <= hsyncstart) + hsyncend += 0x00000020; +#endif + + svga_log("Last scanline in the vertical period: %i\n" + "First scanline after the last of active display: %i\n" + "First scanline with vertical retrace asserted: %i\n" + "First scanline after the last with vertical retrace asserted: %i\n" + "First scanline of blanking: %i\n" + "First scanline after the last of blanking: %i\n" + "\n" + "Last character in the horizontal period: %i\n" + "First character of active display: %i\n" + "First character after the last of active display: %i\n" + "First character with horizontal retrace asserted: %i\n" + "First character after the last with horizontal retrace asserted: %i\n" + "First character of blanking: %i\n" + "First character after the last of blanking: %i\n" + "\n" + "\n", + svga->vtotal, svga->dispend, svga->vsyncstart, vsyncend, + svga->vblankstart, vblankend, + svga->htotal, hdispstart, hdispend, hsyncstart, hsyncend, + svga->hblankstart, svga->hblankend + ); + disptime = svga->htotal; _dispontime = svga->hdisp_time; @@ -643,6 +746,8 @@ svga_poll(void *p) uint32_t x, blink_delay; int wx, wy; int ret, old_ma; + // int lines_num = (svga->vtotal > svga->vsyncstart) ? svga->vtotal : svga->vsyncstart; + // int lines_num = svga->vsyncstart + 3 + 19; if (!svga->linepos) { if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena) { @@ -721,7 +826,7 @@ svga_poll(void *p) svga->displine++; if (svga->interlace) svga->displine++; - if ((svga->cgastat & 8) && ((svga->displine & 15) == (svga->crtc[0x11] & 15)) && svga->vslines) + if ((svga->cgastat & 8) && ((svga->displine & 15) == (svga->crtc[0x11] & 15))) svga->cgastat &= ~8; svga->vslines++; if (svga->displine > 1500) @@ -773,11 +878,12 @@ svga_poll(void *p) if (ret) { if (svga->interlace && svga->oddeven) - svga->ma = svga->maback = (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5); + svga->ma = svga->maback = (svga->rowoffset << 1) + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub; else - svga->ma = svga->maback = ((svga->crtc[5] & 0x60) >> 5); + svga->ma = svga->maback = ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub; svga->ma = (svga->ma << 2); svga->maback = (svga->maback << 2); + svga->sc = 0; if (svga->attrregs[0x10] & 0x20) { svga->scrollcache = 0; @@ -842,9 +948,9 @@ svga_poll(void *p) svga->vslines = 0; if (svga->interlace && svga->oddeven) - svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5); + svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub; else - svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[5] & 0x60) >> 5); + svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub; svga->ca = ((svga->crtc[0xe] << 8) | svga->crtc[0xf]) + ((svga->crtc[0xb] & 0x60) >> 5) + svga->ca_adj; svga->ma = (svga->ma << 2); @@ -854,6 +960,7 @@ svga_poll(void *p) if (svga->vsync_callback) svga->vsync_callback(svga); } + // if (svga->vc == lines_num) { if (svga->vc == svga->vtotal) { svga->vc = 0; svga->sc = 0; @@ -973,6 +1080,7 @@ svga_init(const device_t *info, svga_t *svga, void *p, 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; } diff --git a/src/video/vid_table.c b/src/video/vid_table.c index 3a929fe73..3f0095088 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -111,6 +111,8 @@ video_cards[] = { { "tvga9000b", &tvga9000b_device }, { "tgkorvga", &et4000k_isa_device }, { "et2000", &et2000_device }, + { "et3000ax", &et3000_isa_device }, + { "et4000ax_tc6058af", &et4000_tc6058af_isa_device }, { "et4000ax", &et4000_isa_device }, { "et4000w32", &et4000w32_device }, { "et4000w32i", &et4000w32i_isa_device }, diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 33686f07e..15e86c28a 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -46,10 +46,7 @@ ifeq ($(DEV_BUILD), y) HEDAKA := y endif ifndef I450KX - I450KX := y - endif - ifndef M154X - M154X := y + I450KX := y endif ifndef LASERXT LASERXT := y @@ -78,9 +75,6 @@ ifeq ($(DEV_BUILD), y) ifndef SIO_DETECT SIO_DETECT := y endif - ifndef M154X - M154X := y - endif ifndef M6117 M6117 := y endif @@ -99,6 +93,9 @@ ifeq ($(DEV_BUILD), y) ifndef OLIVETTI OLIVETTI := y endif + ifndef NEW_KBC + NEW_KBC := n + endif else ifndef DEBUG DEBUG := n @@ -124,9 +121,6 @@ else ifndef LASERXT LASERXT := n endif - ifndef M154X - M154X := n - endif ifndef MGA MGA := n endif @@ -151,9 +145,6 @@ else ifndef SIO_DETECT SIO_DETECT := n endif - ifndef M154X - M154X := n - endif ifndef M6117 M6117 := n endif @@ -172,6 +163,9 @@ else ifndef OLIVETTI OLIVETTI := n endif + ifndef NEW_KBC + NEW_KBC := n + endif endif # Defaults for several build options (possibly defined in a chained file.) @@ -557,11 +551,6 @@ OPTS += -DUSE_SIO_DETECT DEVBROBJ += sio_detect.o endif -ifeq ($(M154X), y) -OPTS += -DUSE_M154X -DEVBROBJ += ali1531.o ali1543.o -endif - ifeq ($(M6117), y) OPTS += -DUSE_M6117 DEVBROBJ += ali6117.o @@ -598,8 +587,8 @@ CXXFLAGS := $(CFLAGS) ######################################################################### # Create the (final) list of objects to build. # ######################################################################### -MAINOBJ := 86box.o config.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \ - nmi.o pic.o pit.o port_92.o ppi.o pci.o mca.o \ +MAINOBJ := 86box.o config.o log.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \ + nmi.o pic.o pit.o port_6x.o port_92.o ppi.o pci.o mca.o \ usb.o device.o nvr.o nvr_at.o nvr_ps2.o \ $(VNCOBJ) @@ -610,13 +599,18 @@ CPUOBJ := cpu.o cpu_table.o fpu.o x86.o \ x86seg.o x87.o x87_timings.o \ $(DYNARECOBJ) -CHIPSETOBJ := acc2168.o cs8230.o ali1217.o ali1429.o ali1489.o et6000.o headland.o intel_82335.o cs4031.o \ - intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \ - neat.o opti495.o opti822.o opti895.o opti5x7.o scamp.o scat.o via_vt82c49x.o via_vt82c505.o \ - gc100.o \ - sis_85c310.o sis_85c4xx.o sis_85c496.o sis_85c50x.o sis_5511.o sis_5571.o sis_5598.o stpc.o opti283.o opti291.o \ - umc_8886.o umc_8890.o umc_hb4.o \ - via_apollo.o via_pipc.o wd76c10.o vl82c480.o +CHIPSETOBJ := acc2168.o \ + cs4031.o cs8230.o \ + ali1217.o ali1429.o ali1489.o ali1531.o ali1543.o \ + gc100.o headland.o \ + intel_82335.o intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \ + neat.o \ + opti283.o opti291.o opti391.o opti495.o opti822.o opti895.o opti5x7.o \ + scamp.o scat.o \ + stpc.o \ + wd76c10.o vl82c480.o \ + via_vt82c49x.o via_vt82c505.o via_apollo.o via_pipc.o \ + sis_85c310.o sis_85c4xx.o sis_85c496.o sis_85c50x.o sis_5511.o sis_5571.o MCHOBJ := machine.o machine_table.o \ m_xt.o m_xt_compaq.o \ @@ -632,10 +626,21 @@ MCHOBJ := machine.o machine_table.o \ m_ps2_isa.o m_ps2_mca.o \ m_at_compaq.o \ m_at_286_386sx.o m_at_386dx_486.o \ - m_at_socket4_5.o m_at_socket7.o m_at_sockets7.o \ + m_at_socket4.o m_at_socket5.o m_at_socket7_3v.o m_at_socket7.o m_at_sockets7.o \ m_at_socket8.o m_at_slot1.o m_at_slot2.o m_at_socket370.o \ m_at_misc.o +ifeq ($(NEW_KBC), y) +DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o ibm_5161.o isamem.o isartc.o \ + lpt.o pci_bridge.o postcard.o serial.o vpc2007.o clock_ics9xxx.o isapnp.o \ + i2c.o i2c_gpio.o smbus_piix4.o \ + keyboard.o \ + keyboard_xt.o kbc_at.o kbd_at.o \ + mouse.o \ + mouse_bus.o \ + mouse_serial.o mouse_ps2.o \ + phoenix_486_jumper.o +else DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o ibm_5161.o isamem.o isartc.o \ lpt.o pci_bridge.o postcard.o serial.o vpc2007.o clock_ics9xxx.o isapnp.o \ i2c.o i2c_gpio.o smbus_piix4.o \ @@ -645,10 +650,11 @@ DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o ibm mouse_bus.o \ mouse_serial.o mouse_ps2.o \ phoenix_486_jumper.o +endif SIOOBJ := sio_acc3221.o \ sio_f82c710.o sio_82091aa.o sio_fdc37c651.o \ - sio_fdc37c661.o sio_fdc37c66x.o sio_fdc37c669.o sio_fdc37c93x.o sio_fdc37m60x.o \ + sio_fdc37c661.o sio_fdc37c66x.o sio_fdc37c67x.o sio_fdc37c669.o sio_fdc37c93x.o sio_fdc37m60x.o \ sio_it8661f.o \ sio_pc87306.o sio_pc87307.o sio_pc87309.o sio_pc87310.o sio_pc87311.o sio_pc87332.o \ sio_prime3b.o sio_prime3c.o \ @@ -753,6 +759,7 @@ VIDOBJ := video.o \ vid_bt48x_ramdac.o \ vid_av9194.o vid_icd2061.o vid_ics2494.o vid_ics2595.o \ vid_cl54xx.o \ + vid_et3000.o \ vid_et4000.o vid_sc1148x_ramdac.o \ vid_sc1502x_ramdac.o \ vid_et4000w32.o vid_stg_ramdac.o \ diff --git a/src/win/win.c b/src/win/win.c index 0854dac64..5f8dd60f5 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -508,7 +508,8 @@ main_thread(void *param) frames = 0; } } else /* Just so we dont overload the host OS. */ - Sleep(1); + Sleep((drawits < -1) ? 1 : 0); + // Sleep(1); /* If needed, handle a screen resize. */ if (doresize && !video_fullscreen) { From a896953dd5f7590a403b8cbeb1d72878967b6be9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 4 Jul 2021 18:16:35 +0200 Subject: [PATCH 02/96] Current WIP ALi work. --- src/chipset/CMakeLists.txt | 4 +- src/chipset/ali1531.c | 19 +- src/chipset/ali1541.c | 656 ++++++++++++++++ src/chipset/ali1543.c | 257 +++++-- src/chipset/ali1621.c | 757 +++++++++++++++++++ src/chipset/intel_piix.c | 2 +- src/chipset/via_pipc.c | 2 +- src/device/CMakeLists.txt | 4 +- src/device/pci_bridge.c | 157 +++- src/device/smbus_ali7101.c | 312 ++++++++ src/device/smbus_piix4.c | 2 +- src/include/86box/chipset.h | 2 + src/include/86box/machine.h | 3 + src/include/86box/pci.h | 7 +- src/include/86box/{smbus_piix4.h => smbus.h} | 18 +- src/machine/m_at_sockets7.c | 66 ++ src/machine/machine_table.c | 6 + src/win/Makefile.mingw | 4 +- 18 files changed, 2190 insertions(+), 88 deletions(-) create mode 100644 src/chipset/ali1541.c create mode 100644 src/chipset/ali1621.c create mode 100644 src/device/smbus_ali7101.c rename src/include/86box/{smbus_piix4.h => smbus.h} (66%) diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index ab8f96e61..ead771da7 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -13,8 +13,8 @@ # Copyright 2020,2021 David Hrdlička. # -add_library(chipset OBJECT acc2168.c cs8230.c ali1217.c ali1429.c ali1489.c ali1531.c ali1543.c - headland.c intel_82335.c cs4031.c intel_420ex.c intel_4x0.c intel_sio.c intel_piix.c +add_library(chipset OBJECT acc2168.c cs8230.c ali1217.c ali1429.c ali1489.c ali1531.c ali1541.c + ali1543.c headland.c intel_82335.c cs4031.c intel_420ex.c intel_4x0.c intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c opti495.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 sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c diff --git a/src/chipset/ali1531.c b/src/chipset/ali1531.c index ce161ce7c..59080144f 100644 --- a/src/chipset/ali1531.c +++ b/src/chipset/ali1531.c @@ -253,27 +253,10 @@ ali1531_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf[addr] = val & 0x7f; break; - case 0x60: /* DRB's */ - case 0x62: - case 0x64: - case 0x66: - case 0x68: - case 0x6a: - case 0x6c: - case 0x6e: + case 0x60 ... 0x6f: /* DRB's */ dev->pci_conf[addr] = val; spd_write_drbs_interleaved(dev->pci_conf, 0x60, 0x6f, 1); break; - case 0x61: - case 0x63: - case 0x65: - case 0x67: - case 0x69: - case 0x6b: - case 0x6d: - case 0x6f: - dev->pci_conf[addr] = val; - break; case 0x70: case 0x71: dev->pci_conf[addr] = val; diff --git a/src/chipset/ali1541.c b/src/chipset/ali1541.c new file mode 100644 index 000000000..16587b3fc --- /dev/null +++ b/src/chipset/ali1541.c @@ -0,0 +1,656 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the ALi M1541/2 CPU-to-PCI Bridge. + * + * Authors: Miran Grca, + * + * Copyright 2021 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/timer.h> + +#include <86box/device.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/pci.h> +#include <86box/smram.h> +#include <86box/spd.h> + +#include <86box/chipset.h> + + +typedef struct ali1541_t +{ + uint8_t pci_conf[256]; + + smram_t * smram; + void * agp_bridge; +} ali1541_t; + + +#ifdef ENABLE_ALI1541_LOG +int ali1541_do_log = ENABLE_ALI1541_LOG; +static void +ali1541_log(const char *fmt, ...) +{ + va_list ap; + + if (ali1541_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define ali1541_log(fmt, ...) +#endif + + +static void +ali1541_smram_recalc(uint8_t val, ali1541_t *dev) +{ + smram_disable_all(); + + if (val & 1) { + switch (val & 0x0c) { + case 0x00: + ali1541_log("SMRAM: D0000 -> B0000 (%i)\n", val & 2); + smram_enable(dev->smram, 0xd0000, 0xb0000, 0x10000, val & 2, 1); + if (val & 0x10) + mem_set_mem_state_smram_ex(1, 0xd0000, 0x10000, 0x02); + break; + case 0x04: + ali1541_log("SMRAM: A0000 -> A0000 (%i)\n", val & 2); + smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, val & 2, 1); + if (val & 0x10) + mem_set_mem_state_smram_ex(1, 0xa0000, 0x20000, 0x02); + break; + case 0x08: + ali1541_log("SMRAM: 30000 -> B0000 (%i)\n", val & 2); + smram_enable(dev->smram, 0x30000, 0xb0000, 0x10000, val & 2, 1); + if (val & 0x10) + mem_set_mem_state_smram_ex(1, 0x30000, 0x10000, 0x02); + break; + } + } + + flushmmucache_nopc(); +} + + +static void +ali1541_shadow_recalc(int cur_reg, ali1541_t *dev) +{ + int i, bit, r_reg, w_reg; + uint32_t base, flags = 0; + + shadowbios = shadowbios_write = 0; + + for (i = 0; i < 16; i++) { + base = 0x000c0000 + (i << 14); + bit = i & 7; + r_reg = 0x56 + (i >> 3); + w_reg = 0x58 + (i >> 3); + + flags = (dev->pci_conf[r_reg] & (1 << bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + flags |= ((dev->pci_conf[w_reg] & (1 << bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY); + + if (base >= 0x000e0000) { + if (dev->pci_conf[r_reg] & (1 << bit)) + shadowbios |= 1; + if (dev->pci_conf[w_reg] & (1 << bit)) + shadowbios_write |= 1; + } + + ali1541_log("%08X-%08X shadow: R%c, W%c\n", base, base + 0x00003fff, + (dev->pci_conf[r_reg] & (1 << bit)) ? 'I' : 'E', (dev->pci_conf[w_reg] & (1 << bit)) ? 'I' : 'E'); + mem_set_mem_state_both(base, 0x00004000, flags); + } + + flushmmucache_nopc(); +} + + +static void +ali1541_mask_bar(ali1541_t *dev) +{ + uint32_t bar, mask; + + switch (dev->pci_conf[0xbc] & 0x0f) { + case 0x00: + default: + mask = 0x00000000; + break; + case 0x01: + mask = 0xfff00000; + break; + case 0x02: + mask = 0xffe00000; + break; + case 0x03: + mask = 0xffc00000; + break; + case 0x04: + mask = 0xff800000; + break; + case 0x06: + mask = 0xff000000; + break; + case 0x07: + mask = 0xfe000000; + break; + case 0x08: + mask = 0xfc000000; + break; + case 0x09: + mask = 0xf8000000; + break; + case 0x0a: + mask = 0xf0000000; + break; + } + + bar = ((dev->pci_conf[0x13] << 24) | (dev->pci_conf[0x12] << 16)) & mask; + dev->pci_conf[0x12] = (bar >> 16) & 0xff; + dev->pci_conf[0x13] = (bar >> 24) & 0xff; +} + + +static void +ali1541_write(int func, int addr, uint8_t val, void *priv) +{ + ali1541_t *dev = (ali1541_t *)priv; + + switch (addr) { + case 0x04: + dev->pci_conf[addr] = val; + break; + case 0x05: + dev->pci_conf[addr] = val & 0x01; + break; + + case 0x07: + dev->pci_conf[addr] &= ~(val & 0xf8); + break; + + case 0x0d: + dev->pci_conf[addr] = val & 0xf8; + break; + + case 0x12: + dev->pci_conf[0x12] = (val & 0xc0); + ali1541_mask_bar(dev); + break; + case 0x13: + dev->pci_conf[0x13] = val; + ali1541_mask_bar(dev); + break; + + case 0x2c: /* Subsystem Vendor ID */ + case 0x2d: + case 0x2e: + case 0x2f: + if (dev->pci_conf[0x90] & 0x01) + dev->pci_conf[addr] = val; + break; + + case 0x34: + if (dev->pci_conf[0x90] & 0x02) + dev->pci_conf[addr] = val; + break; + + case 0x40: + dev->pci_conf[addr] = val & 0x7f; + break; + + case 0x41: + dev->pci_conf[addr] = val & 0x7f; + break; + + case 0x42: /* L2 Cache */ + dev->pci_conf[addr] = val; + cpu_cache_ext_enabled = !!(val & 1); + cpu_update_waitstates(); + break; + + case 0x43: /* PLCTL-Pipe Line Control */ + dev->pci_conf[addr] = val & 0xf7; + break; + + case 0x44: + dev->pci_conf[addr] = val; + break; + case 0x45: + dev->pci_conf[addr] = val; + break; + case 0x46: + dev->pci_conf[addr] = val & 0xf0; + break; + case 0x47: + dev->pci_conf[addr] = val; + break; + + case 0x48: + dev->pci_conf[addr] = val; + break; + case 0x49: + dev->pci_conf[addr] = val; + break; + + case 0x4a: + dev->pci_conf[addr] = val & 0xf8; + break; + + case 0x4b: + dev->pci_conf[addr] = val; + break; + + case 0x4c: + dev->pci_conf[addr] = val; + break; + case 0x4d: + dev->pci_conf[addr] = val; + break; + + case 0x4e: + dev->pci_conf[addr] = val; + break; + case 0x4f: + dev->pci_conf[addr] = val; + break; + + case 0x50: + dev->pci_conf[addr] = val & 0x71; + break; + + case 0x51: + dev->pci_conf[addr] = val; + break; + + case 0x52: + dev->pci_conf[addr] = val; + break; + + case 0x53: + dev->pci_conf[addr] = val; + break; + + case 0x54: + dev->pci_conf[addr] = val & 0x3c; + + if (mem_size > 0xe00000) + mem_set_mem_state_both(0xe00000, 0x100000, (val & 0x20) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); + + if (mem_size > 0xf00000) + mem_set_mem_state_both(0xf00000, 0x100000, (val & 0x10) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); + + mem_set_mem_state_both(0xa0000, 0x20000, (val & 8) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + mem_set_mem_state_both(0x80000, 0x20000, (val & 4) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); + + flushmmucache_nopc(); + break; + + case 0x55: /* SMRAM */ + dev->pci_conf[addr] = val & 0x1f; + ali1541_smram_recalc(val, dev); + break; + + case 0x56 ... 0x59: /* Shadow RAM */ + dev->pci_conf[addr] = val; + ali1541_shadow_recalc(val, dev); + break; + + case 0x5a: case 0x5b: + dev->pci_conf[addr] = val; + break; + + case 0x5c: + dev->pci_conf[addr] = val; + break; + + case 0x5d: + dev->pci_conf[addr] = val & 0x17; + break; + + case 0x5e: + dev->pci_conf[addr] = val; + break; + + case 0x5f: + dev->pci_conf[addr] = val & 0xc1; + break; + + case 0x60 ... 0x6f: /* DRB's */ + dev->pci_conf[addr] = val; + spd_write_drbs_interleaved(dev->pci_conf, 0x60, 0x6f, 1); + break; + + case 0x70: + dev->pci_conf[addr] = val; + break; + + case 0x71: + dev->pci_conf[addr] = val; + break; + + case 0x72: + dev->pci_conf[addr] = val & 0xc7; + break; + + case 0x73: + dev->pci_conf[addr] = val & 0x1f; + break; + + case 0x84: case 0x85: + dev->pci_conf[addr] = val; + break; + + case 0x86: + dev->pci_conf[addr] = val & 0x0f; + break; + + case 0x87: /* H2PO */ + dev->pci_conf[addr] = val; + /* Find where the Shut-down Special cycle is initiated. */ + // if (!(val & 0x20)) + // outb(0x92, 0x01); + break; + + case 0x88: + dev->pci_conf[addr] = val; + break; + + case 0x89: + dev->pci_conf[addr] = val; + break; + + case 0x8a: + dev->pci_conf[addr] = val; + break; + + case 0x8b: + dev->pci_conf[addr] = val & 0x3f; + break; + + case 0x8c: + dev->pci_conf[addr] = val; + break; + + case 0x8d: + dev->pci_conf[addr] = val; + break; + + case 0x8e: + dev->pci_conf[addr] = val; + break; + + case 0x8f: + dev->pci_conf[addr] = val; + break; + + case 0x90: + dev->pci_conf[addr] = val; + pci_bridge_set_ctl(dev->agp_bridge, val); + break; + + case 0x91: + dev->pci_conf[addr] = val; + break; + + case 0xb4: + if (dev->pci_conf[0x90] & 0x01) + dev->pci_conf[addr] = val & 0x03; + break; + case 0xb5: + if (dev->pci_conf[0x90] & 0x01) + dev->pci_conf[addr] = val & 0x02; + break; + case 0xb7: + if (dev->pci_conf[0x90] & 0x01) + dev->pci_conf[addr] = val; + break; + + case 0xb8: + dev->pci_conf[addr] = val & 0x03; + break; + case 0xb9: + dev->pci_conf[addr] = val & 0x03; + break; + case 0xbb: + dev->pci_conf[addr] = val; + break; + + case 0xbc: + dev->pci_conf[addr] = val & 0x0f; + ali1541_mask_bar(dev); + break; + case 0xbd: + dev->pci_conf[addr] = val & 0xf0; + break; + case 0xbe: case 0xbf: + dev->pci_conf[addr] = val; + break; + + case 0xc0: + dev->pci_conf[addr] = val & 0x90; + break; + case 0xc1: case 0xc2: + case 0xc3: + dev->pci_conf[addr] = val; + break; + + case 0xc8: case 0xc9: + dev->pci_conf[addr] = val; + break; + + case 0xd1: + dev->pci_conf[addr] = val & 0xf1; + break; + case 0xd2: case 0xd3: + dev->pci_conf[addr] = val; + break; + + case 0xe0: case 0xe1: + if (dev->pci_conf[0x90] & 0x20) + dev->pci_conf[addr] = val; + break; + case 0xe2: + if (dev->pci_conf[0x90] & 0x20) + dev->pci_conf[addr] = val & 0x3f; + break; + case 0xe3: + if (dev->pci_conf[0x90] & 0x20) + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0xe4: + if (dev->pci_conf[0x90] & 0x20) + dev->pci_conf[addr] = val & 0x03; + break; + case 0xe5: + if (dev->pci_conf[0x90] & 0x20) + dev->pci_conf[addr] = val; + break; + + case 0xe6: + if (dev->pci_conf[0x90] & 0x20) + dev->pci_conf[addr] = val & 0xc0; + break; + + case 0xe7: + if (dev->pci_conf[0x90] & 0x20) + dev->pci_conf[addr] = val; + break; + + case 0xe8: case 0xe9: + if (dev->pci_conf[0x90] & 0x04) + dev->pci_conf[addr] = val; + break; + + case 0xea: + dev->pci_conf[addr] = val & 0xcf; + break; + + case 0xeb: + dev->pci_conf[addr] = val & 0xcf; + break; + + case 0xec: + dev->pci_conf[addr] = val & 0x3f; + break; + + case 0xed: + dev->pci_conf[addr] = val; + break; + + case 0xee: + dev->pci_conf[addr] = val & 0x3e; + break; + case 0xef: + dev->pci_conf[addr] = val; + break; + + case 0xf3: + dev->pci_conf[addr] = val & 0x08; + break; + + case 0xf5: + dev->pci_conf[addr] = val; + break; + + case 0xf6: + dev->pci_conf[addr] = val; + break; + + case 0xf7: + dev->pci_conf[addr] = val & 0x43; + break; + } +} + + +static uint8_t +ali1541_read(int func, int addr, void *priv) +{ + ali1541_t *dev = (ali1541_t *)priv; + uint8_t ret = 0xff; + + ret = dev->pci_conf[addr]; + + return ret; +} + + +static void +ali1541_reset(void *priv) +{ + ali1541_t *dev = (ali1541_t *)priv; + int i; + + /* Default Registers */ + dev->pci_conf[0x00] = 0xb9; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x41; + dev->pci_conf[0x03] = 0x15; + dev->pci_conf[0x04] = 0x06; + dev->pci_conf[0x05] = 0x00; + dev->pci_conf[0x06] = 0x10; + dev->pci_conf[0x07] = 0x04; + 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] = 0x20; + dev->pci_conf[0x0e] = 0x00; + dev->pci_conf[0x0f] = 0x00; + dev->pci_conf[0x2c] = 0xb9; + dev->pci_conf[0x2d] = 0x10; + dev->pci_conf[0x2e] = 0x41; + dev->pci_conf[0x2f] = 0x15; + dev->pci_conf[0x34] = 0xb0; + dev->pci_conf[0x89] = 0x20; + dev->pci_conf[0x8a] = 0x20; + dev->pci_conf[0x91] = 0x13; + dev->pci_conf[0xb0] = 0x02; + dev->pci_conf[0xb1] = 0xe0; + dev->pci_conf[0xb2] = 0x10; + dev->pci_conf[0xb4] = 0x03; + dev->pci_conf[0xb5] = 0x02; + dev->pci_conf[0xb7] = 0x1c; + dev->pci_conf[0xc8] = 0xbf; + dev->pci_conf[0xc9] = 0x0a; + dev->pci_conf[0xe0] = 0x01; + + cpu_cache_int_enabled = 1; + ali1541_write(0, 0x42, 0x00, dev); + + ali1541_write(0, 0x54, 0x00, dev); + ali1541_write(0, 0x55, 0x00, dev); + + for (i = 0; i < 4; i++) + ali1541_write(0, 0x56 + i, 0x00, dev); + + ali1541_write(0, 0x60 + i, 0x07, dev); + ali1541_write(0, 0x61 + i, 0x40, dev); + for (i = 0; i < 14; i += 2) { + ali1541_write(0, 0x62 + i, 0x00, dev); + ali1541_write(0, 0x63 + i, 0x00, dev); + } +} + + +static void +ali1541_close(void *priv) +{ + ali1541_t *dev = (ali1541_t *)priv; + + smram_del(dev->smram); + free(dev); +} + + +static void * +ali1541_init(const device_t *info) +{ + ali1541_t *dev = (ali1541_t *)malloc(sizeof(ali1541_t)); + memset(dev, 0, sizeof(ali1541_t)); + + pci_add_card(PCI_ADD_NORTHBRIDGE, ali1541_read, ali1541_write, dev); + + dev->smram = smram_add(); + + ali1541_reset(dev); + + dev->agp_bridge = device_add(&ali5243_agp_device); + + return dev; +} + + +const device_t ali1541_device = { + "ALi M1541 CPU-to-PCI Bridge", + DEVICE_PCI, + 0, + ali1541_init, + ali1541_close, + ali1541_reset, + {NULL}, + NULL, + NULL, + NULL +}; diff --git a/src/chipset/ali1543.c b/src/chipset/ali1543.c index 4f0d3cbff..e15c77b77 100644 --- a/src/chipset/ali1543.c +++ b/src/chipset/ali1543.c @@ -34,15 +34,13 @@ #include <86box/fdc.h> #include <86box/hdc_ide.h> #include <86box/hdc_ide_sff8038i.h> -#include <86box/keyboard.h> #include <86box/lpt.h> #include <86box/mem.h> #include <86box/nvr.h> #include <86box/pci.h> -#include <86box/pic.h> #include <86box/port_92.h> #include <86box/serial.h> -#include <86box/smbus_piix4.h> +#include <86box/smbus.h> #include <86box/usb.h> #include <86box/acpi.h> @@ -55,7 +53,7 @@ typedef struct ali1543_t uint8_t pci_conf[256], pmu_conf[256], usb_conf[256], ide_conf[256], sio_regs[256], device_regs[8][256], sio_index, in_configuration_mode, pci_slot, ide_slot, usb_slot, pmu_slot, usb_dev_enable, ide_dev_enable, - pmu_dev_enable; + pmu_dev_enable, type; apm_t * apm; acpi_t * acpi; @@ -65,7 +63,7 @@ typedef struct ali1543_t port_92_t * port_92; serial_t * uart[2]; sff8038i_t * ide_controller[2]; - smbus_piix4_t * smbus; + smbus_ali7101_t * smbus; usb_t * usb; } ali1543_t; @@ -120,8 +118,6 @@ static void ali1533_write(int func, int addr, uint8_t val, void *priv) { ali1543_t *dev = (ali1543_t *)priv; - int irq; - ali1543_log("M1533: dev->pci_conf[%02x] = %02x\n", addr, val); if (func > 0) @@ -129,8 +125,15 @@ ali1533_write(int func, int addr, uint8_t val, void *priv) switch (addr) { case 0x04: /* Command Register */ - if (!(dev->pci_conf[0x5f] & 0x08)) - dev->pci_conf[0x04] = val; + if (dev->type == 1) { + if (dev->pci_conf[0x5f] & 0x08) + dev->pci_conf[0x04] = val & 0x0f; + else + dev->pci_conf[0x04] = val; + } else { + if (!(dev->pci_conf[0x5f] & 0x08)) + dev->pci_conf[0x04] = val; + } break; case 0x05: /* Command Register */ if (!(dev->pci_conf[0x5f] & 0x08)) @@ -222,11 +225,13 @@ ali1533_write(int func, int addr, uint8_t val, void *priv) break; case 0x4d: /* MBIRQ0(SIRQI#), MBIRQ1(SIRQII#) Interrupt to ISA IRQ routing table */ - dev->pci_conf[addr] = val; + if (dev->type == 0) { + dev->pci_conf[addr] = val; - ali1543_log("SIRQI = IRQ %i; SIRQII = IRQ %i\n", ali1533_irq_routing[(val >> 4) & 0x0f], ali1533_irq_routing[val & 0x0f]); - // pci_set_mirq_routing(PCI_MIRQ0, ali1533_irq_routing[(val >> 4) & 0x0f]); - // pci_set_mirq_routing(PCI_MIRQ1, ali1533_irq_routing[val & 0x0f]); + ali1543_log("SIRQI = IRQ %i; SIRQII = IRQ %i\n", ali1533_irq_routing[(val >> 4) & 0x0f], ali1533_irq_routing[val & 0x0f]); + // pci_set_mirq_routing(PCI_MIRQ0, ali1533_irq_routing[(val >> 4) & 0x0f]); + // pci_set_mirq_routing(PCI_MIRQ1, ali1533_irq_routing[val & 0x0f]); + } break; /* I/O cycle posted-write first port definition */ @@ -242,7 +247,10 @@ ali1533_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf[addr] = val; break; case 0x53: - dev->pci_conf[addr] = val & 0xcf; + if (dev->type == 1) + dev->pci_conf[addr] = val; + else + dev->pci_conf[addr] = val & 0xcf; /* This actually enables/disables the USB *device* rather than the interface itself. */ dev->usb_dev_enable = !(val & 0x40); break; @@ -254,7 +262,10 @@ ali1533_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf[addr] = val; break; case 0x57: - dev->pci_conf[addr] = val & 0xc7; + if (dev->type == 1) + dev->pci_conf[addr] = val & 0xf0; + else + dev->pci_conf[addr] = val & 0xe0; break; /* IDE interface control @@ -277,7 +288,8 @@ ali1533_write(int func, int addr, uint8_t val, void *priv) dev->ide_slot = 0x0d; /* A24 = slot 13 */ break; } - ali1543_log("IDE slot = %02X (A%0i)\n", dev->ide_slot, dev->ide_slot + 11 - 5); + ali1543_log("IDE slot = %02X (A%0i)\n", dev->ide_slot - 5, dev->ide_slot + 11); + pclog("IDE slot = %02X (A%0i)\n", dev->ide_slot - 5, dev->ide_slot + 11); ali5229_ide_irq_handler(dev); break; @@ -303,7 +315,10 @@ ali1533_write(int func, int addr, uint8_t val, void *priv) break; case 0x5e: - dev->pci_conf[addr] = val & 0xe0; + if (dev->type == 1) + dev->pci_conf[addr] = val & 0xe1; + else + dev->pci_conf[addr] = val & 0xe0; break; case 0x5f: @@ -343,7 +358,8 @@ ali1533_write(int func, int addr, uint8_t val, void *priv) dev->pmu_slot = 0x04; /* A15 = slot 04 */ break; } - ali1543_log("PMU slot = %02X (A%0i)\n", dev->pmu_slot, dev->pmu_slot + 11 - 5); + ali1543_log("PMU slot = %02X (A%0i)\n", dev->pmu_slot - 5, dev->pmu_slot + 11); + pclog("PMU slot = %02X (A%0i)\n", dev->pmu_slot - 5, dev->pmu_slot + 11); switch (val & 0x03) { case 0x00: dev->usb_slot = 0x14; /* A31 = slot 20 */ @@ -358,7 +374,8 @@ ali1533_write(int func, int addr, uint8_t val, void *priv) dev->usb_slot = 0x01; /* A12 = slot 01 */ break; } - ali1543_log("USB slot = %02X (A%0i)\n", dev->usb_slot, dev->usb_slot + 11 - 5); + ali1543_log("USB slot = %02X (A%0i)\n", dev->usb_slot - 5, dev->usb_slot + 11); + pclog("USB slot = %02X (A%0i)\n", dev->usb_slot - 5, dev->usb_slot + 11); break; case 0x73: /* DDMA Base Address */ @@ -382,9 +399,15 @@ ali1533_write(int func, int addr, uint8_t val, void *priv) break; case 0x76: /* PMU IRQ Routing - we cheat and use MIRQ5 */ - dev->pci_conf[addr] = val & 0x1f; + if (dev->type == 1) + dev->pci_conf[addr] = val & 0x9f; + else + dev->pci_conf[addr] = val & 0x1f; acpi_set_mirq_is_level(dev->acpi, !!(val & 0x10)); - pci_set_mirq_routing(PCI_MIRQ5, ali1533_irq_routing[val & 0x0f]); + if ((dev->type == 1) && (val & 0x80)) + pci_set_mirq_routing(PCI_MIRQ5, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ5, ali1533_irq_routing[val & 0x0f]); /* TODO: Tell ACPI to use MIRQ5 */ break; @@ -392,10 +415,24 @@ ali1533_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf[addr] = val & 0x1f; pci_set_mirq_routing(PCI_MIRQ6, ali1533_irq_routing[val & 0x0f]); break; + + case 0x78: + if (dev->type == 1) { + pclog("PCI78 = %02X\n", val); + dev->pci_conf[addr] = val & 0x33; + } + break; + + case 0x7c ... 0xff: + if ((dev->type == 1) && !dev->pmu_dev_enable) { + dev->pmu_dev_enable = 1; + ali7101_write(func, addr, val, priv); + dev->pmu_dev_enable = 0; + } + break; } } - static uint8_t ali1533_read(int func, int addr, void *priv) { @@ -411,6 +448,11 @@ ali1533_read(int func, int addr, void *priv) ret |= (keyboard_at_get_mouse_scan() << 2); else if (addr == 0x58) ret = (ret & 0xbf) | (dev->ide_dev_enable ? 0x40 : 0x00); + else if ((dev->type == 1) && ((addr >= 0x7c) && (addr <= 0xff)) && !dev->pmu_dev_enable) { + dev->pmu_dev_enable = 1; + ret = ali7101_read(func, addr, priv); + dev->pmu_dev_enable = 0; + } } } @@ -506,6 +548,7 @@ ali5229_ide_irq_handler(ali1543_t *dev) static void ali5229_ide_handler(ali1543_t *dev) +ali5229_ide_handler(ali1543_t *dev) { uint32_t ch = 0; @@ -617,7 +660,14 @@ ali5229_chip_reset(ali1543_t *dev) dev->ide_conf[0x67] = 0x01; dev->ide_conf[0x78] = 0x21; - ali5229_write(0, 0x04, 0x01, dev); + if (dev->type == 1) { + dev->ide_conf[0x08] = 0xc1; + dev->ide_conf[0x4b] = 0x4a; + dev->ide_conf[0x4e] = 0xba; + dev->ide_conf[0x4f] = 0x1a; + } + + ali5229_write(0, 0x04, 0x00 /*0x01*/, dev); ali5229_write(0, 0x10, 0xf1, dev); ali5229_write(0, 0x11, 0x01, dev); ali5229_write(0, 0x14, 0xf5, dev); @@ -672,10 +722,12 @@ ali5229_write(int func, int addr, uint8_t val, void *priv) case 0x09: /* Control */ ali1543_log("IDE09: %02X\n", val); -#ifdef M1543_C - val &= ~(dev->ide_conf[0x43]); - val |= (dev->ide_conf[addr] & dev->ide_conf[0x43]); -#endif + + if (dev->type == 1) { + val &= ~(dev->ide_conf[0x43]); + val |= (dev->ide_conf[addr] & dev->ide_conf[0x43]); + } + if (dev->ide_conf[0x4d] & 0x80) dev->ide_conf[addr] = (dev->ide_conf[addr] & 0xfa) | (val & 0x05); else @@ -710,18 +762,23 @@ ali5229_write(int func, int addr, uint8_t val, void *priv) break; /* The machines don't touch anything beyond that point so we avoid any programming */ -#ifdef M1543_C case 0x43: - dev->ide_conf[addr] = val & 0x7f; + if (dev->type == 1) + dev->ide_conf[addr] = val & 0x7f; + break; + + case 0x4b: + if (dev->type == 1) + dev->ide_conf[addr] = val; break; -#endif case 0x4d: dev->ide_conf[addr] = val & 0x80; break; case 0x4f: - dev->ide_conf[addr] = val & 0x3f; + if (dev->type == 0) + dev->ide_conf[addr] = val & 0x3f; break; case 0x50: /* Configuration */ @@ -830,8 +887,13 @@ ali5237_write(int func, int addr, uint8_t val, void *priv) case 0x0c: /* Cache Line Size */ case 0x0d: /* Latency Timer */ case 0x3c: /* Interrupt Line Register */ - case 0x40 ... 0x43: /* Test Mode Register */ - dev->usb_conf[addr] = val; + + case 0x42: /* Test Mode Register */ + dev->usb_conf[addr] = val & 0x10; + break; + case 0x43: + if (dev->type == 1) + dev->usb_conf[addr] = val & 0x04; break; /* USB Base I/O */ @@ -888,7 +950,10 @@ ali7101_write(int func, int addr, uint8_t val, void *priv) ali1543_log("PMU04: %02X\n", val); dev->pmu_conf[addr] = val & 0x01; acpi_update_io_mapping(dev->acpi, (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0), dev->pmu_conf[0x04] & 1); - smbus_piix4_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1)); + if (dev->type == 1) + smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xc0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1)); + else + smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1)); break; /* PMU Base I/O */ @@ -899,6 +964,7 @@ ali7101_write(int func, int addr, uint8_t val, void *priv) else if (addr == 0x11) dev->pmu_conf[addr] = val; + pclog("New ACPI base address: %08X\n", (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0)); acpi_update_io_mapping(dev->acpi, (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0), dev->pmu_conf[0x04] & 1); } break; @@ -906,12 +972,21 @@ ali7101_write(int func, int addr, uint8_t val, void *priv) /* SMBus Base I/O */ case 0x14: case 0x15: if (!(dev->pmu_conf[0x5b] & 0x04)) { - if (addr == 0x14) - dev->pmu_conf[addr] = (val & 0xe0) | 1; - else if (addr == 0x15) + if (addr == 0x14) { + if (dev->type == 1) + dev->pmu_conf[addr] = (val & 0xc0) | 1; + else + dev->pmu_conf[addr] = (val & 0xe0) | 1; + } else if (addr == 0x15) dev->pmu_conf[addr] = val; - smbus_piix4_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1)); + if (dev->type == 1) { + pclog("New SMBUS base address: %08X\n", (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xc0)); + smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xc0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1)); + } else { + pclog("New SMBUS base address: %08X\n", (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0)); + smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1)); + } } break; @@ -977,6 +1052,16 @@ ali7101_write(int func, int addr, uint8_t val, void *priv) dev->pmu_conf[addr] &= ~(val & 1); break; + case 0x50: case 0x51: + if (dev->type == 1) + dev->pmu_conf[addr] = val; + break; + + case 0x52: case 0x53: + if (dev->type == 1) + dev->pmu_conf[addr] &= ~val; + break; + case 0x54: /* Standby timer */ dev->pmu_conf[addr] = val; break; @@ -988,7 +1073,10 @@ ali7101_write(int func, int addr, uint8_t val, void *priv) break; case 0x5b: /* ACPI/SMB Base I/O Control */ - dev->pmu_conf[addr] = val & 0x7f; + if (dev->type == 1) + dev->pmu_conf[addr] = val & 0x87; + else + dev->pmu_conf[addr] = val & 0x7f; break; case 0x60: @@ -1022,7 +1110,10 @@ ali7101_write(int func, int addr, uint8_t val, void *priv) dev->pmu_conf[addr] = val & 0xbf; break; case 0x6f: - dev->pmu_conf[addr] = val & 0x1f; + if (dev->type == 1) + dev->pmu_conf[addr] = val & 0x1e; + else + dev->pmu_conf[addr] = val & 0x1f; break; case 0x70: @@ -1065,11 +1156,17 @@ ali7101_write(int func, int addr, uint8_t val, void *priv) break; case 0x7a: - dev->pmu_conf[addr] = val & 0x02; + if (dev->type == 1) + dev->pmu_conf[addr] = val & 0x07; + else + dev->pmu_conf[addr] = val & 0x02; break; case 0x7b: - dev->pmu_conf[addr] = val & 0x7f; + if (dev->type == 1) + dev->pmu_conf[addr] = val; + else + dev->pmu_conf[addr] = val & 0x7f; break; case 0x7c ... 0x7f: @@ -1080,12 +1177,34 @@ ali7101_write(int func, int addr, uint8_t val, void *priv) dev->pmu_conf[addr] = val & 0xf0; break; + case 0x82: + if (dev->type == 1) + dev->pmu_conf[addr] = val & 0x01; + break; + + case 0x84 ... 0x87: + if (dev->type == 1) + dev->pmu_conf[addr] = val; + break; + case 0x88 ... 0x8b: + if (dev->type == 1) + dev->pmu_conf[addr] = val; + break; + case 0x8c: case 0x8d: dev->pmu_conf[addr] = val & 0x0f; break; case 0x90: - dev->pmu_conf[addr] = val & 0x01; + if (dev->type == 1) + dev->pmu_conf[addr] = val & 0x0f; + else + dev->pmu_conf[addr] = val & 0x01; + break; + + case 0x91: + if (dev->type == 1) + dev->pmu_conf[addr] = val & 0x02; break; case 0x94: @@ -1095,6 +1214,11 @@ ali7101_write(int func, int addr, uint8_t val, void *priv) dev->pmu_conf[addr] = val; break; + case 0x98: case 0x99: + if (dev->type == 1) + dev->pmu_conf[addr] = val; + break; + case 0xa4: case 0xa5: dev->pmu_conf[addr] = val; break; @@ -1115,6 +1239,11 @@ ali7101_write(int func, int addr, uint8_t val, void *priv) dev->pmu_conf[addr] = val & 0x0f; break; + case 0xb8: case 0xb9: + if (dev->type == 1) + dev->pmu_conf[addr] = val; + break; + case 0xbc: outb(0x70, val); break; @@ -1160,6 +1289,15 @@ ali7101_write(int func, int addr, uint8_t val, void *priv) dev->pmu_conf[addr] = val; break; + case 0xcc: + if (dev->type == 1) + dev->pmu_conf[addr] = val & 0x1f; + break; + case 0xcd: + if (dev->type == 1) + dev->pmu_conf[addr] = val & 0x33; + break; + case 0xd4: dev->pmu_conf[addr] = val & 0x01; break; @@ -1167,10 +1305,17 @@ ali7101_write(int func, int addr, uint8_t val, void *priv) case 0xd8: dev->pmu_conf[addr] = val & 0xfd; break; + case 0xd9: + if (dev->type == 1) + dev->pmu_conf[addr] = val & 0x3f; + break; case 0xe0: dev->pmu_conf[addr] = val & 0x03; - smbus_piix4_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); + if (dev->type == 1) + smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xc0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); + else + smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1) && (!(dev->pci_conf[0x5f] & 4))); break; case 0xe1: @@ -1382,7 +1527,7 @@ ali1543_reset(void *priv) ali5229_chip_reset(dev); /* M5237 */ - memset(dev->usb_conf, 0x00, sizeof(dev->pmu_conf)); + memset(dev->usb_conf, 0x00, sizeof(dev->usb_conf)); dev->usb_conf[0x00] = 0xb9; dev->usb_conf[0x01] = 0x10; dev->usb_conf[0x02] = 0x37; @@ -1444,6 +1589,8 @@ ali1543_reset(void *priv) dev->pci_conf[0x03] = 0x15; dev->pci_conf[0x04] = 0x0f; dev->pci_conf[0x07] = 0x02; + if (dev->type == 1) + dev->pci_conf[0x08] = 0xc0; dev->pci_conf[0x0a] = 0x01; dev->pci_conf[0x0b] = 0x06; @@ -1534,9 +1681,6 @@ ali1543_init(const device_t *info) dev->acpi = device_add(&acpi_ali_device); dev->nvr = device_add(&piix4_nvr_device); - /* APM */ - // dev->apm = device_add(&apm_pci_device); - /* DMA */ dma_alias_set(); @@ -1563,7 +1707,7 @@ ali1543_init(const device_t *info) dev->uart[1] = device_add_inst(&ns16550_device, 2); /* Standard SMBus */ - dev->smbus = device_add(&piix4_smbus_device); + dev->smbus = device_add(&ali7101_smbus_device); /* Super I/O Configuration Mechanism */ dev->in_configuration_mode = 0; @@ -1571,6 +1715,8 @@ ali1543_init(const device_t *info) /* USB */ dev->usb = device_add(&usb_device); + dev->type = info->local; + pci_enable_mirq(0); pci_enable_mirq(1); pci_enable_mirq(2); @@ -1597,3 +1743,16 @@ const device_t ali1543_device = { NULL, NULL }; + +const device_t ali1543c_device = { + "ALi M1543C Desktop South Bridge", + DEVICE_PCI, + 1, + ali1543_init, + ali1543_close, + ali1543_reset, + { NULL }, + NULL, + NULL, + NULL +}; diff --git a/src/chipset/ali1621.c b/src/chipset/ali1621.c new file mode 100644 index 000000000..97fbeb522 --- /dev/null +++ b/src/chipset/ali1621.c @@ -0,0 +1,757 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the ALi M1621/2 CPU-to-PCI Bridge. + * + * Authors: Miran Grca, + * + * Copyright 2021 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/timer.h> + +#include <86box/device.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/pci.h> +#include <86box/smram.h> +#include <86box/spd.h> + +#include <86box/chipset.h> + + +typedef struct ali1621_t +{ + uint8_t pci_conf[256]; + + smram_t * smram; + void * agp_bridge; +} ali1621_t; + + +#ifdef ENABLE_ALI1621_LOG +int ali1621_do_log = ENABLE_ALI1621_LOG; +static void +ali1621_log(const char *fmt, ...) +{ + va_list ap; + + if (ali1621_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define ali1621_log(fmt, ...) +#endif + + +static void +ali1621_smram_recalc(uint8_t val, ali1621_t *dev) +{ + smram_disable_all(); + + if (val & 1) { + switch (val & 0x0c) { + case 0x00: + ali1621_log("SMRAM: D0000 -> B0000 (%i)\n", val & 2); + smram_enable(dev->smram, 0xd0000, 0xb0000, 0x10000, val & 2, 1); + if (val & 0x10) + mem_set_mem_state_smram_ex(1, 0xd0000, 0x10000, 0x02); + break; + case 0x04: + ali1621_log("SMRAM: A0000 -> A0000 (%i)\n", val & 2); + smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, val & 2, 1); + if (val & 0x10) + mem_set_mem_state_smram_ex(1, 0xa0000, 0x20000, 0x02); + break; + case 0x08: + ali1621_log("SMRAM: 30000 -> B0000 (%i)\n", val & 2); + smram_enable(dev->smram, 0x30000, 0xb0000, 0x10000, val & 2, 1); + if (val & 0x10) + mem_set_mem_state_smram_ex(1, 0x30000, 0x10000, 0x02); + break; + } + } + + flushmmucache_nopc(); +} + + +static void +ali1621_shadow_recalc(int cur_reg, ali1621_t *dev) +{ + int i, bit, r_reg, w_reg; + uint32_t base, flags = 0; + + shadowbios = shadowbios_write = 0; + + for (i = 0; i < 16; i++) { + base = 0x000c0000 + (i << 14); + bit = i & 7; + r_reg = 0x56 + (i >> 3); + w_reg = 0x58 + (i >> 3); + + flags = (dev->pci_conf[r_reg] & (1 << bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + flags |= ((dev->pci_conf[w_reg] & (1 << bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY); + + if (base >= 0x000e0000) { + if (dev->pci_conf[r_reg] & (1 << bit)) + shadowbios |= 1; + if (dev->pci_conf[w_reg] & (1 << bit)) + shadowbios_write |= 1; + } + + ali1621_log("%08X-%08X shadow: R%c, W%c\n", base, base + 0x00003fff, + (dev->pci_conf[r_reg] & (1 << bit)) ? 'I' : 'E', (dev->pci_conf[w_reg] & (1 << bit)) ? 'I' : 'E'); + mem_set_mem_state_both(base, 0x00004000, flags); + } + + flushmmucache_nopc(); +} + + +static void +ali1621_mask_bar(ali1621_t *dev) +{ + uint32_t bar, mask; + + switch (dev->pci_conf[0xbc] & 0x0f) { + case 0x00: + default: + mask = 0x00000000; + break; + case 0x01: + mask = 0xfff00000; + break; + case 0x02: + mask = 0xffe00000; + break; + case 0x03: + mask = 0xffc00000; + break; + case 0x04: + mask = 0xff800000; + break; + case 0x06: + mask = 0xff000000; + break; + case 0x07: + mask = 0xfe000000; + break; + case 0x08: + mask = 0xfc000000; + break; + case 0x09: + mask = 0xf8000000; + break; + case 0x0a: + mask = 0xf0000000; + break; + } + + bar = ((dev->pci_conf[0x13] << 24) | (dev->pci_conf[0x12] << 16)) & mask; + dev->pci_conf[0x12] = (bar >> 16) & 0xff; + dev->pci_conf[0x13] = (bar >> 24) & 0xff; +} + + +static void +ali1621_write(int func, int addr, uint8_t val, void *priv) +{ + ali1621_t *dev = (ali1621_t *)priv; + + switch (addr) { + case 0x04: + dev->pci_conf[addr] = val & 0x01; + break; + case 0x05: + dev->pci_conf[addr] = val & 0x01; + break; + + case 0x07: + dev->pci_conf[addr] &= ~(val & 0xf0); + break; + + case 0x0d: + dev->pci_conf[addr] = val & 0xf8; + break; + + case 0x12: + dev->pci_conf[0x12] = (val & 0xc0); + ali1621_mask_bar(dev); + break; + case 0x13: + dev->pci_conf[0x13] = val; + ali1621_mask_bar(dev); + break; + + case 0x34: + dev->pci_conf[addr] = val; + break; + + case 0x40: + dev->pci_conf[addr] = val; + break; + case 0x41: + dev->pci_conf[addr] = val; + break; + + case 0x42: + dev->pci_conf[addr] = val; + break; + case 0x43: + dev->pci_conf[addr] = val; + break; + + case 0x44: + dev->pci_conf[addr] = val; + break; + case 0x45: + dev->pci_conf[addr] = val; + break; + + case 0x46: + dev->pci_conf[addr] = val; + break; + case 0x47: + dev->pci_conf[addr] = val; + break; + + case 0x48: + dev->pci_conf[addr] = val; + break; + case 0x49: + dev->pci_conf[addr] = val; + break; + + case 0x4a: + dev->pci_conf[addr] = val; + break; + + case 0x4b: + dev->pci_conf[addr] = val & 0x0f; + break; + + case 0x4c: + dev->pci_conf[addr] = val; + break; + + case 0x4d: + dev->pci_conf[addr] = val; + break; + + case 0x4e: + dev->pci_conf[addr] = val; + break; + case 0x4f: + dev->pci_conf[addr] = val; + break; + + case 0x50: + dev->pci_conf[addr] = val & 0xef; + break; + + case 0x51: + dev->pci_conf[addr] = val; + break; + + case 0x52: + dev->pci_conf[addr] = val & 0x9f; + break; + + case 0x53: + dev->pci_conf[addr] = val; + break; + + case 0x54: + dev->pci_conf[addr] = val & 0xb4; + break; + case 0x55: + dev->pci_conf[addr] = val & 0x01; + break; + + case 0x56: + dev->pci_conf[addr] = val & 0x3f; + break; + + case 0x57: + dev->pci_conf[addr] = val & 0x08; + break; + + case 0x58: + dev->pci_conf[addr] = val; + break; + + case 0x59: + dev->pci_conf[addr] = val; + break; + + case 0x5a: + dev->pci_conf[addr] = val; + break; + + case 0x5c: + dev->pci_conf[addr] = val & 0x01; + break; + + case 0x60: + dev->pci_conf[addr] = val; + break; + + case 0x61: + dev->pci_conf[addr] = val; + break; + + case 0x62: + dev->pci_conf[addr] = val; + break; + + case 0x63: + dev->pci_conf[addr] = val; + break; + + case 0x64: + dev->pci_conf[addr] = val & 0xb7; + break; + case 0x65: + dev->pci_conf[addr] = val & 0x01; + break; + + case 0x66: + dev->pci_conf[addr] &= ~(val & 0x33); + break; + + case 0x67: + dev->pci_conf[addr] = val; + break; + + case 0x68: + dev->pci_conf[addr] = val; + break; + + case 0x69: + dev->pci_conf[addr] = val; + break; + + case 0x6c ... case 0x7b: + /* Bits 22:20 = DRAM Row size: + - 000: 4 MB; + - 001: 8 MB; + - 010: 16 MB; + - 011: 32 MB; + - 100: 64 MB; + - 101: 128 MB; + - 110: 256 MB; + - 111: Reserved. */ + dev->pci_conf[addr] = val; + break; + + case 0x7c ... 0x7f: + dev->pci_conf[addr] = val; + break; + + case 0x80: + dev->pci_conf[addr] = val; + break; + case 0x81: + dev->pci_conf[addr] = val & 0xdf; + break; + + case 0x82: + dev->pci_conf[addr] = val & 0xf7; + break; + + case 0x54: + dev->pci_conf[addr] = val & 0x3c; + + if (mem_size > 0xe00000) + mem_set_mem_state_both(0xe00000, 0x100000, (val & 0x20) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); + + if (mem_size > 0xf00000) + mem_set_mem_state_both(0xf00000, 0x100000, (val & 0x10) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); + + mem_set_mem_state_both(0xa0000, 0x20000, (val & 8) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); + mem_set_mem_state_both(0x80000, 0x20000, (val & 4) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); + + flushmmucache_nopc(); + break; + + case 0x55: /* SMRAM */ + dev->pci_conf[addr] = val & 0x1f; + ali1621_smram_recalc(val, dev); + break; + + case 0x56 ... 0x59: /* Shadow RAM */ + dev->pci_conf[addr] = val; + ali1621_shadow_recalc(val, dev); + break; + + case 0x5a: case 0x5b: + dev->pci_conf[addr] = val; + break; + + case 0x5c: + dev->pci_conf[addr] = val; + break; + + case 0x5d: + dev->pci_conf[addr] = val & 0x17; + break; + + case 0x5e: + dev->pci_conf[addr] = val; + break; + + case 0x5f: + dev->pci_conf[addr] = val & 0xc1; + break; + + case 0x60 ... 0x6f: /* DRB's */ + dev->pci_conf[addr] = val; + spd_write_drbs_interleaved(dev->pci_conf, 0x60, 0x6f, 1); + break; + + case 0x70: + dev->pci_conf[addr] = val; + break; + + case 0x71: + dev->pci_conf[addr] = val; + break; + + case 0x72: + dev->pci_conf[addr] = val & 0xc7; + break; + + case 0x73: + dev->pci_conf[addr] = val & 0x1f; + break; + + case 0x84: case 0x85: + dev->pci_conf[addr] = val; + break; + + case 0x86: + dev->pci_conf[addr] = val & 0x0f; + break; + + case 0x87: /* H2PO */ + dev->pci_conf[addr] = val; + /* Find where the Shut-down Special cycle is initiated. */ + // if (!(val & 0x20)) + // outb(0x92, 0x01); + break; + + case 0x88: + dev->pci_conf[addr] = val; + break; + + case 0x89: + dev->pci_conf[addr] = val; + break; + + case 0x8a: + dev->pci_conf[addr] = val; + break; + + case 0x8b: + dev->pci_conf[addr] = val & 0x3f; + break; + + case 0x8c: + dev->pci_conf[addr] = val; + break; + + case 0x8d: + dev->pci_conf[addr] = val; + break; + + case 0x8e: + dev->pci_conf[addr] = val; + break; + + case 0x8f: + dev->pci_conf[addr] = val; + break; + + case 0x90: + dev->pci_conf[addr] = val; + pci_bridge_set_ctl(dev->agp_bridge, val); + break; + + case 0x91: + dev->pci_conf[addr] = val; + break; + + case 0xb4: + if (dev->pci_conf[0x90] & 0x01) + dev->pci_conf[addr] = val & 0x03; + break; + case 0xb5: + if (dev->pci_conf[0x90] & 0x01) + dev->pci_conf[addr] = val & 0x02; + break; + case 0xb7: + if (dev->pci_conf[0x90] & 0x01) + dev->pci_conf[addr] = val; + break; + + case 0xb8: + dev->pci_conf[addr] = val & 0x03; + break; + case 0xb9: + dev->pci_conf[addr] = val & 0x03; + break; + case 0xbb: + dev->pci_conf[addr] = val; + break; + + case 0xbc: + dev->pci_conf[addr] = val & 0x0f; + ali1621_mask_bar(dev); + break; + case 0xbd: + dev->pci_conf[addr] = val & 0xf0; + break; + case 0xbe: case 0xbf: + dev->pci_conf[addr] = val; + break; + + case 0xc0: + dev->pci_conf[addr] = val & 0x90; + break; + case 0xc1: case 0xc2: + case 0xc3: + dev->pci_conf[addr] = val; + break; + + case 0xc8: case 0xc9: + dev->pci_conf[addr] = val; + break; + + case 0xd1: + dev->pci_conf[addr] = val & 0xf1; + break; + case 0xd2: case 0xd3: + dev->pci_conf[addr] = val; + break; + + case 0xe0: case 0xe1: + if (dev->pci_conf[0x90] & 0x20) + dev->pci_conf[addr] = val; + break; + case 0xe2: + if (dev->pci_conf[0x90] & 0x20) + dev->pci_conf[addr] = val & 0x3f; + break; + case 0xe3: + if (dev->pci_conf[0x90] & 0x20) + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0xe4: + if (dev->pci_conf[0x90] & 0x20) + dev->pci_conf[addr] = val & 0x03; + break; + case 0xe5: + if (dev->pci_conf[0x90] & 0x20) + dev->pci_conf[addr] = val; + break; + + case 0xe6: + if (dev->pci_conf[0x90] & 0x20) + dev->pci_conf[addr] = val & 0xc0; + break; + + case 0xe7: + if (dev->pci_conf[0x90] & 0x20) + dev->pci_conf[addr] = val; + break; + + case 0xe8: case 0xe9: + if (dev->pci_conf[0x90] & 0x04) + dev->pci_conf[addr] = val; + break; + + case 0xea: + dev->pci_conf[addr] = val & 0xcf; + break; + + case 0xeb: + dev->pci_conf[addr] = val & 0xcf; + break; + + case 0xec: + dev->pci_conf[addr] = val & 0x3f; + break; + + case 0xed: + dev->pci_conf[addr] = val; + break; + + case 0xee: + dev->pci_conf[addr] = val & 0x3e; + break; + case 0xef: + dev->pci_conf[addr] = val; + break; + + case 0xf3: + dev->pci_conf[addr] = val & 0x08; + break; + + case 0xf5: + dev->pci_conf[addr] = val; + break; + + case 0xf6: + dev->pci_conf[addr] = val; + break; + + case 0xf7: + dev->pci_conf[addr] = val & 0x43; + break; + } +} + + +static uint8_t +ali1621_read(int func, int addr, void *priv) +{ + ali1621_t *dev = (ali1621_t *)priv; + uint8_t ret = 0xff; + + ret = dev->pci_conf[addr]; + + return ret; +} + + +static void +ali1621_reset(void *priv) +{ + ali1621_t *dev = (ali1621_t *)priv; + int i; + + /* Default Registers */ + dev->pci_conf[0x00] = 0xb9; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x21; + dev->pci_conf[0x03] = 0x16; + dev->pci_conf[0x04] = 0x06; + dev->pci_conf[0x05] = 0x00; + dev->pci_conf[0x06] = 0x10; + dev->pci_conf[0x07] = 0x04; + dev->pci_conf[0x08] = 0x01; + dev->pci_conf[0x09] = 0x00; + dev->pci_conf[0x0a] = 0x00; + dev->pci_conf[0x0b] = 0x06; + dev->pci_conf[0x10] = 0x08; + dev->pci_conf[0x34] = 0xb0; + dev->pci_conf[0x40] = 0x0c; + dev->pci_conf[0x41] = 0x0c; + dev->pci_conf[0x4c] = 0x04; + dev->pci_conf[0x4d] = 0x04; + dev->pci_conf[0x4e] = 0x7f; + dev->pci_conf[0x4f] = 0x7f; + dev->pci_conf[0x50] = 0x0c; + dev->pci_conf[0x53] = 0x02; + dev->pci_conf[0x5a] = 0x02; + dev->pci_conf[0x63] = 0x02; + dev->pci_conf[0x6c] = dev->pci_conf[0x70] = dev->pci_conf[0x74] = dev->pci_conf[0x78] = 0xff; + dev->pci_conf[0x6d] = dev->pci_conf[0x71] = dev->pci_conf[0x75] = dev->pci_conf[0x79] = 0xff; + dev->pci_conf[0x6e] = dev->pci_conf[0x72] = dev->pci_conf[0x76] = dev->pci_conf[0x7a] = 0x00; + dev->pci_conf[0x6f] = dev->pci_conf[0x73] = dev->pci_conf[0x77] = dev->pci_conf[0x7b] = 0xe0; + dev->pci_conf[0x6f] |= 0x06; + dev->pci_conf[0x7c] = 0x11; + dev->pci_conf[0x7d] = 0xc4; + dev->pci_conf[0x7e] = 0xc7; + dev->pci_conf[0x80] = 0x01; + dev->pci_conf[0x81] = 0xc0; + + dev->pci_conf[0x89] = 0x20; + dev->pci_conf[0x8a] = 0x20; + dev->pci_conf[0x91] = 0x13; + dev->pci_conf[0xb0] = 0x02; + dev->pci_conf[0xb1] = 0xe0; + dev->pci_conf[0xb2] = 0x10; + dev->pci_conf[0xb4] = 0x03; + dev->pci_conf[0xb5] = 0x02; + dev->pci_conf[0xb7] = 0x1c; + dev->pci_conf[0xc8] = 0xbf; + dev->pci_conf[0xc9] = 0x0a; + dev->pci_conf[0xe0] = 0x01; + + cpu_cache_int_enabled = 1; + ali1621_write(0, 0x42, 0x00, dev); + + ali1621_write(0, 0x54, 0x00, dev); + ali1621_write(0, 0x55, 0x00, dev); + + for (i = 0; i < 4; i++) + ali1621_write(0, 0x56 + i, 0x00, dev); + + ali1621_write(0, 0x60 + i, 0x07, dev); + ali1621_write(0, 0x61 + i, 0x40, dev); + for (i = 0; i < 14; i += 2) { + ali1621_write(0, 0x62 + i, 0x00, dev); + ali1621_write(0, 0x63 + i, 0x00, dev); + } +} + + +static void +ali1621_close(void *priv) +{ + ali1621_t *dev = (ali1621_t *)priv; + + smram_del(dev->smram); + free(dev); +} + + +static void * +ali1621_init(const device_t *info) +{ + ali1621_t *dev = (ali1621_t *)malloc(sizeof(ali1621_t)); + memset(dev, 0, sizeof(ali1621_t)); + + pci_add_card(PCI_ADD_NORTHBRIDGE, ali1621_read, ali1621_write, dev); + + dev->smram = smram_add(); + + ali1621_reset(dev); + + dev->agp_bridge = device_add(&ali5243_agp_device); + + return dev; +} + + +const device_t ali1621_device = { + "ALi M1621 CPU-to-PCI Bridge", + DEVICE_PCI, + 0, + ali1621_init, + ali1621_close, + ali1621_reset, + {NULL}, + NULL, + NULL, + NULL +}; diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index 2c3e0fa89..d31f0f835 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -45,7 +45,7 @@ #include <86box/hdc_ide_sff8038i.h> #include <86box/usb.h> #include <86box/machine.h> -#include <86box/smbus_piix4.h> +#include <86box/smbus.h> #include <86box/chipset.h> diff --git a/src/chipset/via_pipc.c b/src/chipset/via_pipc.c index d488035ee..bae8e59fc 100644 --- a/src/chipset/via_pipc.c +++ b/src/chipset/via_pipc.c @@ -45,7 +45,7 @@ #include <86box/hdc_ide_sff8038i.h> #include <86box/usb.h> #include <86box/machine.h> -#include <86box/smbus_piix4.h> +#include <86box/smbus.h> #include <86box/chipset.h> #include <86box/sio.h> #include <86box/hwm.h> diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index f09051ac9..41f6228fa 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -16,8 +16,8 @@ add_library(dev OBJECT bugger.c hwm.c hwm_lm75.c hwm_lm78.c hwm_gl518sm.c hwm_vt82c686.c ibm_5161.c isamem.c isartc.c ../lpt.c pci_bridge.c postcard.c serial.c vpc2007.c clock_ics9xxx.c isapnp.c i2c.c i2c_gpio.c - smbus_piix4.c keyboard.c keyboard_xt.c keyboard_at.c mouse.c mouse_bus.c - mouse_serial.c mouse_ps2.c phoenix_486_jumper.c) + smbus_piix4.c smbus_ali7101.c keyboard.c keyboard_xt.c keyboard_at.c + mouse.c mouse_bus.c mouse_serial.c mouse_ps2.c phoenix_486_jumper.c) if(LASERXT) target_compile_definitions(dev PRIVATE USE_LASERXT) diff --git a/src/device/pci_bridge.c b/src/device/pci_bridge.c index ab2d010ac..6a175d302 100644 --- a/src/device/pci_bridge.c +++ b/src/device/pci_bridge.c @@ -33,6 +33,7 @@ #define PCI_BRIDGE_DEC_21150 0x10110022 +#define AGP_BRIDGE_ALI_M5243 0x10b95243 #define AGP_BRIDGE_INTEL_440LX 0x80867181 #define AGP_BRIDGE_INTEL_440BX 0x80867191 #define AGP_BRIDGE_INTEL_440GX 0x808671a1 @@ -41,15 +42,16 @@ #define AGP_BRIDGE_VIA_691 0x11068691 #define AGP_BRIDGE_VIA_8601 0x11068601 +#define AGP_BRIDGE_ALI(x) (((x) >> 16) == 0x10b9) #define AGP_BRIDGE_INTEL(x) (((x) >> 16) == 0x8086) #define AGP_BRIDGE_VIA(x) (((x) >> 16) == 0x1106) -#define AGP_BRIDGE(x) ((x) >= AGP_BRIDGE_VIA_597) +#define AGP_BRIDGE(x) ((x) >= AGP_BRIDGE_ALI_M5243) typedef struct { uint32_t local; - uint8_t type; + uint8_t type, ctl; uint8_t regs[256]; uint8_t bus_index; @@ -77,6 +79,15 @@ pci_bridge_log(const char *fmt, ...) #endif +void +pci_bridge_set_ctl(void *priv, uint8_t ctl) +{ + pci_bridge_t *dev = (pci_bridge_t *) priv; + + dev->ctl = ctl; +} + + static void pci_bridge_write(int func, int addr, uint8_t val, void *priv) { @@ -94,21 +105,24 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x1e: case 0x34: case 0x3d: case 0x67: case 0xdc: - case 0xdd: case 0xde: case 0xdf: case 0xe0: - case 0xe1: case 0xe2: case 0xe3: + case 0xdd: case 0xde: case 0xdf: return; case 0x04: if (AGP_BRIDGE_INTEL(dev->local)) { if (dev->local == AGP_BRIDGE_INTEL_440BX) val &= 0x1f; - } else + } else if (AGP_BRIDGE_ALI(dev->local)) + val |= 0x02; + else val &= 0x67; break; case 0x05: if (AGP_BRIDGE_INTEL(dev->local)) val &= 0x01; + else if (AGP_BRIDGE_ALI(dev->local)) + val &= 0x01; else val &= 0x03; break; @@ -116,6 +130,8 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) case 0x07: if (dev->local == AGP_BRIDGE_INTEL_440LX) dev->regs[addr] &= ~(val & 0x40); + else if (AGP_BRIDGE_ALI(dev->local)) + dev->regs[addr] &= ~(val & 0xf8); return; case 0x0c: case 0x18: @@ -129,6 +145,8 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) return; else if (AGP_BRIDGE_INTEL(dev->local)) val &= 0xf8; + else if (AGP_BRIDGE_ALI(dev->local)) + val &= 0xf8; break; case 0x19: @@ -144,7 +162,8 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) else if ((dev->local == AGP_BRIDGE_INTEL_440BX) || (dev->local == AGP_BRIDGE_INTEL_440GX)) dev->regs[addr] &= ~(val & 0xf0); - } + } else if (AGP_BRIDGE_ALI(dev->local)) + dev->regs[addr] &= ~(val & 0xf0); return; case 0x1c: case 0x1d: case 0x20: case 0x22: @@ -152,6 +171,11 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) val &= 0xf0; break; + case 0x3c: + if (!(dev->ctl & 0x80)) + return; + break; + case 0x3e: if (AGP_BRIDGE_VIA(dev->local)) val &= 0x0c; @@ -170,7 +194,9 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) if (dev->local == AGP_BRIDGE_INTEL_440LX) { dev->regs[addr] = ((dev->regs[addr] & 0x04) | (val & 0x02)) & ~(val & 0x04); return; - } else if (AGP_BRIDGE(dev->local)) + } else if (AGP_BRIDGE_ALI(dev->local)) + val &= 0x06; + else if (AGP_BRIDGE(dev->local)) return; else if (dev->local == PCI_BRIDGE_DEC_21150) val &= 0x0f; @@ -207,6 +233,94 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) if (dev->local == PCI_BRIDGE_DEC_21150) val &= 0x3f; break; + + case 0x86: + if (AGP_BRIDGE_ALI(dev->local)) + val &= 0x3f; + break; + + case 0x87: + if (AGP_BRIDGE_ALI(dev->local)) + val &= 0x60; + break; + + case 0x88: + if (AGP_BRIDGE_ALI(dev->local)) + val &= 0x8c; + break; + + case 0x8b: + if (AGP_BRIDGE_ALI(dev->local)) + val &= 0x0f; + break; + + case 0x8c: + if (AGP_BRIDGE_ALI(dev->local)) + val &= 0x83; + break; + + case 0x8d: + if (AGP_BRIDGE_ALI(dev->local)) + return; + break; + + case 0xe0: case 0xe1: + if (AGP_BRIDGE_ALI(dev->local)) { + if (!(dev->ctl & 0x20)) + return; + } else + return; + break; + + case 0xe2: + if (AGP_BRIDGE_ALI(dev->local)) { + if (dev->ctl & 0x20) + val &= 0x3f; + else + return; + } else + return; + break; + case 0xe3: + if (AGP_BRIDGE_ALI(dev->local)) { + if (dev->ctl & 0x20) + val &= 0xfe; + else + return; + } else + return; + break; + + case 0xe4: + if (AGP_BRIDGE_ALI(dev->local)) { + if (dev->ctl & 0x20) + val &= 0x03; + else + return; + } + break; + case 0xe5: + if (AGP_BRIDGE_ALI(dev->local)) { + if (!(dev->ctl & 0x20)) + return; + } + break; + + case 0xe6: + if (AGP_BRIDGE_ALI(dev->local)) { + if (dev->ctl & 0x20) + val &= 0xc0; + else + return; + } + break; + + case 0xe7: + if (AGP_BRIDGE_ALI(dev->local)) { + if (!(dev->ctl & 0x20)) + return; + } + break; } dev->regs[addr] = val; @@ -251,6 +365,21 @@ pci_bridge_reset(void *priv) dev->regs[0x07] = 0x02; break; + case AGP_BRIDGE_ALI_M5243: + dev->regs[0x04] = 0x06; + dev->regs[0x07] = 0x04; + dev->regs[0x0d] = 0x20; + dev->regs[0x19] = 0x01; + dev->regs[0x1b] = 0x20; + dev->regs[0x34] = 0xe0; + dev->regs[0x89] = 0x20; + dev->regs[0x8a] = 0xa0; + dev->regs[0x8e] = 0x20; + dev->regs[0x8f] = 0x20; + dev->regs[0xe0] = 0x01; + pci_remap_bus(dev->bus_index, 0x01); + break; + case AGP_BRIDGE_INTEL_440LX: dev->regs[0x06] = 0xa0; dev->regs[0x07] = 0x02; @@ -362,6 +491,20 @@ const device_t dec21150_device = }; /* AGP bridges */ +const device_t ali5243_agp_device = +{ + "ALi M5243 AGP Bridge", + DEVICE_PCI, + AGP_BRIDGE_ALI_M5243, + pci_bridge_init, + NULL, + pci_bridge_reset, + { NULL }, + NULL, + NULL, + NULL +}; + const device_t i440lx_agp_device = { "Intel 82443LX/EX AGP Bridge", diff --git a/src/device/smbus_ali7101.c b/src/device/smbus_ali7101.c new file mode 100644 index 000000000..1a3f49c03 --- /dev/null +++ b/src/device/smbus_ali7101.c @@ -0,0 +1,312 @@ +/* + * 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 ALi M7101-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/smbus.h> + + +#ifdef ENABLE_SMBUS_ALI7101_LOG +int smbus_ali7101_do_log = ENABLE_SMBUS_ALI7101_LOG; + + +static void +smbus_ali7101_log(const char *fmt, ...) +{ + va_list ap; + + if (smbus_ali7101_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define smbus_ali7101_log(fmt, ...) +#endif + + +static uint8_t +smbus_ali7101_read(uint16_t addr, void *priv) +{ + smbus_ali7101_t *dev = (smbus_ali7101_t *) priv; + uint8_t ret = 0x00; + + switch (addr - dev->io_base) { + case 0x00: + ret = dev->stat; + break; + + case 0x02: + dev->index = 0; /* reading from this resets the block data index */ + ret = dev->ctl; + break; + + case 0x03: + ret = dev->addr; + break; + + case 0x04: + ret = dev->data0; + break; + + case 0x05: + ret = dev->data1; + break; + + case 0x06: + ret = dev->data[dev->index++]; + if (dev->index >= SMBUS_ALI7101_BLOCK_DATA_SIZE) + dev->index = 0; + break; + + case 0x07: + ret = dev->cmd; + break; + } + + smbus_ali7101_log("SMBus ALI7101: read(%02X) = %02x\n", addr, ret); + + return ret; +} + + +static void +smbus_ali7101_write(uint16_t addr, uint8_t val, void *priv) +{ + smbus_ali7101_t *dev = (smbus_ali7101_t *) priv; + uint8_t smbus_addr, cmd, read, prev_stat; + uint16_t timer_bytes = 0; + + smbus_ali7101_log("SMBus ALI7101: write(%02X, %02X)\n", addr, val); + + prev_stat = dev->next_stat; + dev->next_stat = 0x04; + switch (addr - dev->io_base) { + case 0x00: + dev->stat &= ~(val & 0xe2); + /* Make sure IDLE is set if we're not busy or errored. */ + if (dev->stat == 0x00) + dev->stat = 0x04; + break; + + case 0x01: + dev->ctl = val & 0xfc; + if (val & 0x04) { /* 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 & 0x08) { /* T_OUT_CMD */ + if (prev_stat) { /* cancel only if a command is in progress */ + timer_disable(&dev->response_timer); + dev->stat = 0x20; /* raise DEVICE_ERR */ + } + } + break; + + case 0x02: + /* dispatch command if START is set */ + timer_bytes++; /* address */ + + smbus_addr = (dev->addr >> 1); + read = dev->addr & 0x01; + + cmd = (dev->ctl >> 4) & 0x7; + smbus_ali7101_log("SMBus ALI7101: 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 = 0x20; + break; + } + + dev->next_stat = 0x10; /* raise INTER (command completed) by default */ + + /* Decode the command protocol. */ + switch (cmd) { + case 0x0: /* quick R/W */ + break; + + case 0x1: /* byte R/W */ + if (read) /* byte read */ + dev->data0 = i2c_read(i2c_smbus, smbus_addr); + else /* byte write */ + i2c_write(i2c_smbus, smbus_addr, dev->data0); + 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->data0 = i2c_read(i2c_smbus, smbus_addr); + else /* byte write */ + i2c_write(i2c_smbus, smbus_addr, dev->data0); + 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->data0 = i2c_read(i2c_smbus, smbus_addr); + dev->data1 = i2c_read(i2c_smbus, smbus_addr); + } else { /* word write */ + i2c_write(i2c_smbus, smbus_addr, dev->data0); + i2c_write(i2c_smbus, smbus_addr, dev->data1); + } + timer_bytes += 2; + + break; + + case 0x4: /* block R/W */ + timer_bytes++; /* count the SMBus length byte now */ + + /* fall-through */ + + default: /* unknown */ + dev->next_stat = 0x20; /* raise DEV_ERR */ + timer_bytes = 0; + break; + } + + /* Finish transfer. */ + i2c_stop(i2c_smbus, smbus_addr); + break; + + case 0x03: + dev->addr = val; + break; + + case 0x04: + dev->data0 = val; + break; + + case 0x05: + dev->data1 = val; + break; + + case 0x06: + dev->data[dev->index++] = val; + if (dev->index >= SMBUS_ALI7101_BLOCK_DATA_SIZE) + dev->index = 0; + break; + + case 0x07: + dev->cmd = val; + 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_ali7101_response(void *priv) +{ + smbus_ali7101_t *dev = (smbus_ali7101_t *) priv; + + /* Dispatch the status register update. */ + dev->stat = dev->next_stat; +} + + +void +smbus_ali7101_remap(smbus_ali7101_t *dev, uint16_t new_io_base, uint8_t enable) +{ + if (dev->io_base) + io_removehandler(dev->io_base, 0x10, smbus_ali7101_read, NULL, NULL, smbus_ali7101_write, NULL, NULL, dev); + + dev->io_base = new_io_base; + smbus_ali7101_log("SMBus ALI7101: remap to %04Xh (%sabled)\n", dev->io_base, enable ? "en" : "dis"); + + if (enable && dev->io_base) + io_sethandler(dev->io_base, 0x10, smbus_ali7101_read, NULL, NULL, smbus_ali7101_write, NULL, NULL, dev); +} + + +static void +smbus_ali7101_reset(void *priv) +{ + smbus_ali7101_t *dev = (smbus_ali7101_t *) priv; + + timer_disable(&dev->response_timer); + dev->stat = 0x04; +} + + +static void * +smbus_ali7101_init(const device_t *info) +{ + smbus_ali7101_t *dev = (smbus_ali7101_t *) malloc(sizeof(smbus_ali7101_t)); + memset(dev, 0, sizeof(smbus_ali7101_t)); + + dev->local = info->local; + dev->stat = 0x04; + /* 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_ali7101"); + + timer_add(&dev->response_timer, smbus_ali7101_response, dev, 0); + + return dev; +} + + +static void +smbus_ali7101_close(void *priv) +{ + smbus_ali7101_t *dev = (smbus_ali7101_t *) priv; + + if (i2c_smbus == dev->i2c) + i2c_smbus = NULL; + i2c_removebus(dev->i2c); + + free(dev); +} + + +const device_t ali7101_smbus_device = { + "ALi M7101-compatible SMBus Host Controller", + DEVICE_AT, + 0, + smbus_ali7101_init, smbus_ali7101_close, smbus_ali7101_reset, + { NULL }, NULL, NULL, + NULL +}; diff --git a/src/device/smbus_piix4.c b/src/device/smbus_piix4.c index f3b14eda0..09d46999d 100644 --- a/src/device/smbus_piix4.c +++ b/src/device/smbus_piix4.c @@ -26,7 +26,7 @@ #include <86box/device.h> #include <86box/timer.h> #include <86box/i2c.h> -#include <86box/smbus_piix4.h> +#include <86box/smbus.h> #ifdef ENABLE_SMBUS_PIIX4_LOG diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index b0a3cb71f..d20618051 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -26,7 +26,9 @@ extern const device_t ali1217_device; extern const device_t ali1429_device; extern const device_t ali1489_device; extern const device_t ali1531_device; +extern const device_t ali1541_device; extern const device_t ali1543_device; +extern const device_t ali1543c_device; #if defined(DEV_BRANCH) && defined(USE_M6117) extern const device_t ali6117d_device; #endif diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index c63a3b991..b3e9b66d5 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -497,6 +497,9 @@ extern int machine_at_m560_init(const machine_t *); extern int machine_at_ms5164_init(const machine_t *); /* m_at_sockets7.c */ +extern int machine_at_m579_init(const machine_t *); +extern int machine_at_ga_5aa_init(const machine_t *); + extern int machine_at_ax59pro_init(const machine_t *); extern int machine_at_mvp3_init(const machine_t *); extern int machine_at_ficva503a_init(const machine_t *); diff --git a/src/include/86box/pci.h b/src/include/86box/pci.h index 8e28fbbdf..18c19dd55 100644 --- a/src/include/86box/pci.h +++ b/src/include/86box/pci.h @@ -45,10 +45,6 @@ #define PCI_MIRQ1 1 #define PCI_MIRQ2 2 #define PCI_MIRQ3 3 -#define PCI_MIRQ4 4 -#define PCI_MIRQ5 5 -#define PCI_MIRQ6 6 -#define PCI_MIRQ7 7 #define PCI_IRQ_DISABLED -1 @@ -123,10 +119,13 @@ extern void trc_init(void); extern uint8_t trc_read(uint16_t port, void *priv); extern void trc_write(uint16_t port, uint8_t val, void *priv); +extern void pci_bridge_set_ctl(void *priv, uint8_t ctl); + #ifdef EMU_DEVICE_H extern const device_t dec21150_device; +extern const device_t ali5243_agp_device; extern const device_t i440lx_agp_device; extern const device_t i440bx_agp_device; extern const device_t i440gx_agp_device; diff --git a/src/include/86box/smbus_piix4.h b/src/include/86box/smbus.h similarity index 66% rename from src/include/86box/smbus_piix4.h rename to src/include/86box/smbus.h index 3173ead4e..514ef4bde 100644 --- a/src/include/86box/smbus_piix4.h +++ b/src/include/86box/smbus.h @@ -6,7 +6,7 @@ * * This file is part of the 86Box distribution. * - * Definitions for the generic PIIX4-compatible SMBus host controller. + * Definitions for the SMBus host controllers. * * * @@ -21,6 +21,9 @@ #define SMBUS_PIIX4_BLOCK_DATA_SIZE 32 #define SMBUS_PIIX4_BLOCK_DATA_MASK (SMBUS_PIIX4_BLOCK_DATA_SIZE - 1) +#define SMBUS_ALI7101_BLOCK_DATA_SIZE 32 +#define SMBUS_ALI7101_BLOCK_DATA_MASK (SMBUS_ALI7101_BLOCK_DATA_SIZE - 1) + enum { SMBUS_PIIX4 = 0, @@ -37,13 +40,26 @@ typedef struct { void *i2c; } smbus_piix4_t; +typedef struct { + uint32_t local; + uint16_t io_base; + uint8_t stat, next_stat, ctl, cmd, addr, + data0, data1, + index, data[SMBUS_ALI7101_BLOCK_DATA_SIZE]; + pc_timer_t response_timer; + void *i2c; +} smbus_ali7101_t; + extern void smbus_piix4_remap(smbus_piix4_t *dev, uint16_t new_io_base, uint8_t enable); +extern void smbus_ali7101_remap(smbus_ali7101_t *dev, uint16_t new_io_base, uint8_t enable); #ifdef EMU_DEVICE_H extern const device_t piix4_smbus_device; extern const device_t via_smbus_device; + +extern const device_t ali7101_smbus_device; #endif diff --git a/src/machine/m_at_sockets7.c b/src/machine/m_at_sockets7.c index f15ddf01b..e51fda097 100644 --- a/src/machine/m_at_sockets7.c +++ b/src/machine/m_at_sockets7.c @@ -42,6 +42,72 @@ #include <86box/machine.h> +int +machine_at_m579_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/m579/MS6260S_Socket7_ALi_M1542_AMI.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_AGPBRIDGE, 1, 2, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x10, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); + device_add(&ali1541_device); + device_add(&ali1543c_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sst_flash_29ee010_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 128); + + return ret; +} + + +int +machine_at_ga_5aa_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ga-5aa/GA-5AA.F7b", + 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_AGPBRIDGE, 1, 2, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + 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); + device_add(&ali1541_device); + device_add(&ali1543c_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sst_flash_29ee010_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 128); + + return ret; +} + + int machine_at_ax59pro_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 75dad8e60..f80d66334 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -667,6 +667,12 @@ const machine_t machines[] = { { "[ALi ALADDiN IV] MSI MS-5164", "ms5164", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2100, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_ms5164_init, NULL }, /* Super Socket 7 machines */ + /* ALi ALADDiN V */ + /* Is the exact same as the Matsonic MS6260S. Has the ALi M1543C southbridge + with on-chip KBC. */ + { "[ALi ALADDiN V] PC Chips M579", "m579", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 2000, 3200, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,2097152, 8192, 255, machine_at_m579_init, NULL }, + { "[ALi ALADDiN V] Gigabyte GA-5AA", "ga-5aa", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 2000, 3200, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,2097152, 8192, 255, machine_at_ga_5aa_init, NULL }, + /* Apollo MVP3 */ /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA VT82C42N. */ diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 15e86c28a..beed254e0 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -601,7 +601,7 @@ CPUOBJ := cpu.o cpu_table.o fpu.o x86.o \ CHIPSETOBJ := acc2168.o \ cs4031.o cs8230.o \ - ali1217.o ali1429.o ali1489.o ali1531.o ali1543.o \ + ali1217.o ali1429.o ali1489.o ali1531.o ali1541.o ali1543.o \ gc100.o headland.o \ intel_82335.o intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \ neat.o \ @@ -633,7 +633,7 @@ MCHOBJ := machine.o machine_table.o \ ifeq ($(NEW_KBC), y) DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o ibm_5161.o isamem.o isartc.o \ lpt.o pci_bridge.o postcard.o serial.o vpc2007.o clock_ics9xxx.o isapnp.o \ - i2c.o i2c_gpio.o smbus_piix4.o \ + i2c.o i2c_gpio.o smbus_ali7101.o smbus_piix4.o \ keyboard.o \ keyboard_xt.o kbc_at.o kbd_at.o \ mouse.o \ From 2f24523802c92c766c2da7e96c388160f888759f Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 4 Jul 2021 18:22:00 +0200 Subject: [PATCH 03/96] And more fixes. --- src/chipset/ali1543.c | 7 ++++++- src/include/86box/pci.h | 4 ++++ src/win/Makefile.mingw | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/chipset/ali1543.c b/src/chipset/ali1543.c index e15c77b77..bec3663cc 100644 --- a/src/chipset/ali1543.c +++ b/src/chipset/ali1543.c @@ -34,10 +34,12 @@ #include <86box/fdc.h> #include <86box/hdc_ide.h> #include <86box/hdc_ide_sff8038i.h> +#include <86box/keyboard.h> #include <86box/lpt.h> #include <86box/mem.h> #include <86box/nvr.h> #include <86box/pci.h> +#include <86box/pic.h> #include <86box/port_92.h> #include <86box/serial.h> #include <86box/smbus.h> @@ -113,11 +115,15 @@ static void ali5229_ide_irq_handler(ali1543_t *dev); static void ali5229_write(int func, int addr, uint8_t val, void *priv); +static void ali7101_write(int func, int addr, uint8_t val, void *priv); +static uint8_t ali7101_read(int func, int addr, void *priv); + static void ali1533_write(int func, int addr, uint8_t val, void *priv) { ali1543_t *dev = (ali1543_t *)priv; + int irq; ali1543_log("M1533: dev->pci_conf[%02x] = %02x\n", addr, val); if (func > 0) @@ -548,7 +554,6 @@ ali5229_ide_irq_handler(ali1543_t *dev) static void ali5229_ide_handler(ali1543_t *dev) -ali5229_ide_handler(ali1543_t *dev) { uint32_t ch = 0; diff --git a/src/include/86box/pci.h b/src/include/86box/pci.h index 18c19dd55..0041855e4 100644 --- a/src/include/86box/pci.h +++ b/src/include/86box/pci.h @@ -45,6 +45,10 @@ #define PCI_MIRQ1 1 #define PCI_MIRQ2 2 #define PCI_MIRQ3 3 +#define PCI_MIRQ4 4 +#define PCI_MIRQ5 5 +#define PCI_MIRQ6 6 +#define PCI_MIRQ7 7 #define PCI_IRQ_DISABLED -1 diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index beed254e0..9c515eaa8 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -643,7 +643,7 @@ DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o ibm else DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o ibm_5161.o isamem.o isartc.o \ lpt.o pci_bridge.o postcard.o serial.o vpc2007.o clock_ics9xxx.o isapnp.o \ - i2c.o i2c_gpio.o smbus_piix4.o \ + i2c.o i2c_gpio.o smbus_ali7101.o smbus_piix4.o \ keyboard.o \ keyboard_xt.o keyboard_at.o \ mouse.o \ From 9d62da4548f6592a6e2b9fa1654be2e64f7b417e Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 4 Jul 2021 18:24:23 +0200 Subject: [PATCH 04/96] And SPD. --- src/mem/spd.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/mem/spd.c b/src/mem/spd.c index 821f88e71..74346417b 100644 --- a/src/mem/spd.c +++ b/src/mem/spd.c @@ -388,7 +388,8 @@ void spd_write_drbs_interleaved(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit) { uint8_t row, dimm, drb, apollo = 0; - uint16_t size, rows[SPD_MAX_SLOTS]; + uint16_t size, size_acc; + uint16_t rows[SPD_MAX_SLOTS]; /* Special case for VIA Apollo Pro family, which jumps from 5F to 56. */ if (reg_max < reg_min) { @@ -426,15 +427,16 @@ spd_write_drbs_interleaved(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint if (apollo && ((drb & 0xf) < 0xa)) drb = apollo + (drb & 0xf); - /* Write DRB register, adding the previous DRB's value. */ + /* Calculate previous and new size. */ if (row == 0) - regs[drb] = 0; - else if ((apollo) && (drb == apollo)) - regs[drb] = regs[drb | 0xf]; /* 5F comes before 56 */ + size_acc = 0; else - regs[drb] = regs[drb - 1]; - if (size) - regs[drb] += size / drb_unit; /* this will intentionally overflow on 440GX with 2 GB */ + size_acc += (size / drb_unit); + + /* Write DRB register, adding the previous DRB's value. */ + regs[drb] = size_acc & 0xff; + regs[drb + 1] = (regs[drb + 1] & 0xf0) | ((size_acc >> 8) & 0x0f); + spd_log("SPD: DRB[%d] = %d MB (%02Xh raw)\n", row >> 1, size, regs[drb]); } } From 29c8e36e6ef2344e27392eb732168be58fca3682 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 4 Jul 2021 20:50:03 +0200 Subject: [PATCH 05/96] Fixed miscellaneous bugs reported by Coverity. --- src/chipset/ali1489.c | 16 ++++++++-------- src/chipset/intel_4x0.c | 6 +++--- src/chipset/opti895.c | 4 ++-- src/chipset/via_apollo.c | 13 ++++++------- src/chipset/via_vt82c49x.c | 4 ++-- src/device/hwm_lm75.c | 5 +++-- src/device/pci_bridge.c | 6 ++++-- src/include/86box/hwm.h | 1 + src/mem/sst_flash.c | 6 ++++-- src/sio/sio_fdc37c93x.c | 2 +- src/video/vid_et4000.c | 9 ++++++--- src/win/win_joystick_rawinput.c | 2 +- src/win/win_settings.c | 2 ++ 13 files changed, 43 insertions(+), 33 deletions(-) diff --git a/src/chipset/ali1489.c b/src/chipset/ali1489.c index 47e7cbd9b..03c1f4519 100644 --- a/src/chipset/ali1489.c +++ b/src/chipset/ali1489.c @@ -199,10 +199,10 @@ ali1489_defaults(ali1489_t *dev) smi_line = 0; in_smm = 0; - pci_set_irq(PCI_INTA, PCI_IRQ_DISABLED); - pci_set_irq(PCI_INTB, PCI_IRQ_DISABLED); - pci_set_irq(PCI_INTC, PCI_IRQ_DISABLED); - pci_set_irq(PCI_INTD, PCI_IRQ_DISABLED); + 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); } @@ -570,10 +570,10 @@ ali1489_reset(void *priv) { ali1489_t *dev = (ali1489_t *)priv; - pci_set_irq(PCI_INTA, PCI_IRQ_DISABLED); - pci_set_irq(PCI_INTB, PCI_IRQ_DISABLED); - pci_set_irq(PCI_INTC, PCI_IRQ_DISABLED); - pci_set_irq(PCI_INTD, PCI_IRQ_DISABLED); + 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); ali1489_defaults(dev); } diff --git a/src/chipset/intel_4x0.c b/src/chipset/intel_4x0.c index 0b157f4dd..6da41c24f 100644 --- a/src/chipset/intel_4x0.c +++ b/src/chipset/intel_4x0.c @@ -1303,11 +1303,11 @@ static void regs[0x0d] = 0x20; /* According to information from FreeBSD 3.x source code: 0x00 = 486DX, 0x20 = 486SX, 0x40 = 486DX2 or 486DX4, 0x80 = Pentium OverDrive. */ - if (!(hasfpu) && (cpu_multi = 1)) + if (!(hasfpu) && (cpu_multi == 1)) regs[0x50] = 0x20; - else if (!(hasfpu) && (cpu_multi = 2)) + else if (!(hasfpu) && (cpu_multi == 2)) regs[0x50] = 0x60; /* Guess based on the SX, DX, and DX2 values. */ - else if (hasfpu && (cpu_multi = 1)) + else if (hasfpu && (cpu_multi == 1)) regs[0x50] = 0x00; else if (hasfpu && (cpu_multi >= 2) && !(cpu_s->cpu_type == CPU_P24T)) regs[0x50] = 0x40; diff --git a/src/chipset/opti895.c b/src/chipset/opti895.c index 447d64fa3..289388391 100644 --- a/src/chipset/opti895.c +++ b/src/chipset/opti895.c @@ -187,7 +187,7 @@ opti895_write(uint16_t addr, uint8_t val, void *priv) case 0xe1: case 0xe2: - dev->scratch[addr] = val; + dev->scratch[addr - 0xe1] = val; break; } } @@ -214,7 +214,7 @@ opti895_read(uint16_t addr, void *priv) break; case 0xe1: case 0xe2: - ret = dev->scratch[addr]; + ret = dev->scratch[addr - 0xe1]; break; } diff --git a/src/chipset/via_apollo.c b/src/chipset/via_apollo.c index 22de563c8..bf593c487 100644 --- a/src/chipset/via_apollo.c +++ b/src/chipset/via_apollo.c @@ -213,13 +213,12 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv) return; /*Read-only addresses*/ - if ((addr < 4) || ((addr >= 5) && (addr < 7)) || ((addr >= 8) && (addr < 0xd)) || - ((addr >= 0xe) && (addr < 0x12)) || ((addr >= 0x14) && (addr < 0x50)) || - (addr == 0x69) || ((addr >= 0x79) && (addr < 0x7e)) || - ((addr >= 0x81) && (addr < 0x84)) || ((addr >= 0x85) && (addr < 0x88)) || - ((addr >= 0x8c) && (addr < 0xa8)) || ((addr >= 0xaa) && (addr < 0xac)) || - ((addr >= 0xad) && (addr < 0xf0)) || ((addr >= 0xf8) && (addr < 0xfc)) || - (addr == 0xfd)) + if ((addr < 4) || ((addr > 5) && (addr < 7)) || ((addr >= 8) && (addr < 0xd)) || + ((addr >= 0xe) && (addr != 0x0f) && (addr < 0x12)) || ((addr >= 0x14) && (addr < 0x50)) || + ((addr > 0x7a) && (addr < 0x7e)) || ((addr >= 0x81) && (addr < 0x84)) || + ((addr >= 0x85) && (addr < 0x88)) || ((addr >= 0x8c) && (addr < 0xa8)) || + ((addr >= 0xaa) && (addr < 0xac)) || ((addr > 0xad) && (addr < 0xf0)) || + ((addr >= 0xf8) && (addr < 0xfc))) return; if (((addr == 0x78) || (addr >= 0xad)) && (dev->id == VIA_597)) return; diff --git a/src/chipset/via_vt82c49x.c b/src/chipset/via_vt82c49x.c index 712ad8f5a..20824b006 100644 --- a/src/chipset/via_vt82c49x.c +++ b/src/chipset/via_vt82c49x.c @@ -133,9 +133,9 @@ vt82c49x_recalc(vt82c49x_t *dev) state = (dev->regs[0x33] & 0x10) ? MEM_WRITE_ROMCS : MEM_WRITE_EXTERNAL; if ((dev->regs[0x32]) & (1 << (bit + 1))) - state = MEM_READ_INTERNAL; + state |= MEM_READ_INTERNAL; else - state = (dev->regs[0x33] & 0x10) ? MEM_READ_ROMCS : MEM_READ_EXTERNAL; + state |= (dev->regs[0x33] & 0x10) ? MEM_READ_ROMCS : MEM_READ_EXTERNAL; } else if ((base >= 0xe8000) && (base <= 0xeffff)) { if (dev->regs[0x40] & 0x20) state = MEM_WRITE_DISABLED; diff --git a/src/device/hwm_lm75.c b/src/device/hwm_lm75.c index 9faf73326..30615d912 100644 --- a/src/device/hwm_lm75.c +++ b/src/device/hwm_lm75.c @@ -187,13 +187,14 @@ lm75_remap(lm75_t *dev, uint8_t addr) { lm75_log("LM75: remapping to SMBus %02Xh\n", addr); - if (dev->i2c_addr < 0x80) + if (dev->i2c_enabled) i2c_removehandler(i2c_smbus, dev->i2c_addr, 1, lm75_i2c_start, lm75_i2c_read, lm75_i2c_write, NULL, dev); if (addr < 0x80) i2c_sethandler(i2c_smbus, addr, 1, lm75_i2c_start, lm75_i2c_read, lm75_i2c_write, NULL, dev); - dev->i2c_addr = addr; + dev->i2c_addr = addr & 0x7f; + dev->i2c_enabled = !!(addr & 0x80); } diff --git a/src/device/pci_bridge.c b/src/device/pci_bridge.c index 6a175d302..8e1353cc1 100644 --- a/src/device/pci_bridge.c +++ b/src/device/pci_bridge.c @@ -452,8 +452,10 @@ pci_bridge_init(const device_t *info) dev->slot = pci_add_card(AGP_BRIDGE(dev->local) ? PCI_ADD_AGPBRIDGE : PCI_ADD_BRIDGE, pci_bridge_read, pci_bridge_write, dev); interrupt_count = sizeof(interrupts); interrupt_mask = interrupt_count - 1; - for (i = 0; i < interrupt_count; i++) - interrupts[i] = pci_get_int(dev->slot, PCI_INTA + i); + if (dev->slot < 32) { + for (i = 0; i < interrupt_count; i++) + interrupts[i] = pci_get_int(dev->slot, PCI_INTA + i); + } pci_bridge_log("PCI Bridge %d: upstream bus %02X slot %02X interrupts %02X %02X %02X %02X\n", dev->bus_index, (dev->slot >> 5) & 0xff, dev->slot & 31, interrupts[0], interrupts[1], interrupts[2], interrupts[3]); if (info->local == PCI_BRIDGE_DEC_21150) diff --git a/src/include/86box/hwm.h b/src/include/86box/hwm.h index 6172ec693..28e6c031c 100644 --- a/src/include/86box/hwm.h +++ b/src/include/86box/hwm.h @@ -36,6 +36,7 @@ typedef struct { uint8_t regs[8]; uint8_t addr_register; uint8_t i2c_addr: 7, i2c_state: 2; + uint8_t i2c_enabled; } lm75_t; diff --git a/src/mem/sst_flash.c b/src/mem/sst_flash.c index 2b8c4a54d..9358d554c 100644 --- a/src/mem/sst_flash.c +++ b/src/mem/sst_flash.c @@ -402,8 +402,10 @@ sst_close(void *p) if (dev->dirty) { f = nvr_fopen(flash_path, "wb"); - fwrite(&(dev->array[0x00000]), dev->size, 1, f); - fclose(f); + if (f != NULL) { + fwrite(&(dev->array[0x00000]), dev->size, 1, f); + fclose(f); + } } free(dev->array); diff --git a/src/sio/sio_fdc37c93x.c b/src/sio/sio_fdc37c93x.c index 35cfe862b..a20349aff 100644 --- a/src/sio/sio_fdc37c93x.c +++ b/src/sio/sio_fdc37c93x.c @@ -206,7 +206,7 @@ fdc37c93x_nvr_sec_handler(fdc37c93x_t *dev) dev->nvr_sec_base = ld_port = make_port_sec(dev, 6) & 0xFFFE; /* Datasheet erratum: First it says minimum address is 0x0100, but later implies that it's 0x0000 and that default is 0x0070, same as (unrelocatable) primary NVR. */ - if ((ld_port >= 0x0000) && (ld_port <= 0x0FFE)) + if (ld_port <= 0x0FFE) nvr_at_sec_handler(1, dev->nvr_sec_base, dev->nvr); } } diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index 3bce65159..f1dedf4a2 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -464,7 +464,8 @@ et4000_kasan_out(uint16_t addr, uint8_t val, void *priv) break; case 1: case 2: - et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val; + if ((et4000->kasan_cfg_index - 0xF0) <= 16) + et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val; io_removehandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000); et4000->kasan_access_addr = (et4000->kasan_cfg_regs[2] << 8) | et4000->kasan_cfg_regs[1]; io_sethandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000); @@ -507,8 +508,10 @@ et4000_kasan_out(uint16_t addr, uint8_t val, void *priv) case 3: case 4: case 5: - if (et4000->kasan_cfg_regs[0] & 1) - et4000->kasan_font_data[addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)] = val; + if (et4000->kasan_cfg_regs[0] & 1) { + if ((addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)) <= 4) + et4000->kasan_font_data[addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)] = val; + } break; case 6: if ((et4000->kasan_cfg_regs[0] & 1) && (et4000->kasan_font_data[3] & !(val & 0x80)) && (et4000->get_korean_font_base & 0x7F) >= 0x20 && (et4000->get_korean_font_base & 0x7F) < 0x7F) { diff --git a/src/win/win_joystick_rawinput.c b/src/win/win_joystick_rawinput.c index c4f947bac..be808fc47 100644 --- a/src/win/win_joystick_rawinput.c +++ b/src/win/win_joystick_rawinput.c @@ -56,7 +56,7 @@ typedef struct { HANDLE hdevice; PHIDP_PREPARSED_DATA data; - USAGE usage_button[128]; + USAGE usage_button[256]; struct raw_axis_t { USAGE usage; diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 067f7c9f9..a5f426ded 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -949,6 +949,8 @@ win_settings_machine_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) win_settings_machine_recalc_machine(hdlg); } + + free(lptsTemp); } break; case IDC_COMBO_MACHINE: From 8e14514660b200b8bdffe6b7c4706854419d08e3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 4 Jul 2021 21:03:28 +0200 Subject: [PATCH 06/96] More HWM fixes. --- src/device/hwm_gl518sm.c | 10 +++++++--- src/device/hwm_lm75.c | 4 ++-- src/device/hwm_lm78.c | 10 ++++++---- src/include/86box/hwm.h | 2 +- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/device/hwm_gl518sm.c b/src/device/hwm_gl518sm.c index c340ce59c..9c8eae920 100644 --- a/src/device/hwm_gl518sm.c +++ b/src/device/hwm_gl518sm.c @@ -41,7 +41,7 @@ typedef struct { uint16_t regs[32]; uint8_t addr_register: 5; - uint8_t i2c_addr: 7, i2c_state: 2; + uint8_t i2c_addr: 7, i2c_state: 2, i2c_enabled: 1; } gl518sm_t; @@ -78,12 +78,14 @@ gl518sm_remap(gl518sm_t *dev, uint8_t addr) { gl518sm_log("GL518SM: remapping to SMBus %02Xh\n", addr); - i2c_removehandler(i2c_smbus, dev->i2c_addr, 1, gl518sm_i2c_start, gl518sm_i2c_read, gl518sm_i2c_write, NULL, dev); + if (dev->i2c_enabled) + i2c_removehandler(i2c_smbus, dev->i2c_addr, 1, gl518sm_i2c_start, gl518sm_i2c_read, gl518sm_i2c_write, NULL, dev); if (addr < 0x80) i2c_sethandler(i2c_smbus, addr, 1, gl518sm_i2c_start, gl518sm_i2c_read, gl518sm_i2c_write, NULL, dev); - dev->i2c_addr = addr; + dev->i2c_addr = addr & 0x7f; + dev->i2c_enabled = !(addr & 0x80); } @@ -244,6 +246,8 @@ gl518sm_reset(gl518sm_t *dev) dev->regs[0x0b] = 0xdac5; dev->regs[0x0c] = 0xdac5; dev->regs[0x0f] = 0xf8; + + gl518sm_remap(dev, dev->i2c_addr | (dev->i2c_enabled ? 0x00 : 0x80)); } diff --git a/src/device/hwm_lm75.c b/src/device/hwm_lm75.c index 30615d912..3a28e2a1f 100644 --- a/src/device/hwm_lm75.c +++ b/src/device/hwm_lm75.c @@ -194,7 +194,7 @@ lm75_remap(lm75_t *dev, uint8_t addr) i2c_sethandler(i2c_smbus, addr, 1, lm75_i2c_start, lm75_i2c_read, lm75_i2c_write, NULL, dev); dev->i2c_addr = addr & 0x7f; - dev->i2c_enabled = !!(addr & 0x80); + dev->i2c_enabled = !(addr & 0x80); } @@ -204,7 +204,7 @@ lm75_reset(lm75_t *dev) dev->regs[0x3] = 0x4b; dev->regs[0x5] = 0x50; - lm75_remap(dev, dev->local & 0x7f); + lm75_remap(dev, dev->i2c_addr | (dev->i2c_enabled ? 0x00 : 0x80)); } diff --git a/src/device/hwm_lm78.c b/src/device/hwm_lm78.c index e849190cf..e93989afe 100644 --- a/src/device/hwm_lm78.c +++ b/src/device/hwm_lm78.c @@ -72,7 +72,7 @@ typedef struct { }; uint8_t addr_register, data_register; - uint8_t i2c_addr: 7, i2c_state: 1; + uint8_t i2c_addr: 7, i2c_state: 1, i2c_enabled: 1; } lm78_t; @@ -315,7 +315,7 @@ lm78_reset(void *priv) dev->regs[0x49] = 0x40; } - lm78_remap(dev, dev->i2c_addr); + lm78_remap(dev, dev->i2c_addr | (dev->i2c_enabled ? 0x00 : 0x80)); } @@ -665,12 +665,14 @@ lm78_remap(lm78_t *dev, uint8_t addr) lm78_log("LM78: remapping to SMBus %02Xh\n", addr); - i2c_removehandler(i2c_smbus, dev->i2c_addr, 1, lm78_i2c_start, lm78_i2c_read, lm78_i2c_write, NULL, dev); + if (dev->i2c_enabled) + i2c_removehandler(i2c_smbus, dev->i2c_addr, 1, lm78_i2c_start, lm78_i2c_read, lm78_i2c_write, NULL, dev); if (addr < 0x80) i2c_sethandler(i2c_smbus, addr, 1, lm78_i2c_start, lm78_i2c_read, lm78_i2c_write, NULL, dev); - dev->i2c_addr = addr; + dev->i2c_addr = addr & 0x7f; + dev->i2c_enabled = !(addr & 0x80); if (dev->local & LM78_AS99127F) { /* Store our handle on the primary LM75 device to ensure reads/writes diff --git a/src/include/86box/hwm.h b/src/include/86box/hwm.h index 28e6c031c..e4613f05b 100644 --- a/src/include/86box/hwm.h +++ b/src/include/86box/hwm.h @@ -36,7 +36,7 @@ typedef struct { uint8_t regs[8]; uint8_t addr_register; uint8_t i2c_addr: 7, i2c_state: 2; - uint8_t i2c_enabled; + uint8_t i2c_enabled: 1; } lm75_t; From 2bf2489f5051d7b2e03a7590fd181084583cd92d Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 9 Jul 2021 00:15:39 +0200 Subject: [PATCH 07/96] ALi SMBUS fixes. --- src/device/smbus_ali7101.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/device/smbus_ali7101.c b/src/device/smbus_ali7101.c index 1a3f49c03..f5a3d4d70 100644 --- a/src/device/smbus_ali7101.c +++ b/src/device/smbus_ali7101.c @@ -61,11 +61,6 @@ smbus_ali7101_read(uint16_t addr, void *priv) ret = dev->stat; break; - case 0x02: - dev->index = 0; /* reading from this resets the block data index */ - ret = dev->ctl; - break; - case 0x03: ret = dev->addr; break; From ab86ee8f4a074d7409f53112005776dc17de5bdb Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 9 Jul 2021 00:17:02 +0200 Subject: [PATCH 08/96] And another fix. --- src/device/smbus_ali7101.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/device/smbus_ali7101.c b/src/device/smbus_ali7101.c index f5a3d4d70..32cc0a22e 100644 --- a/src/device/smbus_ali7101.c +++ b/src/device/smbus_ali7101.c @@ -122,6 +122,9 @@ smbus_ali7101_write(uint16_t addr, uint8_t val, void *priv) dev->stat = 0x20; /* raise DEVICE_ERR */ } } + + if (val & 0x80) + dev->index = 0; break; case 0x02: From 903a54c0f1ebd0104b6f8bc3eeb83c290db638b5 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 9 Jul 2021 04:33:59 +0200 Subject: [PATCH 09/96] SMBus header fixes. --- src/include/86box/smbus.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/include/86box/smbus.h b/src/include/86box/smbus.h index 514ef4bde..6661a25c6 100644 --- a/src/include/86box/smbus.h +++ b/src/include/86box/smbus.h @@ -33,6 +33,8 @@ enum { typedef struct { uint32_t local; uint16_t io_base; + int clock; + double bit_period; uint8_t stat, next_stat, ctl, cmd, addr, data0, data1, index, data[SMBUS_PIIX4_BLOCK_DATA_SIZE]; @@ -52,6 +54,8 @@ typedef struct { 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); From a7bda63022068e69d6837698a94678c49cdf8fa9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 9 Jul 2021 04:35:48 +0200 Subject: [PATCH 10/96] An unused smbus_piix4.h just to make merges easier. --- src/include/86box/smbus_piix4.h | 50 +++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/include/86box/smbus_piix4.h diff --git a/src/include/86box/smbus_piix4.h b/src/include/86box/smbus_piix4.h new file mode 100644 index 000000000..3173ead4e --- /dev/null +++ b/src/include/86box/smbus_piix4.h @@ -0,0 +1,50 @@ +/* + * 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 generic PIIX4-compatible SMBus host controller. + * + * + * + * Authors: RichardG, + * + * Copyright 2020 RichardG. + */ +#ifndef EMU_SMBUS_PIIX4_H +# define EMU_SMBUS_PIIX4_H + + +#define SMBUS_PIIX4_BLOCK_DATA_SIZE 32 +#define SMBUS_PIIX4_BLOCK_DATA_MASK (SMBUS_PIIX4_BLOCK_DATA_SIZE - 1) + + +enum { + SMBUS_PIIX4 = 0, + SMBUS_VIA +}; + +typedef struct { + uint32_t local; + uint16_t io_base; + uint8_t stat, next_stat, ctl, cmd, addr, + data0, data1, + index, data[SMBUS_PIIX4_BLOCK_DATA_SIZE]; + pc_timer_t response_timer; + void *i2c; +} smbus_piix4_t; + + +extern void smbus_piix4_remap(smbus_piix4_t *dev, uint16_t new_io_base, uint8_t enable); + + +#ifdef EMU_DEVICE_H +extern const device_t piix4_smbus_device; +extern const device_t via_smbus_device; +#endif + + +#endif /*EMU_SMBUS_PIIX4_H*/ From f3213527dcceb76f91c417411015322546915a50 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 9 Jul 2021 04:38:29 +0200 Subject: [PATCH 11/96] Makefile change. --- src/win/Makefile.mingw | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 9c515eaa8..c67fa66f6 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -631,8 +631,9 @@ MCHOBJ := machine.o machine_table.o \ m_at_misc.o ifeq ($(NEW_KBC), y) -DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o ibm_5161.o isamem.o isartc.o \ - lpt.o pci_bridge.o postcard.o serial.o vpc2007.o clock_ics9xxx.o isapnp.o \ +DEVOBJ := bugger.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ + ibm_5161.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o \ + vpc2007.o clock_ics9xxx.o isapnp.o \ i2c.o i2c_gpio.o smbus_ali7101.o smbus_piix4.o \ keyboard.o \ keyboard_xt.o kbc_at.o kbd_at.o \ @@ -641,8 +642,9 @@ DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o ibm mouse_serial.o mouse_ps2.o \ phoenix_486_jumper.o else -DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o ibm_5161.o isamem.o isartc.o \ - lpt.o pci_bridge.o postcard.o serial.o vpc2007.o clock_ics9xxx.o isapnp.o \ +DEVOBJ := bugger.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ + ibm_5161.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o \ + vpc2007.o clock_ics9xxx.o isapnp.o \ i2c.o i2c_gpio.o smbus_ali7101.o smbus_piix4.o \ keyboard.o \ keyboard_xt.o keyboard_at.o \ From 950fef202ea5ef2406b6f3f4cc5ac63e390286f5 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 9 Jul 2021 04:39:43 +0200 Subject: [PATCH 12/96] And another. --- src/win/Makefile.mingw | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index c67fa66f6..e4e961306 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -634,7 +634,8 @@ ifeq ($(NEW_KBC), y) DEVOBJ := bugger.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ ibm_5161.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o \ vpc2007.o clock_ics9xxx.o isapnp.o \ - i2c.o i2c_gpio.o smbus_ali7101.o smbus_piix4.o \ + i2c.o i2c_gpio.o smbus_piix4.o \ + smbus_ali7101.o \ keyboard.o \ keyboard_xt.o kbc_at.o kbd_at.o \ mouse.o \ From 38fc26403cebf78a893e8d64d3bb9e571340cae7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 9 Jul 2021 04:40:42 +0200 Subject: [PATCH 13/96] And another. --- src/win/Makefile.mingw | 1 + 1 file changed, 1 insertion(+) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index e4e961306..0ca531268 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -631,6 +631,7 @@ MCHOBJ := machine.o machine_table.o \ m_at_misc.o ifeq ($(NEW_KBC), y) + DEVOBJ := bugger.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ ibm_5161.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o \ vpc2007.o clock_ics9xxx.o isapnp.o \ From 638dff832fffe9b53b03a6a80b334e537870b2f2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 9 Jul 2021 04:41:43 +0200 Subject: [PATCH 14/96] I have to do this. --- src/win/Makefile.mingw | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 0ca531268..9524aa123 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -630,8 +630,6 @@ MCHOBJ := machine.o machine_table.o \ m_at_socket8.o m_at_slot1.o m_at_slot2.o m_at_socket370.o \ m_at_misc.o -ifeq ($(NEW_KBC), y) - DEVOBJ := bugger.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ ibm_5161.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o \ vpc2007.o clock_ics9xxx.o isapnp.o \ @@ -643,6 +641,8 @@ DEVOBJ := bugger.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c68 mouse_bus.o \ mouse_serial.o mouse_ps2.o \ phoenix_486_jumper.o +ifeq ($(NEW_KBC), y) + else DEVOBJ := bugger.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ ibm_5161.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o \ From 99b9174e02e7b97bcd6599c5dfa04c4c291bdd07 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 9 Jul 2021 04:43:12 +0200 Subject: [PATCH 15/96] Back to normal. --- src/win/Makefile.mingw | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 9524aa123..c67fa66f6 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -630,19 +630,17 @@ MCHOBJ := machine.o machine_table.o \ m_at_socket8.o m_at_slot1.o m_at_slot2.o m_at_socket370.o \ m_at_misc.o +ifeq ($(NEW_KBC), y) DEVOBJ := bugger.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ ibm_5161.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o \ vpc2007.o clock_ics9xxx.o isapnp.o \ - i2c.o i2c_gpio.o smbus_piix4.o \ - smbus_ali7101.o \ + i2c.o i2c_gpio.o smbus_ali7101.o smbus_piix4.o \ keyboard.o \ keyboard_xt.o kbc_at.o kbd_at.o \ mouse.o \ mouse_bus.o \ mouse_serial.o mouse_ps2.o \ phoenix_486_jumper.o -ifeq ($(NEW_KBC), y) - else DEVOBJ := bugger.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ ibm_5161.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o \ From 9cba2a91dc98c8c1dc6b5ea32508cad105b74811 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 9 Jul 2021 04:46:08 +0200 Subject: [PATCH 16/96] Reverted the PIT and Soyo 4SA2 changes. --- src/acpi.c | 1 + src/include/86box/pit.h | 35 ++- src/machine/m_at_386dx_486.c | 9 +- src/pit.c | 469 ++++++++++------------------------- 4 files changed, 152 insertions(+), 362 deletions(-) diff --git a/src/acpi.c b/src/acpi.c index d8e6a12aa..d83b087bc 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -642,6 +642,7 @@ acpi_reg_write_common_regs(int size, uint16_t addr, uint8_t val, void *p) break; case 0x04: case 0x05: /* PMCNTRL - Power Management Control Register (IO) */ + pclog("addr = %02X, val = %02X\n", addr, val); if ((addr == 0x05) && (val & 0x20)) { sus_typ = (val >> 2) & 7; switch (sus_typ) { diff --git a/src/include/86box/pit.h b/src/include/86box/pit.h index 93f6c594e..bf8d71048 100644 --- a/src/include/86box/pit.h +++ b/src/include/86box/pit.h @@ -18,34 +18,33 @@ # define EMU_PIT_H -typedef struct ctr_s { +typedef struct { uint8_t m, ctrl, read_status, latch, s1_det, l_det, - bcd, flag_64k; + bcd, pad; - uint16_t l, rl; - - union { - uint16_t count; - struct { - uint16_t units :4; - uint16_t tens :4; - uint16_t hundreds :4; - uint16_t thousands :4; - uint16_t myriads :4; - }; - }; + uint16_t rl; int rm, wm, gate, out, newcount, clock, using_timer, latched, - state, null_count, do_read_status, do_load; + state, null_count, do_read_status; + + union { + int count; + struct { + int units :4; + int tens :4; + int hundreds :4; + int thousands :4; + int myriads :4; + }; + }; + + uint32_t l; - void (*tick_func)(struct ctr_s *ctr); void (*load_func)(uint8_t new_m, int new_count); void (*out_func)(int new_out, int old_out); - - struct PIT *pit; } ctr_t; diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index eb6efeb96..93d5d9499 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -990,13 +990,10 @@ machine_at_4sa2_init(const machine_t *model) pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); - // device_add(&w83787f_device); - device_add(&prime3b_device); - // device_add(&keyboard_ps2_pci_device); - device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83787f_device); + device_add(&keyboard_ps2_pci_device); - // device_add(&intel_flash_bxt_device); - device_add(&sst_flash_29ee010_device); + device_add(&intel_flash_bxt_device); return ret; } diff --git a/src/pit.c b/src/pit.c index fc1e91927..9db4c45dd 100644 --- a/src/pit.c +++ b/src/pit.c @@ -64,7 +64,6 @@ int64_t firsttime = 1; #define PIT_EXT_IO 32 /* The PIT has externally specified port I/O. */ #define PIT_CUSTOM_CLOCK 64 /* The PIT uses custom clock inputs provided by another provider. */ #define PIT_SECONDARY 128 /* The PIT is secondary (ports 0048-004B). */ -#define PIT_OLIVETTI 256 /* The PIT is that of the Olivetti 486 (has slight timing differences). */ enum { @@ -93,214 +92,67 @@ pit_log(const char *fmt, ...) #endif -#define NEW_PIT_CODE 1 - - -#ifdef NEW_PIT_CODE -typedef void (*tf_t)(ctr_t *ctr); - - -static void ctr_tick_mode_0(ctr_t *ctr); -static void ctr_tick_mode_1(ctr_t *ctr); -static void ctr_tick_mode_2_and_6(ctr_t *ctr); -static void ctr_tick_mode_3_and_7(ctr_t *ctr); -static void ctr_tick_mode_4_and_5(ctr_t *ctr); - - -static tf_t ctr_tick_funcs[8] = { ctr_tick_mode_0, ctr_tick_mode_1, ctr_tick_mode_2_and_6, - ctr_tick_mode_3_and_7, ctr_tick_mode_4_and_5, ctr_tick_mode_4_and_5, - ctr_tick_mode_2_and_6, ctr_tick_mode_3_and_7 }; - - -/* MODE 0: Interrupt on Terminal Count. */ static void -ctr_tick_mode_0(ctr_t *ctr) +ctr_set_out(ctr_t *ctr, int out) { - uint8_t state = ctr->state; + if (ctr == NULL) + return; - switch (state) { - case 1: - /* Load count. */ - ctr->count = ctr->l; - ctr->null_count = 0; - /* Switch to next state. */ - ctr->state++; - case 2: case 3: - if (ctr->gate) { - /* Decrease counter. */ - if ((state == 3) || ctr->gate) - ctr->count--; - if ((state == 2) && ctr->gate && (ctr->count == 0)) { - /* Terminal count reached, switch to next state. */ - ctr->state++; - /* Set output high. */ - if (ctr->out_func != NULL) - ctr->out_func(1, ctr->out); - ctr->out = 1; - } - } - break; - } -} - - -/* MODE 1: Programmale One-Shoft. */ -static void -ctr_tick_mode_1(ctr_t *ctr) -{ - uint8_t state = ctr->state; - - switch (state) { - case 1: - /* Load count. */ - ctr->count = ctr->l; - ctr->null_count = 0; - /* Switch to next state. */ - ctr->state++; - /* Set output low. */ - if (ctr->out_func != NULL) - ctr->out_func(0, ctr->out); - ctr->out = 0; - break; - case 2: case 3: - /* Decrease counter. */ - ctr->count--; - if ((state == 2) && (ctr->count == 0)) { - /* Terminal count reached, switch to next state. */ - ctr->state++; - /* Set output high. */ - if (ctr->out_func != NULL) - ctr->out_func(1, ctr->out); - ctr->out = 1; - } - break; - } + if (ctr->out_func != NULL) + ctr->out_func(out, ctr->out); + ctr->out = out; } static void -ctr_tick_mode_2_and_6(ctr_t *ctr) +ctr_decrease_count(ctr_t *ctr) { - uint8_t state = ctr->state; - - switch (state) { - case 1: case 3: - /* Load count. */ - ctr->count = ctr->l; - ctr->null_count = 0; - if (ctr->state == 3) { - /* Set output high. */ - if (ctr->out_func != NULL) - ctr->out_func(1, ctr->out); - ctr->out = 1; - } - /* Switch to next state. */ - ctr->state = 2; - break; - case 2: - /* Decrease counter. */ - if (ctr->gate) { - ctr->count--; - if (ctr->count == 1) { - /* Terminal count reached, switch to previous state. */ - ctr->state = 3; - /* Set output low. */ - if (ctr->out_func != NULL) - ctr->out_func(0, ctr->out); - ctr->out = 0; + if (ctr->bcd) { + ctr->units--; + if (ctr->units == 0xff) { + ctr->units = 9; + ctr->tens--; + if (ctr->tens == 0xff) { + ctr->tens = 9; + ctr->hundreds--; + if (ctr->hundreds == 0xff) { + ctr->hundreds = 9; + ctr->thousands--; + if (ctr->thousands == 0xff) { + ctr->thousands = 9; + ctr->myriads--; + if (ctr->myriads == 0xff) + ctr->myriads = 0; /* 0 - 1 should wrap around to 9999. */ + } } } - break; - } -} - - -static void -ctr_tick_mode_3_and_7(ctr_t *ctr) -{ - uint8_t state = ctr->state; - uint16_t old_count = ctr->count; - - switch (state) { - case 1: - /* Load count. */ - ctr->count = ctr->l; - ctr->flag_64k = !ctr->count; - ctr->null_count = 0; - ctr->newcount = ctr->count & 1; - /* Switch to next state. */ - ctr->state = 2; - case 2: case 3: - if (ctr->gate) { - ctr->count -= (ctr->newcount ? ((ctr->state == 3) ? 3 : 1) : 2); - if (!ctr->flag_64k && (ctr->count > old_count)) { - /* Load count. */ - ctr->count = ctr->l; - ctr->flag_64k = !ctr->count; - ctr->null_count = 0; - ctr->newcount = ctr->count & 1; - /* Switch to next state. */ - ctr->state ^= 1; - /* Set output low. */ - if (ctr->out_func != NULL) - ctr->out_func(state & 1, ctr->out); - ctr->out = state & 1; - } else { - if (ctr->newcount) - ctr->newcount = 0; - ctr->flag_64k = 0; - } - } - break; - } -} - - -static void -ctr_tick_mode_4_and_5(ctr_t *ctr) -{ - uint8_t state = ctr->state; - - /* Software triggered strobe */ - /* Hardware triggered strobe */ - if (ctr->gate || (ctr->m != 4)) { - switch(state) { - case 0: case 2: - ctr->count--; - if ((state == 2) && (ctr->count < 1)) { - ctr->state++; - if (ctr->out_func != NULL) - ctr->out_func(0, ctr->out); - ctr->out = 0; - } - break; - case 3: - ctr->state = 0; - if (ctr->out_func != NULL) - ctr->out_func(1, ctr->out); - ctr->out = 1; - break; } - } + } else + ctr->count = (ctr->count - 1) & 0xffff; } -#else + + +static void +ctr_load_count(ctr_t *ctr) +{ + int l = ctr->l ? ctr->l : 0x10000; + + ctr->count = l; + pit_log("ctr->count = %i\n", l); + ctr->null_count = 0; + ctr->newcount = !!(l & 1); +} + + static void ctr_tick(ctr_t *ctr) { uint8_t state = ctr->state; - uint16_t old_count = ctr->count; if (state == 1) { /* This is true for all modes */ - ctr->count = ctr->l; - ctr->null_count = 0; - ctr->newcount = !!(ctr->count & 1); - ctr->state++; - if ((ctr->m & 0x07) == 1) { - if (ctr->out_func != NULL) - ctr->out_func(0, ctr->out); - ctr->out = 0; - } + ctr_load_count(ctr); + ctr->state = 2; return; } @@ -309,35 +161,38 @@ ctr_tick(ctr_t *ctr) /* Interrupt on terminal count */ switch (state) { case 2: - if (ctr->gate) { - ctr->count--; + if (ctr->gate && (ctr->count >= 1)) { + ctr_decrease_count(ctr); if (ctr->count < 1) { - ctr->state++; - if (ctr->out_func != NULL) - ctr->out_func(1, ctr->out); - ctr->out = 1; + ctr->state = 3; + ctr_set_out(ctr, 1); } } break; case 3: - ctr->count--; + ctr_decrease_count(ctr); break; } break; case 1: /* Hardware retriggerable one-shot */ switch (state) { + case 1: + ctr_load_count(ctr); + ctr->state = 2; + ctr_set_out(ctr, 0); + break; case 2: - ctr->count--; - if (ctr->count < 1) { - ctr->state++; - if (ctr->out_func != NULL) - ctr->out_func(1, ctr->out); - ctr->out = 1; + if (ctr->count >= 1) { + ctr_decrease_count(ctr); + if (ctr->count < 1) { + ctr->state = 3; + ctr_set_out(ctr, 1); + } } break; case 3: - ctr->count--; + ctr_decrease_count(ctr); break; } break; @@ -345,40 +200,59 @@ ctr_tick(ctr_t *ctr) /* Rate generator */ switch (state) { case 3: - ctr->count = ctr->l; - ctr->null_count = 0; - ctr->state ^= 1; - if (ctr->out_func != NULL) - ctr->out_func(1, ctr->out); - ctr->out = 1; + ctr_load_count(ctr); + ctr->state = 2; + ctr_set_out(ctr, 1); break; case 2: - // if (ctr->gate) { - ctr->count--; + if (ctr->gate == 0) + break; + else if (ctr->count >= 2) { + ctr_decrease_count(ctr); if (ctr->count < 2) { - ctr->state ^= 1; - if (ctr->out_func != NULL) - ctr->out_func(0, ctr->out); - ctr->out = 0; + ctr->state = 3; + ctr_set_out(ctr, 0); } - // } + } break; } break; case 3: case 7: /* Square wave mode */ switch (state) { - case 2: case 3: - if (ctr->gate != 0) { - ctr->count -= (ctr->newcount ? ((state & 1) ? 3 : 1) : 2); - if (ctr->count > old_count) { - ctr->count = ctr->l; - ctr->null_count = 0; - ctr->newcount = !!(ctr->count & 1); - ctr->state ^= 1; - if (ctr->out_func != NULL) - ctr->out_func(0, ctr->out); - ctr->out = 0; + case 2: + if (ctr->gate == 0) + break; + else if (ctr->count >= 0) { + if (ctr->bcd) { + ctr_decrease_count(ctr); + if (!ctr->newcount) + ctr_decrease_count(ctr); + } else + ctr->count -= (ctr->newcount ? 1 : 2); + if (ctr->count < 0) { + ctr_load_count(ctr); + ctr->state = 3; + ctr_set_out(ctr, 0); + } else if (ctr->newcount) + ctr->newcount = 0; + } + break; + case 3: + if (ctr->gate == 0) + break; + else if (ctr->count >= 0) { + if (ctr->bcd) { + ctr_decrease_count(ctr); + ctr_decrease_count(ctr); + if (ctr->newcount) + ctr_decrease_count(ctr); + } else + ctr->count -= (ctr->newcount ? 3 : 2); + if (ctr->count < 0) { + ctr_load_count(ctr); + ctr->state = 2; + ctr_set_out(ctr, 1); } else if (ctr->newcount) ctr->newcount = 0; } @@ -390,20 +264,21 @@ ctr_tick(ctr_t *ctr) /* Hardware triggered strobe */ if ((ctr->gate != 0) || (ctr->m != 4)) { switch(state) { - case 0: case 2: - ctr->count--; - if ((state == 2) && (ctr->count < 1)) { - ctr->state++; - if (ctr->out_func != NULL) - ctr->out_func(0, ctr->out); - ctr->out = 0; + case 0: + ctr_decrease_count(ctr); + break; + case 2: + if (ctr->count >= 1) { + ctr_decrease_count(ctr); + if (ctr->count < 1) { + ctr->state = 3; + ctr_set_out(ctr, 0); + } } break; case 3: ctr->state = 0; - if (ctr->out_func != NULL) - ctr->out_func(1, ctr->out); - ctr->out = 1; + ctr_set_out(ctr, 1); break; } } @@ -412,24 +287,19 @@ ctr_tick(ctr_t *ctr) break; } } -#endif static void ctr_clock(ctr_t *ctr) { - /* FIXME: Is this even needed? */ + /* FIXME: Is this even needed? */ if ((ctr->state == 3) && (ctr->m != 2) && (ctr->m != 3)) return; if (ctr->using_timer) return; -#ifdef NEW_PIT_CODE - ctr->tick_func(ctr); -#else ctr_tick(ctr); -#endif } @@ -480,11 +350,6 @@ ctr_latch_count(ctr_t *ctr) { int count = (ctr->latch || (ctr->state == 1)) ? ctr->l : ctr->count; - // if ((ctr->pit->flags & PIT_OLIVETTI) && (ctr->state == 0)) - // count--; - - pit_log("PIT latch count with state %i (%i)\n", ctr->state, ctr->latch); - switch (ctr->rm & 0x03) { case 0x00: /* This should never happen. */ @@ -550,21 +415,15 @@ pit_ctr_set_gate(ctr_t *ctr, int gate) if (!old && gate) { /* Here we handle the rising edges. */ if (mode & 1) { - if (mode != 1) { - if (ctr->out_func != NULL) - ctr->out_func(1, ctr->out); - ctr->out = 1; - } + if (mode != 1) + ctr_set_out(ctr, 1); ctr->state = 1; } else if (mode == 2) ctr->state = 3; } else if (old && !gate) { /* Here we handle the lowering edges. */ - if (mode & 2) { - if (ctr->out_func != NULL) - ctr->out_func(1, ctr->out); - ctr->out = 1; - } + if (mode & 2) + ctr_set_out(ctr, 1); } break; } @@ -578,27 +437,12 @@ pit_ctr_set_clock_common(ctr_t *ctr, int clock) ctr->clock = clock; - if (!ctr->using_timer) - return; - -#if 0 - if ((ctr->pit->flags & PIT_OLIVETTI) && !old && ctr->clock) { - if (ctr->do_load) { - if (ctr->do_load == 3) - ctr_load(ctr); - ctr->do_load++; - if (ctr->do_load == 4) - ctr->do_load = 0; - } - } -#endif - - if (ctr->latch) { + if (ctr->using_timer && ctr->latch) { if (old && !ctr->clock) { ctr_set_state_1(ctr); ctr->latch = 0; } - } else if (!ctr->latch) { + } else if (ctr->using_timer && !ctr->latch) { if (ctr->state == 1) { if (!old && ctr->clock) ctr->s1_det = 1; /* Rising edge. */ @@ -606,19 +450,11 @@ pit_ctr_set_clock_common(ctr_t *ctr, int clock) ctr->s1_det++; /* Falling edge. */ if (ctr->s1_det >= 2) { ctr->s1_det = 0; -#ifdef NEW_PIT_CODE - ctr->tick_func(ctr); -#else ctr_tick(ctr); -#endif } } } else if (old && !ctr->clock) -#ifdef NEW_PIT_CODE - ctr->tick_func(ctr); -#else ctr_tick(ctr); -#endif } } @@ -702,14 +538,9 @@ pit_write(uint16_t addr, uint8_t val, void *priv) ctr->m = (val >> 1) & 7; if (ctr->m > 5) ctr->m &= 3; -#ifdef NEW_PIT_CODE - ctr->tick_func = ctr_tick_funcs[ctr->m]; -#endif ctr->null_count = 1; ctr->bcd = (ctr->ctrl & 0x01); - if (ctr->out_func != NULL) - ctr->out_func(!!ctr->m, ctr->out); - ctr->out = !!ctr->m; + ctr_set_out(ctr, !!ctr->m); ctr->state = 0; if (ctr->latched) { pit_log("PIT %i: Reload while counter is latched\n", t); @@ -732,44 +563,27 @@ pit_write(uint16_t addr, uint8_t val, void *priv) break; case 1: ctr->l = val; - if (ctr->m == 0) { - if (ctr->out_func != NULL) - ctr->out_func(0, ctr->out); - ctr->out = 0; - } - if (dev->flags & PIT_OLIVETTI) - ctr->do_load = 1; - else - ctr_load(ctr); + if (ctr->m == 0) + ctr_set_out(ctr, 0); + ctr_load(ctr); break; case 2: ctr->l = (val << 8); - if (ctr->m == 0) { - if (ctr->out_func != NULL) - ctr->out_func(0, ctr->out); - ctr->out = 0; - } - if (dev->flags & PIT_OLIVETTI) - ctr->do_load = 1; - else - ctr_load(ctr); + if (ctr->m == 0) + ctr_set_out(ctr, 0); + ctr_load(ctr); break; case 3: case 0x83: if (ctr->wm & 0x80) { ctr->l = (ctr->l & 0x00ff) | (val << 8); pit_log("PIT %i: Written high byte %02X, latch now %04X\n", t, val, ctr->l); - if (dev->flags & PIT_OLIVETTI) - ctr->do_load = 1; - else - ctr_load(ctr); + ctr_load(ctr); } else { ctr->l = (ctr->l & 0xff00) | val; pit_log("PIT %i: Written low byte %02X, latch now %04X\n", t, val, ctr->l); if (ctr->m == 0) { ctr->state = 0; - if (ctr->out_func != NULL) - ctr->out_func(0, ctr->out); - ctr->out = 0; + ctr_set_out(ctr, 0); } } @@ -943,7 +757,7 @@ pit_nmi_timer_ps2(int new_out, int old_out) static void -ctr_reset(pit_t *dev, ctr_t *ctr) +ctr_reset(ctr_t *ctr) { ctr->ctrl = 0; ctr->m = 0; @@ -957,8 +771,6 @@ ctr_reset(pit_t *dev, ctr_t *ctr) ctr->s1_det = 0; ctr->l_det = 0; - - ctr->pit = dev; } @@ -972,15 +784,10 @@ pit_reset(pit_t *dev) dev->clock = 0; for (i = 0; i < 3; i++) - ctr_reset(dev, &dev->counters[i]); + ctr_reset(&dev->counters[i]); /* Disable speaker gate. */ dev->counters[2].gate = 0; - -#ifdef NEW_PIT_CODE - dev->counters[0].tick_func = dev->counters[1].tick_func = - dev->counters[2].tick_func = ctr_tick_funcs[0]; -#endif } @@ -1051,17 +858,6 @@ const device_t i8254_device = }; -const device_t i8254_olivetti_device = -{ - "Intel 8254 Programmable Interval Timer (Olivetti)", - DEVICE_ISA, - PIT_8254 | PIT_OLIVETTI, - pit_init, pit_close, NULL, - { NULL }, NULL, NULL, - NULL -}; - - const device_t i8254_sec_device = { "Intel 8254 Programmable Interval Timer (Secondary)", @@ -1108,9 +904,6 @@ pit_common_init(int type, void (*out0)(int new_out, int old_out), void (*out1)(i case PIT_8254: pit = device_add(&i8254_device); break; - case (PIT_8254 | PIT_OLIVETTI): - pit = device_add(&i8254_olivetti_device); - break; } for (i = 0; i < 3; i++) { From 3fa7579d66228db1d21c7a875f7fa5ca49fa2ad8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 9 Jul 2021 04:47:02 +0200 Subject: [PATCH 17/96] Reverted excess ACPI logging. --- src/acpi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/acpi.c b/src/acpi.c index d83b087bc..d8e6a12aa 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -642,7 +642,6 @@ acpi_reg_write_common_regs(int size, uint16_t addr, uint8_t val, void *p) break; case 0x04: case 0x05: /* PMCNTRL - Power Management Control Register (IO) */ - pclog("addr = %02X, val = %02X\n", addr, val); if ((addr == 0x05) && (val & 0x20)) { sus_typ = (val >> 2) & 7; switch (sus_typ) { From dbddb3e30979cc8cedaae08b80fa39615ba1c264 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 12 Jul 2021 05:56:06 +0200 Subject: [PATCH 18/96] Finished the ALADDiN-PRO II, implemented the Contaq/Cypress 82C596(A) and 82C597 chipsets, added the ASUS P5A, Gigabyte GA-5AX, PC CHIPS M729, and Green-B, removed the "Virtual PC 2007" device as it turns out it was actually SMBus all along, did some fixes to the ALi SMBUS, fixed start LM75 SMBus address and enabled it by default, and added a ASUS P5A-specific version of the Winbond W83781D hardware monitor. --- src/chipset/CMakeLists.txt | 12 +- src/chipset/ali1543.c | 37 +-- src/chipset/ali1621.c | 436 ++++++++++++++------------------ src/chipset/contaq_82c59x.c | 476 +++++++++++++++++++++++++++++++++++ src/device/CMakeLists.txt | 2 +- src/device/hwm_lm75.c | 3 + src/device/hwm_lm78.c | 21 +- src/device/pci_bridge.c | 46 +++- src/device/smbus_ali7101.c | 4 +- src/device/vpc2007.c | 186 -------------- src/include/86box/chipset.h | 5 + src/include/86box/hwm.h | 1 + src/include/86box/machine.h | 5 + src/include/86box/mem.h | 11 + src/include/86box/pci.h | 1 + src/include/86box/spd.h | 1 + src/machine/m_at_386dx_486.c | 26 +- src/machine/m_at_misc.c | 1 - src/machine/m_at_slot1.c | 33 +++ src/machine/m_at_sockets7.c | 73 ++++++ src/machine/machine_table.c | 11 + src/mem/mem.c | 11 +- src/mem/spd.c | 87 ++++++- src/win/Makefile.mingw | 7 +- 24 files changed, 1007 insertions(+), 489 deletions(-) create mode 100644 src/chipset/contaq_82c59x.c delete mode 100644 src/device/vpc2007.c diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index ead771da7..14ca76962 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -14,12 +14,12 @@ # add_library(chipset OBJECT acc2168.c cs8230.c ali1217.c ali1429.c ali1489.c ali1531.c ali1541.c - ali1543.c headland.c intel_82335.c cs4031.c intel_420ex.c intel_4x0.c intel_sio.c intel_piix.c - ../ioapic.c neat.c opti283.c opti291.c opti391.c opti495.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 sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c - gc100.c stpc.c - via_apollo.c via_pipc.c vl82c480.c wd76c10.c) + ali1543.c ali1621.c headland.c intel_82335.c contaq_82c59x.c cs4031.c intel_420ex.c + intel_4x0.c intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c + opti495.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 sis_85c310.c + sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c stpc.c via_apollo.c via_pipc.c vl82c480.c + wd76c10.c) if(I450KX) target_sources(chipset PRIVATE intel_i450kx.c) diff --git a/src/chipset/ali1543.c b/src/chipset/ali1543.c index bec3663cc..5e43ec9fd 100644 --- a/src/chipset/ali1543.c +++ b/src/chipset/ali1543.c @@ -295,7 +295,6 @@ ali1533_write(int func, int addr, uint8_t val, void *priv) break; } ali1543_log("IDE slot = %02X (A%0i)\n", dev->ide_slot - 5, dev->ide_slot + 11); - pclog("IDE slot = %02X (A%0i)\n", dev->ide_slot - 5, dev->ide_slot + 11); ali5229_ide_irq_handler(dev); break; @@ -365,7 +364,6 @@ ali1533_write(int func, int addr, uint8_t val, void *priv) break; } ali1543_log("PMU slot = %02X (A%0i)\n", dev->pmu_slot - 5, dev->pmu_slot + 11); - pclog("PMU slot = %02X (A%0i)\n", dev->pmu_slot - 5, dev->pmu_slot + 11); switch (val & 0x03) { case 0x00: dev->usb_slot = 0x14; /* A31 = slot 20 */ @@ -381,7 +379,6 @@ ali1533_write(int func, int addr, uint8_t val, void *priv) break; } ali1543_log("USB slot = %02X (A%0i)\n", dev->usb_slot - 5, dev->usb_slot + 11); - pclog("USB slot = %02X (A%0i)\n", dev->usb_slot - 5, dev->usb_slot + 11); break; case 0x73: /* DDMA Base Address */ @@ -424,7 +421,7 @@ ali1533_write(int func, int addr, uint8_t val, void *priv) case 0x78: if (dev->type == 1) { - pclog("PCI78 = %02X\n", val); + ali1543_log("PCI78 = %02X\n", val); dev->pci_conf[addr] = val & 0x33; } break; @@ -557,10 +554,10 @@ ali5229_ide_handler(ali1543_t *dev) { uint32_t ch = 0; - uint16_t native_base_pri_addr = (dev->ide_conf[0x11] | dev->ide_conf[0x10] << 8); - uint16_t native_side_pri_addr = (dev->ide_conf[0x15] | dev->ide_conf[0x14] << 8); - uint16_t native_base_sec_addr = (dev->ide_conf[0x19] | dev->ide_conf[0x18] << 8); - uint16_t native_side_sec_addr = (dev->ide_conf[0x1c] | dev->ide_conf[0x1b] << 8); + uint16_t native_base_pri_addr = ((dev->ide_conf[0x11] | dev->ide_conf[0x10] << 8)) & 0xfffe; + uint16_t native_side_pri_addr = ((dev->ide_conf[0x15] | dev->ide_conf[0x14] << 8)) & 0xfffe; + uint16_t native_base_sec_addr = ((dev->ide_conf[0x19] | dev->ide_conf[0x18] << 8)) & 0xfffe; + uint16_t native_side_sec_addr = ((dev->ide_conf[0x1c] | dev->ide_conf[0x1b] << 8)) & 0xfffe; uint16_t comp_base_pri_addr = 0x01f0; uint16_t comp_side_pri_addr = 0x03f6; @@ -597,7 +594,7 @@ ali5229_ide_handler(ali1543_t *dev) if (dev->ide_conf[0x04] & 0x01) { /* Primary Channel Setup */ - if (dev->ide_conf[0x09] & 0x20) { + if ((dev->ide_conf[0x09] & 0x20) || (dev->ide_conf[0x4d] & 0x80)) { ali1543_log("ali5229_ide_handler(): Primary IDE base now %04X...\n", current_pri_base); ide_set_base(0, current_pri_base); ali1543_log("ali5229_ide_handler(): Primary IDE side now %04X...\n", current_pri_side); @@ -611,7 +608,7 @@ ali5229_ide_handler(ali1543_t *dev) } /* Secondary Channel Setup */ - if (dev->ide_conf[0x09] & 0x10) { + if ((dev->ide_conf[0x09] & 0x10) || (dev->ide_conf[0x4d] & 0x80)) { ali1543_log("ali5229_ide_handler(): Secondary IDE base now %04X...\n", current_sec_base); ide_set_base(1, current_sec_base); ali1543_log("ali5229_ide_handler(): Secondary IDE side now %04X...\n", current_sec_side); @@ -650,8 +647,8 @@ ali5229_chip_reset(ali1543_t *dev) dev->ide_conf[0x15] = 0x03; dev->ide_conf[0x18] = 0x71; dev->ide_conf[0x19] = 0x01; - dev->ide_conf[0x1a] = 0x75; - dev->ide_conf[0x1b] = 0x03; + dev->ide_conf[0x1c] = 0x75; + dev->ide_conf[0x1d] = 0x03; dev->ide_conf[0x20] = 0x01; dev->ide_conf[0x21] = 0xf0; dev->ide_conf[0x3d] = 0x01; @@ -667,12 +664,13 @@ ali5229_chip_reset(ali1543_t *dev) if (dev->type == 1) { dev->ide_conf[0x08] = 0xc1; + dev->ide_conf[0x43] = 0x00; dev->ide_conf[0x4b] = 0x4a; dev->ide_conf[0x4e] = 0xba; dev->ide_conf[0x4f] = 0x1a; } - ali5229_write(0, 0x04, 0x00 /*0x01*/, dev); + ali5229_write(0, 0x04, 0x05, dev); ali5229_write(0, 0x10, 0xf1, dev); ali5229_write(0, 0x11, 0x01, dev); ali5229_write(0, 0x14, 0xf5, dev); @@ -742,10 +740,12 @@ ali5229_write(int func, int addr, uint8_t val, void *priv) break; /* Primary Base Address */ - case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: + case 0x10: case 0x11: case 0x14: case 0x15: + /* FALLTHROUGH */ /* Secondary Base Address */ - case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: + case 0x18: case 0x19: case 0x1c: case 0x1d: + /* FALLTHROUGH */ /* Bus Mastering Base Address */ case 0x20: case 0x21: case 0x22: case 0x23: @@ -779,6 +779,7 @@ ali5229_write(int func, int addr, uint8_t val, void *priv) case 0x4d: dev->ide_conf[addr] = val & 0x80; + ali5229_ide_handler(dev); break; case 0x4f: @@ -969,7 +970,7 @@ ali7101_write(int func, int addr, uint8_t val, void *priv) else if (addr == 0x11) dev->pmu_conf[addr] = val; - pclog("New ACPI base address: %08X\n", (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0)); + ali1543_log("New ACPI base address: %08X\n", (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0)); acpi_update_io_mapping(dev->acpi, (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0), dev->pmu_conf[0x04] & 1); } break; @@ -986,10 +987,10 @@ ali7101_write(int func, int addr, uint8_t val, void *priv) dev->pmu_conf[addr] = val; if (dev->type == 1) { - pclog("New SMBUS base address: %08X\n", (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xc0)); + ali1543_log("New SMBUS base address: %08X\n", (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xc0)); smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xc0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1)); } else { - pclog("New SMBUS base address: %08X\n", (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0)); + ali1543_log("New SMBUS base address: %08X\n", (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0)); smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1)); } } diff --git a/src/chipset/ali1621.c b/src/chipset/ali1621.c index 97fbeb522..cc83899e8 100644 --- a/src/chipset/ali1621.c +++ b/src/chipset/ali1621.c @@ -36,8 +36,7 @@ typedef struct ali1621_t { uint8_t pci_conf[256]; - smram_t * smram; - void * agp_bridge; + smram_t * smram[2]; } ali1621_t; @@ -60,34 +59,80 @@ ali1621_log(const char *fmt, ...) #endif +/* Table translated to a more sensible format: + Read cycles: + SMREN SMM Mode Code Data + 0 X X PCI PCI + 1 0 Close PCI PCI + 1 0 Lock PCI PCI + 1 0 Protect PCI PCI + 1 0 Open DRAM DRAM + 1 1 Open DRAM DRAM + 1 1 Protect DRAM DRAM + 1 1 Close DRAM PCI + 1 1 Lock DRAM PCI + + Write cycles: + SMWEN SMM Mode Data + 0 X X PCI + 1 0 Close PCI + 1 0 Lock PCI + 1 0 Protect PCI + 1 0 Open DRAM + 1 1 Open DRAM + 1 1 Protect DRAM + 1 1 Close PCI + 1 1 Lock PCI + + Explanation of the modes based above: + If SM*EN = 0, SMRAM is entirely disabled, otherwise: + If mode is Close or Lock, then SMRAM always goes to PCI outside SMM, + and data to PCI, code to DRAM in SMM; + If mode is Protect, then SMRAM always goes to PCI outside SMM and + DRAM in SMM; + If mode is Open, then SMRAM always goes to DRAM. + Read and write are enabled separately. + */ static void ali1621_smram_recalc(uint8_t val, ali1621_t *dev) { + uint16_t access_smm = 0x0000, access_normal = 0x0000; + smram_disable_all(); - if (val & 1) { - switch (val & 0x0c) { - case 0x00: - ali1621_log("SMRAM: D0000 -> B0000 (%i)\n", val & 2); - smram_enable(dev->smram, 0xd0000, 0xb0000, 0x10000, val & 2, 1); - if (val & 0x10) - mem_set_mem_state_smram_ex(1, 0xd0000, 0x10000, 0x02); - break; - case 0x04: - ali1621_log("SMRAM: A0000 -> A0000 (%i)\n", val & 2); - smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, val & 2, 1); - if (val & 0x10) - mem_set_mem_state_smram_ex(1, 0xa0000, 0x20000, 0x02); - break; - case 0x08: - ali1621_log("SMRAM: 30000 -> B0000 (%i)\n", val & 2); - smram_enable(dev->smram, 0x30000, 0xb0000, 0x10000, val & 2, 1); - if (val & 0x10) - mem_set_mem_state_smram_ex(1, 0x30000, 0x10000, 0x02); + if (val & 0xc0) { + /* SMRAM 0: A0000-BFFFF */ + if (val & 0x80) { + access_smm = ACCESS_SMRAM_X; + + switch (val & 0x30) { + case 0x10: /* Open. */ + access_normal = ACCESS_SMRAM_RX; + /* FALLTHROUGH */ + case 0x30: /* Protect. */ + access_smm |= ACCESS_SMRAM_R; + break; + } + } + + if (val & 0x40) switch (val & 0x30) { + case 0x10: /* Open. */ + access_normal |= ACCESS_SMRAM_W; + /* FALLTHROUGH */ + case 0x30: /* Protect. */ + access_smm |= ACCESS_SMRAM_W; break; } + + smram_enable(dev->smram[0], 0xa0000, 0xa0000, 0x20000, ((val & 0x30) == 0x10), (val & 0x30)); + + mem_set_access(ACCESS_NORMAL, 3, 0xa0000, 0x20000, access_normal); + mem_set_access(ACCESS_SMM, 3, 0xa0000, 0x20000, access_smm); } + if (val & 0x08) + smram_enable(dev->smram[1], 0x38000, 0xa8000, 0x08000, 0, 1); + flushmmucache_nopc(); } @@ -95,32 +140,61 @@ ali1621_smram_recalc(uint8_t val, ali1621_t *dev) static void ali1621_shadow_recalc(int cur_reg, ali1621_t *dev) { - int i, bit, r_reg, w_reg; + int i, r_bit, w_bit, reg; uint32_t base, flags = 0; shadowbios = shadowbios_write = 0; - for (i = 0; i < 16; i++) { + /* C0000-EFFFF */ + for (i = 0; i < 12; i++) { base = 0x000c0000 + (i << 14); - bit = i & 7; - r_reg = 0x56 + (i >> 3); - w_reg = 0x58 + (i >> 3); + r_bit = (i << 1) + 4; + reg = 0x84; + if (r_bit > 23) { + r_bit &= 7; + reg += 3; + } else if (r_bit > 15) { + r_bit &= 7; + reg += 2; + } else if (r_bit > 7) { + r_bit &= 7; + reg++; + } + w_bit = r_bit + 1; - flags = (dev->pci_conf[r_reg] & (1 << bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - flags |= ((dev->pci_conf[w_reg] & (1 << bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY); + flags = (dev->pci_conf[reg] & (1 << r_bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + flags |= ((dev->pci_conf[reg] & (1 << w_bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY); if (base >= 0x000e0000) { - if (dev->pci_conf[r_reg] & (1 << bit)) + if (dev->pci_conf[reg] & (1 << r_bit)) shadowbios |= 1; - if (dev->pci_conf[w_reg] & (1 << bit)) + if (dev->pci_conf[reg] & (1 << r_bit)) shadowbios_write |= 1; } ali1621_log("%08X-%08X shadow: R%c, W%c\n", base, base + 0x00003fff, - (dev->pci_conf[r_reg] & (1 << bit)) ? 'I' : 'E', (dev->pci_conf[w_reg] & (1 << bit)) ? 'I' : 'E'); + (dev->pci_conf[reg] & (1 << r_bit)) ? 'I' : 'E', (dev->pci_conf[reg] & (1 << w_bit)) ? 'I' : 'E'); mem_set_mem_state_both(base, 0x00004000, flags); } + /* F0000-FFFFF */ + base = 0x000f0000; + r_bit = 4; + w_bit = 5; + reg = 0x87; + + flags = (dev->pci_conf[reg] & (1 << r_bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + flags |= ((dev->pci_conf[reg] & (1 << w_bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY); + + if (dev->pci_conf[reg] & (1 << r_bit)) + shadowbios |= 1; + if (dev->pci_conf[reg] & (1 << r_bit)) + shadowbios_write |= 1; + + ali1621_log("%08X-%08X shadow: R%c, W%c\n", base, base + 0x0000ffff, + (dev->pci_conf[reg] & (1 << r_bit)) ? 'I' : 'E', (dev->pci_conf[reg] & (1 << w_bit)) ? 'I' : 'E'); + mem_set_mem_state_both(base, 0x00010000, flags); + flushmmucache_nopc(); } @@ -348,7 +422,7 @@ ali1621_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf[addr] = val; break; - case 0x6c ... case 0x7b: + case 0x6c ... 0x7b: /* Bits 22:20 = DRAM Row size: - 000: 4 MB; - 001: 8 MB; @@ -359,6 +433,7 @@ ali1621_write(int func, int addr, uint8_t val, void *priv) - 110: 256 MB; - 111: Reserved. */ dev->pci_conf[addr] = val; + spd_write_drbs_ali1621(dev->pci_conf, 0x6c, 0x7b); break; case 0x7c ... 0x7f: @@ -376,148 +451,53 @@ ali1621_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf[addr] = val & 0xf7; break; - case 0x54: - dev->pci_conf[addr] = val & 0x3c; - - if (mem_size > 0xe00000) - mem_set_mem_state_both(0xe00000, 0x100000, (val & 0x20) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); - - if (mem_size > 0xf00000) - mem_set_mem_state_both(0xf00000, 0x100000, (val & 0x10) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); - - mem_set_mem_state_both(0xa0000, 0x20000, (val & 8) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); - mem_set_mem_state_both(0x80000, 0x20000, (val & 4) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); - - flushmmucache_nopc(); + case 0x83: + dev->pci_conf[addr] = val & 0xfc; + ali1621_smram_recalc(val & 0xfc, dev); break; - case 0x55: /* SMRAM */ - dev->pci_conf[addr] = val & 0x1f; - ali1621_smram_recalc(val, dev); - break; - - case 0x56 ... 0x59: /* Shadow RAM */ - dev->pci_conf[addr] = val; + case 0x84 ... 0x87: + if (addr == 0x87) + dev->pci_conf[addr] = val & 0x3f; + else + dev->pci_conf[addr] = val; ali1621_shadow_recalc(val, dev); break; - case 0x5a: case 0x5b: + case 0x88: case 0x89: dev->pci_conf[addr] = val; break; - - case 0x5c: - dev->pci_conf[addr] = val; - break; - - case 0x5d: - dev->pci_conf[addr] = val & 0x17; - break; - - case 0x5e: - dev->pci_conf[addr] = val; - break; - - case 0x5f: - dev->pci_conf[addr] = val & 0xc1; - break; - - case 0x60 ... 0x6f: /* DRB's */ - dev->pci_conf[addr] = val; - spd_write_drbs_interleaved(dev->pci_conf, 0x60, 0x6f, 1); - break; - - case 0x70: - dev->pci_conf[addr] = val; - break; - - case 0x71: - dev->pci_conf[addr] = val; - break; - - case 0x72: - dev->pci_conf[addr] = val & 0xc7; - break; - - case 0x73: - dev->pci_conf[addr] = val & 0x1f; - break; - - case 0x84: case 0x85: - dev->pci_conf[addr] = val; - break; - - case 0x86: - dev->pci_conf[addr] = val & 0x0f; - break; - - case 0x87: /* H2PO */ - dev->pci_conf[addr] = val; - /* Find where the Shut-down Special cycle is initiated. */ - // if (!(val & 0x20)) - // outb(0x92, 0x01); - break; - - case 0x88: - dev->pci_conf[addr] = val; - break; - - case 0x89: - dev->pci_conf[addr] = val; - break; - case 0x8a: - dev->pci_conf[addr] = val; + dev->pci_conf[addr] = val & 0xc5; break; - case 0x8b: - dev->pci_conf[addr] = val & 0x3f; + dev->pci_conf[addr] = val & 0xbf; break; - case 0x8c: - dev->pci_conf[addr] = val; - break; - - case 0x8d: - dev->pci_conf[addr] = val; - break; - - case 0x8e: - dev->pci_conf[addr] = val; - break; - - case 0x8f: + case 0x8c ... 0x8f: dev->pci_conf[addr] = val; break; case 0x90: dev->pci_conf[addr] = val; - pci_bridge_set_ctl(dev->agp_bridge, val); + break; + case 0x91: + dev->pci_conf[addr] = val & 0x07; break; - case 0x91: + case 0x94 ... 0x97: dev->pci_conf[addr] = val; break; - case 0xb4: - if (dev->pci_conf[0x90] & 0x01) - dev->pci_conf[addr] = val & 0x03; - break; - case 0xb5: - if (dev->pci_conf[0x90] & 0x01) - dev->pci_conf[addr] = val & 0x02; - break; - case 0xb7: - if (dev->pci_conf[0x90] & 0x01) - dev->pci_conf[addr] = val; + case 0x98 ... 0x9b: + dev->pci_conf[addr] = val; break; - case 0xb8: - dev->pci_conf[addr] = val & 0x03; + case 0x9c ... 0x9f: + dev->pci_conf[addr] = val; break; - case 0xb9: - dev->pci_conf[addr] = val & 0x03; - break; - case 0xbb: + + case 0xa0: case 0xa1: dev->pci_conf[addr] = val; break; @@ -533,99 +513,53 @@ ali1621_write(int func, int addr, uint8_t val, void *priv) break; case 0xc0: - dev->pci_conf[addr] = val & 0x90; + dev->pci_conf[addr] = val & 0xb1; break; - case 0xc1: case 0xc2: - case 0xc3: + + case 0xc4 ... 0xc7: dev->pci_conf[addr] = val; break; - case 0xc8: case 0xc9: + case 0xc8: + dev->pci_conf[addr] = val & 0x8c; + break; + case 0xc9: + dev->pci_conf[addr] = val; + break; + case 0xca: + dev->pci_conf[addr] = val & 0x7f; + break; + case 0xcb: + dev->pci_conf[addr] = val & 0x87; + break; + + case 0xcc ... 0xcf: dev->pci_conf[addr] = val; break; - case 0xd1: - dev->pci_conf[addr] = val & 0xf1; + case 0xd0: + dev->pci_conf[addr] = val & 0x80; break; - case 0xd2: case 0xd3: + case 0xd2: + dev->pci_conf[addr] = val & 0x40; + break; + case 0xd3: + dev->pci_conf[addr] = val & 0xb0; + break; + + case 0xd4: + dev->pci_conf[addr] = val; + break; + case 0xd5: + dev->pci_conf[addr] = val & 0xef; + break; + case 0xd6: case 0xd7: dev->pci_conf[addr] = val; break; - case 0xe0: case 0xe1: - if (dev->pci_conf[0x90] & 0x20) - dev->pci_conf[addr] = val; - break; - case 0xe2: - if (dev->pci_conf[0x90] & 0x20) - dev->pci_conf[addr] = val & 0x3f; - break; - case 0xe3: - if (dev->pci_conf[0x90] & 0x20) - dev->pci_conf[addr] = val & 0xfe; - break; - - case 0xe4: - if (dev->pci_conf[0x90] & 0x20) - dev->pci_conf[addr] = val & 0x03; - break; - case 0xe5: - if (dev->pci_conf[0x90] & 0x20) - dev->pci_conf[addr] = val; - break; - - case 0xe6: - if (dev->pci_conf[0x90] & 0x20) - dev->pci_conf[addr] = val & 0xc0; - break; - - case 0xe7: - if (dev->pci_conf[0x90] & 0x20) - dev->pci_conf[addr] = val; - break; - - case 0xe8: case 0xe9: - if (dev->pci_conf[0x90] & 0x04) - dev->pci_conf[addr] = val; - break; - - case 0xea: - dev->pci_conf[addr] = val & 0xcf; - break; - - case 0xeb: - dev->pci_conf[addr] = val & 0xcf; - break; - - case 0xec: - dev->pci_conf[addr] = val & 0x3f; - break; - - case 0xed: + case 0xf0 ... 0xff: dev->pci_conf[addr] = val; break; - - case 0xee: - dev->pci_conf[addr] = val & 0x3e; - break; - case 0xef: - dev->pci_conf[addr] = val; - break; - - case 0xf3: - dev->pci_conf[addr] = val & 0x08; - break; - - case 0xf5: - dev->pci_conf[addr] = val; - break; - - case 0xf6: - dev->pci_conf[addr] = val; - break; - - case 0xf7: - dev->pci_conf[addr] = val & 0x43; - break; } } @@ -683,35 +617,26 @@ ali1621_reset(void *priv) dev->pci_conf[0x7e] = 0xc7; dev->pci_conf[0x80] = 0x01; dev->pci_conf[0x81] = 0xc0; - - dev->pci_conf[0x89] = 0x20; - dev->pci_conf[0x8a] = 0x20; - dev->pci_conf[0x91] = 0x13; + dev->pci_conf[0x8e] = 0x01; + dev->pci_conf[0xa0] = 0x20; dev->pci_conf[0xb0] = 0x02; - dev->pci_conf[0xb1] = 0xe0; dev->pci_conf[0xb2] = 0x10; dev->pci_conf[0xb4] = 0x03; dev->pci_conf[0xb5] = 0x02; - dev->pci_conf[0xb7] = 0x1c; - dev->pci_conf[0xc8] = 0xbf; - dev->pci_conf[0xc9] = 0x0a; - dev->pci_conf[0xe0] = 0x01; + dev->pci_conf[0xb7] = 0x20; + dev->pci_conf[0xc0] = 0x80; + dev->pci_conf[0xc9] = 0x28; + dev->pci_conf[0xd4] = 0x10; + dev->pci_conf[0xd5] = 0x01; + dev->pci_conf[0xf0] = dev->pci_conf[0xf4] = dev->pci_conf[0xf8] = dev->pci_conf[0xfc] = 0x20; + dev->pci_conf[0xf1] = dev->pci_conf[0xf5] = dev->pci_conf[0xf9] = dev->pci_conf[0xfd] = 0x43; + dev->pci_conf[0xf2] = dev->pci_conf[0xf6] = dev->pci_conf[0xfa] = dev->pci_conf[0xfe] = 0x21; + dev->pci_conf[0xf3] = dev->pci_conf[0xf7] = dev->pci_conf[0xfb] = dev->pci_conf[0xff] = 0x43; - cpu_cache_int_enabled = 1; - ali1621_write(0, 0x42, 0x00, dev); - - ali1621_write(0, 0x54, 0x00, dev); - ali1621_write(0, 0x55, 0x00, dev); + ali1621_write(0, 0x83, 0x08, dev); for (i = 0; i < 4; i++) - ali1621_write(0, 0x56 + i, 0x00, dev); - - ali1621_write(0, 0x60 + i, 0x07, dev); - ali1621_write(0, 0x61 + i, 0x40, dev); - for (i = 0; i < 14; i += 2) { - ali1621_write(0, 0x62 + i, 0x00, dev); - ali1621_write(0, 0x63 + i, 0x00, dev); - } + ali1621_write(0, 0x84 + i, 0x00, dev); } @@ -720,7 +645,9 @@ ali1621_close(void *priv) { ali1621_t *dev = (ali1621_t *)priv; - smram_del(dev->smram); + smram_del(dev->smram[1]); + smram_del(dev->smram[0]); + free(dev); } @@ -733,11 +660,12 @@ ali1621_init(const device_t *info) pci_add_card(PCI_ADD_NORTHBRIDGE, ali1621_read, ali1621_write, dev); - dev->smram = smram_add(); + dev->smram[0] = smram_add(); + dev->smram[1] = smram_add(); ali1621_reset(dev); - dev->agp_bridge = device_add(&ali5243_agp_device); + device_add(&ali5247_agp_device); return dev; } diff --git a/src/chipset/contaq_82c59x.c b/src/chipset/contaq_82c59x.c new file mode 100644 index 000000000..48c84dd87 --- /dev/null +++ b/src/chipset/contaq_82c59x.c @@ -0,0 +1,476 @@ +/* + * 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 Contaq/Cypress 82C596(A) and 597 chipsets. + * + * Authors: Miran Grca, + * + * Copyright 2021 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/mem.h> +#include <86box/smram.h> +#include <86box/chipset.h> + + +#ifdef ENABLE_CONTAQ_82C59X_LOG +int contaq_82c59x_do_log = ENABLE_CONTAQ_82C59X_LOG; + +static void +contaq_82c59x_log(const char *fmt, ...) +{ + va_list ap; + + if (contaq_82c59x_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define contaq_82c59x_log(fmt, ...) +#endif + + +typedef struct +{ + uint32_t phys, virt; +} mem_remapping_t; + + +typedef struct +{ + uint8_t index, green, + smi_status_set, + regs[256], smi_status[2]; + + smram_t *smram[2]; +} contaq_82c59x_t; + + +static void +contaq_82c59x_isa_speed_recalc(contaq_82c59x_t *dev) +{ + if (dev->regs[0x1c] & 0x02) + cpu_set_isa_speed(7159091); + else { + /* TODO: ISA clock dividers for 386 and alt. 486. */ + switch (dev->regs[0x10] & 0x03) { + case 0x00: + cpu_set_isa_pci_div(4); + break; + case 0x01: + cpu_set_isa_pci_div(6); + break; + case 0x02: + cpu_set_isa_pci_div(8); + break; + case 0x04: + cpu_set_isa_pci_div(5); + break; + } + } +} + + +static void +contaq_82c59x_shadow_recalc(contaq_82c59x_t *dev) +{ + uint32_t i, base; + uint8_t bit; + + shadowbios = shadowbios_write = 0; + + /* F0000-FFFFF */ + if (dev->regs[0x15] & 0x80) { + shadowbios |= 1; + mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); + } else { + shadowbios_write |= 1; + mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + } + + /* C0000-CFFFF */ + if (dev->regs[0x15] & 0x01) + mem_set_mem_state_both(0xc0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + else { + for (i = 0; i < 4; i++) { + base = 0xc0000 + (i << 14); + bit = 1 << (i + 2); + if (dev->regs[0x15] & bit) { + if (dev->regs[0x15] & 0x02) + mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + else + mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + } else + mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } + } + + if (dev->green) { + /* D0000-DFFFF */ + if (dev->regs[0x6e] & 0x01) + mem_set_mem_state_both(0xd0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + else { + for (i = 0; i < 4; i++) { + base = 0xd0000 + (i << 14); + bit = 1 << (i + 2); + if (dev->regs[0x6e] & bit) { + if (dev->regs[0x6e] & 0x02) + mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + else + mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } else + mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } + } + + /* E0000-EFFFF */ + if (dev->regs[0x6f] & 0x01) + mem_set_mem_state_both(0xe0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + else { + for (i = 0; i < 4; i++) { + base = 0xe0000 + (i << 14); + bit = 1 << (i + 2); + if (dev->regs[0x6f] & bit) { + shadowbios |= 1; + if (dev->regs[0x6f] & 0x02) + mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + else { + shadowbios_write |= 1; + mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + } else + mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } + } + } +} + + +static void +contaq_82c59x_smram_recalc(contaq_82c59x_t *dev) +{ + smram_disable(dev->smram[1]); + + if (dev->regs[0x70] & 0x04) + smram_enable(dev->smram[1], 0x00040000, 0x000a0000, 0x00020000, 1, 1); +} + + +static void +contaq_82c59x_write(uint16_t addr, uint8_t val, void *priv) +{ + contaq_82c59x_t *dev = (contaq_82c59x_t *)priv; + + switch (addr) { + case 0x22: + dev->index = val; + break; + + case 0x23: + contaq_82c59x_log("Contaq 82C59x: dev->regs[%02x] = %02x\n", dev->index, val); + + if ((dev->index >= 0x60) && !dev->green) + return; + + switch (dev->index) { + /* Registers common to 82C596(A) and 82C597. */ + case 0x10: + dev->regs[dev->index] = val; + contaq_82c59x_isa_speed_recalc(dev); + break; + + case 0x11: + dev->regs[dev->index] = val; + cpu_cache_int_enabled = !!(val & 0x01); + cpu_update_waitstates(); + break; + + case 0x12: + dev->regs[dev->index] = val; + break; + + case 0x13: + dev->regs[dev->index] = val; + break; + + case 0x14: + dev->regs[dev->index] = val; + reset_on_hlt = !!(val & 0x80); + break; + + case 0x15: + dev->regs[dev->index] = val; + contaq_82c59x_shadow_recalc(dev); + break; + + case 0x16: + dev->regs[dev->index] = val; + break; + + case 0x17: + dev->regs[dev->index] = val; + break; + + case 0x18: + dev->regs[dev->index] = val; + break; + + case 0x19: + dev->regs[dev->index] = val; + break; + + case 0x1a: + dev->regs[dev->index] = val; + break; + + case 0x1b: + dev->regs[dev->index] = val; + break; + + case 0x1c: + /* TODO: What's NPRST (generated if bit 3 is set)? */ + dev->regs[dev->index] = val; + contaq_82c59x_isa_speed_recalc(dev); + break; + + case 0x1d: + dev->regs[dev->index] = val; + break; + + case 0x1e: + dev->regs[dev->index] = val; + break; + + case 0x1f: + dev->regs[dev->index] = val; + break; + + /* Green (82C597-specific) registers. */ + case 0x60: + dev->regs[dev->index] = val; + break; + + case 0x61: + dev->regs[dev->index] = val; + break; + + case 0x62: + dev->regs[dev->index] = val; + break; + + case 0x63: + dev->regs[dev->index] = val; + break; + + case 0x64: + dev->regs[dev->index] = val; + if (val & 0x80) { + if (dev->regs[0x65] & 0x80) + smi_line = 1; + dev->smi_status[0] |= 0x10; + } + break; + + case 0x65: + dev->regs[dev->index] = val; + break; + + case 0x66: + dev->regs[dev->index] = val; + break; + + case 0x67: + dev->regs[dev->index] = val; + break; + + case 0x68: + dev->regs[dev->index] = val; + break; + + case 0x69: + dev->regs[dev->index] = val; + break; + + case 0x6a: + dev->regs[dev->index] = val; + dev->smi_status_set = !!(val & 0x80); + break; + + case 0x6b: + dev->regs[dev->index] = val; + break; + + case 0x6c: + dev->regs[dev->index] = val; + break; + + case 0x6d: + dev->regs[dev->index] = val; + break; + + case 0x6e: case 0x6f: + dev->regs[dev->index] = val; + contaq_82c59x_shadow_recalc(dev); + break; + + case 0x70: + dev->regs[dev->index] = val; + contaq_82c59x_smram_recalc(dev); + break; + + case 0x71: + dev->regs[dev->index] = val; + break; + + case 0x72: + dev->regs[dev->index] = val; + break; + + case 0x73: + dev->regs[dev->index] = val; + break; + + case 0x74: + dev->regs[dev->index] = val; + break; + + case 0x75: + dev->regs[dev->index] = val; + break; + + case 0x76: + dev->regs[dev->index] = val; + break; + + case 0x77: + dev->regs[dev->index] = val; + break; + + case 0x78: + dev->regs[dev->index] = val; + break; + + case 0x79: + dev->regs[dev->index] = val; + break; + + case 0x7b: + dev->regs[dev->index] = val; + break; + + case 0x7c: + dev->regs[dev->index] = val; + break; + } + break; + } +} + + +static uint8_t +contaq_82c59x_read(uint16_t addr, void *priv) +{ + contaq_82c59x_t *dev = (contaq_82c59x_t *)priv; + uint8_t ret = 0xff; + + if (addr == 0x23) { + if (dev->index == 0x6a) { + ret = dev->smi_status[dev->smi_status_set]; + /* I assume it's cleared on read. */ + dev->smi_status[dev->smi_status_set] = 0x00; + } else + ret = dev->regs[dev->index]; + } + + return ret; +} + + +static void +contaq_82c59x_close(void *priv) +{ + contaq_82c59x_t *dev = (contaq_82c59x_t *)priv; + + free(dev); +} + + +static void * +contaq_82c59x_init(const device_t *info) +{ + contaq_82c59x_t *dev = (contaq_82c59x_t *)malloc(sizeof(contaq_82c59x_t)); + memset(dev, 0x00, sizeof(contaq_82c59x_t)); + + dev->green = info->local; + + io_sethandler(0x0022, 0x0002, contaq_82c59x_read, NULL, NULL, contaq_82c59x_write, NULL, NULL, dev); + + contaq_82c59x_isa_speed_recalc(dev); + + cpu_cache_int_enabled = 0; + cpu_update_waitstates(); + + reset_on_hlt = 0; + + contaq_82c59x_shadow_recalc(dev); + + if (dev->green) { + /* SMRAM 0: Fixed A0000-BFFFF to A0000-BFFFF DRAM. */ + dev->smram[0] = smram_add(); + smram_enable(dev->smram[0], 0x000a0000, 0x000a0000, 0x00020000, 0, 1); + + /* SMRAM 1: Optional. */ + dev->smram[1] = smram_add(); + contaq_82c59x_smram_recalc(dev); + } + + return dev; +} + + +const device_t contaq_82c596a_device = { + "Contaq 82C596A", + 0, + 0, + contaq_82c59x_init, + contaq_82c59x_close, + NULL, + { NULL }, + NULL, + NULL, + NULL +}; + + +const device_t contaq_82c597_device = { + "Contaq 82C597", + 0, + 1, + contaq_82c59x_init, + contaq_82c59x_close, + NULL, + { NULL }, + NULL, + NULL, + NULL +}; diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index 86ebeabb2..6140e8e2d 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -15,7 +15,7 @@ add_library(dev OBJECT bugger.c hasp.c hwm.c hwm_lm75.c hwm_lm78.c hwm_gl518sm.c hwm_vt82c686.c ibm_5161.c isamem.c isartc.c ../lpt.c pci_bridge.c - postcard.c serial.c vpc2007.c clock_ics9xxx.c isapnp.c i2c.c i2c_gpio.c + postcard.c serial.c clock_ics9xxx.c isapnp.c i2c.c i2c_gpio.c smbus_piix4.c smbus_ali7101.c keyboard.c keyboard_xt.c keyboard_at.c mouse.c mouse_bus.c mouse_serial.c mouse_ps2.c phoenix_486_jumper.c) diff --git a/src/device/hwm_lm75.c b/src/device/hwm_lm75.c index 3a28e2a1f..b6988232b 100644 --- a/src/device/hwm_lm75.c +++ b/src/device/hwm_lm75.c @@ -232,6 +232,9 @@ lm75_init(const device_t *info) hwm_values.temperatures[dev->local >> 8] = 30; dev->values = &hwm_values; + dev->i2c_addr = dev->local & 0x7f; + dev->i2c_enabled = 1; + lm75_reset(dev); return dev; diff --git a/src/device/hwm_lm78.c b/src/device/hwm_lm78.c index e93989afe..9df3c4b6d 100644 --- a/src/device/hwm_lm78.c +++ b/src/device/hwm_lm78.c @@ -37,6 +37,7 @@ #define LM78_AS99127F_REV1 0x040000 #define LM78_AS99127F_REV2 0x080000 #define LM78_W83782D 0x100000 +#define LM78_P5A 0x200000 #define LM78_AS99127F (LM78_AS99127F_REV1 | LM78_AS99127F_REV2) /* special mask covering both _REV1 and _REV2 */ #define LM78_WINBOND (LM78_W83781D | LM78_AS99127F | LM78_W83782D) /* special mask covering all Winbond variants */ #define LM78_WINBOND_VENDOR_ID ((dev->local & LM78_AS99127F_REV1) ? 0x12c3 : 0x5ca3) @@ -258,8 +259,13 @@ lm78_reset(void *priv) dev->regs[0x46] = 0x40; dev->regs[0x47] = 0x50; if (dev->local & LM78_I2C) { - if (!initialization) /* don't reset main I2C address if the reset was triggered by the INITIALIZATION bit */ - dev->i2c_addr = 0x2d; + if (!initialization) { /* don't reset main I2C address if the reset was triggered by the INITIALIZATION bit */ + if (dev->local & LM78_P5A) + dev->i2c_addr = 0x77; + else + dev->i2c_addr = 0x2d; + dev->i2c_enabled = 1; + } dev->regs[0x48] = dev->i2c_addr; if (dev->local & LM78_WINBOND) dev->regs[0x4a] = 0x01; @@ -797,6 +803,17 @@ const device_t w83781d_device = { }; +/* Winbond W83781D on ISA and SMBus. */ +const device_t w83781d_p5a_device = { + "Winbond W83781D Hardware Monitor (ASUS P5A)", + DEVICE_ISA, + 0x290 | LM78_I2C | LM78_W83781D | LM78_P5A, + lm78_init, lm78_close, lm78_reset, + { NULL }, NULL, NULL, + NULL +}; + + /* The AS99127F is an ASIC manufactured by Holtek for ASUS, containing an I2C-only W83781D clone with additional voltages, GPIOs and fan control. */ const device_t as99127f_device = { diff --git a/src/device/pci_bridge.c b/src/device/pci_bridge.c index 8e1353cc1..3980f8df6 100644 --- a/src/device/pci_bridge.c +++ b/src/device/pci_bridge.c @@ -34,6 +34,7 @@ #define PCI_BRIDGE_DEC_21150 0x10110022 #define AGP_BRIDGE_ALI_M5243 0x10b95243 +#define AGP_BRIDGE_ALI_M5247 0x10b95247 #define AGP_BRIDGE_INTEL_440LX 0x80867181 #define AGP_BRIDGE_INTEL_440BX 0x80867191 #define AGP_BRIDGE_INTEL_440GX 0x808671a1 @@ -98,6 +99,9 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) if (func > 0) return; + if ((dev->local == AGP_BRIDGE_ALI_M5247) && (addr >= 0x40)) + return; + switch (addr) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x06: case 0x08: case 0x09: case 0x0a: @@ -112,8 +116,10 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) if (AGP_BRIDGE_INTEL(dev->local)) { if (dev->local == AGP_BRIDGE_INTEL_440BX) val &= 0x1f; - } else if (AGP_BRIDGE_ALI(dev->local)) + } else if (dev->local == AGP_BRIDGE_ALI_M5243) val |= 0x02; + else if (dev->local == AGP_BRIDGE_ALI_M5247) + val &= 0xc3; else val &= 0x67; break; @@ -130,8 +136,10 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) case 0x07: if (dev->local == AGP_BRIDGE_INTEL_440LX) dev->regs[addr] &= ~(val & 0x40); - else if (AGP_BRIDGE_ALI(dev->local)) + else if (dev->local == AGP_BRIDGE_ALI_M5243) dev->regs[addr] &= ~(val & 0xf8); + else if (dev->local == AGP_BRIDGE_ALI_M5247) + dev->regs[addr] &= ~(val & 0xc0); return; case 0x0c: case 0x18: @@ -179,6 +187,10 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) case 0x3e: if (AGP_BRIDGE_VIA(dev->local)) val &= 0x0c; + else if (dev->local == AGP_BRIDGE_ALI_M5247) + val &= 0x0f; + else if (dev->local == AGP_BRIDGE_ALI_M5243) + return; else if (AGP_BRIDGE(dev->local)) { if ((dev->local == AGP_BRIDGE_INTEL_440BX) || (dev->local == AGP_BRIDGE_INTEL_440GX)) @@ -194,7 +206,9 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv) if (dev->local == AGP_BRIDGE_INTEL_440LX) { dev->regs[addr] = ((dev->regs[addr] & 0x04) | (val & 0x02)) & ~(val & 0x04); return; - } else if (AGP_BRIDGE_ALI(dev->local)) + } else if (dev->local == AGP_BRIDGE_ALI_M5247) + return; + else if (dev->local == AGP_BRIDGE_ALI_M5243) val &= 0x06; else if (AGP_BRIDGE(dev->local)) return; @@ -380,6 +394,11 @@ pci_bridge_reset(void *priv) pci_remap_bus(dev->bus_index, 0x01); break; + case AGP_BRIDGE_ALI_M5247: + dev->regs[0x04] = 0x03; + dev->regs[0x08] = 0x01; + break; + case AGP_BRIDGE_INTEL_440LX: dev->regs[0x06] = 0xa0; dev->regs[0x07] = 0x02; @@ -395,7 +414,7 @@ pci_bridge_reset(void *priv) case AGP_BRIDGE_VIA_597: case AGP_BRIDGE_VIA_598: case AGP_BRIDGE_VIA_691: - case AGP_BRIDGE_VIA_8601: + case AGP_BRIDGE_VIA_8601: dev->regs[0x04] = 0x07; dev->regs[0x06] = 0x20; dev->regs[0x07] = 0x02; @@ -413,7 +432,9 @@ pci_bridge_reset(void *priv) else dev->regs[0x1c] = dev->regs[0x1d] = 0x01; - if (!AGP_BRIDGE_VIA(dev->local)) { + if (dev->local == AGP_BRIDGE_ALI_M5247) + dev->regs[0x1e] = 0x20; + else if (!AGP_BRIDGE_VIA(dev->local)) { dev->regs[0x1e] = AGP_BRIDGE(dev->local) ? 0xa0 : 0x80; dev->regs[0x1f] = 0x02; } @@ -507,6 +528,21 @@ const device_t ali5243_agp_device = NULL }; +/* AGP bridges */ +const device_t ali5247_agp_device = +{ + "ALi M5247 AGP Bridge", + DEVICE_PCI, + AGP_BRIDGE_ALI_M5247, + pci_bridge_init, + NULL, + pci_bridge_reset, + { NULL }, + NULL, + NULL, + NULL +}; + const device_t i440lx_agp_device = { "Intel 82443LX/EX AGP Bridge", diff --git a/src/device/smbus_ali7101.c b/src/device/smbus_ali7101.c index 32cc0a22e..5b112a1a5 100644 --- a/src/device/smbus_ali7101.c +++ b/src/device/smbus_ali7101.c @@ -103,7 +103,7 @@ smbus_ali7101_write(uint16_t addr, uint8_t val, void *priv) dev->next_stat = 0x04; switch (addr - dev->io_base) { case 0x00: - dev->stat &= ~(val & 0xe2); + dev->stat &= ~(val & 0xf2); /* Make sure IDLE is set if we're not busy or errored. */ if (dev->stat == 0x00) dev->stat = 0x04; @@ -139,7 +139,7 @@ smbus_ali7101_write(uint16_t addr, uint8_t val, void *priv) /* 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 = 0x20; + dev->next_stat = 0x40; break; } diff --git a/src/device/vpc2007.c b/src/device/vpc2007.c deleted file mode 100644 index 4caf77fbb..000000000 --- a/src/device/vpc2007.c +++ /dev/null @@ -1,186 +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 port 440h device from Virtual PC 2007. - * - * - * - * Author: RichardG, - * - * Copyright 2020 RichardG. - */ -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/io.h> -#include <86box/device.h> -#include <86box/machine.h> -#include <86box/plat.h> -#include <86box/ui.h> -#include <86box/mem.h> -#include "cpu.h" - - -typedef struct { - uint8_t port440, port440read, port442, port443, port444; -} vpc2007_t; - - -#ifdef ENABLE_VPC2007_LOG -int vpc2007_do_log = ENABLE_VPC2007_LOG; - - -static void -vpc2007_log(const char *fmt, ...) -{ - va_list ap; - - if (vpc2007_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -int vpc2007_do_log = 0; - -#define vpc2007_log(fmt, ...) -#endif - - -static uint8_t -vpc2007_read(uint16_t port, void *priv) -{ - vpc2007_t *dev = (vpc2007_t *) priv; - uint8_t ret = 0xff; - - switch (port) { - case 0x440: - ret = dev->port440read; - dev->port440read = 0x02; - break; - - case 0x445: - if ((dev->port440 == 0x1e) && (dev->port442 == 0x48) && (dev->port444 == 0xa7)) { - switch (dev->port443) { - case 0x0b: - ret = 0x00; - break; - - case 0x1b: case 0x05: - ret = 0x01; - break; - - case 0x02: - ret = 0x02; - break; - - case 0x11: - ret = 0x04; - break; - - case 0x12: - ret = 0x06; - break; - - case 0x04: case 0x0d: - ret = 0x08; - break; - - case 0x03: case 0x09: - ret = 0x0b; - break; - - case 0x15: - ret = 0x12; - break; - - case 0x17: - ret = 0x40; - break; - } - } - - if (ret == 0xff) - vpc2007_log("VPC2007: unknown combination %02X %02X %02X %02X\n", dev->port440, dev->port442, dev->port443, dev->port444); - - break; - - default: - vpc2007_log("VPC2007: read from unknown port %02X\n", port); - break; - } - - return ret; -} - - -static void -vpc2007_write(uint16_t port, uint8_t val, void *priv) -{ - vpc2007_t *dev = (vpc2007_t *) priv; - - switch (port) { - case 0x440: - dev->port440 = val; - dev->port440read = 0x03; - break; - - case 0x442: - dev->port442 = val; - break; - - case 0x443: - dev->port443 = val; - break; - - case 0x444: - dev->port444 = val; - break; - } -} - - -static void * -vpc2007_init(const device_t *info) -{ - vpc2007_t *dev = (vpc2007_t *) malloc(sizeof(vpc2007_t)); - memset(dev, 0, sizeof(vpc2007_t)); - - io_sethandler(0x440, 6, - vpc2007_read, NULL, NULL, vpc2007_write, NULL, NULL, dev); - - return dev; -} - - -static void -vpc2007_close(void *priv) -{ - vpc2007_t *dev = (vpc2007_t *) priv; - - io_removehandler(0x440, 6, - vpc2007_read, NULL, NULL, vpc2007_write, NULL, NULL, dev); - - free(dev); -} - - -const device_t vpc2007_device = { - "Virtual PC 2007 Port 440h Device", - DEVICE_ISA, - 0, - vpc2007_init, vpc2007_close, NULL, - { NULL }, NULL, NULL, - NULL -}; diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index f52168777..c94205277 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -29,6 +29,7 @@ extern const device_t ali1531_device; extern const device_t ali1541_device; extern const device_t ali1543_device; extern const device_t ali1543c_device; +extern const device_t ali1621_device; #if defined(DEV_BRANCH) && defined(USE_M6117) extern const device_t ali6117d_device; #endif @@ -36,6 +37,10 @@ extern const device_t ali6117d_device; /* AMD */ extern const device_t amd640_device; +/* Contaq/Cypress */ +extern const device_t contaq_82c596a_device; +extern const device_t contaq_82c597_device; + /* C&T */ extern const device_t neat_device; extern const device_t scat_device; diff --git a/src/include/86box/hwm.h b/src/include/86box/hwm.h index e4613f05b..ef5621da6 100644 --- a/src/include/86box/hwm.h +++ b/src/include/86box/hwm.h @@ -64,6 +64,7 @@ extern const device_t lm75_w83781d_device; extern const device_t lm78_device; extern const device_t w83781d_device; +extern const device_t w83781d_p5a_device; extern const device_t as99127f_device; extern const device_t as99127f_rev2_device; extern const device_t w83782d_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index b3e9b66d5..b4b7b6037 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -340,6 +340,7 @@ 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_vi15g_init(const machine_t *); +extern int machine_at_green_b_init(const machine_t *); extern int machine_at_r418_init(const machine_t *); extern int machine_at_ls486e_init(const machine_t *); @@ -497,8 +498,10 @@ extern int machine_at_m560_init(const machine_t *); extern int machine_at_ms5164_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_ga_5aa_init(const machine_t *); +extern int machine_at_ga_5ax_init(const machine_t *); extern int machine_at_ax59pro_init(const machine_t *); extern int machine_at_mvp3_init(const machine_t *); @@ -522,6 +525,8 @@ extern void machine_at_p65up5_common_init(const machine_t *, const device_t *nor extern int machine_at_p65up5_cp6nd_init(const machine_t *); /* m_at_slot1.c */ +extern int machine_at_m729_init(const machine_t *); + extern int machine_at_p65up5_cpknd_init(const machine_t *); extern int machine_at_kn97_init(const machine_t *); diff --git a/src/include/86box/mem.h b/src/include/86box/mem.h index 700c92981..2bd76eb30 100644 --- a/src/include/86box/mem.h +++ b/src/include/86box/mem.h @@ -64,6 +64,15 @@ #define ACCESS_READ 1 #define ACCESS_WRITE 2 +#define ACCESS_SMRAM_OFF 0 +#define ACCESS_SMRAM_X 1 +#define ACCESS_SMRAM_W 2 +#define ACCESS_SMRAM_WX 3 +#define ACCESS_SMRAM_R 4 +#define ACCESS_SMRAM_RX 5 +#define ACCESS_SMRAM_RW 6 +#define ACCESS_SMRAM_RWX 7 + /* Conversion #define's - we need these to seamlessly convert the old mem_set_mem_state() calls to the new stuff in order to make this a drop in replacement. @@ -81,6 +90,8 @@ #define MEM_READ_EXTERNAL_EX 0 #define MEM_READ_SMRAM (ACCESS_X_SMRAM | ACCESS_R_SMRAM) #define MEM_READ_SMRAM_EX (ACCESS_X_SMRAM) +#define MEM_EXEC_SMRAM MEM_READ_SMRAM_EX +#define MEM_READ_SMRAM_2 (ACCESS_R_SMRAM) /* Theese two are going to be identical. */ #define MEM_READ_DISABLED_EX MEM_READ_DISABLED #define MEM_READ_MASK 0x7c1f diff --git a/src/include/86box/pci.h b/src/include/86box/pci.h index 0041855e4..4ca5d94c4 100644 --- a/src/include/86box/pci.h +++ b/src/include/86box/pci.h @@ -130,6 +130,7 @@ extern void pci_bridge_set_ctl(void *priv, uint8_t ctl); extern const device_t dec21150_device; extern const device_t ali5243_agp_device; +extern const device_t ali5247_agp_device; extern const device_t i440lx_agp_device; extern const device_t i440bx_agp_device; extern const device_t i440gx_agp_device; diff --git a/src/include/86box/spd.h b/src/include/86box/spd.h index db283cc87..81216a6f6 100644 --- a/src/include/86box/spd.h +++ b/src/include/86box/spd.h @@ -107,6 +107,7 @@ typedef struct { extern void spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size); extern void spd_write_drbs(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit); extern void spd_write_drbs_interleaved(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit); +extern void spd_write_drbs_ali1621(uint8_t *regs, uint8_t reg_min, uint8_t reg_max); #endif /*EMU_SPD_H*/ diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 93d5d9499..4497b1b97 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -697,7 +697,7 @@ machine_at_sis_85c471_common_init(const machine_t *model) machine_at_common_init(model); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); device_add(&sis_85c471_device); } @@ -817,6 +817,30 @@ machine_at_vi15g_init(const machine_t *model) } +int +machine_at_green_b_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/green-b/4gpv31-ami-1993-8273517.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_82c597_device); + + device_add(&keyboard_at_ami_device); + + return ret; +} + + static void machine_at_sis_85c496_common_init(const machine_t *model) { diff --git a/src/machine/m_at_misc.c b/src/machine/m_at_misc.c index aff270d95..e8e6c96b5 100644 --- a/src/machine/m_at_misc.c +++ b/src/machine/m_at_misc.c @@ -68,7 +68,6 @@ machine_at_vpc2007_init(const machine_t *model) device_add(&w83977f_370_device); device_add(&keyboard_ps2_ami_pci_device); device_add(&intel_flash_bxt_device); - device_add(&vpc2007_device); spd_register(SPD_TYPE_SDRAM, 0xF, 256); /* real VPC provides invalid SPD data */ return ret; diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index e57e315dd..9ed1f3ccb 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -690,3 +690,36 @@ machine_at_ms6168_init(const machine_t *model) return ret; } + + +int +machine_at_m729_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/m729/M729NEW.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_AGPBRIDGE, 1, 2, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x10, PCI_CARD_NORMAL, 3, 4, 1, 2); + device_add(&ali1621_device); + device_add(&ali1543c_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sst_flash_29ee010_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 128); + + return ret; +} diff --git a/src/machine/m_at_sockets7.c b/src/machine/m_at_sockets7.c index e51fda097..47ee28a29 100644 --- a/src/machine/m_at_sockets7.c +++ b/src/machine/m_at_sockets7.c @@ -40,6 +40,44 @@ #include <86box/video.h> #include "cpu.h" #include <86box/machine.h> +#include <86box/clock.h> + + +int +machine_at_p5a_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/p5a/1011.005", + 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(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + 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(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 4, 1, 2); + device_add(&ali1541_device); + device_add(&ali1543c_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0xF, 256); + device_add(&w83781d_p5a_device); /* fans: Chassis, CPU, Power; temperatures: MB, unused, CPU */ + + return ret; +} int @@ -108,6 +146,41 @@ machine_at_ga_5aa_init(const machine_t *model) } +int +machine_at_ga_5ax_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ga-5ax/5AX.F4", + 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_AGPBRIDGE, 1, 2, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + 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(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + device_add(&ali1541_device); + device_add(&ali1543c_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sst_flash_29ee010_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 128); + + return ret; +} + + int machine_at_ax59pro_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index f80d66334..f44ca808f 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -370,6 +370,8 @@ const machine_t machines[] = { /* 486 machines - Socket 3 */ /* 486 machines with just the ISA slot */ + /* Has AMI MegaKey KBC firmware. */ + { "[Contaq 82C597] Green-B", "green-b", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_green_b_init, NULL }, /* Has a VIA VT82C42N KBC. */ { "[OPTi 895] Jetway J-403TG", "403tg", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_403tg_init, NULL }, /* Has JetKey 5 KBC Firmware which looks like it is a clone of AMIKey type F. */ @@ -668,10 +670,15 @@ const machine_t machines[] = { /* Super Socket 7 machines */ /* ALi ALADDiN V */ + /* Has the ALi M1543C southbridge with on-chip KBC. */ + { "[ALi ALADDiN V] ASUS P5A", "p5a", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 2000, 3200, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,2097152, 8192, 255, machine_at_p5a_init, NULL }, /* Is the exact same as the Matsonic MS6260S. Has the ALi M1543C southbridge with on-chip KBC. */ { "[ALi ALADDiN V] PC Chips M579", "m579", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 2000, 3200, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,2097152, 8192, 255, machine_at_m579_init, NULL }, + /* Has the ALi M1543C southbridge with on-chip KBC. */ { "[ALi ALADDiN V] Gigabyte GA-5AA", "ga-5aa", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 2000, 3200, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,2097152, 8192, 255, machine_at_ga_5aa_init, NULL }, + /* Has the ALi M1543C southbridge with on-chip KBC. */ + { "[ALi ALADDiN V] Gigabyte GA-5AX", "ga-5ax", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 2000, 3200, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,2097152, 8192, 255, machine_at_ga_5ax_init, NULL }, /* Apollo MVP3 */ /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA @@ -716,6 +723,10 @@ const machine_t machines[] = { { "[i440FX] PC Partner MB600N", "mb600n", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_mb600n_init, NULL }, /* Slot 1 machines */ + /* ALi ALADDiN V */ + /* Has the ALi M1543C southbridge with on-chip KBC. */ + { "[ALi ALADDiN-PRO II] PC Chips M729", "m729", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 50000000, 66666667, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,2097152, 8192, 255, machine_at_m729_init, NULL }, + /* 440FX */ /* The base board has AMIKey-2 (updated 'H') KBC firmware. */ { "[i440FX] ASUS P/I-P65UP5 (C-PKND)", "p65up5_cpknd", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 50000000, 66666667, 1800, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 127, machine_at_p65up5_cpknd_init, NULL }, diff --git a/src/mem/mem.c b/src/mem/mem.c index 79e27f011..225fafcbd 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -2493,6 +2493,7 @@ mem_set_access(uint8_t bitmap, int mode, uint32_t base, uint32_t size, uint16_t uint16_t mask, smstate = 0x0000; const uint16_t smstates[4] = { 0x0000, (MEM_READ_SMRAM | MEM_WRITE_SMRAM), MEM_READ_SMRAM_EX, (MEM_READ_DISABLED_EX | MEM_WRITE_DISABLED_EX) }; + int i; if (mode) @@ -2504,7 +2505,15 @@ mem_set_access(uint8_t bitmap, int mode, uint32_t base, uint32_t size, uint16_t if (mode == 1) access = !!access; - smstate = smstates[access & 0x03]; + if (mode == 3) { + if (access & ACCESS_SMRAM_X) + smstate |= MEM_EXEC_SMRAM; + if (access & ACCESS_SMRAM_R) + smstate |= MEM_READ_SMRAM_2; + if (access & ACCESS_SMRAM_W) + smstate |= MEM_WRITE_SMRAM; + } else + smstate = smstates[access & 0x07]; } else smstate = access & 0x6f7b; diff --git a/src/mem/spd.c b/src/mem/spd.c index 74346417b..8e79833ad 100644 --- a/src/mem/spd.c +++ b/src/mem/spd.c @@ -384,19 +384,15 @@ spd_write_drbs(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit } +/* Used by ALi M1531 and M1541/2. */ void spd_write_drbs_interleaved(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit) { - uint8_t row, dimm, drb, apollo = 0; + uint8_t row, dimm; + uint8_t drb; uint16_t size, size_acc; uint16_t rows[SPD_MAX_SLOTS]; - /* Special case for VIA Apollo Pro family, which jumps from 5F to 56. */ - if (reg_max < reg_min) { - apollo = reg_max; - reg_max = reg_min + 7; - } - /* No SPD: split SIMMs into pairs as if they were "DIMM"s. */ if (!spd_present) { dimm = ((reg_max - reg_min) + 1) >> 2; /* amount of "DIMM"s, also used to determine the maximum "DIMM" size */ @@ -424,8 +420,6 @@ spd_write_drbs_interleaved(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint /* Determine the DRB register to write. */ drb = reg_min + row; - if (apollo && ((drb & 0xf) < 0xa)) - drb = apollo + (drb & 0xf); /* Calculate previous and new size. */ if (row == 0) @@ -442,6 +436,81 @@ spd_write_drbs_interleaved(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint } +/* This is needed because the ALi M1621 does this stuff completely differently, + as it has DRAM bank registers instead of DRAM row boundary registers. */ +void +spd_write_drbs_ali1621(uint8_t *regs, uint8_t reg_min, uint8_t reg_max) +{ + uint8_t dimm, drb; + uint16_t size; + uint16_t rows[SPD_MAX_SLOTS]; + + /* No SPD: split SIMMs into pairs as if they were "DIMM"s. */ + if (!spd_present) { + dimm = ((reg_max - reg_min) + 1) >> 2; /* amount of "DIMM"s, also used to determine the maximum "DIMM" size */ + spd_populate(rows, dimm, mem_size >> 10, 4, 1 << (log2i((machines[machine].max_ram >> 10) / dimm)), 0); + } + + /* Write DRBs for each row. */ + spd_log("SPD: Writing DRBs... regs=[%02X:%02X] unit=%d\n", reg_min, reg_max, drb_unit); + for (dimm = 0; dimm <= ((reg_max - reg_min) >> 2); dimm++) { + size = 0; + drb = reg_min + (dimm << 2); + + regs[drb] = 0xff; + regs[drb + 1] = 0xff; + regs[drb + 2] = 0x00; + regs[drb + 3] = 0xf0; + + if (spd_modules[dimm] == NULL) + continue; + + if (spd_present) { + /* SPD enabled: use SPD info for this slot, if present. */ + size = (spd_modules[dimm]->row1 + spd_modules[dimm]->row2) >> 1; + } else { + /* No SPD: use the values calculated above. */ + size = (rows[dimm] >> 1); + } + + if (spd_modules[dimm]->row1) + regs[drb + 3] |= 0x06; + + switch (size) { + case 4: + default: + regs[drb + 2] = 0x00; + break; + case 8: + regs[drb + 2] = 0x10; + break; + case 16: + regs[drb + 2] = 0x20; + break; + case 32: + regs[drb + 2] = 0x30; + break; + case 64: + regs[drb + 2] = 0x40; + break; + case 128: + regs[drb + 2] = 0x50; + break; + case 256: + regs[drb + 2] = 0x60; + break; + } + + if (spd_modules[dimm]->row2) { + regs[drb + 3] |= 0x01; + regs[drb + 2] |= 0x80; + } + + spd_log("SPD: DIMM %i: %02X %02X %02X %02X\n", regs[drb], regs[drb + 1], regs[drb + 2], regs[drb + 3]); + } +} + + static const device_t spd_device = { "Serial Presence Detect ROMs", DEVICE_ISA, diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index c67fa66f6..10fde74f7 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -600,8 +600,9 @@ CPUOBJ := cpu.o cpu_table.o fpu.o x86.o \ $(DYNARECOBJ) CHIPSETOBJ := acc2168.o \ + contaq_82c59x.o \ cs4031.o cs8230.o \ - ali1217.o ali1429.o ali1489.o ali1531.o ali1541.o ali1543.o \ + ali1217.o ali1429.o ali1489.o ali1531.o ali1541.o ali1543.o ali1621.o \ gc100.o headland.o \ intel_82335.o intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \ neat.o \ @@ -633,7 +634,7 @@ MCHOBJ := machine.o machine_table.o \ ifeq ($(NEW_KBC), y) DEVOBJ := bugger.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ ibm_5161.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o \ - vpc2007.o clock_ics9xxx.o isapnp.o \ + clock_ics9xxx.o isapnp.o \ i2c.o i2c_gpio.o smbus_ali7101.o smbus_piix4.o \ keyboard.o \ keyboard_xt.o kbc_at.o kbd_at.o \ @@ -644,7 +645,7 @@ DEVOBJ := bugger.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c68 else DEVOBJ := bugger.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ ibm_5161.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o \ - vpc2007.o clock_ics9xxx.o isapnp.o \ + clock_ics9xxx.o isapnp.o \ i2c.o i2c_gpio.o smbus_ali7101.o smbus_piix4.o \ keyboard.o \ keyboard_xt.o keyboard_at.o \ From 6aeeba135173b19033c01b1ab9813a19b4fecd81 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 13 Jul 2021 05:24:52 +0200 Subject: [PATCH 19/96] The Contaq chipsets now close SMRAM on close. --- src/chipset/contaq_82c59x.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/chipset/contaq_82c59x.c b/src/chipset/contaq_82c59x.c index 48c84dd87..19a3d5b44 100644 --- a/src/chipset/contaq_82c59x.c +++ b/src/chipset/contaq_82c59x.c @@ -411,6 +411,9 @@ contaq_82c59x_close(void *priv) { contaq_82c59x_t *dev = (contaq_82c59x_t *)priv; + smram_del(dev->smram[1]); + smram_del(dev->smram[0]); + free(dev); } From 36bb5847630c448c1b1c5e5fd4f8ec3f5f6f0d32 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 2 Aug 2021 06:55:35 +0200 Subject: [PATCH 20/96] Preparation for bringing it up to par with master. --- src/win/Makefile.mingw | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 10fde74f7..42b3fbbbc 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -632,7 +632,7 @@ MCHOBJ := machine.o machine_table.o \ m_at_misc.o ifeq ($(NEW_KBC), y) -DEVOBJ := bugger.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ +DEVOBJ := bugger.o cartridge.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ ibm_5161.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o \ clock_ics9xxx.o isapnp.o \ i2c.o i2c_gpio.o smbus_ali7101.o smbus_piix4.o \ @@ -643,7 +643,7 @@ DEVOBJ := bugger.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c68 mouse_serial.o mouse_ps2.o \ phoenix_486_jumper.o else -DEVOBJ := bugger.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ +DEVOBJ := bugger.o cartridge.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ ibm_5161.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o \ clock_ics9xxx.o isapnp.o \ i2c.o i2c_gpio.o smbus_ali7101.o smbus_piix4.o \ From 15cc6cc12cf9ec7a2b312c3df6ee52455797ee0b Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 2 Aug 2021 06:56:36 +0200 Subject: [PATCH 21/96] And one more. --- src/win/Makefile.mingw | 1 - 1 file changed, 1 deletion(-) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 42b3fbbbc..4390235a9 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -631,7 +631,6 @@ MCHOBJ := machine.o machine_table.o \ m_at_socket8.o m_at_slot1.o m_at_slot2.o m_at_socket370.o \ m_at_misc.o -ifeq ($(NEW_KBC), y) DEVOBJ := bugger.o cartridge.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ ibm_5161.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o \ clock_ics9xxx.o isapnp.o \ From 4a6c064d0f59491cd2ca336e4d9ebcae8ae8c2c7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 2 Aug 2021 06:57:51 +0200 Subject: [PATCH 22/96] Temporary revert of keyboard_at.c. --- src/device/keyboard_at.c | 2785 ++++++++++++++------------------------ 1 file changed, 1039 insertions(+), 1746 deletions(-) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 92690db1f..581f55f30 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -57,7 +57,9 @@ #define STAT_IFULL 0x02 #define STAT_OFULL 0x01 -#define RESET_DELAY_TIME 1000 /* 100 ms */ +#define PS2_REFRESH_TIME (16 * TIMER_USEC) + +#define RESET_DELAY_TIME (100 * 10) /* 600ms */ #define CCB_UNUSED 0x80 #define CCB_TRANSLATE 0x40 @@ -72,136 +74,49 @@ #define MODE_MASK 0x6c #define KBC_TYPE_ISA 0x00 /* AT ISA-based chips */ -#define KBC_TYPE_PS2_1 0x04 /* PS2 type, no refresh */ -/* This only differs in that translation is forced off. */ -#define KBC_TYPE_PS2_2 0x05 /* PS2 on PS/2, type 2 */ -#define KBC_TYPE_MASK 0x07 +#define KBC_TYPE_PS2_NOREF 0x01 /* PS2 type, no refresh */ +#define KBC_TYPE_PS2_1 0x02 /* PS2 on PS/2, type 1 */ +#define KBC_TYPE_PS2_2 0x03 /* PS2 on PS/2, type 2 */ +#define KBC_TYPE_MASK 0x03 -#define KBC_FLAG_PS2 0x04 - -/* We need to redefine this: - Currently, we use bits 3-7 for vendor, we should instead use bits 4-7 - for vendor, 0-3 for revision/variant, and have a dev->ps2 flag controlling - controller mode, normally set according to the flags, but togglable on - AMIKey: - 0000 0000 0x00 IBM, AT - 0000 0001 0x01 MR - 0000 0010 0x02 Xi8088, clone of IBM PS/2 type 1 - 0001 0000 0x10 Olivetti - 0010 0000 0x20 Toshiba - 0011 0000 0x30 Quadtel - 0100 0000 0x40 Phoenix MultiKey/42 - 0101 0000 0x50 AMI KF - 0101 0001 0x51 AMI KH - 0101 0010 0x52 AMIKey - 0101 0011 0x53 AMIKey-2 - 0101 0100 0x54 JetKey (clone of AMI KF/AMIKey) - 0110 0000 0x60 Award - 0110 0001 0x61 Award 286 (has some AMI commands apparently) - 0111 0000 0x70 Siemens -*/ - -/* Standard IBM controller */ #define KBC_VEN_GENERIC 0x00 -/* All commands are standard PS/2 */ +#define KBC_VEN_AMI 0x04 #define KBC_VEN_IBM_MCA 0x08 -/* Standard IBM commands, differs in input port bits */ -#define KBC_VEN_IBM_PS1 0x10 -/* Olivetti - proprietary commands and port 62h with switches - readout */ -#define KBC_VEN_OLIVETTI 0x20 -/* Toshiba T3100e - has a bunch of proprietary commands, also sets - IFULL on command AA */ -#define KBC_VEN_TOSHIBA 0x28 -/* Standard IBM commands, uses input port as a switches readout */ -#define KBC_VEN_NCR 0x30 -/* Xi8088 - standard IBM commands, has a turbo bit on port 61h, and the - polarity of the video type bit in the input port is inverted */ -#define KBC_VEN_XI8088 0x38 -/* QuadtelKey - currently guesswork */ -#define KBC_VEN_QUADTEL 0x40 -/* Phoenix MultiKey/42 - not yet implemented */ -#define KBC_VEN_PHOENIX 0x48 -/* Generic commands, XI8088-like input port handling of video type, - maybe we just need a flag for that? */ -#define KBC_VEN_ACER 0x50 -/* AMI KF/KH/AMIKey/AMIKey-2 */ -#define KBC_VEN_AMI 0xf0 -/* Standard AMI commands, differs in input port bits */ -#define KBC_VEN_INTEL_AMI 0xf8 -#define KBC_VEN_MASK 0xf8 - - -/* Flags should be fully 32-bit: - Bits 7- 0: Vendor and revision/variant; - Bits 15- 8: Input port mask; - Bits 23-16: Input port bits that are always on; - Bits 31-24: Flags: - Bit 0: Invert P1 video type bit polarity; - Bit 1: Is PS/2; - Bit 2: Translation forced always off. - - So for example, the IBM PS/2 type 1 controller flags would be: 00000010 00000000 11111111 00000000 = 0200ff00 . */ +#define KBC_VEN_QUADTEL 0x0c +#define KBC_VEN_TOSHIBA 0x10 +#define KBC_VEN_XI8088 0x14 +#define KBC_VEN_IBM_PS1 0x18 +#define KBC_VEN_ACER 0x1c +#define KBC_VEN_INTEL_AMI 0x20 +#define KBC_VEN_OLIVETTI 0x24 +#define KBC_VEN_NCR 0x28 +#define KBC_VEN_SAMSUNG 0x2c +#define KBC_VEN_MASK 0x3c typedef struct { - uint8_t status, ib, ob, p1, p2, old_p2, p2_locked, fast_a20_phase, - secr_phase, mem_index, ami_stat, ami_mode, - kbc_in, kbc_cmd, kbc_in_cmd, kbc_poll_phase, kbc_to_send, - kbc_send_pending, kbc_channel, kbc_stat_hi, kbc_wait_for_response, inhibit, - kbd_in, kbd_cmd, kbd_in_cmd, kbd_written, kbd_data, kbd_poll_phase, kbd_inhibit, - mouse_in, mouse_cmd, mouse_in_cmd, mouse_written, mouse_data, mouse_poll_phase, mouse_inhibit, - kbc_written[3], kbc_data[3]; + uint8_t command, status, old_status, out, old_out, secr_phase, + mem_addr, input_port, output_port, old_output_port, + key_command, output_locked, ami_stat, want60, + wantirq, key_wantdata, refresh, first_write; - uint8_t mem_int[0x40], mem[0x240]; + uint8_t mem[0x100]; - uint16_t last_irq, kbc_phase, kbd_phase, mouse_phase; + int last_irq, old_last_irq, + reset_delay, + out_new, out_delayed; uint32_t flags; - pc_timer_t pulse_cb, send_delay_timer; + pc_timer_t refresh_time, pulse_cb; uint8_t (*write60_ven)(void *p, uint8_t val); uint8_t (*write64_ven)(void *p, uint8_t val); + + pc_timer_t send_delay_timer; } atkbd_t; -enum -{ - CHANNEL_KBC = 0, - CHANNEL_KBD, - CHANNEL_MOUSE -}; - -enum -{ - KBD_MAIN_LOOP = 0, - KBD_CMD_PROCESS -}; - -enum -{ - MOUSE_MAIN_LOOP_1 = 0, - MOUSE_CMD_PROCESS, - MOUSE_CMD_END, - MOUSE_MAIN_LOOP_2 -}; - -enum { - KBC_MAIN_LOOP = 0, - KBC_RESET = 1, - KBC_WAIT = 4, - KBC_WAIT_FOR_KBD, - KBC_WAIT_FOR_MOUSE, - KBC_WAIT_FOR_BOTH -}; - - -static void kbd_cmd_process(atkbd_t *dev); - -static void kbc_wait(atkbd_t *dev, uint8_t flags); - - /* bit 0 = repeat, bit 1 = makes break code? */ uint8_t keyboard_set3_flags[512]; uint8_t keyboard_set3_all_repeat; @@ -210,9 +125,9 @@ uint8_t keyboard_set3_all_break; /* Bits 0 - 1 = scan code set, bit 6 = translate or not. */ uint8_t keyboard_mode = 0x42; -uint8_t * ami_copr = (uint8_t *) "(C)1994 AMI"; - +static uint8_t key_ctrl_queue[16]; +static int key_ctrl_queue_start = 0, key_ctrl_queue_end = 0; static uint8_t key_queue[16]; static int key_queue_start = 0, key_queue_end = 0; uint8_t mouse_queue[16]; @@ -653,27 +568,9 @@ static const scancode scancode_set3[512] = { }; -#define UISTR_LEN 256 -static char kbd_str[UISTR_LEN]; /* UI output string */ static void add_data_kbd(uint16_t val); -extern void ui_sb_bugui(char *__str); - - -static void -kbd_status(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vsprintf(kbd_str, fmt, ap); - ui_sb_bugui(kbd_str); - va_end(ap); -} - - -// #define ENABLE_KEYBOARD_AT_LOG 1 #ifdef ENABLE_KEYBOARD_AT_LOG int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG; @@ -734,6 +631,9 @@ kbc_queue_reset(uint8_t channel) } else if (channel == 1) { key_queue_start = key_queue_end = 0; memset(key_queue, 0x00, sizeof(key_queue)); + } else { + key_ctrl_queue_start = key_ctrl_queue_end = 0; + memset(key_ctrl_queue, 0x00, sizeof(key_ctrl_queue)); } } @@ -741,6 +641,15 @@ kbc_queue_reset(uint8_t channel) static void kbc_queue_add(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) { + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + + if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) + stat_hi |= ((dev->input_port & 0x80) ? 0x10 : 0x00); + else + stat_hi |= 0x10; + + dev->status = (dev->status & 0x0f) | stat_hi; + if (channel == 2) { kbd_log("ATkbc: mouse_queue[%02X] = %02X;\n", mouse_queue_end, val); mouse_queue[mouse_queue_end] = val; @@ -749,1042 +658,83 @@ kbc_queue_add(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); key_queue[key_queue_end] = val; key_queue_end = (key_queue_end + 1) & 0xf; - } else - fatal("Adding %02X to invalid channel %02X\n", val, channel); + } else { + kbd_log("ATkbc: key_ctrl_queue[%02X] = %02X;\n", key_ctrl_queue_end, val); + key_ctrl_queue[key_ctrl_queue_end] = val; + key_ctrl_queue_end = (key_ctrl_queue_end + 1) & 0xf; + } +} + + +static void +add_to_kbc_queue_front(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) +{ + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + + if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) + stat_hi |= ((dev->input_port & 0x80) ? 0x10 : 0x00); + else + stat_hi |= 0x10; + + kbd_log("ATkbc: Adding %02X to front...\n", val); + dev->wantirq = 0; + if (channel == 2) { + if (dev->mem[0] & 0x02) + picint(0x1000); + dev->last_irq = 0x1000; + } else { + if (dev->mem[0] & 0x01) + picint(2); + dev->last_irq = 2; + } + dev->out = val; + if (channel == 2) + dev->status = (dev->status & ~STAT_IFULL) | (STAT_OFULL | STAT_MFULL) | stat_hi; + else + dev->status = (dev->status & ~(STAT_IFULL | STAT_MFULL)) | STAT_OFULL | stat_hi; } static void add_data_kbd_queue(atkbd_t *dev, int direct, uint8_t val) { - if ((!keyboard_scan && !direct) || (key_queue_end >= 16)) { - kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i\n", !keyboard_scan, (key_queue_end >= 16)); + if ((!keyboard_scan && !direct) || (dev->reset_delay > 0) || (key_queue_end >= 16)) { + kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i, %i\n", !keyboard_scan, (dev->reset_delay > 0), (key_queue_end >= 16)); return; } - - kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); + kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); kbc_queue_add(dev, val, 1, 0x00); kbd_last_scan_code = val; } -static void -kbc_send(atkbd_t *dev, uint8_t val, uint8_t channel) -{ - dev->kbc_written[channel] = 1; - dev->kbc_data[channel] = val; -} - static void -kbd_send_to_host(atkbd_t *dev, uint8_t val) +add_data_kbd_direct(atkbd_t *dev, uint8_t val) { - kbc_send(dev, val, CHANNEL_KBD); -} + int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); + int translate = (keyboard_mode & 0x40); + uint8_t send; - -static void -kbd_chip_reset(atkbd_t *dev) -{ - kbc_queue_reset(1); - dev->kbc_written[1] = 0x00; - kbd_last_scan_code = 0x00; - - /* Set scan code set to 2. */ - keyboard_mode = (keyboard_mode & 0xfc) | 0x02; - set_scancode_map(dev); - - dev->kbd_phase = 0; - dev->kbd_in = 0; -} - - -static void -kbd_command(atkbd_t *dev) -{ - uint8_t val = dev->kbd_data; - - if ((dev->kbd_phase > 0) && (dev->kbd_cmd == 0xff)) { - dev->kbd_phase++; - if (dev->kbd_phase == RESET_DELAY_TIME) { - kbd_send_to_host(dev, 0xaa); - dev->kbd_phase = 0; - dev->kbd_cmd = 0x00; - } - return; - } - - if (dev->kbd_phase == 2) { - dev->kbd_phase = 0; - - switch (dev->kbd_cmd) { - case 0xf2: - kbd_send_to_host(dev, 0x83); - break; - default: - fatal("Invalid command for phase 2: %02X\n", dev->kbd_cmd); - break; - } - - /* Keyboard command is now done. */ - if (dev->kbd_phase == 0) - dev->kbd_cmd = 0x00; - return; - } else if (dev->kbd_phase == 1) { - dev->kbd_phase = 0; - - switch (dev->kbd_cmd) { - case 0xf0: - kbd_log("Get scan code set: %02X\n", keyboard_mode & 3); - kbd_send_to_host(dev, keyboard_mode & 3); - break; - case 0xf2: - kbd_send_to_host(dev, 0xab); - dev->kbd_phase = 2; - break; - default: - fatal("Invalid command for phase 1: %02X\n", dev->kbd_cmd); - break; - } - - /* Keyboard command is now done. */ - if (dev->kbd_phase == 0) - dev->kbd_cmd = 0x00; - return; - } - - if (dev->kbd_in && (val < 0xed)) { - dev->kbd_in = 0; - dev->kbd_phase = 0; - - switch (dev->kbd_cmd) { - case 0xed: /* set/reset LEDs */ - kbd_log("ATkbd: set LEDs [%02x]\n", val); - kbd_send_to_host(dev, 0xfa); - break; - - case 0xf0: /* get/set scancode set */ - kbd_send_to_host(dev, 0xfa); - if (val == 0) - dev->kbd_phase = 1; - else { - if ((val <= 3) && (val != 1)) { - keyboard_mode &= 0xfc; - keyboard_mode |= (val & 3); - kbd_log("Scan code set now: %02X\n", val); - } - set_scancode_map(dev); - } - break; - - case 0xf3: /* set typematic rate/delay */ - kbd_send_to_host(dev, 0xfa); - break; - - default: - kbd_log("ATkbd: bad keyboard 0060 write %02X command %02X\n", val, dev->kbd_cmd); - kbd_send_to_host(dev, 0xfe); - break; - } - - /* Keyboard command is now done. */ - if (dev->kbd_phase == 0) - dev->kbd_cmd = 0x00; - } else { - /* No keyboard command in progress. */ - dev->kbd_in = 0; - dev->kbd_cmd = 0x00; - dev->kbd_phase = 0; - - switch (val) { - case 0x00: - kbd_log("ATkbd: command 00\n"); - kbd_send_to_host(dev, 0xfa); - break; - - case 0x05: /*??? - sent by NT 4.0*/ - kbd_log("ATkbd: command 05 (NT 4.0)\n"); - kbd_send_to_host(dev, 0xfe); - break; - - case 0xed: /* set/reset LEDs */ - kbd_log("ATkbd: set/reset leds\n"); - kbd_send_to_host(dev, 0xfa); - - dev->kbd_in = 1; - break; - - case 0xee: /* diagnostic echo */ - kbd_log("ATkbd: ECHO\n"); - kbd_send_to_host(dev, 0xee); - break; - - case 0xef: /* NOP (reserved for future use) */ - kbd_log("ATkbd: NOP\n"); - break; - - case 0xf0: /* get/set scan code set */ - kbd_log("ATkbd: scan code set\n"); - kbd_send_to_host(dev, 0xfa); - dev->kbd_in = 1; - break; - - case 0xf2: /* read ID */ - /* Fixed as translation will be done in add_data_kbd(). */ - kbd_log("ATkbd: read keyboard id\n"); - /* TODO: After keyboard type selection is implemented, make this - return the correct keyboard ID for the selected type. */ - kbd_send_to_host(dev, 0xfa); - dev->kbd_phase = 1; - break; - - case 0xf3: /* set typematic rate/delay */ - kbd_log("ATkbd: set typematic rate/delay\n"); - kbd_send_to_host(dev, 0xfa); - dev->kbd_in = 1; - break; - - case 0xf4: /* enable keyboard */ - kbd_log("ATkbd: enable keyboard\n"); - kbd_send_to_host(dev, 0xfa); - keyboard_scan = 1; - break; - - case 0xf5: /* set defaults and disable keyboard */ - case 0xf6: /* set defaults */ - kbd_log("ATkbd: set defaults%s\n", (val == 0xf6) ? "" : " and disable keyboard"); - keyboard_scan = (val == 0xf6); - kbd_log("val = %02X, keyboard_scan = %i, dev->mem[0x20] = %02X\n", - val, keyboard_scan, dev->mem[0x20]); - kbd_send_to_host(dev, 0xfa); - - keyboard_set3_all_break = 0; - keyboard_set3_all_repeat = 0; - memset(keyboard_set3_flags, 0, 512); - keyboard_mode = (keyboard_mode & 0xfc) | 0x02; - set_scancode_map(dev); - break; - - case 0xf7: /* set all keys to repeat */ - kbd_log("ATkbd: set all keys to repeat\n"); - kbd_send_to_host(dev, 0xfa); - keyboard_set3_all_break = 1; - break; - - case 0xf8: /* set all keys to give make/break codes */ - kbd_log("ATkbd: set all keys to give make/break codes\n"); - kbd_send_to_host(dev, 0xfa); - keyboard_set3_all_break = 1; - break; - - case 0xf9: /* set all keys to give make codes only */ - kbd_log("ATkbd: set all keys to give make codes only\n"); - kbd_send_to_host(dev, 0xfa); - keyboard_set3_all_break = 0; - break; - - case 0xfa: /* set all keys to repeat and give make/break codes */ - kbd_log("ATkbd: set all keys to repeat and give make/break codes\n"); - kbd_send_to_host(dev, 0xfa); - keyboard_set3_all_repeat = 1; - keyboard_set3_all_break = 1; - break; - - case 0xfe: /* resend last scan code */ - kbd_log("ATkbd: reset last scan code\n"); - kbd_send_to_host(dev, kbd_last_scan_code); - break; - - case 0xff: /* reset */ - kbd_log("ATkbd: kbd reset\n"); - kbd_chip_reset(dev); - kbd_send_to_host(dev, 0xfa); - dev->kbd_phase = 1; - break; - - default: - kbd_log("ATkbd: bad keyboard command %02X\n", val); - kbd_send_to_host(dev, 0xfe); - } - - /* If command needs data, remember command. */ - if ((dev->kbd_in == 1) || (dev->kbd_phase > 0)) - dev->kbd_cmd = val; - } -} - - -static void -kbd_do_command(atkbd_t *dev) -{ - kbd_command(dev); - if (dev->kbd_written) - dev->kbd_poll_phase = KBD_CMD_PROCESS; - else if ((dev->kbd_phase == 0) && !dev->kbd_in) { - dev->kbd_in_cmd = 0; - if (dev->kbd_data != 0xf5) - keyboard_scan = 1; - dev->kbd_poll_phase = KBD_MAIN_LOOP; - } else { - keyboard_scan = 0; - dev->kbd_in_cmd = 1; - dev->kbd_poll_phase = KBD_CMD_PROCESS; - } -} - - -static void -kbd_nack(atkbd_t *dev) -{ - kbd_send_to_host(dev, 0xfe); - dev->kbd_poll_phase = KBD_MAIN_LOOP; -} - - -static void -kbd_main_loop(atkbd_t *dev) -{ - uint8_t scan = !dev->kbd_inhibit && keyboard_scan; - - if (dev->kbd_written) { - dev->kbd_written = 0; - kbd_cmd_process(dev); - } else if (scan && (key_queue_start != key_queue_end)) { - /* Scan here. */ - kbd_log("ATkbd: Get %02X from FIFO\n", key_queue[key_queue_start]); - kbd_send_to_host(dev, key_queue[key_queue_start]); - key_queue_start = (key_queue_start + 1) & 0xf; - } -} - - -static void -kbd_cmd_process(atkbd_t *dev) -{ - uint8_t written = dev->kbd_written; - - /* We want data, nothing has been written yet, return. */ - if (dev->kbd_in && !dev->kbd_written) + if (dev->reset_delay) return; - dev->kbd_written = 0; + translate = translate || (keyboard_mode & 0x40) || xt_mode; + translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); - if (!written && !keyboard_scan && dev->kbd_in_cmd && (dev->kbd_phase > 0)) { - kbd_log("ATkbd: Keyboard not written, not scanning, in command, and phase > 0\n"); - kbd_do_command(dev); - } else if (dev->kbd_data == 0xfe) { - kbd_log("ATkbd: Send last byte %02X\n", kbd_last_scan_code); - kbd_send_to_host(dev, kbd_last_scan_code); - dev->kbd_poll_phase = KBD_MAIN_LOOP; - } else if (dev->kbd_data == 0xee) { - kbd_log("ATkbd: Echo EE\n"); - kbd_send_to_host(dev, 0xee); - dev->kbd_poll_phase = KBD_MAIN_LOOP; - } else if (dev->kbd_data >= 0xed) { - kbd_log("ATkbd: Command %02X\n", dev->kbd_data); - if (!keyboard_scan && dev->kbd_in_cmd && (dev->kbd_cmd == 0xed)) { - kbd_log("ATkbd: Not scanning, in command, old command is ED\n"); - keyboard_scan = 1; - dev->kbd_in_cmd = 0; - } - kbd_do_command(dev); - } else { - if (!keyboard_scan && dev->kbd_in_cmd) { - if ((dev->kbd_cmd == 0xf3) && (dev->kbd_data & 0x80)) { - kbd_log("ATkbd: Command F3 data %02X has bit 7 set\n", dev->kbd_data); - kbd_nack(dev); - } else { - kbd_log("ATkbd: Command %02X data %02X\n", dev->kbd_cmd, dev->kbd_data); - kbd_do_command(dev); - } - } else { - kbd_log("ATkbd: Scanning or not in command, NACK\n"); - kbd_nack(dev); - } - } -} + if (translate) + send = nont_to_t[val]; + else + send = val; - -/* Keyboard processing */ -static void -kbd_process(atkbd_t *dev) -{ - /* The real 8048 keyboard firmware stops transmitting if host wants to transmit. */ - if (dev->kbc_written[1] && dev->kbd_written) - dev->kbc_written[1] = 0; - - /* The host has either acknowledged the transmitted byte or we have not transmitted anything (yet). */ - if (!dev->kbc_written[1]) switch (dev->kbd_poll_phase) { - case KBD_MAIN_LOOP: - kbd_main_loop(dev); - break; - case KBD_CMD_PROCESS: - kbd_cmd_process(dev); - break; - } + add_data_kbd_queue(dev, 1, send); } static void -kbc_send_to_ob(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) +add_data_kbd_raw(atkbd_t *dev, uint8_t val) { - uint8_t ch = (channel > 0) ? channel : 1; - uint8_t do_irq = (dev->mem[0x20] & ch); - int translate = (channel == 1) && (keyboard_mode & 0x60); - - if ((channel == 2) && !(dev->flags & KBC_FLAG_PS2)) - return; - - stat_hi |= dev->inhibit; - - if (!dev->kbc_send_pending) { - dev->kbc_send_pending = 1; - dev->kbc_to_send = val; - dev->kbc_channel = channel; - dev->kbc_stat_hi = stat_hi; - return; - } - - if (translate) { - /* Allow for scan code translation. */ - if (val == 0xf0) { - kbd_log("ATkbd: translate is on, F0 prefix detected\n"); - sc_or = 0x80; - return; - } - - /* Skip break code if translated make code has bit 7 set. */ - if ((sc_or == 0x80) && (val & 0x80)) { - kbd_log("ATkbd: translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val); - sc_or = 0; - return; - } - } - - dev->last_irq = (ch == 2) ? 0x1000 : 0x0002; - if (do_irq) { - kbd_log("[%04X:%08X] ATKbc: IRQ %i\n", CS, cpu_state.pc, (ch == 2) ? 12 : 1); - picint(dev->last_irq); - } - kbd_log("ATkbc: %02X coming from channel %i (%i)\n", val, channel, do_irq); - dev->ob = translate ? (nont_to_t[val] | sc_or) : val; - - dev->status = (dev->status & 0x0f) | (stat_hi | (dev->mem[0x20] & STAT_SYSFLAG) | STAT_OFULL); - if (ch == 2) - dev->status |= STAT_MFULL; - - if (translate && (sc_or == 0x80)) - sc_or = 0; -} - - -static void -write_output(atkbd_t *dev, uint8_t val) -{ - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - kbd_log("ATkbc: write output port: %02X (old: %02X)\n", val, dev->p2); - - if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) - val |= ((dev->mem[0x20] << 4) & 0x30); - - dev->kbd_inhibit = (val & 0x40); - dev->mouse_inhibit = (val & 0x08); - - if ((dev->p2 ^ val) & 0x20) { /*IRQ 12*/ - if (val & 0x20) { - kbd_log("ATkbc: write_output(): IRQ 12\n"); - picint(1 << 12); - } else - picintc(1 << 12); - } - if ((dev->p2 ^ val) & 0x10) { /*IRQ 1*/ - if (val & 0x10) { - kbd_log("ATkbc: write_output(): IRQ 1\n"); - picint(1 << 1); - } else - picintc(1 << 1); - } - if ((dev->p2 ^ val) & 0x02) { /*A20 enable change*/ - mem_a20_key = val & 0x02; - mem_a20_recalc(); - flushmmucache(); - } - if ((dev->p2 ^ val) & 0x01) { /*Reset*/ - if (! (val & 0x01)) { - /* Pin 0 selected. */ - softresetx86(); /*Pulse reset!*/ - cpu_set_edx(); - smbase = is_am486dxl ? 0x00060000 : 0x00030000; - } - } - /* Mask off the A20 stuff because we use mem_a20_key directly for that. */ - dev->p2 = val; -} - - -static void -write_cmd(atkbd_t *dev, uint8_t val) -{ - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - kbd_log("ATkbc: write command byte: %02X (old: %02X)\n", val, dev->mem[0x20]); - - /* PS/2 type 2 keyboard controllers always force the XLAT bit to 0. */ - if ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2) - val &= ~CCB_TRANSLATE; - - dev->mem[0x20] = val; - - /* Scan code translate ON/OFF. */ - keyboard_mode &= 0x93; - keyboard_mode |= (val & MODE_MASK); - - kbd_log("ATkbc: keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled"); - - /* ISA AT keyboard controllers use bit 5 for keyboard mode (1 = PC/XT, 2 = AT); - PS/2 (and EISA/PCI) keyboard controllers use it as the PS/2 mouse enable switch. - The AMIKEY firmware apparently uses this bit for something else. */ - if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) { - keyboard_mode &= ~CCB_PCMODE; - /* Update the output port to mirror the KBD DIS and AUX DIS bits, if active. */ - write_output(dev, dev->p2); - - kbd_log("ATkbc: mouse interrupt is now %s\n", (val & 0x02) ? "enabled" : "disabled"); - } - - kbd_log("Command byte now: %02X (%02X)\n", dev->mem[0x20], val); - - dev->status = (dev->status & ~STAT_SYSFLAG) | (val & STAT_SYSFLAG); -} - - -static void -pulse_output(atkbd_t *dev, uint8_t mask) -{ - if (mask != 0x0f) { - dev->old_p2 = dev->p2 & ~(0xf0 | mask); - kbd_log("pulse_output(): Output port now: %02X\n", dev->p2 & (0xf0 | mask | (dev->mem[0x20] & 0x30))); - write_output(dev, dev->p2 & (0xf0 | mask | (dev->mem[0x20] & 0x30))); - timer_set_delay_u64(&dev->pulse_cb, 6ULL * TIMER_USEC); - } -} - - -static void -set_enable_kbd(atkbd_t *dev, uint8_t enable) -{ - dev->mem[0x20] &= 0xef; - dev->mem[0x20] |= (enable ? 0x00 : 0x10); -} - - -static void -set_enable_mouse(atkbd_t *dev, uint8_t enable) -{ - dev->mem[0x20] &= 0xdf; - dev->mem[0x20] |= (enable ? 0x00 : 0x20); -} - - -static void -kbc_transmit(atkbd_t *dev, uint8_t val) -{ - kbc_send_to_ob(dev, val, 0, 0x00); -} - - -static void -kbc_command(atkbd_t *dev) -{ - uint8_t mask, val = dev->ib; - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - int bad = 1; - - if ((dev->kbc_phase > 0) && (dev->kbc_cmd == 0xac)) { - if (dev-> kbc_phase < 16) - kbc_transmit(dev, dev->mem[dev->kbc_phase]); - else if (dev-> kbc_phase == 16) - kbc_transmit(dev, (dev->p1 & 0xf0) | 0x80); - else if (dev-> kbc_phase == 17) - kbc_transmit(dev, dev->p2); - else if (dev-> kbc_phase == 18) - kbc_transmit(dev, dev->status); - - dev->kbc_phase++; - if (dev->kbc_phase == 19) { - dev->kbc_phase = 0; - dev->kbc_cmd = 0x00; - } - return; - } else if ((dev->kbc_phase > 0) && (dev->kbc_cmd == 0xa0) && (kbc_ven >= KBC_VEN_AMI)) { - val = ami_copr[dev->kbc_phase]; - kbc_transmit(dev, val); - if (val == 0x00) { - dev->kbc_phase = 0; - dev->kbc_cmd = 0x00; - } else - dev->kbc_phase++; - return; - } else if ((dev->kbc_in > 0) && (dev->kbc_cmd == 0xa5) && (dev->flags & KBC_FLAG_PS2)) { - /* load security */ - kbd_log("ATkbc: load security\n"); - dev->mem[0x50 + dev->kbc_in - 0x01] = val; - if ((dev->kbc_in == 0x80) && (val != 0x00)) { - /* Security string too long, set it to 0x00. */ - dev->mem[0x50] = 0x00; - dev->kbc_in = 0; - dev->kbc_cmd = 0; - } else if (val == 0x00) { - /* Security string finished. */ - dev->kbc_in = 0; - dev->kbc_cmd = 0; - } else /* Increase pointer and request another byte. */ - dev->kbc_in++; - return; - } - - /* If the written port is 64, go straight to the beginning of the command. */ - if (!(dev->status & STAT_CD) && dev->kbc_in) { - /* Write data to controller. */ - dev->kbc_in = 0; - dev->kbc_phase = 0; - - switch (dev->kbc_cmd) { - case 0x60 ... 0x7f: - if (dev->kbc_cmd == 0x60) - write_cmd(dev, val); - else - dev->mem[(dev->kbc_cmd & 0x1f) + 0x20] = val; - break; - - case 0xc7: /* or input port with system data */ - dev->p1 |= val; - break; - - case 0xcb: /* set keyboard mode */ - kbd_log("New AMIKey mode: %02X\n", val); - dev->ami_mode = val; - dev->flags &= ~KBC_FLAG_PS2; - if (val & 1) - dev->flags |= KBC_FLAG_PS2; - break; - - case 0xd1: /* write output port */ - kbd_log("ATkbc: write output port\n"); - if (dev->p2_locked) { - /*If keyboard controller lines P22-P23 are blocked, - we force them to remain unchanged.*/ - val &= ~0x0c; - val |= (dev->p2 & 0x0c); - } - write_output(dev, val); - break; - - case 0xd2: /* write to keyboard output buffer */ - kbd_log("ATkbc: write to keyboard output buffer\n"); - // kbc_send_to_ob(dev, val, 1, 0x00); - /* Should be channel 1, but we send to 0 to avoid translation, - since bytes output using this command do *NOT* get translated. */ - kbc_send_to_ob(dev, val, 0, 0x00); - break; - - case 0xd3: /* write to mouse output buffer */ - kbd_log("ATkbc: write to mouse output buffer\n"); - if (dev->flags & KBC_FLAG_PS2) - kbc_send_to_ob(dev, val, 2, 0x00); - break; - - case 0xd4: /* write to mouse */ - kbd_log("ATkbc: write to mouse (%02X)\n", val); - - if (dev->flags & KBC_FLAG_PS2) { - set_enable_mouse(dev, 1); - dev->mem[0x20] &= ~0x20; - if (mouse_write && !dev->kbc_written[2]) { - kbd_log("ATkbc: Sending %02X to mouse...\n", dev->ib); - dev->mouse_data = val; - dev->mouse_written = 1; - dev->kbc_wait_for_response = 2; - } else - kbc_send_to_ob(dev, 0xfe, 2, 0x40); - } - break; - - default: - /* - * Run the vendor-specific handler - * if we have one. Otherwise, or if - * it returns an error, log a bad - * controller command. - */ - if (dev->write60_ven) - bad = dev->write60_ven(dev, val); - -#ifdef ENABLE_KEYBOARD_AT_LOG - if (bad) - kbd_log("ATkbc: bad controller command %02x data %02x\n", dev->kbc_cmd, val); -#endif - } - } else { - /* Controller command. */ - kbd_log("ATkbc: Controller command: %02X\n", val); - dev->kbc_in = 0; - dev->kbc_phase = 0; - - switch (val) { - /* Read data from KBC memory. */ - case 0x20 ... 0x3f: - kbc_transmit(dev, dev->mem[(val & 0x1f) + 0x20]); - break; - - /* Write data to KBC memory. */ - case 0x60 ... 0x7f: - dev->kbc_in = 1; - break; - - case 0xaa: /* self-test */ - kbd_log("ATkbc: self-test\n"); - write_output(dev, (dev->flags & KBC_FLAG_PS2) ? 0x4b : 0xcf); - - /* Always reinitialize all queues - the real hardware pulls keyboard and mouse - clocks high, which stops keyboard scanning. */ - kbd_log("ATkbc: self-test reinitialization\n"); - dev->kbd_in_cmd = dev->mouse_in_cmd = 0; - dev->status &= ~STAT_OFULL; - dev->last_irq = 0; - dev->kbc_phase = 0; - - /* Phoenix MultiKey should have 0x60 | STAT_SYSFLAG. */ - if (dev->flags & KBC_FLAG_PS2) - write_cmd(dev, 0x30 | STAT_SYSFLAG); - else - write_cmd(dev, 0x10 | STAT_SYSFLAG); - kbc_transmit(dev, 0x55); - break; - - case 0xab: /* interface test */ - kbd_log("ATkbc: interface test\n"); - /* No error. */ - kbc_transmit(dev, 0x00); - break; - - case 0xac: /* diagnostic dump */ - kbd_log("ATkbc: diagnostic dump\n"); - kbc_transmit(dev, dev->mem[0x20]); - dev->kbc_phase = 1; - break; - - case 0xad: /* disable keyboard */ - kbd_log("ATkbc: disable keyboard\n"); - set_enable_kbd(dev, 0); - break; - - case 0xae: /* enable keyboard */ - kbd_log("ATkbc: enable keyboard\n"); - set_enable_kbd(dev, 1); - break; - - case 0xc7: /* or input port with system data */ - kbd_log("ATkbc: Phoenix - or input port with system data\n"); - dev->kbc_in = 1; - break; - - case 0xca: /* read keyboard mode */ - kbd_log("ATkbc: AMI - read keyboard mode\n"); - kbc_transmit(dev, dev->ami_mode); - break; - - case 0xcb: /* set keyboard mode */ - kbd_log("ATkbc: AMI - set keyboard mode\n"); - dev->kbc_in = 1; - break; - - case 0xd0: /* read output port */ - kbd_log("ATkbc: read output port\n"); - mask = 0xff; - if (dev->mem[0x20] & 0x10) - mask &= 0xbf; - if ((dev->flags & KBC_FLAG_PS2) && (dev->mem[0x20] & 0x20)) - mask &= 0xf7; - kbc_transmit(dev, dev->p2 & mask); - break; - - case 0xd1: /* write output port */ - kbd_log("ATkbc: write output port\n"); - dev->kbc_in = 1; - break; - - case 0xd2: /* write keyboard output buffer */ - kbd_log("ATkbc: write keyboard output buffer\n"); - if (dev->flags & KBC_FLAG_PS2) - dev->kbc_in = 1; - else - kbc_transmit(dev, 0x00); /* NCR */ - break; - - case 0xdd: /* disable A20 address line */ - case 0xdf: /* enable A20 address line */ - kbd_log("ATkbc: %sable A20\n", (val == 0xdd) ? "dis": "en"); - write_output(dev, (dev->p2 & 0xfd) | (val & 0x02)); - break; - - case 0xe0: /* read test inputs */ - kbd_log("ATkbc: read test inputs\n"); - kbc_transmit(dev, 0x00); - break; - - case 0xe1: case 0xea: - kbd_log("ATkbc: setting P23-P21 to %01X\n", val & 0x0e); - write_output(dev, (dev->p2 & 0xf1) | (val & 0x0e)); - break; - - default: - /* - * Unrecognized controller command. - * - * If we have a vendor-specific handler, run - * that. Otherwise, or if that handler fails, - * log a bad command. - */ - if (dev->write64_ven) - bad = dev->write64_ven(dev, val); - - kbd_log(bad ? "ATkbc: bad controller command %02X\n" : "", val); - } - - /* If the command needs data, remember the command. */ - if (dev->kbc_in || (dev->kbc_phase > 0)) - dev->kbc_cmd = val; - } -} - - -static void -kbc_dev_data_to_ob(atkbd_t *dev, uint8_t channel) -{ - dev->kbc_written[channel] = 0; - kbd_log("ATkbd: Forwarding %02X from channel %i...\n", dev->kbc_data[channel], channel); - kbc_send_to_ob(dev, dev->kbc_data[channel], channel, 0x00); -} - - -static void -kbc_main_loop_scan(atkbd_t *dev) -{ - uint8_t port_dis = dev->mem[0x20] & 0x30; - uint8_t ps2 = (dev->flags & KBC_FLAG_PS2); - - if (!ps2) - port_dis |= 0x20; - - if (!(dev->status & STAT_OFULL)) { - if (port_dis & 0x20) { - if (!(port_dis & 0x10)) { - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Main loop\n" - "ATkbc: Scan: AUX DIS, KBD EN\n"); - // kbd_log("ATkbc: Scan: AUX DIS, KBD EN\n"); - /* Enable communication with keyboard. */ - dev->p2 &= 0xbf; - dev->kbd_inhibit = 0; - kbc_wait(dev, 1); - } -#ifdef ENABLE_KEYBOARD_AT_LOG - else { - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Main loop\n" - "ATkbc: Scan: AUX DIS, KBD DIS\n"); - // kbd_log("ATkbc: Scan: AUX DIS, KBD DIS\n"); - } -#endif - } else { - /* Enable communication with mouse. */ - dev->p2 &= 0xf7; - dev->mouse_inhibit = 0; - if (dev->mem[0x20] & 0x10) { - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Main loop\n" - "ATkbc: Scan: AUX EN , KBD DIS\n"); - // kbd_log("ATkbc: Scan: AUX EN , KBD DIS\n"); - kbc_wait(dev, 2); - } else { - /* Enable communication with keyboard. */ - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Main loop\n" - "ATkbc: Scan: AUX EN , KBD EN\n"); - // kbd_log("ATkbc: Scan: AUX EN , KBD EN\n"); - dev->p2 &= 0xbf; - dev->kbd_inhibit = 0; - kbc_wait(dev, 3); - } - } - } -#ifdef ENABLE_KEYBOARD_AT_LOG - else { - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Main loop\n" - "ATkbc: Scan: IBF not full and OBF full, do nothing\n"); - // kbd_log("ATkbc: Scan: IBF not full and OBF full, do nothing\n"); - } -#endif -} - - -static void -kbc_process_ib(atkbd_t *dev) -{ - dev->status &= ~STAT_IFULL; - - if (dev->status & STAT_CD) { - dev->kbc_in_cmd = 1; - kbc_command(dev); - - if ((dev->kbc_phase == 0) && !dev->kbc_in) - dev->kbc_in_cmd = 0; - else - return; - } else { - dev->mem[0x20] &= ~0x10; - dev->kbd_data = dev->ib; - dev->kbd_written = 1; - dev->kbc_wait_for_response = 1; - } - - dev->kbc_poll_phase = KBC_MAIN_LOOP; - if (!dev->kbc_wait_for_response) - kbc_main_loop_scan(dev); -} - - -static void -kbc_wait(atkbd_t *dev, uint8_t flags) -{ - if ((flags & 1) && dev->kbc_written[1]) { - /* Disable communication with mouse. */ - dev->p2 |= 0x08; - dev->mouse_inhibit = 1; - /* Send keyboard byte to host. */ - kbc_dev_data_to_ob(dev, CHANNEL_KBD); - dev->kbc_poll_phase = KBC_MAIN_LOOP; - } else if ((flags & 2) && dev->kbc_written[2]) { - /* Disable communication with keyboard. */ - dev->p2 |= 0x40; - dev->kbd_inhibit = 1; - /* Send mouse byte to host. */ - kbc_dev_data_to_ob(dev, CHANNEL_MOUSE); - dev->kbc_poll_phase = KBC_MAIN_LOOP; - } else if (dev->status & STAT_IFULL) { - /* Disable communication with keyboard and mouse. */ - dev->p2 |= 0x48; - dev->kbd_inhibit = dev->mouse_inhibit = 1; - kbc_process_ib(dev); - } else - dev->kbc_poll_phase = KBC_WAIT | flags; -} - - -/* Controller processing */ -static void -kbc_process(atkbd_t *dev) -{ - // kbd_log("ATkbc: kbc_process()\n"); - - /* If we're waiting for the response from the keyboard or mouse, do nothing - until the device has repsonded back. */ - if (dev->kbc_wait_for_response > 0) { - if (dev->kbc_written[dev->kbc_wait_for_response]) - dev->kbc_wait_for_response = 0; - else - return; - } - - if (dev->kbc_send_pending) { - kbd_log("ATkbc: Sending delayed %02X on channel %i with high status %02X\n", - dev->kbc_to_send, dev->kbc_channel, dev->kbc_stat_hi); - kbc_send_to_ob(dev, dev->kbc_to_send, dev->kbc_channel, dev->kbc_stat_hi); - dev->kbc_send_pending = 0; - } - - if (dev->kbc_poll_phase == KBC_RESET) { - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Reset loop()\n"); - - if (dev->status & STAT_IFULL) { - dev->status &= ~STAT_IFULL; - - if ((dev->status & STAT_CD) && (dev->ib == 0xaa)) { - dev->kbc_in_cmd = 1; - kbc_command(dev); - - if ((dev->kbc_phase == 0) && !dev->kbc_in) - dev->kbc_in_cmd = 0; - - dev->kbc_poll_phase = KBC_MAIN_LOOP; - } - } - - return; - } - - if (dev->kbc_in_cmd || (dev->kbc_phase > 0) || dev->kbc_in) { - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: In a command\n"); - if (!dev->kbc_in && (dev->status & STAT_OFULL)) { - kbd_log("ATkbc: !dev->kbc_in && (dev->status & STAT_OFULL)\n"); - return; /* We do not want input and we're waiting for the host to read the data - we transmitted, but it has not done that yet, do nothing. */ - } else if (dev->kbc_in && !(dev->status & STAT_IFULL)) { - kbd_log("ATkbc: dev->kbc_in && !(dev->status & STAT_IFULL)\n"); - return; /* We want input and the host has not provided us with any yet, do nothing. */ - } -#ifdef ENABLE_KEYBOARD_AT_LOG - else - kbd_log("ATkbc: Normal condition\n"); -#endif - - if (dev->status & STAT_IFULL) { - dev->status &= ~STAT_IFULL; - - if (dev->status & STAT_CD) { - kbd_log("ATkbc: Resetting command\n"); - dev->kbc_phase = 0; - dev->kbc_in = 0; - } - } - - /* Process command. */ - kbc_command(dev); - - if ((dev->kbc_phase == 0) && !dev->kbc_in) - dev->kbc_in_cmd = 0; - else - return; - - if (!(dev->status & STAT_OFULL)) - kbc_main_loop_scan(dev); - /* Make absolutely sure to do nothing if OBF is full and IBF is empty. */ - } else if (!(dev->status & STAT_OFULL) || (dev->status & STAT_IFULL)) switch (dev->kbc_poll_phase) { - case KBC_MAIN_LOOP: - // kbd_log("ATkbc: Main loop\n"); - if (dev->status & STAT_IFULL) { - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Main loop\n" - "ATkbc: IBF full, process\n"); - kbc_process_ib(dev); - } else - kbc_main_loop_scan(dev); - break; - case KBC_WAIT_FOR_KBD: - case KBC_WAIT_FOR_MOUSE: - case KBC_WAIT_FOR_BOTH: - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Scan: Phase %i\n", dev->kbc_poll_phase); - kbc_wait(dev, dev->kbc_poll_phase & 3); - break; - default: - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Scan: Invalid phase %i\n", dev->kbc_poll_phase); - break; - } + add_data_kbd_queue(dev, 1, val); } @@ -1792,29 +742,105 @@ static void kbd_poll(void *priv) { atkbd_t *dev = (atkbd_t *)priv; +#ifdef ENABLE_KEYBOARD_AT_LOG + const uint8_t channels[4] = { 1, 2, 0, 0 }; +#endif timer_advance_u64(&dev->send_delay_timer, (100ULL * TIMER_USEC)); - /* We process all three devices at the same time, in an arbitrary order. */ + if (dev->out_new != -1 && !dev->last_irq) { + dev->wantirq = 0; + if (dev->out_new & 0x100) { + if (dev->mem[0] & 0x02) + picint(0x1000); + kbd_log("ATkbc: %02X coming from channel 2\n"); + dev->out = dev->out_new & 0xff; + dev->out_new = -1; + dev->status = (dev->status & ~STAT_IFULL) | (STAT_OFULL | STAT_MFULL); + dev->last_irq = 0x1000; + } else { + if (dev->mem[0] & 0x01) + picint(2); + kbd_log("ATkbc: %02X coming from channel %i\n", dev->out_new & 0xff, channels[(dev->out_new >> 8) & 0x03]); + dev->out = dev->out_new & 0xff; + dev->out_new = -1; + dev->status = (dev->status & ~(STAT_IFULL | STAT_MFULL)) | STAT_OFULL; + dev->last_irq = 2; + } + } - /* Keyboard processing */ - kbd_process(dev); + if (dev->out_new == -1 && !(dev->status & STAT_OFULL) && key_ctrl_queue_start != key_ctrl_queue_end) { + kbd_log("ATkbc: %02X on channel 0\n", key_ctrl_queue[key_ctrl_queue_start]); + dev->out_new = key_ctrl_queue[key_ctrl_queue_start] | 0x200; + key_ctrl_queue_start = (key_ctrl_queue_start + 1) & 0xf; + } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && dev->out_delayed != -1) { + kbd_log("ATkbc: %02X delayed on channel %i\n", dev->out_delayed & 0xff, channels[(dev->out_delayed >> 8) & 0x03]); + dev->out_new = dev->out_delayed; + dev->out_delayed = -1; + } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && mouse_queue_start != mouse_queue_end) { + kbd_log("ATkbc: %02X on channel 2\n", mouse_queue[mouse_queue_start]); + dev->out_new = mouse_queue[mouse_queue_start] | 0x100; + mouse_queue_start = (mouse_queue_start + 1) & 0xf; + } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && !(dev->mem[0] & 0x10) && key_queue_start != key_queue_end) { + kbd_log("ATkbc: %02X on channel 1\n", key_queue[key_queue_start]); + dev->out_new = key_queue[key_queue_start]; + key_queue_start = (key_queue_start + 1) & 0xf; + } - /* TODO: Mouse processing */ - // mouse_process(dev); + if (dev->reset_delay) { + dev->reset_delay--; + if (!dev->reset_delay) { + kbd_log("ATkbc: Sending AA on keyboard reset...\n"); + add_data_kbd_direct(dev, 0xaa); + } + } +} - /* Controller processing */ - kbc_process(dev); + +static void +add_data(atkbd_t *dev, uint8_t val) +{ + kbd_log("ATkbc: add to queue\n"); + + kbd_log("ATkbc: key_ctrl_queue[%02X] = %02X;\n", key_ctrl_queue_end, val); + kbc_queue_add(dev, val, 0, 0x00); + + if (!(dev->out_new & 0x300)) { + dev->out_delayed = dev->out_new; + dev->out_new = -1; + } } static void add_data_vals(atkbd_t *dev, uint8_t *val, uint8_t len) { + int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); + int translate = (keyboard_mode & 0x40); int i; + uint8_t or = 0; + uint8_t send; - for (i = 0; i < len; i++) - add_data_kbd_queue(dev, 0, val[i]); + if (dev->reset_delay) + return; + + translate = translate || (keyboard_mode & 0x40) || xt_mode; + translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); + + for (i = 0; i < len; i++) { + if (translate) { + if (val[i] == 0xf0) { + or = 0x80; + continue; + } + send = nont_to_t[val[i]] | or; + if (or == 0x80) + or = 0; + } else + send = val[i]; + + add_data_kbd_queue(dev, 0, send); + } } @@ -1822,21 +848,56 @@ static void add_data_kbd(uint16_t val) { atkbd_t *dev = SavedKbd; + int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); + int translate = (keyboard_mode & 0x40); uint8_t fake_shift[4]; uint8_t num_lock = 0, shift_states = 0; uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - if (dev->kbd_in || (dev->kbd_phase > 0)) + if (dev->reset_delay) return; + translate = translate || (keyboard_mode & 0x40) || xt_mode; + translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); + keyboard_get_states(NULL, &num_lock, NULL); shift_states = keyboard_get_shift() & STATE_SHIFT_MASK; - /* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */ - if ((dev != NULL) && (kbc_ven == KBC_VEN_TOSHIBA) && (keyboard_recv(0xb8) || keyboard_recv(0x9d)) && - (val >= 0x4f) && (val <= 0x54) && (val != 0x4e)) - t3100e_notify_set((val + 2) & 0x0f); + /* Allow for scan code translation. */ + if (translate && (val == 0xf0)) { + kbd_log("ATkbd: translate is on, F0 prefix detected\n"); + sc_or = 0x80; + return; + } + /* Skip break code if translated make code has bit 7 set. */ + if (translate && (sc_or == 0x80) && (val & 0x80)) { + kbd_log("ATkbd: translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val); + sc_or = 0; + return; + } + + /* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */ + if ((dev != NULL) && (kbc_ven == KBC_VEN_TOSHIBA) && + (keyboard_recv(0xb8) || keyboard_recv(0x9d))) switch (val) { + case 0x4f: t3100e_notify_set(0x01); break; /* End */ + case 0x50: t3100e_notify_set(0x02); break; /* Down */ + case 0x51: t3100e_notify_set(0x03); break; /* PgDn */ + case 0x52: t3100e_notify_set(0x04); break; /* Ins */ + case 0x53: t3100e_notify_set(0x05); break; /* Del */ + case 0x54: t3100e_notify_set(0x06); break; /* SysRQ */ + case 0x45: t3100e_notify_set(0x07); break; /* NumLock */ + case 0x46: t3100e_notify_set(0x08); break; /* ScrLock */ + case 0x47: t3100e_notify_set(0x09); break; /* Home */ + case 0x48: t3100e_notify_set(0x0a); break; /* Up */ + case 0x49: t3100e_notify_set(0x0b); break; /* PgUp */ + case 0x4A: t3100e_notify_set(0x0c); break; /* Keypad -*/ + case 0x4B: t3100e_notify_set(0x0d); break; /* Left */ + case 0x4C: t3100e_notify_set(0x0e); break; /* KP 5 */ + case 0x4D: t3100e_notify_set(0x0f); break; /* Right */ + } + + kbd_log("ATkbd: translate is %s, ", translate ? "on" : "off"); switch(val) { case FAKE_LSHIFT_ON: kbd_log("fake left shift on, scan code: "); @@ -1969,7 +1030,18 @@ add_data_kbd(uint16_t val) break; default: - add_data_kbd_queue(dev, 0, val); +#ifdef ENABLE_KEYBOARD_AT_LOG + kbd_log("scan code: "); + if (translate) { + kbd_log("%02X (original: ", (nont_to_t[val] | sc_or)); + if (sc_or == 0x80) + kbd_log("F0 "); + kbd_log("%02X)\n", val); + } else + kbd_log("%02X\n", val); +#endif + + add_data_kbd_queue(dev, 0, translate ? (nont_to_t[val] | sc_or) : val); break; } @@ -1978,13 +1050,121 @@ add_data_kbd(uint16_t val) } +static void +write_output(atkbd_t *dev, uint8_t val) +{ + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + kbd_log("ATkbc: write output port: %02X (old: %02X)\n", val, dev->output_port); + + if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF)) + val |= ((dev->mem[0] << 4) & 0x10); + + if ((dev->output_port ^ val) & 0x20) { /*IRQ 12*/ + if (val & 0x20) + picint(1 << 12); + else + picintc(1 << 12); + } + if ((dev->output_port ^ val) & 0x10) { /*IRQ 1*/ + if (val & 0x10) + picint(1 << 1); + else + picintc(1 << 1); + } + if ((dev->output_port ^ val) & 0x02) { /*A20 enable change*/ + mem_a20_key = val & 0x02; + mem_a20_recalc(); + flushmmucache(); + } + if ((dev->output_port ^ val) & 0x01) { /*Reset*/ + if (! (val & 0x01)) { + /* Pin 0 selected. */ + softresetx86(); /*Pulse reset!*/ + cpu_set_edx(); + smbase = is_am486dxl ? 0x00060000 : 0x00030000; + } + } + /* Mask off the A20 stuff because we use mem_a20_key directly for that. */ + dev->output_port = val; +} + + +static void +write_cmd(atkbd_t *dev, uint8_t val) +{ + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + kbd_log("ATkbc: write command byte: %02X (old: %02X)\n", val, dev->mem[0]); + + if ((val & 1) && (dev->status & STAT_OFULL)) + dev->wantirq = 1; + if (!(val & 1) && dev->wantirq) + dev->wantirq = 0; + + /* PS/2 type 2 keyboard controllers always force the XLAT bit to 0. */ + if ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2) { + val &= ~CCB_TRANSLATE; + dev->mem[0] &= ~CCB_TRANSLATE; + } + + /* Scan code translate ON/OFF. */ + keyboard_mode &= 0x93; + keyboard_mode |= (val & MODE_MASK); + + kbd_log("ATkbc: keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled"); + + /* ISA AT keyboard controllers use bit 5 for keyboard mode (1 = PC/XT, 2 = AT); + PS/2 (and EISA/PCI) keyboard controllers use it as the PS/2 mouse enable switch. + The AMIKEY firmware apparently uses this bit for something else. */ + if ((kbc_ven == KBC_VEN_AMI) || + ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) { + keyboard_mode &= ~CCB_PCMODE; + /* Update the output port to mirror the KBD DIS and AUX DIS bits, if active. */ + write_output(dev, dev->output_port); + + kbd_log("ATkbc: mouse interrupt is now %s\n", (val & 0x02) ? "enabled" : "disabled"); + } + + kbd_log("Command byte now: %02X (%02X)\n", dev->mem[0], val); + + dev->status = (dev->status & ~STAT_SYSFLAG) | (val & STAT_SYSFLAG); +} + + +static void +pulse_output(atkbd_t *dev, uint8_t mask) +{ + if (mask != 0x0f) { + dev->old_output_port = dev->output_port & ~(0xf0 | mask); + kbd_log("pulse_output(): Output port now: %02X\n", dev->output_port & (0xf0 | mask)); + write_output(dev, dev->output_port & (0xf0 | mask)); + timer_set_delay_u64(&dev->pulse_cb, 6ULL * TIMER_USEC); + } +} + + static void pulse_poll(void *priv) { atkbd_t *dev = (atkbd_t *)priv; - kbd_log("pulse_poll(): Output port now: %02X\n", dev->p2 | dev->old_p2); - write_output(dev, dev->p2 | dev->old_p2); + kbd_log("pulse_poll(): Output port now: %02X\n", dev->output_port | dev->old_output_port); + write_output(dev, dev->output_port | dev->old_output_port); +} + + +static void +set_enable_kbd(atkbd_t *dev, uint8_t enable) +{ + dev->mem[0] &= 0xef; + dev->mem[0] |= (enable ? 0x00 : 0x10); +} + + +static void +set_enable_mouse(atkbd_t *dev, uint8_t enable) +{ + dev->mem[0] &= 0xdf; + dev->mem[0] |= (enable ? 0x00 : 0x20); } @@ -1993,70 +1173,49 @@ write64_generic(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; uint8_t current_drive, fixed_bits; - uint8_t kbc_ven = 0x0; - kbc_ven = dev->flags & KBC_VEN_MASK; + uint8_t kbc_ven = 0x0; + kbc_ven = dev->flags & KBC_VEN_MASK; + switch (val) { case 0xa4: /* check if password installed */ - if (dev->flags & KBC_FLAG_PS2) { + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: check if password installed\n"); - kbc_transmit(dev, (dev->mem[0x50] == 0x00) ? 0xf1 : 0xfa); - return 0; - } - break; - - case 0xa5: /* load security */ - if (dev->flags & KBC_FLAG_PS2) { - kbd_log("ATkbc: load security\n"); - dev->kbc_in = 1; + add_data(dev, 0xf1); return 0; } break; case 0xa7: /* disable mouse port */ - if (dev->flags & KBC_FLAG_PS2) { + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: disable mouse port\n"); - // kbc_transmit(dev, 0); + set_enable_mouse(dev, 0); return 0; } break; case 0xa8: /*Enable mouse port*/ - if (dev->flags & KBC_FLAG_PS2) { + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: enable mouse port\n"); - // kbc_transmit(dev, 1); + set_enable_mouse(dev, 1); return 0; } break; case 0xa9: /*Test mouse port*/ kbd_log("ATkbc: test mouse port\n"); - if (dev->flags & KBC_FLAG_PS2) { - /* No error, this is testing the channel 2 interface. */ - kbc_transmit(dev, 0x00); + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + add_data(dev, 0x00); /* no error, this is testing the channel 2 interface */ return 0; } break; case 0xaf: /* read keyboard version */ kbd_log("ATkbc: read keyboard version\n"); - kbc_transmit(dev, 0x00); + add_data(dev, 0x00); return 0; case 0xc0: /* read input port */ - /* IBM PS/1: - Bit 2 and 4 ignored (we return always 0), - Bit 6 must 1 for 5.25" floppy drive, 0 for 3.5". - Intel AMI: - Bit 2 ignored (we return always 1), - Bit 4 must be 1, - Bit 6 must be 1 or else error in SMM. - Acer: - Bit 2 must be 0 (and Acer V10 disables CMOS setup if it's 1), - Bit 4 must be 0, - Bit 6 ignored. - P6RP4: - Bit 2 must be 1 or CMOS setup is disabled. */ kbd_log("ATkbc: read input port\n"); fixed_bits = 4; /* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */ @@ -2064,8 +1223,11 @@ write64_generic(void *priv, uint8_t val) fixed_bits |= 0x40; if (kbc_ven == KBC_VEN_IBM_PS1) { current_drive = fdc_get_current_drive(); - kbc_transmit(dev, dev->p1 | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00)); - dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc) | (fdd_is_525(current_drive) ? 0x40 : 0x00); + add_to_kbc_queue_front(dev, dev->input_port | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00), + 0, 0x00); + dev->input_port = ((dev->input_port + 1) & 3) | + (dev->input_port & 0xfc) | + (fdd_is_525(current_drive) ? 0x40 : 0x00); } else if (kbc_ven == KBC_VEN_NCR) { /* switch settings * bit 7: keyboard disable @@ -2077,34 +1239,39 @@ write64_generic(void *priv, uint8_t val) * bit 1: high/auto speed * bit 0: dma mode */ - kbc_transmit(dev, (dev->p1 | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf); - dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc); + add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf, + 0, 0x00); + dev->input_port = ((dev->input_port + 1) & 3) | + (dev->input_port & 0xfc); } else { - pclog("[%04X:%08X] Reading %02X from input port\n", CS, cpu_state.pc, ((dev->p1 | fixed_bits) & 0xf0) | 0x0c); - if ((dev->flags & KBC_FLAG_PS2) && ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI)) - // kbc_transmit(dev, ((dev->p1 | fixed_bits) & 0xf0) | 0x0c); - kbc_transmit(dev, ((dev->p1 | fixed_bits) & 0xf0) | 0x08); - // kbc_transmit(dev, (dev->p1 | fixed_bits) & (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0xeb : 0xef)); + if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) && + ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI)) + add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits) & + (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0xeb : 0xef), 0, 0x00); else - kbc_transmit(dev, dev->p1 | fixed_bits); - dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc); + add_to_kbc_queue_front(dev, dev->input_port | fixed_bits, 0, 0x00); + dev->input_port = ((dev->input_port + 1) & 3) | + (dev->input_port & 0xfc); } return 0; case 0xd3: /* write mouse output buffer */ - if (dev->flags & KBC_FLAG_PS2) { + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: write mouse output buffer\n"); - dev->kbc_in = 1; + dev->want60 = 1; return 0; } break; case 0xd4: /* write to mouse */ kbd_log("ATkbc: write to mouse\n"); - dev->kbc_in = 1; + dev->want60 = 1; return 0; - case 0xf0 ... 0xff: + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: kbd_log("ATkbc: pulse %01X\n", val & 0x0f); pulse_output(dev, val & 0x0f); return 0; @@ -2119,168 +1286,35 @@ static uint8_t write60_ami(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; - uint16_t index = 0x00c0; - switch(dev->kbc_cmd) { - /* 0x40 - 0x5F are aliases for 0x60 - 0x7F */ - case 0x40 ... 0x5f: - kbd_log("ATkbc: AMI - alias write to %08X\n", dev->kbc_cmd); - if (dev->kbc_cmd == 0x40) + switch(dev->command) { + /* 0x40 - 0x5F are aliases for 0x60-0x7F */ + case 0x40: case 0x41: case 0x42: case 0x43: + case 0x44: case 0x45: case 0x46: case 0x47: + case 0x48: case 0x49: case 0x4a: case 0x4b: + 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: case 0x5f: + kbd_log("ATkbc: AMI - alias write to %08X\n", dev->command); + dev->mem[dev->command & 0x1f] = val; + if (dev->command == 0x60) write_cmd(dev, val); - else - dev->mem[(dev->kbc_cmd & 0x1f) + 0x20] = val; return 0; case 0xaf: /* set extended controller RAM */ - kbd_log("ATkbc: AMI - set extended controller RAM, input phase %i\n", dev->secr_phase); - if (dev->secr_phase == 0) { - dev->mem_index = val; - dev->kbc_in = 1; - dev->secr_phase++; - } else if (dev->secr_phase == 1) { - if (dev->mem_index == 0x20) - write_cmd(dev, val); - else - dev->mem[dev->mem_index] = val; + kbd_log("ATkbc: AMI - set extended controller RAM\n"); + if (dev->secr_phase == 1) { + dev->mem_addr = val; + dev->want60 = 1; + dev->secr_phase = 2; + } else if (dev->secr_phase == 2) { + dev->mem[dev->mem_addr] = val; dev->secr_phase = 0; } return 0; - case 0xb8: - kbd_log("ATkbc: AMI MegaKey - memory index %02X\n", val); - dev->mem_index = val; - return 0; - - case 0xbb: - kbd_log("ATkbc: AMI MegaKey - write %02X to memory index %02X\n", val, dev->mem_index); - if (dev->mem_index >= 0x80) { - switch (dev->mem[0x9b] & 0xc0) { - case 0x00: - index = 0x0080; - break; - case 0x40: case 0x80: - index = 0x0000; - break; - case 0xc0: - index = 0x0100; - break; - } - dev->mem[index + dev->mem_index] = val; - } else if (dev->mem_index == 0x60) - write_cmd(dev, val); - else if (dev->mem_index == 0x42) - dev->status = val; - else if (dev->mem_index >= 0x40) - dev->mem[dev->mem_index - 0x40] = val; - else - dev->mem_int[dev->mem_index] = val; - return 0; - - case 0xbd: - kbd_log("ATkbc: AMI MegaKey - write %02X to config index %02X\n", val, dev->mem_index); - switch (dev->mem_index) { - case 0x00: /* STAT8042 */ - dev->status = val; - break; - case 0x01: /* Password_ptr */ - dev->mem[0x1c] = val; - break; - case 0x02: /* Wakeup_Tsk_Reg */ - dev->mem[0x1e] = val; - break; - case 0x03: /* CCB */ - write_cmd(dev, val); - break; - case 0x04: /* Debounce_time */ - dev->mem[0x4d] = val; - break; - case 0x05: /* Pulse_Width */ - dev->mem[0x4e] = val; - break; - case 0x06: /* Pk_sel_byte */ - dev->mem[0x4c] = val; - break; - case 0x07: /* Func_Tsk_Reg */ - dev->mem[0x7e] = val; - break; - case 0x08: /* TypematicRate */ - dev->mem[0x80] = val; - break; - case 0x09: /* Led_Flag_Byte */ - dev->mem[0x81] = val; - break; - case 0x0a: /* Kbms_Command_St */ - dev->mem[0x87] = val; - break; - case 0x0b: /* Delay_Count_Byte */ - dev->mem[0x86] = val; - break; - case 0x0c: /* KBC_Flags */ - dev->mem[0x9b] = val; - break; - case 0x0d: /* SCODE_HK1 */ - dev->mem[0x50] = val; - break; - case 0x0e: /* SCODE_HK2 */ - dev->mem[0x51] = val; - break; - case 0x0f: /* SCODE_HK3 */ - dev->mem[0x52] = val; - break; - case 0x10: /* SCODE_HK4 */ - dev->mem[0x53] = val; - break; - case 0x11: /* SCODE_HK5 */ - dev->mem[0x54] = val; - break; - case 0x12: /* SCODE_HK6 */ - dev->mem[0x55] = val; - break; - case 0x13: /* TASK_HK1 */ - dev->mem[0x56] = val; - break; - case 0x14: /* TASK_HK2 */ - dev->mem[0x57] = val; - break; - case 0x15: /* TASK_HK3 */ - dev->mem[0x58] = val; - break; - case 0x16: /* TASK_HK4 */ - dev->mem[0x59] = val; - break; - case 0x17: /* TASK_HK5 */ - dev->mem[0x5a] = val; - break; - /* The next 4 bytes have uncertain correspondences. */ - case 0x18: /* Batt_Poll_delay_Time */ - dev->mem[0x5b] = val; - break; - case 0x19: /* Batt_Alarm_Reg1 */ - dev->mem[0x5c] = val; - break; - case 0x1a: /* Batt_Alarm_Reg2 */ - dev->mem[0x5d] = val; - break; - case 0x1b: /* Batt_Alarm_Tsk_Reg */ - dev->mem[0x5e] = val; - break; - case 0x1c: /* Kbc_State1 */ - dev->mem[0x9d] = val; - break; - case 0x1d: /* Aux_Config */ - dev->mem[0x75] = val; - break; - case 0x1e: /* Kbc_State3 */ - dev->mem[0x73] = val; - break; - } - return 0; - - case 0xc1: /* write input port */ - kbd_log("ATkbc: AMI MegaKey - write %02X to input port\n", val); - dev->p1 = val; - return 0; - case 0xcb: /* set keyboard mode */ kbd_log("ATkbc: AMI - set keyboard mode\n"); return 0; @@ -2294,50 +1328,62 @@ static uint8_t write64_ami(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; - uint16_t index = 0x00c0; switch (val) { - case 0x00 ... 0x1f: + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x18: case 0x19: case 0x1a: case 0x1b: + case 0x1c: case 0x1d: case 0x1e: case 0x1f: kbd_log("ATkbc: AMI - alias read from %08X\n", val); - kbc_transmit(dev, dev->mem[val + 0x20]); + add_data(dev, dev->mem[val]); return 0; - case 0x40 ... 0x5f: - kbd_log("ATkbc: AMI - alias write to %08X\n", dev->kbc_cmd); - dev->kbc_in = 1; + case 0x40: case 0x41: case 0x42: case 0x43: + case 0x44: case 0x45: case 0x46: case 0x47: + case 0x48: case 0x49: case 0x4a: case 0x4b: + 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: case 0x5f: + kbd_log("ATkbc: AMI - alias write to %08X\n", dev->command); + dev->want60 = 1; return 0; case 0xa0: /* copyright message */ - kbc_transmit(dev, ami_copr[0]); - dev->kbc_phase = 1; - return 0; + add_data(dev, 0x28); + add_data(dev, 0x00); + break; case 0xa1: /* get controller version */ kbd_log("ATkbc: AMI - get controller version\n"); - // kbc_transmit(dev, 'H'); - kbc_transmit(dev, '5'); + add_data(dev, 'H'); return 0; case 0xa2: /* clear keyboard controller lines P22/P23 */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - clear KBC lines P22 and P23\n"); - write_output(dev, dev->p2 & 0xf3); - kbc_transmit(dev, 0x00); + write_output(dev, dev->output_port & 0xf3); + add_data(dev, 0x00); return 0; } break; case 0xa3: /* set keyboard controller lines P22/P23 */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - set KBC lines P22 and P23\n"); - write_output(dev, dev->p2 | 0x0c); - kbc_transmit(dev, 0x00); + write_output(dev, dev->output_port | 0x0c); + add_data(dev, 0x00); return 0; } break; case 0xa4: /* write clock = low */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - write clock = low\n"); dev->ami_stat &= 0xfe; return 0; @@ -2345,7 +1391,7 @@ write64_ami(void *priv, uint8_t val) break; case 0xa5: /* write clock = high */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - write clock = high\n"); dev->ami_stat |= 0x01; return 0; @@ -2353,15 +1399,15 @@ write64_ami(void *priv, uint8_t val) break; case 0xa6: /* read clock */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - read clock\n"); - kbc_transmit(dev, !!(dev->ami_stat & 1)); + add_data(dev, !!(dev->ami_stat & 1)); return 0; } break; case 0xa7: /* write cache bad */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - write cache bad\n"); dev->ami_stat &= 0xfd; return 0; @@ -2369,7 +1415,7 @@ write64_ami(void *priv, uint8_t val) break; case 0xa8: /* write cache good */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - write cache good\n"); dev->ami_stat |= 0x02; return 0; @@ -2377,237 +1423,68 @@ write64_ami(void *priv, uint8_t val) break; case 0xa9: /* read cache */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - read cache\n"); - kbc_transmit(dev, !!(dev->ami_stat & 2)); + add_data(dev, !!(dev->ami_stat & 2)); return 0; } break; case 0xaf: /* set extended controller RAM */ kbd_log("ATkbc: set extended controller RAM\n"); - dev->kbc_in = 1; + dev->want60 = 1; + dev->secr_phase = 1; return 0; - case 0xb0 ... 0xb3: + case 0xb0: case 0xb1: case 0xb2: case 0xb3: /* set KBC lines P10-P13 (input port bits 0-3) low */ kbd_log("ATkbc: set KBC lines P10-P13 (input port bits 0-3) low\n"); - if (!(dev->flags & KBC_FLAG_PS2) || (val > 0xb1)) { - dev->p1 &= ~(1 << (val & 0x03)); - } - kbc_transmit(dev, 0x00); + if (!PCI || (val > 0xb1)) + dev->input_port &= ~(1 << (val & 0x03)); + add_data(dev, 0x00); return 0; case 0xb4: case 0xb5: /* set KBC lines P22-P23 (output port bits 2-3) low */ kbd_log("ATkbc: set KBC lines P22-P23 (output port bits 2-3) low\n"); - if (!(dev->flags & KBC_FLAG_PS2)) - write_output(dev, dev->p2 & ~(4 << (val & 0x01))); - kbc_transmit(dev, 0x00); + if (! PCI) + write_output(dev, dev->output_port & ~(4 << (val & 0x01))); + add_data(dev, 0x00); return 0; -#if 0 - case 0xb8 ... 0xbb: -#else - case 0xb9: -#endif + case 0xb8: case 0xb9: case 0xba: case 0xbb: /* set KBC lines P10-P13 (input port bits 0-3) high */ kbd_log("ATkbc: set KBC lines P10-P13 (input port bits 0-3) high\n"); - if (!(dev->flags & KBC_FLAG_PS2) || (val > 0xb9)) { - dev->p1 |= (1 << (val & 0x03)); - kbc_transmit(dev, 0x00); + if (!PCI || (val > 0xb9)) { + dev->input_port |= (1 << (val & 0x03)); + add_data(dev, 0x00); } return 0; - case 0xb8: - kbd_log("ATkbc: AMI MegaKey - memory index\n"); - dev->kbc_in = 1; - return 0; - - case 0xba: - kbd_log("ATkbc: AMI MegaKey - read %02X memory from index %02X\n", dev->mem[dev->mem_index], dev->mem_index); - if (dev->mem_index >= 0x80) { - switch (dev->mem[0x9b] & 0xc0) { - case 0x00: - index = 0x0080; - break; - case 0x40: case 0x80: - index = 0x0000; - break; - case 0xc0: - index = 0x0100; - break; - } - kbc_transmit(dev, dev->mem[index + dev->mem_index]); - } else if (dev->mem_index == 0x42) - kbc_transmit(dev, dev->status); - else if (dev->mem_index >= 0x40) - kbc_transmit(dev, dev->mem[dev->mem_index - 0x40]); - else - kbc_transmit(dev, dev->mem_int[dev->mem_index]); - return 0; - - case 0xbb: - kbd_log("ATkbc: AMI MegaKey - write to memory index %02X\n", dev->mem_index); - dev->kbc_in = 1; - return 0; - -#if 0 case 0xbc: case 0xbd: /* set KBC lines P22-P23 (output port bits 2-3) high */ kbd_log("ATkbc: set KBC lines P22-P23 (output port bits 2-3) high\n"); - if (!(dev->flags & KBC_FLAG_PS2)) - write_output(dev, dev->p2 | (4 << (val & 0x01))); - kbc_transmit(dev, 0x00); - return 0; -#endif - - case 0xbc: - switch (dev->mem_index) { - case 0x00: /* STAT8042 */ - kbc_transmit(dev, dev->status); - break; - case 0x01: /* Password_ptr */ - kbc_transmit(dev, dev->mem[0x1c]); - break; - case 0x02: /* Wakeup_Tsk_Reg */ - kbc_transmit(dev, dev->mem[0x1e]); - break; - case 0x03: /* CCB */ - kbc_transmit(dev, dev->mem[0x20]); - break; - case 0x04: /* Debounce_time */ - kbc_transmit(dev, dev->mem[0x4d]); - break; - case 0x05: /* Pulse_Width */ - kbc_transmit(dev, dev->mem[0x4e]); - break; - case 0x06: /* Pk_sel_byte */ - kbc_transmit(dev, dev->mem[0x4c]); - break; - case 0x07: /* Func_Tsk_Reg */ - kbc_transmit(dev, dev->mem[0x7e]); - break; - case 0x08: /* TypematicRate */ - kbc_transmit(dev, dev->mem[0x80]); - break; - case 0x09: /* Led_Flag_Byte */ - kbc_transmit(dev, dev->mem[0x81]); - break; - case 0x0a: /* Kbms_Command_St */ - kbc_transmit(dev, dev->mem[0x87]); - break; - case 0x0b: /* Delay_Count_Byte */ - kbc_transmit(dev, dev->mem[0x86]); - break; - case 0x0c: /* KBC_Flags */ - kbc_transmit(dev, dev->mem[0x9b]); - break; - case 0x0d: /* SCODE_HK1 */ - kbc_transmit(dev, dev->mem[0x50]); - break; - case 0x0e: /* SCODE_HK2 */ - kbc_transmit(dev, dev->mem[0x51]); - break; - case 0x0f: /* SCODE_HK3 */ - kbc_transmit(dev, dev->mem[0x52]); - break; - case 0x10: /* SCODE_HK4 */ - kbc_transmit(dev, dev->mem[0x53]); - break; - case 0x11: /* SCODE_HK5 */ - kbc_transmit(dev, dev->mem[0x54]); - break; - case 0x12: /* SCODE_HK6 */ - kbc_transmit(dev, dev->mem[0x55]); - break; - case 0x13: /* TASK_HK1 */ - kbc_transmit(dev, dev->mem[0x56]); - break; - case 0x14: /* TASK_HK2 */ - kbc_transmit(dev, dev->mem[0x57]); - break; - case 0x15: /* TASK_HK3 */ - kbc_transmit(dev, dev->mem[0x58]); - break; - case 0x16: /* TASK_HK4 */ - kbc_transmit(dev, dev->mem[0x59]); - break; - case 0x17: /* TASK_HK5 */ - kbc_transmit(dev, dev->mem[0x5a]); - break; - /* The next 4 bytes have uncertain correspondences. */ - case 0x18: /* Batt_Poll_delay_Time */ - kbc_transmit(dev, dev->mem[0x5b]); - break; - case 0x19: /* Batt_Alarm_Reg1 */ - kbc_transmit(dev, dev->mem[0x5c]); - break; - case 0x1a: /* Batt_Alarm_Reg2 */ - kbc_transmit(dev, dev->mem[0x5d]); - break; - case 0x1b: /* Batt_Alarm_Tsk_Reg */ - kbc_transmit(dev, dev->mem[0x5e]); - break; - case 0x1c: /* Kbc_State1 */ - kbc_transmit(dev, dev->mem[0x9d]); - break; - case 0x1d: /* Aux_Config */ - kbc_transmit(dev, dev->mem[0x75]); - break; - case 0x1e: /* Kbc_State3 */ - kbc_transmit(dev, dev->mem[0x73]); - break; - default: - kbc_transmit(dev, 0x00); - break; - } - kbd_log("ATkbc: AMI MegaKey - read from config index %02X\n", dev->mem_index); + if (! PCI) + write_output(dev, dev->output_port | (4 << (val & 0x01))); + add_data(dev, 0x00); return 0; - case 0xbd: - kbd_log("ATkbc: AMI MegaKey - write to config index %02X\n", dev->mem_index); - dev->kbc_in = 1; - return 0; - - case 0xc1: /* write input port */ - kbd_log("ATkbc: AMI MegaKey - write input port\n"); - dev->kbc_in = 1; - return 0; - - case 0xc4: - /* set KBC line P14 low */ - kbd_log("ATkbc: set KBC line P14 (input port bit 4) low\n"); - dev->p1 &= 0xef; - kbc_transmit(dev, 0x00); - return 0; - case 0xc5: - /* set KBC line P15 low */ - kbd_log("ATkbc: set KBC line P15 (input port bit 5) low\n"); - dev->p1 &= 0xdf; - kbc_transmit(dev, 0x00); - return 0; - - case 0xc8: case 0xc9: + case 0xc8: /* - * (un)block KBC lines P22/P23 + * unblock KBC lines P22/P23 * (allow command D1 to change bits 2/3 of the output port) */ - kbd_log("ATkbc: AMI - %sblock KBC lines P22 and P23\n", (val & 1) ? "" : "un"); - dev->p2_locked = (val & 1); + kbd_log("ATkbc: AMI - unblock KBC lines P22 and P23\n"); + dev->output_locked = 1; return 0; - case 0xcc: - /* set KBC line P14 high */ - kbd_log("ATkbc: set KBC line P14 (input port bit 4) high\n"); - dev->p1 |= 0x10; - kbc_transmit(dev, 0x00); - return 0; - case 0xcd: - /* set KBC line P15 high */ - kbd_log("ATkbc: set KBC line P15 (input port bit 5) high\n"); - dev->p1 |= 0x20; - kbc_transmit(dev, 0x00); + case 0xc9: + /* + * block KBC lines P22/P23 + * (disallow command D1 from changing bits 2/3 of the port) + */ + kbd_log("ATkbc: AMI - block KBC lines P22 and P23\n"); + dev->output_locked = 1; return 0; case 0xef: /* ??? - sent by AMI486 */ @@ -2628,20 +1505,23 @@ write64_ibm_mca(void *priv, uint8_t val) case 0xc1: /*Copy bits 0 to 3 of input port to status bits 4 to 7*/ kbd_log("ATkbc: copy bits 0 to 3 of input port to status bits 4 to 7\n"); dev->status &= 0x0f; - dev->status |= ((((dev->p1 & 0xfc) | 0x84) & 0x0f) << 4); + dev->status |= ((((dev->input_port & 0xfc) | 0x84) & 0x0f) << 4); return 0; case 0xc2: /*Copy bits 4 to 7 of input port to status bits 4 to 7*/ kbd_log("ATkbc: copy bits 4 to 7 of input port to status bits 4 to 7\n"); dev->status &= 0x0f; - dev->status |= (((dev->p1 & 0xfc) | 0x84) & 0xf0); + dev->status |= (((dev->input_port & 0xfc) | 0x84) & 0xf0); return 0; case 0xaf: kbd_log("ATkbc: bad KBC command AF\n"); return 1; - case 0xf0 ... 0xff: + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: kbd_log("ATkbc: pulse: %01X\n", (val & 0x03) | 0x0c); pulse_output(dev, (val & 0x03) | 0x0c); return 0; @@ -2656,7 +1536,7 @@ write60_quadtel(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; - switch(dev->kbc_cmd) { + switch(dev->command) { case 0xcf: /*??? - sent by MegaPC BIOS*/ kbd_log("ATkbc: ??? - sent by MegaPC BIOS\n"); return 0; @@ -2665,34 +1545,12 @@ write60_quadtel(void *priv, uint8_t val) return 1; } - static uint8_t write64_olivetti(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; switch (val) { - /* This appears to be a clone of "Read input port", in which case, the bis would be: - 7: M290 (AT KBC): - Keyboard lock (1 = unlocked, 0 = locked); - M300 (PS/2 KBC): - Bus expansion board present (1 = present, 0 = not present); - 6: Usually: - Display (1 = MDA, 0 = CGA, but can have its polarity inverted); - 5: Manufacturing jumper (1 = not installed, 0 = installed (infinite loop)); - 4: RAM on motherboard (1 = 256 kB, 0 = 512 kB - which machine actually uses this?); - 3: Fast Ram check (if inactive keyboard works erratically); - 2: Keyboard fuse present - This appears to be in-line with PS/2: 1 = no power, 0 = keyboard power normal; - 1: M290 (AT KBC): - Unused; - M300 (PS/2 KBC): - Mouse data in; - 0: M290 (AT KBC): - Unused; - M300 (PS/2 KBC): - Key data in. - */ case 0x80: /* Olivetti-specific command */ /* * bit 7: bus expansion board present (M300) / keyboard unlocked (M290) @@ -2701,9 +1559,11 @@ write64_olivetti(void *priv, uint8_t val) * bit 2: keyboard fuse present * bits 0-1: ??? */ - kbc_transmit(dev, 0x0c | (is386 ? 0x00 : 0x80)); + add_to_kbc_queue_front(dev, (0x0c | ((is386) ? 0x00 : 0x80)) & 0xdf, 0, 0x00); + dev->input_port = ((dev->input_port + 1) & 3) | + (dev->input_port & 0xfc); return 0; - } + } return write64_generic(dev, val); } @@ -2721,7 +1581,7 @@ write64_quadtel(void *priv, uint8_t val) case 0xcf: /*??? - sent by MegaPC BIOS*/ kbd_log("ATkbc: ??? - sent by MegaPC BIOS\n"); - dev->kbc_in = 1; + dev->want60 = 1; return 0; } @@ -2734,7 +1594,7 @@ write60_toshiba(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; - switch(dev->kbc_cmd) { + switch(dev->command) { case 0xb6: /* T3100e - set color/mono switch */ kbd_log("ATkbc: T3100e - set color/mono switch\n"); t3100e_mono_set(val); @@ -2777,30 +1637,29 @@ write64_toshiba(void *priv, uint8_t val) case 0xb4: /* T3100e: Get configuration / status */ kbd_log("ATkbc: T3100e: Get configuration / status\n"); - kbc_transmit(dev, t3100e_config_get()); + add_data(dev, t3100e_config_get()); return 0; case 0xb5: /* T3100e: Get colour / mono byte */ kbd_log("ATkbc: T3100e: Get colour / mono byte\n"); - kbc_transmit(dev, t3100e_mono_get()); + add_data(dev, t3100e_mono_get()); return 0; case 0xb6: /* T3100e: Set colour / mono byte */ kbd_log("ATkbc: T3100e: Set colour / mono byte\n"); - dev->kbc_in = 1; + dev->want60 = 1; return 0; case 0xb7: /* T3100e: Emulate PS/2 keyboard */ case 0xb8: /* T3100e: Emulate AT keyboard */ - dev->flags &= ~KBC_FLAG_PS2; + dev->flags &= ~KBC_TYPE_MASK; if (val == 0xb7) { kbd_log("ATkbc: T3100e: Emulate PS/2 keyboard\n"); - dev->flags |= KBC_FLAG_PS2; - } -#ifdef ENABLE_KEYBOARD_AT_LOG - else + dev->flags |= KBC_TYPE_PS2_NOREF; + } else { kbd_log("ATkbc: T3100e: Emulate AT keyboard\n"); -#endif + dev->flags |= KBC_TYPE_ISA; + } return 0; case 0xbb: /* T3100e: Read 'Fn' key. @@ -2810,9 +1669,8 @@ write64_toshiba(void *priv, uint8_t val) kbd_log("ATkbc: T3100e: Read 'Fn' key\n"); if (keyboard_recv(0xb8) || /* Right Alt */ keyboard_recv(0x9d)) /* Right Ctrl */ - kbc_transmit(dev, 0x04); - else - kbc_transmit(dev, 0x00); + add_data(dev, 0x04); + else add_data(dev, 0x00); return 0; case 0xbc: /* T3100e: Reset Fn+Key notification */ @@ -2825,8 +1683,8 @@ write64_toshiba(void *priv, uint8_t val) /* The T3100e returns all bits set except bit 6 which * is set by t3100e_mono_set() */ - dev->p1 = (t3100e_mono_get() & 1) ? 0xff : 0xbf; - kbc_transmit(dev, dev->p1); + dev->input_port = (t3100e_mono_get() & 1) ? 0xff : 0xbf; + add_data(dev, dev->input_port); return 0; } @@ -2839,46 +1697,423 @@ static void kbd_write(uint16_t port, uint8_t val, void *priv) { atkbd_t *dev = (atkbd_t *)priv; + int i = 0, bad = 1; + uint8_t mask, kbc_ven = 0x0; + kbc_ven = dev->flags & KBC_VEN_MASK; - kbd_log("[%04X:%08X] ATkbc: write(%04X, %02X)\n", CS, cpu_state.pc, port, val); + if ((kbc_ven == KBC_VEN_XI8088) && (port == 0x63)) + port = 0x61; + + kbd_log((port == 0x61) ? "" : "ATkbc: write(%04X, %02X)\n", port, val); switch (port) { case 0x60: - dev->status = (dev->status & ~STAT_CD) | STAT_IFULL; - dev->ib = val; - // kbd_status("Write %02X: %02X, Status = %02X\n", port, val, dev->status); + dev->status &= ~STAT_CD; + if (dev->want60) { + /* Write data to controller. */ + dev->want60 = 0; -#if 0 - if ((dev->fast_a20_phase == 1)/* && ((val == 0xdd) || (val == 0xdf))*/) { - dev->status &= ~STAT_IFULL; - write_output(dev, val); - dev->fast_a20_phase = 0; + switch (dev->command) { + case 0x60: case 0x61: case 0x62: case 0x63: + case 0x64: case 0x65: case 0x66: case 0x67: + case 0x68: case 0x69: case 0x6a: case 0x6b: + case 0x6c: case 0x6d: case 0x6e: case 0x6f: + case 0x70: case 0x71: case 0x72: case 0x73: + case 0x74: case 0x75: case 0x76: case 0x77: + case 0x78: case 0x79: case 0x7a: case 0x7b: + case 0x7c: case 0x7d: case 0x7e: case 0x7f: + dev->mem[dev->command & 0x1f] = val; + if (dev->command == 0x60) + write_cmd(dev, val); + break; + + case 0xd1: /* write output port */ + kbd_log("ATkbc: write output port\n"); + if (dev->output_locked) { + /*If keyboard controller lines P22-P23 are blocked, + we force them to remain unchanged.*/ + val &= ~0x0c; + val |= (dev->output_port & 0x0c); + } + write_output(dev, val); + break; + + case 0xd2: /* write to keyboard output buffer */ + kbd_log("ATkbc: write to keyboard output buffer\n"); + add_data_kbd_direct(dev, val); + break; + + case 0xd3: /* write to mouse output buffer */ + kbd_log("ATkbc: write to mouse output buffer\n"); + if (mouse_write && ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) + keyboard_at_adddata_mouse(val); + break; + + case 0xd4: /* write to mouse */ + kbd_log("ATkbc: write to mouse (%02X)\n", val); + + if (val == 0xbb) + break; + + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + set_enable_mouse(dev, 1); + if (mouse_write) + mouse_write(val, mouse_p); + else + add_to_kbc_queue_front(dev, 0xfe, 2, 0x40); + } + break; + + default: + /* + * Run the vendor-specific handler + * if we have one. Otherwise, or if + * it returns an error, log a bad + * controller command. + */ + if (dev->write60_ven) + bad = dev->write60_ven(dev, val); + + if (bad) { + kbd_log("ATkbc: bad controller command %02x data %02x\n", dev->command, val); + add_data_kbd(0xfe); + } + } + } else { + /* Write data to keyboard. */ + dev->mem[0] &= ~0x10; + + if (dev->key_wantdata) { + dev->key_wantdata = 0; + + /* + * Several system BIOSes and OS device drivers + * mess up with this, and repeat the command + * code many times. Fun! + */ + if (val == dev->key_command) { + /* Respond NAK and ignore it. */ + add_data_kbd(0xfe); + dev->key_command = 0x00; + break; + } + + switch (dev->key_command) { + case 0xed: /* set/reset LEDs */ + add_data_kbd_direct(dev, 0xfa); + kbd_log("ATkbd: set LEDs [%02x]\n", val); + break; + + case 0xf0: /* get/set scancode set */ + add_data_kbd_direct(dev, 0xfa); + if (val == 0) { + kbd_log("Get scan code set: %02X\n", keyboard_mode & 3); + add_data_kbd_direct(dev, keyboard_mode & 3); + } else { + if ((val <= 3) && (val != 1)) { + keyboard_mode &= 0xfc; + keyboard_mode |= (val & 3); + kbd_log("Scan code set now: %02X\n", val); + } + set_scancode_map(dev); + } + break; + + case 0xf3: /* set typematic rate/delay */ + add_data_kbd_direct(dev, 0xfa); + break; + + default: + kbd_log("ATkbd: bad keyboard 0060 write %02X command %02X\n", val, dev->key_command); + add_data_kbd_direct(dev, 0xfe); + break; + } + + /* Keyboard command is now done. */ + dev->key_command = 0x00; + } else { + /* No keyboard command in progress. */ + dev->key_command = 0x00; + + set_enable_kbd(dev, 1); + + switch (val) { + case 0x00: + kbd_log("ATkbd: command 00\n"); + add_data_kbd_direct(dev, 0xfa); + break; + + case 0x05: /*??? - sent by NT 4.0*/ + kbd_log("ATkbd: command 05 (NT 4.0)\n"); + add_data_kbd_direct(dev, 0xfe); + break; + + /* Sent by Pentium-era AMI BIOS'es.*/ + case 0x71: case 0x82: + kbd_log("ATkbd: Pentium-era AMI BIOS command %02X\n", val); + break; + + case 0xed: /* set/reset LEDs */ + kbd_log("ATkbd: set/reset leds\n"); + add_data_kbd_direct(dev, 0xfa); + + dev->key_wantdata = 1; + break; + + case 0xee: /* diagnostic echo */ + kbd_log("ATkbd: ECHO\n"); + add_data_kbd_direct(dev, 0xee); + break; + + case 0xef: /* NOP (reserved for future use) */ + kbd_log("ATkbd: NOP\n"); + break; + + case 0xf0: /* get/set scan code set */ + kbd_log("ATkbd: scan code set\n"); + add_data_kbd_direct(dev, 0xfa); + dev->key_wantdata = 1; + break; + + case 0xf2: /* read ID */ + /* Fixed as translation will be done in add_data_kbd(). */ + kbd_log("ATkbd: read keyboard id\n"); + /* TODO: After keyboard type selection is implemented, make this + return the correct keyboard ID for the selected type. */ + add_data_kbd_direct(dev, 0xfa); + add_data_kbd_direct(dev, 0xab); + add_data_kbd_direct(dev, 0x83); + break; + + case 0xf3: /* set typematic rate/delay */ + kbd_log("ATkbd: set typematic rate/delay\n"); + add_data_kbd_direct(dev, 0xfa); + dev->key_wantdata = 1; + break; + + case 0xf4: /* enable keyboard */ + kbd_log("ATkbd: enable keyboard\n"); + add_data_kbd_direct(dev, 0xfa); + keyboard_scan = 1; + break; + + case 0xf5: /* set defaults and disable keyboard */ + case 0xf6: /* set defaults */ + kbd_log("ATkbd: set defaults%s\n", (val == 0xf6) ? "" : " and disable keyboard"); + keyboard_scan = (val == 0xf6); + kbd_log("val = %02X, keyboard_scan = %i, dev->mem[0] = %02X\n", + val, keyboard_scan, dev->mem[0]); + add_data_kbd_direct(dev, 0xfa); + + keyboard_set3_all_break = 0; + keyboard_set3_all_repeat = 0; + memset(keyboard_set3_flags, 0, 512); + keyboard_mode = (keyboard_mode & 0xfc) | 0x02; + set_scancode_map(dev); + break; + + case 0xf7: /* set all keys to repeat */ + kbd_log("ATkbd: set all keys to repeat\n"); + add_data_kbd_direct(dev, 0xfa); + keyboard_set3_all_break = 1; + break; + + case 0xf8: /* set all keys to give make/break codes */ + kbd_log("ATkbd: set all keys to give make/break codes\n"); + add_data_kbd_direct(dev, 0xfa); + keyboard_set3_all_break = 1; + break; + + case 0xf9: /* set all keys to give make codes only */ + kbd_log("ATkbd: set all keys to give make codes only\n"); + add_data_kbd_direct(dev, 0xfa); + keyboard_set3_all_break = 0; + break; + + case 0xfa: /* set all keys to repeat and give make/break codes */ + kbd_log("ATkbd: set all keys to repeat and give make/break codes\n"); + add_data_kbd_direct(dev, 0xfa); + keyboard_set3_all_repeat = 1; + keyboard_set3_all_break = 1; + break; + + case 0xfe: /* resend last scan code */ + kbd_log("ATkbd: reset last scan code\n"); + add_data_kbd_raw(dev, kbd_last_scan_code); + break; + + case 0xff: /* reset */ + kbd_log("ATkbd: kbd reset\n"); + kbc_queue_reset(1); + kbd_last_scan_code = 0x00; + add_data_kbd_direct(dev, 0xfa); + + /* Set scan code set to 2. */ + keyboard_mode = (keyboard_mode & 0xfc) | 0x02; + set_scancode_map(dev); + + dev->reset_delay = RESET_DELAY_TIME; + break; + + default: + kbd_log("ATkbd: bad keyboard command %02X\n", val); + add_data_kbd_direct(dev, 0xfe); + } + + /* If command needs data, remember command. */ + if (dev->key_wantdata == 1) + dev->key_command = val; + } } -#endif break; - case 0x64: - dev->status |= (STAT_CD | STAT_IFULL); - dev->ib = val; - // kbd_status("Write %02X: %02X, Status = %02X\n", port, val, dev->status); -#if 0 - if (val == 0xd1) { - dev->status &= ~STAT_IFULL; - dev->fast_a20_phase = 1; - } else if (val == 0xfe) { - dev->status &= ~STAT_IFULL; - pulse_output(dev, 0x0e); - } else if ((val == 0xad) || (val == 0xae)) { - dev->status &= ~STAT_IFULL; - if (val & 0x01) - dev->mem[0x20] |= 0x10; - else - dev->mem[0x20] &= ~0x10; - } else if (val == 0xa1) { - dev->status &= ~STAT_IFULL; - kbc_send_to_ob(dev, 'H', 0, 0x00); + case 0x61: + ppi.pb = (ppi.pb & 0x10) | (val & 0x0f); + + speaker_update(); + speaker_gated = val & 1; + speaker_enable = val & 2; + if (speaker_enable) + was_speaker_enable = 1; + pit_ctr_set_gate(&pit->counters[2], val & 1); + + if (kbc_ven == KBC_VEN_XI8088) + xi8088_turbo_set(!!(val & 0x04)); + break; + + case 0x64: + /* Controller command. */ + dev->want60 = 0; + dev->status |= STAT_CD; + + switch (val) { + /* Read data from KBC memory. */ + case 0x20: case 0x21: case 0x22: case 0x23: + case 0x24: case 0x25: case 0x26: case 0x27: + case 0x28: case 0x29: case 0x2a: case 0x2b: + case 0x2c: case 0x2d: case 0x2e: case 0x2f: + case 0x30: case 0x31: case 0x32: case 0x33: + case 0x34: case 0x35: case 0x36: case 0x37: + case 0x38: case 0x39: case 0x3a: case 0x3b: + case 0x3c: case 0x3d: case 0x3e: case 0x3f: + add_data(dev, dev->mem[val & 0x1f]); + break; + + /* Write data to KBC memory. */ + case 0x60: case 0x61: case 0x62: case 0x63: + case 0x64: case 0x65: case 0x66: case 0x67: + case 0x68: case 0x69: case 0x6a: case 0x6b: + case 0x6c: case 0x6d: case 0x6e: case 0x6f: + case 0x70: case 0x71: case 0x72: case 0x73: + case 0x74: case 0x75: case 0x76: case 0x77: + case 0x78: case 0x79: case 0x7a: case 0x7b: + case 0x7c: case 0x7d: case 0x7e: case 0x7f: + dev->want60 = 1; + break; + + case 0xaa: /* self-test */ + kbd_log("ATkbc: self-test\n"); + if ((kbc_ven == KBC_VEN_TOSHIBA) || (kbc_ven == KBC_VEN_SAMSUNG)) + dev->status |= STAT_IFULL; + write_output(dev, ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x4b : 0xcf); + + /* Always reinitialize all queues - the real hardware pulls keyboard and mouse + clocks high, which stops keyboard scanning. */ + kbd_log("ATkbc: self-test reinitialization\n"); + dev->out_new = dev->out_delayed = -1; + for (i = 0; i < 3; i++) + kbc_queue_reset(i); + kbd_last_scan_code = 0x00; + dev->status &= ~STAT_OFULL; + dev->last_irq = dev->old_last_irq = 0; + + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) + write_cmd(dev, 0x30 | STAT_SYSFLAG); + else + write_cmd(dev, 0x10 | STAT_SYSFLAG); + add_data(dev, 0x55); + break; + + case 0xab: /* interface test */ + kbd_log("ATkbc: interface test\n"); + add_data(dev, 0x00); /*no error*/ + break; + + case 0xac: /* diagnostic dump */ + kbd_log("ATkbc: diagnostic dump\n"); + for (i = 0; i < 16; i++) + add_data(dev, dev->mem[i]); + add_data(dev, (dev->input_port & 0xf0) | 0x80); + add_data(dev, dev->output_port); + add_data(dev, dev->status); + break; + + case 0xad: /* disable keyboard */ + kbd_log("ATkbc: disable keyboard\n"); + set_enable_kbd(dev, 0); + break; + + case 0xae: /* enable keyboard */ + kbd_log("ATkbc: enable keyboard\n"); + set_enable_kbd(dev, 1); + break; + + case 0xca: /* read keyboard mode */ + kbd_log("ATkbc: AMI - read keyboard mode\n"); + add_data(dev, ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x01 : 0x00); /*ISA mode*/ + break; + + case 0xcb: /* set keyboard mode */ + kbd_log("ATkbc: AMI - set keyboard mode\n"); + dev->want60 = 1; + break; + + case 0xd0: /* read output port */ + kbd_log("ATkbc: read output port\n"); + mask = 0xff; + if (((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) && (dev->mem[0] & 0x10)) + mask &= 0xbf; + add_to_kbc_queue_front(dev, dev->output_port & mask, 0, 0x00); + break; + + case 0xd1: /* write output port */ + kbd_log("ATkbc: write output port\n"); + dev->want60 = 1; + break; + + case 0xd2: /* write keyboard output buffer */ + kbd_log("ATkbc: write keyboard output buffer\n"); + dev->want60 = 1; + break; + + case 0xdd: /* disable A20 address line */ + case 0xdf: /* enable A20 address line */ + kbd_log("ATkbc: %sable A20\n", (val == 0xdd) ? "dis": "en"); + write_output(dev, (dev->output_port & 0xfd) | (val & 0x02)); + break; + + case 0xe0: /* read test inputs */ + kbd_log("ATkbc: read test inputs\n"); + add_data(dev, 0x00); + break; + + default: + /* + * Unrecognized controller command. + * + * If we have a vendor-specific handler, run + * that. Otherwise, or if that handler fails, + * log a bad command. + */ + if (dev->write64_ven) + bad = dev->write64_ven(dev, val); + + kbd_log(bad ? "ATkbc: bad controller command %02X\n" : "", val); } -#endif + + /* If the command needs data, remember the command. */ + if (dev->want60) + dev->command = val; break; } } @@ -2889,20 +2124,83 @@ kbd_read(uint16_t port, void *priv) { atkbd_t *dev = (atkbd_t *)priv; uint8_t ret = 0xff; + uint8_t kbc_ven = 0x0; + kbc_ven = dev->flags & KBC_VEN_MASK; - // if (dev->flags & KBC_FLAG_PS2) - // cycles -= ISA_CYCLES(8); + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) + cycles -= ISA_CYCLES(8); + + if ((kbc_ven == KBC_VEN_XI8088) && (port == 0x63)) + port = 0x61; switch (port) { case 0x60: - ret = dev->ob; + ret = dev->out; dev->status &= ~STAT_OFULL; picintc(dev->last_irq); dev->last_irq = 0; break; + case 0x61: + ret = ppi.pb & ~0xe0; + if (ppispeakon) + ret |= 0x20; + if ((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) { + if (dev->refresh) + ret |= 0x10; + else + ret &= ~0x10; + } + if (kbc_ven == KBC_VEN_XI8088) { + if (xi8088_turbo_get()) + ret |= 0x04; + else + ret &= ~0x04; + } + break; + + case 0x62: + ret = 0xff; + if (kbc_ven == KBC_VEN_OLIVETTI) { + /* SWA on Olivetti M240 mainboard (off=1) */ + ret = 0x00; + if (ppi.pb & 0x8) { + /* Switches 4, 5 - floppy drives (number) */ + int i, fdd_count = 0; + for (i = 0; i < FDD_NUM; i++) { + if (fdd_get_flags(i)) + fdd_count++; + } + if (!fdd_count) + ret |= 0x00; + else + ret |= ((fdd_count - 1) << 2); + /* Switches 6, 7 - monitor type */ + if (video_is_mda()) + ret |= 0x3; + else if (video_is_cga()) + ret |= 0x2; /* 0x10 would be 40x25 */ + else + ret |= 0x0; + } else { + /* bit 2 always on */ + ret |= 0x4; + /* Switch 8 - 8087 FPU. */ + if (hasfpu) + ret |= 0x02; + } + } + break; case 0x64: - ret = dev->status; + ret = (dev->status & 0xfb); + if (dev->mem[0] & STAT_SYSFLAG) + ret |= STAT_SYSFLAG; + /* Only clear the transmit timeout flag on non-PS/2 controllers, as on + PS/2 controller, it is the keyboard/mouse output source bit. */ + // dev->status &= ~STAT_RTIMEOUT; + if (((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) && + (kbc_ven != KBC_VEN_IBM_MCA)) + dev->status &= ~STAT_TTIMEOUT; break; default: @@ -2910,12 +2208,22 @@ kbd_read(uint16_t port, void *priv) break; } - kbd_log("[%04X:%08X] ATkbc: read(%04X) = %02X\n",CS, cpu_state.pc, port, ret); + kbd_log((port == 0x61) ? "" : "ATkbc: read(%04X) = %02X\n", port, ret); return(ret); } +static void +kbd_refresh(void *priv) +{ + atkbd_t *dev = (atkbd_t *)priv; + + dev->refresh = !dev->refresh; + timer_advance_u64(&dev->refresh_time, PS2_REFRESH_TIME); +} + + static void kbd_reset(void *priv) { @@ -2924,26 +2232,25 @@ kbd_reset(void *priv) uint8_t kbc_ven = 0x0; kbc_ven = dev->flags & KBC_VEN_MASK; + dev->first_write = 1; + // dev->status = STAT_UNLOCKED | STAT_CD; dev->status = STAT_UNLOCKED; - dev->mem[0x20] = 0x01; - dev->mem[0x20] |= CCB_TRANSLATE; + dev->mem[0] = 0x01; + dev->mem[0] |= CCB_TRANSLATE; + dev->wantirq = 0; write_output(dev, 0xcf); - dev->last_irq = 0; + dev->last_irq = dev->old_last_irq = 0; dev->secr_phase = 0; - dev->kbd_in = 0; - dev->ami_mode = !!(dev->flags & KBC_FLAG_PS2); + dev->key_wantdata = 0; /* Set up the correct Video Type bits. */ - dev->p1 = video_is_mda() ? 0xf0 : 0xb0; if ((kbc_ven == KBC_VEN_XI8088) || (kbc_ven == KBC_VEN_ACER)) - dev->p1 ^= 0x40; - if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) - dev->inhibit = ((dev->p1 & 0x80) >> 3); + dev->input_port = video_is_mda() ? 0xb0 : 0xf0; else - dev->inhibit = 0x10; - kbd_log("ATkbc: input port = %02x\n", dev->p1); + dev->input_port = video_is_mda() ? 0xf0 : 0xb0; + kbd_log("ATkbc: input port = %02x\n", dev->input_port); - keyboard_mode = 0x02 | (dev->mem[0x20] & CCB_TRANSLATE); + keyboard_mode = 0x02 | (dev->mem[0] & CCB_TRANSLATE); /* Enable keyboard, disable mouse. */ set_enable_kbd(dev, 1); @@ -2951,18 +2258,16 @@ kbd_reset(void *priv) set_enable_mouse(dev, 0); mouse_scan = 0; - dev->ob = 0xff; + dev->out_new = dev->out_delayed = -1; + for (i = 0; i < 3; i++) + kbc_queue_reset(i); + kbd_last_scan_code = 0; sc_or = 0; - for (i = 1; i <= 2; i++) - kbc_queue_reset(i); - memset(keyboard_set3_flags, 0, 512); set_scancode_map(dev); - - dev->mem[0x31] = 0xfe; } @@ -2984,6 +2289,7 @@ kbd_close(void *priv) /* Stop timers. */ timer_disable(&dev->send_delay_timer); + timer_disable(&dev->refresh_time); keyboard_scan = 0; keyboard_send = NULL; @@ -3007,14 +2313,17 @@ kbd_init(const device_t *info) dev->flags = info->local; video_reset(gfxcard); - dev->kbc_poll_phase = KBC_RESET; - kbd_send_to_host(dev, 0xaa); + kbd_reset(dev); - io_sethandler(0x0060, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); - io_sethandler(0x0064, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); + io_sethandler(0x0060, 5, + kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); keyboard_send = add_data_kbd; timer_add(&dev->send_delay_timer, kbd_poll, dev, 1); + + if ((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) + timer_add(&dev->refresh_time, kbd_refresh, dev, 1); + timer_add(&dev->pulse_cb, pulse_poll, dev, 0); dev->write60_ven = NULL; @@ -3030,14 +2339,12 @@ kbd_init(const device_t *info) break; case KBC_VEN_OLIVETTI: - /* The Olivetti controller is a special case - starts directly in the - main loop instead of the reset loop. */ - dev->kbc_poll_phase = KBC_MAIN_LOOP; dev->write64_ven = write64_olivetti; break; case KBC_VEN_AMI: case KBC_VEN_INTEL_AMI: + case KBC_VEN_SAMSUNG: dev->write60_ven = write60_ami; dev->write64_ven = write64_ami; break; @@ -3057,8 +2364,6 @@ kbd_init(const device_t *info) break; } - kbd_reset(dev); - /* We need this, sadly. */ SavedKbd = dev; @@ -3086,6 +2391,16 @@ const device_t keyboard_at_ami_device = { { NULL }, NULL, NULL, NULL }; +const device_t keyboard_at_samsung_device = { + "PC/AT Keyboard (Samsung)", + 0, + KBC_TYPE_ISA | KBC_VEN_SAMSUNG, + kbd_init, + kbd_close, + kbd_reset, + { NULL }, NULL, NULL, NULL +}; + const device_t keyboard_at_toshiba_device = { "PC/AT Keyboard (Toshiba)", 0, @@ -3117,6 +2432,16 @@ const device_t keyboard_at_ncr_device = { }; const device_t keyboard_ps2_device = { + "PS/2 Keyboard", + 0, + KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC, + kbd_init, + kbd_close, + kbd_reset, + { NULL }, NULL, NULL, NULL +}; + +const device_t keyboard_ps2_ps2_device = { "PS/2 Keyboard", 0, KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, @@ -3129,7 +2454,7 @@ const device_t keyboard_ps2_device = { const device_t keyboard_ps2_ps1_device = { "PS/2 Keyboard (IBM PS/1)", 0, - KBC_TYPE_PS2_1 | KBC_VEN_IBM_PS1, + KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1, kbd_init, kbd_close, kbd_reset, @@ -3139,7 +2464,7 @@ const device_t keyboard_ps2_ps1_device = { const device_t keyboard_ps2_ps1_pci_device = { "PS/2 Keyboard (IBM PS/1)", DEVICE_PCI, - KBC_TYPE_PS2_1 | KBC_VEN_IBM_PS1, + KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1, kbd_init, kbd_close, kbd_reset, @@ -3159,7 +2484,7 @@ const device_t keyboard_ps2_xi8088_device = { const device_t keyboard_ps2_ami_device = { "PS/2 Keyboard (AMI)", 0, - KBC_TYPE_PS2_1 | KBC_VEN_AMI, + KBC_TYPE_PS2_NOREF | KBC_VEN_AMI, kbd_init, kbd_close, kbd_reset, @@ -3169,7 +2494,7 @@ const device_t keyboard_ps2_ami_device = { const device_t keyboard_ps2_olivetti_device = { "PS/2 Keyboard (Olivetti)", 0, - KBC_TYPE_PS2_1 | KBC_VEN_OLIVETTI, + KBC_TYPE_PS2_NOREF | KBC_VEN_OLIVETTI, kbd_init, kbd_close, kbd_reset, @@ -3199,7 +2524,7 @@ const device_t keyboard_ps2_mca_2_device = { const device_t keyboard_ps2_quadtel_device = { "PS/2 Keyboard (Quadtel/MegaPC)", 0, - KBC_TYPE_PS2_1 | KBC_VEN_QUADTEL, + KBC_TYPE_PS2_NOREF | KBC_VEN_QUADTEL, kbd_init, kbd_close, kbd_reset, @@ -3209,7 +2534,7 @@ const device_t keyboard_ps2_quadtel_device = { const device_t keyboard_ps2_pci_device = { "PS/2 Keyboard", DEVICE_PCI, - KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, + KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC, kbd_init, kbd_close, kbd_reset, @@ -3219,7 +2544,7 @@ const device_t keyboard_ps2_pci_device = { const device_t keyboard_ps2_ami_pci_device = { "PS/2 Keyboard (AMI)", DEVICE_PCI, - KBC_TYPE_PS2_1 | KBC_VEN_AMI, + KBC_TYPE_PS2_NOREF | KBC_VEN_AMI, kbd_init, kbd_close, kbd_reset, @@ -3229,7 +2554,7 @@ const device_t keyboard_ps2_ami_pci_device = { const device_t keyboard_ps2_intel_ami_pci_device = { "PS/2 Keyboard (AMI)", DEVICE_PCI, - KBC_TYPE_PS2_1 | KBC_VEN_INTEL_AMI, + KBC_TYPE_PS2_NOREF | KBC_VEN_INTEL_AMI, kbd_init, kbd_close, kbd_reset, @@ -3239,7 +2564,7 @@ const device_t keyboard_ps2_intel_ami_pci_device = { const device_t keyboard_ps2_acer_pci_device = { "PS/2 Keyboard (Acer 90M002A)", DEVICE_PCI, - KBC_TYPE_PS2_1 | KBC_VEN_ACER, + KBC_TYPE_PS2_NOREF | KBC_VEN_ACER, kbd_init, kbd_close, kbd_reset, @@ -3250,8 +2575,17 @@ const device_t keyboard_ps2_acer_pci_device = { void keyboard_at_set_mouse(void (*func)(uint8_t val, void *priv), void *priv) { - // mouse_write = func; - // mouse_p = priv; + mouse_write = func; + mouse_p = priv; +} + + +void +keyboard_at_adddata_keyboard_raw(uint8_t val) +{ + atkbd_t *dev = SavedKbd; + + add_data_kbd_queue(dev, 0, val); } @@ -3264,30 +2598,10 @@ keyboard_at_adddata_mouse(uint8_t val) } -void -keyboard_at_adddata_mouse_direct(uint8_t val) -{ - // atkbd_t *dev = SavedKbd; - - return; -} - - -void -keyboard_at_adddata_mouse_cmd(uint8_t val) -{ - // atkbd_t *dev = SavedKbd; - - return; -} - - void keyboard_at_mouse_reset(void) { - // atkbd_t *dev = SavedKbd; - - return; + kbc_queue_reset(2); } @@ -3298,22 +2612,13 @@ keyboard_at_mouse_pos(void) } -int -keyboard_at_fixed_channel(void) -{ - // atkbd_t *dev = SavedKbd; - - return 0x000; -} - - void keyboard_at_set_mouse_scan(uint8_t val) { atkbd_t *dev = SavedKbd; uint8_t temp_mouse_scan = val ? 1 : 0; - if (temp_mouse_scan == !(dev->mem[0x20] & 0x20)) + if (temp_mouse_scan == !(dev->mem[0] & 0x20)) return; set_enable_mouse(dev, val ? 1 : 0); @@ -3327,7 +2632,7 @@ keyboard_at_get_mouse_scan(void) { atkbd_t *dev = SavedKbd; - return((dev->mem[0x20] & 0x20) ? 0x00 : 0x10); + return((dev->mem[0] & 0x20) ? 0x00 : 0x10); } @@ -3336,17 +2641,5 @@ keyboard_at_set_a20_key(int state) { atkbd_t *dev = SavedKbd; - write_output(dev, (dev->p2 & 0xfd) | ((!!state) << 1)); -} - - -void -keyboard_at_set_mode(int ps2) -{ - atkbd_t *dev = SavedKbd; - - if (ps2) - dev->flags |= KBC_FLAG_PS2; - else - dev->flags &= ~KBC_FLAG_PS2; + write_output(dev, (dev->output_port & 0xfd) | ((!!state) << 1)); } From e26e387d2798ded42633279f5f272c82c6fb3c7d Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 2 Aug 2021 06:59:06 +0200 Subject: [PATCH 23/96] Bring back the new keyboard_at.c. --- src/device/keyboard_at.c | 2793 ++++++++++++++++++++++++-------------- 1 file changed, 1750 insertions(+), 1043 deletions(-) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 581f55f30..92690db1f 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -57,9 +57,7 @@ #define STAT_IFULL 0x02 #define STAT_OFULL 0x01 -#define PS2_REFRESH_TIME (16 * TIMER_USEC) - -#define RESET_DELAY_TIME (100 * 10) /* 600ms */ +#define RESET_DELAY_TIME 1000 /* 100 ms */ #define CCB_UNUSED 0x80 #define CCB_TRANSLATE 0x40 @@ -74,49 +72,136 @@ #define MODE_MASK 0x6c #define KBC_TYPE_ISA 0x00 /* AT ISA-based chips */ -#define KBC_TYPE_PS2_NOREF 0x01 /* PS2 type, no refresh */ -#define KBC_TYPE_PS2_1 0x02 /* PS2 on PS/2, type 1 */ -#define KBC_TYPE_PS2_2 0x03 /* PS2 on PS/2, type 2 */ -#define KBC_TYPE_MASK 0x03 +#define KBC_TYPE_PS2_1 0x04 /* PS2 type, no refresh */ +/* This only differs in that translation is forced off. */ +#define KBC_TYPE_PS2_2 0x05 /* PS2 on PS/2, type 2 */ +#define KBC_TYPE_MASK 0x07 +#define KBC_FLAG_PS2 0x04 + +/* We need to redefine this: + Currently, we use bits 3-7 for vendor, we should instead use bits 4-7 + for vendor, 0-3 for revision/variant, and have a dev->ps2 flag controlling + controller mode, normally set according to the flags, but togglable on + AMIKey: + 0000 0000 0x00 IBM, AT + 0000 0001 0x01 MR + 0000 0010 0x02 Xi8088, clone of IBM PS/2 type 1 + 0001 0000 0x10 Olivetti + 0010 0000 0x20 Toshiba + 0011 0000 0x30 Quadtel + 0100 0000 0x40 Phoenix MultiKey/42 + 0101 0000 0x50 AMI KF + 0101 0001 0x51 AMI KH + 0101 0010 0x52 AMIKey + 0101 0011 0x53 AMIKey-2 + 0101 0100 0x54 JetKey (clone of AMI KF/AMIKey) + 0110 0000 0x60 Award + 0110 0001 0x61 Award 286 (has some AMI commands apparently) + 0111 0000 0x70 Siemens +*/ + +/* Standard IBM controller */ #define KBC_VEN_GENERIC 0x00 -#define KBC_VEN_AMI 0x04 +/* All commands are standard PS/2 */ #define KBC_VEN_IBM_MCA 0x08 -#define KBC_VEN_QUADTEL 0x0c -#define KBC_VEN_TOSHIBA 0x10 -#define KBC_VEN_XI8088 0x14 -#define KBC_VEN_IBM_PS1 0x18 -#define KBC_VEN_ACER 0x1c -#define KBC_VEN_INTEL_AMI 0x20 -#define KBC_VEN_OLIVETTI 0x24 -#define KBC_VEN_NCR 0x28 -#define KBC_VEN_SAMSUNG 0x2c -#define KBC_VEN_MASK 0x3c +/* Standard IBM commands, differs in input port bits */ +#define KBC_VEN_IBM_PS1 0x10 +/* Olivetti - proprietary commands and port 62h with switches + readout */ +#define KBC_VEN_OLIVETTI 0x20 +/* Toshiba T3100e - has a bunch of proprietary commands, also sets + IFULL on command AA */ +#define KBC_VEN_TOSHIBA 0x28 +/* Standard IBM commands, uses input port as a switches readout */ +#define KBC_VEN_NCR 0x30 +/* Xi8088 - standard IBM commands, has a turbo bit on port 61h, and the + polarity of the video type bit in the input port is inverted */ +#define KBC_VEN_XI8088 0x38 +/* QuadtelKey - currently guesswork */ +#define KBC_VEN_QUADTEL 0x40 +/* Phoenix MultiKey/42 - not yet implemented */ +#define KBC_VEN_PHOENIX 0x48 +/* Generic commands, XI8088-like input port handling of video type, + maybe we just need a flag for that? */ +#define KBC_VEN_ACER 0x50 +/* AMI KF/KH/AMIKey/AMIKey-2 */ +#define KBC_VEN_AMI 0xf0 +/* Standard AMI commands, differs in input port bits */ +#define KBC_VEN_INTEL_AMI 0xf8 +#define KBC_VEN_MASK 0xf8 + + +/* Flags should be fully 32-bit: + Bits 7- 0: Vendor and revision/variant; + Bits 15- 8: Input port mask; + Bits 23-16: Input port bits that are always on; + Bits 31-24: Flags: + Bit 0: Invert P1 video type bit polarity; + Bit 1: Is PS/2; + Bit 2: Translation forced always off. + + So for example, the IBM PS/2 type 1 controller flags would be: 00000010 00000000 11111111 00000000 = 0200ff00 . */ typedef struct { - uint8_t command, status, old_status, out, old_out, secr_phase, - mem_addr, input_port, output_port, old_output_port, - key_command, output_locked, ami_stat, want60, - wantirq, key_wantdata, refresh, first_write; + uint8_t status, ib, ob, p1, p2, old_p2, p2_locked, fast_a20_phase, + secr_phase, mem_index, ami_stat, ami_mode, + kbc_in, kbc_cmd, kbc_in_cmd, kbc_poll_phase, kbc_to_send, + kbc_send_pending, kbc_channel, kbc_stat_hi, kbc_wait_for_response, inhibit, + kbd_in, kbd_cmd, kbd_in_cmd, kbd_written, kbd_data, kbd_poll_phase, kbd_inhibit, + mouse_in, mouse_cmd, mouse_in_cmd, mouse_written, mouse_data, mouse_poll_phase, mouse_inhibit, + kbc_written[3], kbc_data[3]; - uint8_t mem[0x100]; + uint8_t mem_int[0x40], mem[0x240]; - int last_irq, old_last_irq, - reset_delay, - out_new, out_delayed; + uint16_t last_irq, kbc_phase, kbd_phase, mouse_phase; uint32_t flags; - pc_timer_t refresh_time, pulse_cb; + pc_timer_t pulse_cb, send_delay_timer; uint8_t (*write60_ven)(void *p, uint8_t val); uint8_t (*write64_ven)(void *p, uint8_t val); - - pc_timer_t send_delay_timer; } atkbd_t; +enum +{ + CHANNEL_KBC = 0, + CHANNEL_KBD, + CHANNEL_MOUSE +}; + +enum +{ + KBD_MAIN_LOOP = 0, + KBD_CMD_PROCESS +}; + +enum +{ + MOUSE_MAIN_LOOP_1 = 0, + MOUSE_CMD_PROCESS, + MOUSE_CMD_END, + MOUSE_MAIN_LOOP_2 +}; + +enum { + KBC_MAIN_LOOP = 0, + KBC_RESET = 1, + KBC_WAIT = 4, + KBC_WAIT_FOR_KBD, + KBC_WAIT_FOR_MOUSE, + KBC_WAIT_FOR_BOTH +}; + + +static void kbd_cmd_process(atkbd_t *dev); + +static void kbc_wait(atkbd_t *dev, uint8_t flags); + + /* bit 0 = repeat, bit 1 = makes break code? */ uint8_t keyboard_set3_flags[512]; uint8_t keyboard_set3_all_repeat; @@ -125,9 +210,9 @@ uint8_t keyboard_set3_all_break; /* Bits 0 - 1 = scan code set, bit 6 = translate or not. */ uint8_t keyboard_mode = 0x42; +uint8_t * ami_copr = (uint8_t *) "(C)1994 AMI"; + -static uint8_t key_ctrl_queue[16]; -static int key_ctrl_queue_start = 0, key_ctrl_queue_end = 0; static uint8_t key_queue[16]; static int key_queue_start = 0, key_queue_end = 0; uint8_t mouse_queue[16]; @@ -568,9 +653,27 @@ static const scancode scancode_set3[512] = { }; +#define UISTR_LEN 256 +static char kbd_str[UISTR_LEN]; /* UI output string */ static void add_data_kbd(uint16_t val); +extern void ui_sb_bugui(char *__str); + + +static void +kbd_status(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsprintf(kbd_str, fmt, ap); + ui_sb_bugui(kbd_str); + va_end(ap); +} + + +// #define ENABLE_KEYBOARD_AT_LOG 1 #ifdef ENABLE_KEYBOARD_AT_LOG int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG; @@ -631,9 +734,6 @@ kbc_queue_reset(uint8_t channel) } else if (channel == 1) { key_queue_start = key_queue_end = 0; memset(key_queue, 0x00, sizeof(key_queue)); - } else { - key_ctrl_queue_start = key_ctrl_queue_end = 0; - memset(key_ctrl_queue, 0x00, sizeof(key_ctrl_queue)); } } @@ -641,15 +741,6 @@ kbc_queue_reset(uint8_t channel) static void kbc_queue_add(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) { - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - - if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) - stat_hi |= ((dev->input_port & 0x80) ? 0x10 : 0x00); - else - stat_hi |= 0x10; - - dev->status = (dev->status & 0x0f) | stat_hi; - if (channel == 2) { kbd_log("ATkbc: mouse_queue[%02X] = %02X;\n", mouse_queue_end, val); mouse_queue[mouse_queue_end] = val; @@ -658,83 +749,1042 @@ kbc_queue_add(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); key_queue[key_queue_end] = val; key_queue_end = (key_queue_end + 1) & 0xf; - } else { - kbd_log("ATkbc: key_ctrl_queue[%02X] = %02X;\n", key_ctrl_queue_end, val); - key_ctrl_queue[key_ctrl_queue_end] = val; - key_ctrl_queue_end = (key_ctrl_queue_end + 1) & 0xf; - } -} - - -static void -add_to_kbc_queue_front(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) -{ - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - - if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) - stat_hi |= ((dev->input_port & 0x80) ? 0x10 : 0x00); - else - stat_hi |= 0x10; - - kbd_log("ATkbc: Adding %02X to front...\n", val); - dev->wantirq = 0; - if (channel == 2) { - if (dev->mem[0] & 0x02) - picint(0x1000); - dev->last_irq = 0x1000; - } else { - if (dev->mem[0] & 0x01) - picint(2); - dev->last_irq = 2; - } - dev->out = val; - if (channel == 2) - dev->status = (dev->status & ~STAT_IFULL) | (STAT_OFULL | STAT_MFULL) | stat_hi; - else - dev->status = (dev->status & ~(STAT_IFULL | STAT_MFULL)) | STAT_OFULL | stat_hi; + } else + fatal("Adding %02X to invalid channel %02X\n", val, channel); } static void add_data_kbd_queue(atkbd_t *dev, int direct, uint8_t val) { - if ((!keyboard_scan && !direct) || (dev->reset_delay > 0) || (key_queue_end >= 16)) { - kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i, %i\n", !keyboard_scan, (dev->reset_delay > 0), (key_queue_end >= 16)); + if ((!keyboard_scan && !direct) || (key_queue_end >= 16)) { + kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i\n", !keyboard_scan, (key_queue_end >= 16)); return; } - kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); + + kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); kbc_queue_add(dev, val, 1, 0x00); kbd_last_scan_code = val; } - static void -add_data_kbd_direct(atkbd_t *dev, uint8_t val) +kbc_send(atkbd_t *dev, uint8_t val, uint8_t channel) { - int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); - int translate = (keyboard_mode & 0x40); - uint8_t send; - - if (dev->reset_delay) - return; - - translate = translate || (keyboard_mode & 0x40) || xt_mode; - translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); - - if (translate) - send = nont_to_t[val]; - else - send = val; - - add_data_kbd_queue(dev, 1, send); + dev->kbc_written[channel] = 1; + dev->kbc_data[channel] = val; } static void -add_data_kbd_raw(atkbd_t *dev, uint8_t val) +kbd_send_to_host(atkbd_t *dev, uint8_t val) { - add_data_kbd_queue(dev, 1, val); + kbc_send(dev, val, CHANNEL_KBD); +} + + +static void +kbd_chip_reset(atkbd_t *dev) +{ + kbc_queue_reset(1); + dev->kbc_written[1] = 0x00; + kbd_last_scan_code = 0x00; + + /* Set scan code set to 2. */ + keyboard_mode = (keyboard_mode & 0xfc) | 0x02; + set_scancode_map(dev); + + dev->kbd_phase = 0; + dev->kbd_in = 0; +} + + +static void +kbd_command(atkbd_t *dev) +{ + uint8_t val = dev->kbd_data; + + if ((dev->kbd_phase > 0) && (dev->kbd_cmd == 0xff)) { + dev->kbd_phase++; + if (dev->kbd_phase == RESET_DELAY_TIME) { + kbd_send_to_host(dev, 0xaa); + dev->kbd_phase = 0; + dev->kbd_cmd = 0x00; + } + return; + } + + if (dev->kbd_phase == 2) { + dev->kbd_phase = 0; + + switch (dev->kbd_cmd) { + case 0xf2: + kbd_send_to_host(dev, 0x83); + break; + default: + fatal("Invalid command for phase 2: %02X\n", dev->kbd_cmd); + break; + } + + /* Keyboard command is now done. */ + if (dev->kbd_phase == 0) + dev->kbd_cmd = 0x00; + return; + } else if (dev->kbd_phase == 1) { + dev->kbd_phase = 0; + + switch (dev->kbd_cmd) { + case 0xf0: + kbd_log("Get scan code set: %02X\n", keyboard_mode & 3); + kbd_send_to_host(dev, keyboard_mode & 3); + break; + case 0xf2: + kbd_send_to_host(dev, 0xab); + dev->kbd_phase = 2; + break; + default: + fatal("Invalid command for phase 1: %02X\n", dev->kbd_cmd); + break; + } + + /* Keyboard command is now done. */ + if (dev->kbd_phase == 0) + dev->kbd_cmd = 0x00; + return; + } + + if (dev->kbd_in && (val < 0xed)) { + dev->kbd_in = 0; + dev->kbd_phase = 0; + + switch (dev->kbd_cmd) { + case 0xed: /* set/reset LEDs */ + kbd_log("ATkbd: set LEDs [%02x]\n", val); + kbd_send_to_host(dev, 0xfa); + break; + + case 0xf0: /* get/set scancode set */ + kbd_send_to_host(dev, 0xfa); + if (val == 0) + dev->kbd_phase = 1; + else { + if ((val <= 3) && (val != 1)) { + keyboard_mode &= 0xfc; + keyboard_mode |= (val & 3); + kbd_log("Scan code set now: %02X\n", val); + } + set_scancode_map(dev); + } + break; + + case 0xf3: /* set typematic rate/delay */ + kbd_send_to_host(dev, 0xfa); + break; + + default: + kbd_log("ATkbd: bad keyboard 0060 write %02X command %02X\n", val, dev->kbd_cmd); + kbd_send_to_host(dev, 0xfe); + break; + } + + /* Keyboard command is now done. */ + if (dev->kbd_phase == 0) + dev->kbd_cmd = 0x00; + } else { + /* No keyboard command in progress. */ + dev->kbd_in = 0; + dev->kbd_cmd = 0x00; + dev->kbd_phase = 0; + + switch (val) { + case 0x00: + kbd_log("ATkbd: command 00\n"); + kbd_send_to_host(dev, 0xfa); + break; + + case 0x05: /*??? - sent by NT 4.0*/ + kbd_log("ATkbd: command 05 (NT 4.0)\n"); + kbd_send_to_host(dev, 0xfe); + break; + + case 0xed: /* set/reset LEDs */ + kbd_log("ATkbd: set/reset leds\n"); + kbd_send_to_host(dev, 0xfa); + + dev->kbd_in = 1; + break; + + case 0xee: /* diagnostic echo */ + kbd_log("ATkbd: ECHO\n"); + kbd_send_to_host(dev, 0xee); + break; + + case 0xef: /* NOP (reserved for future use) */ + kbd_log("ATkbd: NOP\n"); + break; + + case 0xf0: /* get/set scan code set */ + kbd_log("ATkbd: scan code set\n"); + kbd_send_to_host(dev, 0xfa); + dev->kbd_in = 1; + break; + + case 0xf2: /* read ID */ + /* Fixed as translation will be done in add_data_kbd(). */ + kbd_log("ATkbd: read keyboard id\n"); + /* TODO: After keyboard type selection is implemented, make this + return the correct keyboard ID for the selected type. */ + kbd_send_to_host(dev, 0xfa); + dev->kbd_phase = 1; + break; + + case 0xf3: /* set typematic rate/delay */ + kbd_log("ATkbd: set typematic rate/delay\n"); + kbd_send_to_host(dev, 0xfa); + dev->kbd_in = 1; + break; + + case 0xf4: /* enable keyboard */ + kbd_log("ATkbd: enable keyboard\n"); + kbd_send_to_host(dev, 0xfa); + keyboard_scan = 1; + break; + + case 0xf5: /* set defaults and disable keyboard */ + case 0xf6: /* set defaults */ + kbd_log("ATkbd: set defaults%s\n", (val == 0xf6) ? "" : " and disable keyboard"); + keyboard_scan = (val == 0xf6); + kbd_log("val = %02X, keyboard_scan = %i, dev->mem[0x20] = %02X\n", + val, keyboard_scan, dev->mem[0x20]); + kbd_send_to_host(dev, 0xfa); + + keyboard_set3_all_break = 0; + keyboard_set3_all_repeat = 0; + memset(keyboard_set3_flags, 0, 512); + keyboard_mode = (keyboard_mode & 0xfc) | 0x02; + set_scancode_map(dev); + break; + + case 0xf7: /* set all keys to repeat */ + kbd_log("ATkbd: set all keys to repeat\n"); + kbd_send_to_host(dev, 0xfa); + keyboard_set3_all_break = 1; + break; + + case 0xf8: /* set all keys to give make/break codes */ + kbd_log("ATkbd: set all keys to give make/break codes\n"); + kbd_send_to_host(dev, 0xfa); + keyboard_set3_all_break = 1; + break; + + case 0xf9: /* set all keys to give make codes only */ + kbd_log("ATkbd: set all keys to give make codes only\n"); + kbd_send_to_host(dev, 0xfa); + keyboard_set3_all_break = 0; + break; + + case 0xfa: /* set all keys to repeat and give make/break codes */ + kbd_log("ATkbd: set all keys to repeat and give make/break codes\n"); + kbd_send_to_host(dev, 0xfa); + keyboard_set3_all_repeat = 1; + keyboard_set3_all_break = 1; + break; + + case 0xfe: /* resend last scan code */ + kbd_log("ATkbd: reset last scan code\n"); + kbd_send_to_host(dev, kbd_last_scan_code); + break; + + case 0xff: /* reset */ + kbd_log("ATkbd: kbd reset\n"); + kbd_chip_reset(dev); + kbd_send_to_host(dev, 0xfa); + dev->kbd_phase = 1; + break; + + default: + kbd_log("ATkbd: bad keyboard command %02X\n", val); + kbd_send_to_host(dev, 0xfe); + } + + /* If command needs data, remember command. */ + if ((dev->kbd_in == 1) || (dev->kbd_phase > 0)) + dev->kbd_cmd = val; + } +} + + +static void +kbd_do_command(atkbd_t *dev) +{ + kbd_command(dev); + if (dev->kbd_written) + dev->kbd_poll_phase = KBD_CMD_PROCESS; + else if ((dev->kbd_phase == 0) && !dev->kbd_in) { + dev->kbd_in_cmd = 0; + if (dev->kbd_data != 0xf5) + keyboard_scan = 1; + dev->kbd_poll_phase = KBD_MAIN_LOOP; + } else { + keyboard_scan = 0; + dev->kbd_in_cmd = 1; + dev->kbd_poll_phase = KBD_CMD_PROCESS; + } +} + + +static void +kbd_nack(atkbd_t *dev) +{ + kbd_send_to_host(dev, 0xfe); + dev->kbd_poll_phase = KBD_MAIN_LOOP; +} + + +static void +kbd_main_loop(atkbd_t *dev) +{ + uint8_t scan = !dev->kbd_inhibit && keyboard_scan; + + if (dev->kbd_written) { + dev->kbd_written = 0; + kbd_cmd_process(dev); + } else if (scan && (key_queue_start != key_queue_end)) { + /* Scan here. */ + kbd_log("ATkbd: Get %02X from FIFO\n", key_queue[key_queue_start]); + kbd_send_to_host(dev, key_queue[key_queue_start]); + key_queue_start = (key_queue_start + 1) & 0xf; + } +} + + +static void +kbd_cmd_process(atkbd_t *dev) +{ + uint8_t written = dev->kbd_written; + + /* We want data, nothing has been written yet, return. */ + if (dev->kbd_in && !dev->kbd_written) + return; + + dev->kbd_written = 0; + + if (!written && !keyboard_scan && dev->kbd_in_cmd && (dev->kbd_phase > 0)) { + kbd_log("ATkbd: Keyboard not written, not scanning, in command, and phase > 0\n"); + kbd_do_command(dev); + } else if (dev->kbd_data == 0xfe) { + kbd_log("ATkbd: Send last byte %02X\n", kbd_last_scan_code); + kbd_send_to_host(dev, kbd_last_scan_code); + dev->kbd_poll_phase = KBD_MAIN_LOOP; + } else if (dev->kbd_data == 0xee) { + kbd_log("ATkbd: Echo EE\n"); + kbd_send_to_host(dev, 0xee); + dev->kbd_poll_phase = KBD_MAIN_LOOP; + } else if (dev->kbd_data >= 0xed) { + kbd_log("ATkbd: Command %02X\n", dev->kbd_data); + if (!keyboard_scan && dev->kbd_in_cmd && (dev->kbd_cmd == 0xed)) { + kbd_log("ATkbd: Not scanning, in command, old command is ED\n"); + keyboard_scan = 1; + dev->kbd_in_cmd = 0; + } + kbd_do_command(dev); + } else { + if (!keyboard_scan && dev->kbd_in_cmd) { + if ((dev->kbd_cmd == 0xf3) && (dev->kbd_data & 0x80)) { + kbd_log("ATkbd: Command F3 data %02X has bit 7 set\n", dev->kbd_data); + kbd_nack(dev); + } else { + kbd_log("ATkbd: Command %02X data %02X\n", dev->kbd_cmd, dev->kbd_data); + kbd_do_command(dev); + } + } else { + kbd_log("ATkbd: Scanning or not in command, NACK\n"); + kbd_nack(dev); + } + } +} + + +/* Keyboard processing */ +static void +kbd_process(atkbd_t *dev) +{ + /* The real 8048 keyboard firmware stops transmitting if host wants to transmit. */ + if (dev->kbc_written[1] && dev->kbd_written) + dev->kbc_written[1] = 0; + + /* The host has either acknowledged the transmitted byte or we have not transmitted anything (yet). */ + if (!dev->kbc_written[1]) switch (dev->kbd_poll_phase) { + case KBD_MAIN_LOOP: + kbd_main_loop(dev); + break; + case KBD_CMD_PROCESS: + kbd_cmd_process(dev); + break; + } +} + + +static void +kbc_send_to_ob(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) +{ + uint8_t ch = (channel > 0) ? channel : 1; + uint8_t do_irq = (dev->mem[0x20] & ch); + int translate = (channel == 1) && (keyboard_mode & 0x60); + + if ((channel == 2) && !(dev->flags & KBC_FLAG_PS2)) + return; + + stat_hi |= dev->inhibit; + + if (!dev->kbc_send_pending) { + dev->kbc_send_pending = 1; + dev->kbc_to_send = val; + dev->kbc_channel = channel; + dev->kbc_stat_hi = stat_hi; + return; + } + + if (translate) { + /* Allow for scan code translation. */ + if (val == 0xf0) { + kbd_log("ATkbd: translate is on, F0 prefix detected\n"); + sc_or = 0x80; + return; + } + + /* Skip break code if translated make code has bit 7 set. */ + if ((sc_or == 0x80) && (val & 0x80)) { + kbd_log("ATkbd: translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val); + sc_or = 0; + return; + } + } + + dev->last_irq = (ch == 2) ? 0x1000 : 0x0002; + if (do_irq) { + kbd_log("[%04X:%08X] ATKbc: IRQ %i\n", CS, cpu_state.pc, (ch == 2) ? 12 : 1); + picint(dev->last_irq); + } + kbd_log("ATkbc: %02X coming from channel %i (%i)\n", val, channel, do_irq); + dev->ob = translate ? (nont_to_t[val] | sc_or) : val; + + dev->status = (dev->status & 0x0f) | (stat_hi | (dev->mem[0x20] & STAT_SYSFLAG) | STAT_OFULL); + if (ch == 2) + dev->status |= STAT_MFULL; + + if (translate && (sc_or == 0x80)) + sc_or = 0; +} + + +static void +write_output(atkbd_t *dev, uint8_t val) +{ + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + kbd_log("ATkbc: write output port: %02X (old: %02X)\n", val, dev->p2); + + if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) + val |= ((dev->mem[0x20] << 4) & 0x30); + + dev->kbd_inhibit = (val & 0x40); + dev->mouse_inhibit = (val & 0x08); + + if ((dev->p2 ^ val) & 0x20) { /*IRQ 12*/ + if (val & 0x20) { + kbd_log("ATkbc: write_output(): IRQ 12\n"); + picint(1 << 12); + } else + picintc(1 << 12); + } + if ((dev->p2 ^ val) & 0x10) { /*IRQ 1*/ + if (val & 0x10) { + kbd_log("ATkbc: write_output(): IRQ 1\n"); + picint(1 << 1); + } else + picintc(1 << 1); + } + if ((dev->p2 ^ val) & 0x02) { /*A20 enable change*/ + mem_a20_key = val & 0x02; + mem_a20_recalc(); + flushmmucache(); + } + if ((dev->p2 ^ val) & 0x01) { /*Reset*/ + if (! (val & 0x01)) { + /* Pin 0 selected. */ + softresetx86(); /*Pulse reset!*/ + cpu_set_edx(); + smbase = is_am486dxl ? 0x00060000 : 0x00030000; + } + } + /* Mask off the A20 stuff because we use mem_a20_key directly for that. */ + dev->p2 = val; +} + + +static void +write_cmd(atkbd_t *dev, uint8_t val) +{ + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + kbd_log("ATkbc: write command byte: %02X (old: %02X)\n", val, dev->mem[0x20]); + + /* PS/2 type 2 keyboard controllers always force the XLAT bit to 0. */ + if ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2) + val &= ~CCB_TRANSLATE; + + dev->mem[0x20] = val; + + /* Scan code translate ON/OFF. */ + keyboard_mode &= 0x93; + keyboard_mode |= (val & MODE_MASK); + + kbd_log("ATkbc: keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled"); + + /* ISA AT keyboard controllers use bit 5 for keyboard mode (1 = PC/XT, 2 = AT); + PS/2 (and EISA/PCI) keyboard controllers use it as the PS/2 mouse enable switch. + The AMIKEY firmware apparently uses this bit for something else. */ + if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) { + keyboard_mode &= ~CCB_PCMODE; + /* Update the output port to mirror the KBD DIS and AUX DIS bits, if active. */ + write_output(dev, dev->p2); + + kbd_log("ATkbc: mouse interrupt is now %s\n", (val & 0x02) ? "enabled" : "disabled"); + } + + kbd_log("Command byte now: %02X (%02X)\n", dev->mem[0x20], val); + + dev->status = (dev->status & ~STAT_SYSFLAG) | (val & STAT_SYSFLAG); +} + + +static void +pulse_output(atkbd_t *dev, uint8_t mask) +{ + if (mask != 0x0f) { + dev->old_p2 = dev->p2 & ~(0xf0 | mask); + kbd_log("pulse_output(): Output port now: %02X\n", dev->p2 & (0xf0 | mask | (dev->mem[0x20] & 0x30))); + write_output(dev, dev->p2 & (0xf0 | mask | (dev->mem[0x20] & 0x30))); + timer_set_delay_u64(&dev->pulse_cb, 6ULL * TIMER_USEC); + } +} + + +static void +set_enable_kbd(atkbd_t *dev, uint8_t enable) +{ + dev->mem[0x20] &= 0xef; + dev->mem[0x20] |= (enable ? 0x00 : 0x10); +} + + +static void +set_enable_mouse(atkbd_t *dev, uint8_t enable) +{ + dev->mem[0x20] &= 0xdf; + dev->mem[0x20] |= (enable ? 0x00 : 0x20); +} + + +static void +kbc_transmit(atkbd_t *dev, uint8_t val) +{ + kbc_send_to_ob(dev, val, 0, 0x00); +} + + +static void +kbc_command(atkbd_t *dev) +{ + uint8_t mask, val = dev->ib; + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + int bad = 1; + + if ((dev->kbc_phase > 0) && (dev->kbc_cmd == 0xac)) { + if (dev-> kbc_phase < 16) + kbc_transmit(dev, dev->mem[dev->kbc_phase]); + else if (dev-> kbc_phase == 16) + kbc_transmit(dev, (dev->p1 & 0xf0) | 0x80); + else if (dev-> kbc_phase == 17) + kbc_transmit(dev, dev->p2); + else if (dev-> kbc_phase == 18) + kbc_transmit(dev, dev->status); + + dev->kbc_phase++; + if (dev->kbc_phase == 19) { + dev->kbc_phase = 0; + dev->kbc_cmd = 0x00; + } + return; + } else if ((dev->kbc_phase > 0) && (dev->kbc_cmd == 0xa0) && (kbc_ven >= KBC_VEN_AMI)) { + val = ami_copr[dev->kbc_phase]; + kbc_transmit(dev, val); + if (val == 0x00) { + dev->kbc_phase = 0; + dev->kbc_cmd = 0x00; + } else + dev->kbc_phase++; + return; + } else if ((dev->kbc_in > 0) && (dev->kbc_cmd == 0xa5) && (dev->flags & KBC_FLAG_PS2)) { + /* load security */ + kbd_log("ATkbc: load security\n"); + dev->mem[0x50 + dev->kbc_in - 0x01] = val; + if ((dev->kbc_in == 0x80) && (val != 0x00)) { + /* Security string too long, set it to 0x00. */ + dev->mem[0x50] = 0x00; + dev->kbc_in = 0; + dev->kbc_cmd = 0; + } else if (val == 0x00) { + /* Security string finished. */ + dev->kbc_in = 0; + dev->kbc_cmd = 0; + } else /* Increase pointer and request another byte. */ + dev->kbc_in++; + return; + } + + /* If the written port is 64, go straight to the beginning of the command. */ + if (!(dev->status & STAT_CD) && dev->kbc_in) { + /* Write data to controller. */ + dev->kbc_in = 0; + dev->kbc_phase = 0; + + switch (dev->kbc_cmd) { + case 0x60 ... 0x7f: + if (dev->kbc_cmd == 0x60) + write_cmd(dev, val); + else + dev->mem[(dev->kbc_cmd & 0x1f) + 0x20] = val; + break; + + case 0xc7: /* or input port with system data */ + dev->p1 |= val; + break; + + case 0xcb: /* set keyboard mode */ + kbd_log("New AMIKey mode: %02X\n", val); + dev->ami_mode = val; + dev->flags &= ~KBC_FLAG_PS2; + if (val & 1) + dev->flags |= KBC_FLAG_PS2; + break; + + case 0xd1: /* write output port */ + kbd_log("ATkbc: write output port\n"); + if (dev->p2_locked) { + /*If keyboard controller lines P22-P23 are blocked, + we force them to remain unchanged.*/ + val &= ~0x0c; + val |= (dev->p2 & 0x0c); + } + write_output(dev, val); + break; + + case 0xd2: /* write to keyboard output buffer */ + kbd_log("ATkbc: write to keyboard output buffer\n"); + // kbc_send_to_ob(dev, val, 1, 0x00); + /* Should be channel 1, but we send to 0 to avoid translation, + since bytes output using this command do *NOT* get translated. */ + kbc_send_to_ob(dev, val, 0, 0x00); + break; + + case 0xd3: /* write to mouse output buffer */ + kbd_log("ATkbc: write to mouse output buffer\n"); + if (dev->flags & KBC_FLAG_PS2) + kbc_send_to_ob(dev, val, 2, 0x00); + break; + + case 0xd4: /* write to mouse */ + kbd_log("ATkbc: write to mouse (%02X)\n", val); + + if (dev->flags & KBC_FLAG_PS2) { + set_enable_mouse(dev, 1); + dev->mem[0x20] &= ~0x20; + if (mouse_write && !dev->kbc_written[2]) { + kbd_log("ATkbc: Sending %02X to mouse...\n", dev->ib); + dev->mouse_data = val; + dev->mouse_written = 1; + dev->kbc_wait_for_response = 2; + } else + kbc_send_to_ob(dev, 0xfe, 2, 0x40); + } + break; + + default: + /* + * Run the vendor-specific handler + * if we have one. Otherwise, or if + * it returns an error, log a bad + * controller command. + */ + if (dev->write60_ven) + bad = dev->write60_ven(dev, val); + +#ifdef ENABLE_KEYBOARD_AT_LOG + if (bad) + kbd_log("ATkbc: bad controller command %02x data %02x\n", dev->kbc_cmd, val); +#endif + } + } else { + /* Controller command. */ + kbd_log("ATkbc: Controller command: %02X\n", val); + dev->kbc_in = 0; + dev->kbc_phase = 0; + + switch (val) { + /* Read data from KBC memory. */ + case 0x20 ... 0x3f: + kbc_transmit(dev, dev->mem[(val & 0x1f) + 0x20]); + break; + + /* Write data to KBC memory. */ + case 0x60 ... 0x7f: + dev->kbc_in = 1; + break; + + case 0xaa: /* self-test */ + kbd_log("ATkbc: self-test\n"); + write_output(dev, (dev->flags & KBC_FLAG_PS2) ? 0x4b : 0xcf); + + /* Always reinitialize all queues - the real hardware pulls keyboard and mouse + clocks high, which stops keyboard scanning. */ + kbd_log("ATkbc: self-test reinitialization\n"); + dev->kbd_in_cmd = dev->mouse_in_cmd = 0; + dev->status &= ~STAT_OFULL; + dev->last_irq = 0; + dev->kbc_phase = 0; + + /* Phoenix MultiKey should have 0x60 | STAT_SYSFLAG. */ + if (dev->flags & KBC_FLAG_PS2) + write_cmd(dev, 0x30 | STAT_SYSFLAG); + else + write_cmd(dev, 0x10 | STAT_SYSFLAG); + kbc_transmit(dev, 0x55); + break; + + case 0xab: /* interface test */ + kbd_log("ATkbc: interface test\n"); + /* No error. */ + kbc_transmit(dev, 0x00); + break; + + case 0xac: /* diagnostic dump */ + kbd_log("ATkbc: diagnostic dump\n"); + kbc_transmit(dev, dev->mem[0x20]); + dev->kbc_phase = 1; + break; + + case 0xad: /* disable keyboard */ + kbd_log("ATkbc: disable keyboard\n"); + set_enable_kbd(dev, 0); + break; + + case 0xae: /* enable keyboard */ + kbd_log("ATkbc: enable keyboard\n"); + set_enable_kbd(dev, 1); + break; + + case 0xc7: /* or input port with system data */ + kbd_log("ATkbc: Phoenix - or input port with system data\n"); + dev->kbc_in = 1; + break; + + case 0xca: /* read keyboard mode */ + kbd_log("ATkbc: AMI - read keyboard mode\n"); + kbc_transmit(dev, dev->ami_mode); + break; + + case 0xcb: /* set keyboard mode */ + kbd_log("ATkbc: AMI - set keyboard mode\n"); + dev->kbc_in = 1; + break; + + case 0xd0: /* read output port */ + kbd_log("ATkbc: read output port\n"); + mask = 0xff; + if (dev->mem[0x20] & 0x10) + mask &= 0xbf; + if ((dev->flags & KBC_FLAG_PS2) && (dev->mem[0x20] & 0x20)) + mask &= 0xf7; + kbc_transmit(dev, dev->p2 & mask); + break; + + case 0xd1: /* write output port */ + kbd_log("ATkbc: write output port\n"); + dev->kbc_in = 1; + break; + + case 0xd2: /* write keyboard output buffer */ + kbd_log("ATkbc: write keyboard output buffer\n"); + if (dev->flags & KBC_FLAG_PS2) + dev->kbc_in = 1; + else + kbc_transmit(dev, 0x00); /* NCR */ + break; + + case 0xdd: /* disable A20 address line */ + case 0xdf: /* enable A20 address line */ + kbd_log("ATkbc: %sable A20\n", (val == 0xdd) ? "dis": "en"); + write_output(dev, (dev->p2 & 0xfd) | (val & 0x02)); + break; + + case 0xe0: /* read test inputs */ + kbd_log("ATkbc: read test inputs\n"); + kbc_transmit(dev, 0x00); + break; + + case 0xe1: case 0xea: + kbd_log("ATkbc: setting P23-P21 to %01X\n", val & 0x0e); + write_output(dev, (dev->p2 & 0xf1) | (val & 0x0e)); + break; + + default: + /* + * Unrecognized controller command. + * + * If we have a vendor-specific handler, run + * that. Otherwise, or if that handler fails, + * log a bad command. + */ + if (dev->write64_ven) + bad = dev->write64_ven(dev, val); + + kbd_log(bad ? "ATkbc: bad controller command %02X\n" : "", val); + } + + /* If the command needs data, remember the command. */ + if (dev->kbc_in || (dev->kbc_phase > 0)) + dev->kbc_cmd = val; + } +} + + +static void +kbc_dev_data_to_ob(atkbd_t *dev, uint8_t channel) +{ + dev->kbc_written[channel] = 0; + kbd_log("ATkbd: Forwarding %02X from channel %i...\n", dev->kbc_data[channel], channel); + kbc_send_to_ob(dev, dev->kbc_data[channel], channel, 0x00); +} + + +static void +kbc_main_loop_scan(atkbd_t *dev) +{ + uint8_t port_dis = dev->mem[0x20] & 0x30; + uint8_t ps2 = (dev->flags & KBC_FLAG_PS2); + + if (!ps2) + port_dis |= 0x20; + + if (!(dev->status & STAT_OFULL)) { + if (port_dis & 0x20) { + if (!(port_dis & 0x10)) { + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Main loop\n" + "ATkbc: Scan: AUX DIS, KBD EN\n"); + // kbd_log("ATkbc: Scan: AUX DIS, KBD EN\n"); + /* Enable communication with keyboard. */ + dev->p2 &= 0xbf; + dev->kbd_inhibit = 0; + kbc_wait(dev, 1); + } +#ifdef ENABLE_KEYBOARD_AT_LOG + else { + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Main loop\n" + "ATkbc: Scan: AUX DIS, KBD DIS\n"); + // kbd_log("ATkbc: Scan: AUX DIS, KBD DIS\n"); + } +#endif + } else { + /* Enable communication with mouse. */ + dev->p2 &= 0xf7; + dev->mouse_inhibit = 0; + if (dev->mem[0x20] & 0x10) { + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Main loop\n" + "ATkbc: Scan: AUX EN , KBD DIS\n"); + // kbd_log("ATkbc: Scan: AUX EN , KBD DIS\n"); + kbc_wait(dev, 2); + } else { + /* Enable communication with keyboard. */ + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Main loop\n" + "ATkbc: Scan: AUX EN , KBD EN\n"); + // kbd_log("ATkbc: Scan: AUX EN , KBD EN\n"); + dev->p2 &= 0xbf; + dev->kbd_inhibit = 0; + kbc_wait(dev, 3); + } + } + } +#ifdef ENABLE_KEYBOARD_AT_LOG + else { + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Main loop\n" + "ATkbc: Scan: IBF not full and OBF full, do nothing\n"); + // kbd_log("ATkbc: Scan: IBF not full and OBF full, do nothing\n"); + } +#endif +} + + +static void +kbc_process_ib(atkbd_t *dev) +{ + dev->status &= ~STAT_IFULL; + + if (dev->status & STAT_CD) { + dev->kbc_in_cmd = 1; + kbc_command(dev); + + if ((dev->kbc_phase == 0) && !dev->kbc_in) + dev->kbc_in_cmd = 0; + else + return; + } else { + dev->mem[0x20] &= ~0x10; + dev->kbd_data = dev->ib; + dev->kbd_written = 1; + dev->kbc_wait_for_response = 1; + } + + dev->kbc_poll_phase = KBC_MAIN_LOOP; + if (!dev->kbc_wait_for_response) + kbc_main_loop_scan(dev); +} + + +static void +kbc_wait(atkbd_t *dev, uint8_t flags) +{ + if ((flags & 1) && dev->kbc_written[1]) { + /* Disable communication with mouse. */ + dev->p2 |= 0x08; + dev->mouse_inhibit = 1; + /* Send keyboard byte to host. */ + kbc_dev_data_to_ob(dev, CHANNEL_KBD); + dev->kbc_poll_phase = KBC_MAIN_LOOP; + } else if ((flags & 2) && dev->kbc_written[2]) { + /* Disable communication with keyboard. */ + dev->p2 |= 0x40; + dev->kbd_inhibit = 1; + /* Send mouse byte to host. */ + kbc_dev_data_to_ob(dev, CHANNEL_MOUSE); + dev->kbc_poll_phase = KBC_MAIN_LOOP; + } else if (dev->status & STAT_IFULL) { + /* Disable communication with keyboard and mouse. */ + dev->p2 |= 0x48; + dev->kbd_inhibit = dev->mouse_inhibit = 1; + kbc_process_ib(dev); + } else + dev->kbc_poll_phase = KBC_WAIT | flags; +} + + +/* Controller processing */ +static void +kbc_process(atkbd_t *dev) +{ + // kbd_log("ATkbc: kbc_process()\n"); + + /* If we're waiting for the response from the keyboard or mouse, do nothing + until the device has repsonded back. */ + if (dev->kbc_wait_for_response > 0) { + if (dev->kbc_written[dev->kbc_wait_for_response]) + dev->kbc_wait_for_response = 0; + else + return; + } + + if (dev->kbc_send_pending) { + kbd_log("ATkbc: Sending delayed %02X on channel %i with high status %02X\n", + dev->kbc_to_send, dev->kbc_channel, dev->kbc_stat_hi); + kbc_send_to_ob(dev, dev->kbc_to_send, dev->kbc_channel, dev->kbc_stat_hi); + dev->kbc_send_pending = 0; + } + + if (dev->kbc_poll_phase == KBC_RESET) { + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Reset loop()\n"); + + if (dev->status & STAT_IFULL) { + dev->status &= ~STAT_IFULL; + + if ((dev->status & STAT_CD) && (dev->ib == 0xaa)) { + dev->kbc_in_cmd = 1; + kbc_command(dev); + + if ((dev->kbc_phase == 0) && !dev->kbc_in) + dev->kbc_in_cmd = 0; + + dev->kbc_poll_phase = KBC_MAIN_LOOP; + } + } + + return; + } + + if (dev->kbc_in_cmd || (dev->kbc_phase > 0) || dev->kbc_in) { + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: In a command\n"); + if (!dev->kbc_in && (dev->status & STAT_OFULL)) { + kbd_log("ATkbc: !dev->kbc_in && (dev->status & STAT_OFULL)\n"); + return; /* We do not want input and we're waiting for the host to read the data + we transmitted, but it has not done that yet, do nothing. */ + } else if (dev->kbc_in && !(dev->status & STAT_IFULL)) { + kbd_log("ATkbc: dev->kbc_in && !(dev->status & STAT_IFULL)\n"); + return; /* We want input and the host has not provided us with any yet, do nothing. */ + } +#ifdef ENABLE_KEYBOARD_AT_LOG + else + kbd_log("ATkbc: Normal condition\n"); +#endif + + if (dev->status & STAT_IFULL) { + dev->status &= ~STAT_IFULL; + + if (dev->status & STAT_CD) { + kbd_log("ATkbc: Resetting command\n"); + dev->kbc_phase = 0; + dev->kbc_in = 0; + } + } + + /* Process command. */ + kbc_command(dev); + + if ((dev->kbc_phase == 0) && !dev->kbc_in) + dev->kbc_in_cmd = 0; + else + return; + + if (!(dev->status & STAT_OFULL)) + kbc_main_loop_scan(dev); + /* Make absolutely sure to do nothing if OBF is full and IBF is empty. */ + } else if (!(dev->status & STAT_OFULL) || (dev->status & STAT_IFULL)) switch (dev->kbc_poll_phase) { + case KBC_MAIN_LOOP: + // kbd_log("ATkbc: Main loop\n"); + if (dev->status & STAT_IFULL) { + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Main loop\n" + "ATkbc: IBF full, process\n"); + kbc_process_ib(dev); + } else + kbc_main_loop_scan(dev); + break; + case KBC_WAIT_FOR_KBD: + case KBC_WAIT_FOR_MOUSE: + case KBC_WAIT_FOR_BOTH: + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Scan: Phase %i\n", dev->kbc_poll_phase); + kbc_wait(dev, dev->kbc_poll_phase & 3); + break; + default: + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Scan: Invalid phase %i\n", dev->kbc_poll_phase); + break; + } } @@ -742,105 +1792,29 @@ static void kbd_poll(void *priv) { atkbd_t *dev = (atkbd_t *)priv; -#ifdef ENABLE_KEYBOARD_AT_LOG - const uint8_t channels[4] = { 1, 2, 0, 0 }; -#endif timer_advance_u64(&dev->send_delay_timer, (100ULL * TIMER_USEC)); - if (dev->out_new != -1 && !dev->last_irq) { - dev->wantirq = 0; - if (dev->out_new & 0x100) { - if (dev->mem[0] & 0x02) - picint(0x1000); - kbd_log("ATkbc: %02X coming from channel 2\n"); - dev->out = dev->out_new & 0xff; - dev->out_new = -1; - dev->status = (dev->status & ~STAT_IFULL) | (STAT_OFULL | STAT_MFULL); - dev->last_irq = 0x1000; - } else { - if (dev->mem[0] & 0x01) - picint(2); - kbd_log("ATkbc: %02X coming from channel %i\n", dev->out_new & 0xff, channels[(dev->out_new >> 8) & 0x03]); - dev->out = dev->out_new & 0xff; - dev->out_new = -1; - dev->status = (dev->status & ~(STAT_IFULL | STAT_MFULL)) | STAT_OFULL; - dev->last_irq = 2; - } - } + /* We process all three devices at the same time, in an arbitrary order. */ - if (dev->out_new == -1 && !(dev->status & STAT_OFULL) && key_ctrl_queue_start != key_ctrl_queue_end) { - kbd_log("ATkbc: %02X on channel 0\n", key_ctrl_queue[key_ctrl_queue_start]); - dev->out_new = key_ctrl_queue[key_ctrl_queue_start] | 0x200; - key_ctrl_queue_start = (key_ctrl_queue_start + 1) & 0xf; - } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && dev->out_delayed != -1) { - kbd_log("ATkbc: %02X delayed on channel %i\n", dev->out_delayed & 0xff, channels[(dev->out_delayed >> 8) & 0x03]); - dev->out_new = dev->out_delayed; - dev->out_delayed = -1; - } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && mouse_queue_start != mouse_queue_end) { - kbd_log("ATkbc: %02X on channel 2\n", mouse_queue[mouse_queue_start]); - dev->out_new = mouse_queue[mouse_queue_start] | 0x100; - mouse_queue_start = (mouse_queue_start + 1) & 0xf; - } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && !(dev->mem[0] & 0x10) && key_queue_start != key_queue_end) { - kbd_log("ATkbc: %02X on channel 1\n", key_queue[key_queue_start]); - dev->out_new = key_queue[key_queue_start]; - key_queue_start = (key_queue_start + 1) & 0xf; - } + /* Keyboard processing */ + kbd_process(dev); - if (dev->reset_delay) { - dev->reset_delay--; - if (!dev->reset_delay) { - kbd_log("ATkbc: Sending AA on keyboard reset...\n"); - add_data_kbd_direct(dev, 0xaa); - } - } -} + /* TODO: Mouse processing */ + // mouse_process(dev); - -static void -add_data(atkbd_t *dev, uint8_t val) -{ - kbd_log("ATkbc: add to queue\n"); - - kbd_log("ATkbc: key_ctrl_queue[%02X] = %02X;\n", key_ctrl_queue_end, val); - kbc_queue_add(dev, val, 0, 0x00); - - if (!(dev->out_new & 0x300)) { - dev->out_delayed = dev->out_new; - dev->out_new = -1; - } + /* Controller processing */ + kbc_process(dev); } static void add_data_vals(atkbd_t *dev, uint8_t *val, uint8_t len) { - int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); - int translate = (keyboard_mode & 0x40); int i; - uint8_t or = 0; - uint8_t send; - if (dev->reset_delay) - return; - - translate = translate || (keyboard_mode & 0x40) || xt_mode; - translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); - - for (i = 0; i < len; i++) { - if (translate) { - if (val[i] == 0xf0) { - or = 0x80; - continue; - } - send = nont_to_t[val[i]] | or; - if (or == 0x80) - or = 0; - } else - send = val[i]; - - add_data_kbd_queue(dev, 0, send); - } + for (i = 0; i < len; i++) + add_data_kbd_queue(dev, 0, val[i]); } @@ -848,56 +1822,21 @@ static void add_data_kbd(uint16_t val) { atkbd_t *dev = SavedKbd; - int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); - int translate = (keyboard_mode & 0x40); uint8_t fake_shift[4]; uint8_t num_lock = 0, shift_states = 0; uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - if (dev->reset_delay) + if (dev->kbd_in || (dev->kbd_phase > 0)) return; - translate = translate || (keyboard_mode & 0x40) || xt_mode; - translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); - keyboard_get_states(NULL, &num_lock, NULL); shift_states = keyboard_get_shift() & STATE_SHIFT_MASK; - /* Allow for scan code translation. */ - if (translate && (val == 0xf0)) { - kbd_log("ATkbd: translate is on, F0 prefix detected\n"); - sc_or = 0x80; - return; - } - - /* Skip break code if translated make code has bit 7 set. */ - if (translate && (sc_or == 0x80) && (val & 0x80)) { - kbd_log("ATkbd: translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val); - sc_or = 0; - return; - } - /* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */ - if ((dev != NULL) && (kbc_ven == KBC_VEN_TOSHIBA) && - (keyboard_recv(0xb8) || keyboard_recv(0x9d))) switch (val) { - case 0x4f: t3100e_notify_set(0x01); break; /* End */ - case 0x50: t3100e_notify_set(0x02); break; /* Down */ - case 0x51: t3100e_notify_set(0x03); break; /* PgDn */ - case 0x52: t3100e_notify_set(0x04); break; /* Ins */ - case 0x53: t3100e_notify_set(0x05); break; /* Del */ - case 0x54: t3100e_notify_set(0x06); break; /* SysRQ */ - case 0x45: t3100e_notify_set(0x07); break; /* NumLock */ - case 0x46: t3100e_notify_set(0x08); break; /* ScrLock */ - case 0x47: t3100e_notify_set(0x09); break; /* Home */ - case 0x48: t3100e_notify_set(0x0a); break; /* Up */ - case 0x49: t3100e_notify_set(0x0b); break; /* PgUp */ - case 0x4A: t3100e_notify_set(0x0c); break; /* Keypad -*/ - case 0x4B: t3100e_notify_set(0x0d); break; /* Left */ - case 0x4C: t3100e_notify_set(0x0e); break; /* KP 5 */ - case 0x4D: t3100e_notify_set(0x0f); break; /* Right */ - } + if ((dev != NULL) && (kbc_ven == KBC_VEN_TOSHIBA) && (keyboard_recv(0xb8) || keyboard_recv(0x9d)) && + (val >= 0x4f) && (val <= 0x54) && (val != 0x4e)) + t3100e_notify_set((val + 2) & 0x0f); - kbd_log("ATkbd: translate is %s, ", translate ? "on" : "off"); switch(val) { case FAKE_LSHIFT_ON: kbd_log("fake left shift on, scan code: "); @@ -1030,18 +1969,7 @@ add_data_kbd(uint16_t val) break; default: -#ifdef ENABLE_KEYBOARD_AT_LOG - kbd_log("scan code: "); - if (translate) { - kbd_log("%02X (original: ", (nont_to_t[val] | sc_or)); - if (sc_or == 0x80) - kbd_log("F0 "); - kbd_log("%02X)\n", val); - } else - kbd_log("%02X\n", val); -#endif - - add_data_kbd_queue(dev, 0, translate ? (nont_to_t[val] | sc_or) : val); + add_data_kbd_queue(dev, 0, val); break; } @@ -1050,121 +1978,13 @@ add_data_kbd(uint16_t val) } -static void -write_output(atkbd_t *dev, uint8_t val) -{ - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - kbd_log("ATkbc: write output port: %02X (old: %02X)\n", val, dev->output_port); - - if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF)) - val |= ((dev->mem[0] << 4) & 0x10); - - if ((dev->output_port ^ val) & 0x20) { /*IRQ 12*/ - if (val & 0x20) - picint(1 << 12); - else - picintc(1 << 12); - } - if ((dev->output_port ^ val) & 0x10) { /*IRQ 1*/ - if (val & 0x10) - picint(1 << 1); - else - picintc(1 << 1); - } - if ((dev->output_port ^ val) & 0x02) { /*A20 enable change*/ - mem_a20_key = val & 0x02; - mem_a20_recalc(); - flushmmucache(); - } - if ((dev->output_port ^ val) & 0x01) { /*Reset*/ - if (! (val & 0x01)) { - /* Pin 0 selected. */ - softresetx86(); /*Pulse reset!*/ - cpu_set_edx(); - smbase = is_am486dxl ? 0x00060000 : 0x00030000; - } - } - /* Mask off the A20 stuff because we use mem_a20_key directly for that. */ - dev->output_port = val; -} - - -static void -write_cmd(atkbd_t *dev, uint8_t val) -{ - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - kbd_log("ATkbc: write command byte: %02X (old: %02X)\n", val, dev->mem[0]); - - if ((val & 1) && (dev->status & STAT_OFULL)) - dev->wantirq = 1; - if (!(val & 1) && dev->wantirq) - dev->wantirq = 0; - - /* PS/2 type 2 keyboard controllers always force the XLAT bit to 0. */ - if ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2) { - val &= ~CCB_TRANSLATE; - dev->mem[0] &= ~CCB_TRANSLATE; - } - - /* Scan code translate ON/OFF. */ - keyboard_mode &= 0x93; - keyboard_mode |= (val & MODE_MASK); - - kbd_log("ATkbc: keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled"); - - /* ISA AT keyboard controllers use bit 5 for keyboard mode (1 = PC/XT, 2 = AT); - PS/2 (and EISA/PCI) keyboard controllers use it as the PS/2 mouse enable switch. - The AMIKEY firmware apparently uses this bit for something else. */ - if ((kbc_ven == KBC_VEN_AMI) || - ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) { - keyboard_mode &= ~CCB_PCMODE; - /* Update the output port to mirror the KBD DIS and AUX DIS bits, if active. */ - write_output(dev, dev->output_port); - - kbd_log("ATkbc: mouse interrupt is now %s\n", (val & 0x02) ? "enabled" : "disabled"); - } - - kbd_log("Command byte now: %02X (%02X)\n", dev->mem[0], val); - - dev->status = (dev->status & ~STAT_SYSFLAG) | (val & STAT_SYSFLAG); -} - - -static void -pulse_output(atkbd_t *dev, uint8_t mask) -{ - if (mask != 0x0f) { - dev->old_output_port = dev->output_port & ~(0xf0 | mask); - kbd_log("pulse_output(): Output port now: %02X\n", dev->output_port & (0xf0 | mask)); - write_output(dev, dev->output_port & (0xf0 | mask)); - timer_set_delay_u64(&dev->pulse_cb, 6ULL * TIMER_USEC); - } -} - - static void pulse_poll(void *priv) { atkbd_t *dev = (atkbd_t *)priv; - kbd_log("pulse_poll(): Output port now: %02X\n", dev->output_port | dev->old_output_port); - write_output(dev, dev->output_port | dev->old_output_port); -} - - -static void -set_enable_kbd(atkbd_t *dev, uint8_t enable) -{ - dev->mem[0] &= 0xef; - dev->mem[0] |= (enable ? 0x00 : 0x10); -} - - -static void -set_enable_mouse(atkbd_t *dev, uint8_t enable) -{ - dev->mem[0] &= 0xdf; - dev->mem[0] |= (enable ? 0x00 : 0x20); + kbd_log("pulse_poll(): Output port now: %02X\n", dev->p2 | dev->old_p2); + write_output(dev, dev->p2 | dev->old_p2); } @@ -1173,49 +1993,70 @@ write64_generic(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; uint8_t current_drive, fixed_bits; - uint8_t kbc_ven = 0x0; - kbc_ven = dev->flags & KBC_VEN_MASK; - + uint8_t kbc_ven = 0x0; + kbc_ven = dev->flags & KBC_VEN_MASK; switch (val) { case 0xa4: /* check if password installed */ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + if (dev->flags & KBC_FLAG_PS2) { kbd_log("ATkbc: check if password installed\n"); - add_data(dev, 0xf1); + kbc_transmit(dev, (dev->mem[0x50] == 0x00) ? 0xf1 : 0xfa); + return 0; + } + break; + + case 0xa5: /* load security */ + if (dev->flags & KBC_FLAG_PS2) { + kbd_log("ATkbc: load security\n"); + dev->kbc_in = 1; return 0; } break; case 0xa7: /* disable mouse port */ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + if (dev->flags & KBC_FLAG_PS2) { kbd_log("ATkbc: disable mouse port\n"); - set_enable_mouse(dev, 0); + // kbc_transmit(dev, 0); return 0; } break; case 0xa8: /*Enable mouse port*/ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + if (dev->flags & KBC_FLAG_PS2) { kbd_log("ATkbc: enable mouse port\n"); - set_enable_mouse(dev, 1); + // kbc_transmit(dev, 1); return 0; } break; case 0xa9: /*Test mouse port*/ kbd_log("ATkbc: test mouse port\n"); - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - add_data(dev, 0x00); /* no error, this is testing the channel 2 interface */ + if (dev->flags & KBC_FLAG_PS2) { + /* No error, this is testing the channel 2 interface. */ + kbc_transmit(dev, 0x00); return 0; } break; case 0xaf: /* read keyboard version */ kbd_log("ATkbc: read keyboard version\n"); - add_data(dev, 0x00); + kbc_transmit(dev, 0x00); return 0; case 0xc0: /* read input port */ + /* IBM PS/1: + Bit 2 and 4 ignored (we return always 0), + Bit 6 must 1 for 5.25" floppy drive, 0 for 3.5". + Intel AMI: + Bit 2 ignored (we return always 1), + Bit 4 must be 1, + Bit 6 must be 1 or else error in SMM. + Acer: + Bit 2 must be 0 (and Acer V10 disables CMOS setup if it's 1), + Bit 4 must be 0, + Bit 6 ignored. + P6RP4: + Bit 2 must be 1 or CMOS setup is disabled. */ kbd_log("ATkbc: read input port\n"); fixed_bits = 4; /* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */ @@ -1223,11 +2064,8 @@ write64_generic(void *priv, uint8_t val) fixed_bits |= 0x40; if (kbc_ven == KBC_VEN_IBM_PS1) { current_drive = fdc_get_current_drive(); - add_to_kbc_queue_front(dev, dev->input_port | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00), - 0, 0x00); - dev->input_port = ((dev->input_port + 1) & 3) | - (dev->input_port & 0xfc) | - (fdd_is_525(current_drive) ? 0x40 : 0x00); + kbc_transmit(dev, dev->p1 | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00)); + dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc) | (fdd_is_525(current_drive) ? 0x40 : 0x00); } else if (kbc_ven == KBC_VEN_NCR) { /* switch settings * bit 7: keyboard disable @@ -1239,39 +2077,34 @@ write64_generic(void *priv, uint8_t val) * bit 1: high/auto speed * bit 0: dma mode */ - add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf, - 0, 0x00); - dev->input_port = ((dev->input_port + 1) & 3) | - (dev->input_port & 0xfc); + kbc_transmit(dev, (dev->p1 | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf); + dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc); } else { - if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) && - ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI)) - add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits) & - (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0xeb : 0xef), 0, 0x00); + pclog("[%04X:%08X] Reading %02X from input port\n", CS, cpu_state.pc, ((dev->p1 | fixed_bits) & 0xf0) | 0x0c); + if ((dev->flags & KBC_FLAG_PS2) && ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI)) + // kbc_transmit(dev, ((dev->p1 | fixed_bits) & 0xf0) | 0x0c); + kbc_transmit(dev, ((dev->p1 | fixed_bits) & 0xf0) | 0x08); + // kbc_transmit(dev, (dev->p1 | fixed_bits) & (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0xeb : 0xef)); else - add_to_kbc_queue_front(dev, dev->input_port | fixed_bits, 0, 0x00); - dev->input_port = ((dev->input_port + 1) & 3) | - (dev->input_port & 0xfc); + kbc_transmit(dev, dev->p1 | fixed_bits); + dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc); } return 0; case 0xd3: /* write mouse output buffer */ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + if (dev->flags & KBC_FLAG_PS2) { kbd_log("ATkbc: write mouse output buffer\n"); - dev->want60 = 1; + dev->kbc_in = 1; return 0; } break; case 0xd4: /* write to mouse */ kbd_log("ATkbc: write to mouse\n"); - dev->want60 = 1; + dev->kbc_in = 1; return 0; - case 0xf0: case 0xf1: case 0xf2: case 0xf3: - case 0xf4: case 0xf5: case 0xf6: case 0xf7: - case 0xf8: case 0xf9: case 0xfa: case 0xfb: - case 0xfc: case 0xfd: case 0xfe: case 0xff: + case 0xf0 ... 0xff: kbd_log("ATkbc: pulse %01X\n", val & 0x0f); pulse_output(dev, val & 0x0f); return 0; @@ -1286,35 +2119,168 @@ static uint8_t write60_ami(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; + uint16_t index = 0x00c0; - switch(dev->command) { - /* 0x40 - 0x5F are aliases for 0x60-0x7F */ - case 0x40: case 0x41: case 0x42: case 0x43: - case 0x44: case 0x45: case 0x46: case 0x47: - case 0x48: case 0x49: case 0x4a: case 0x4b: - 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: case 0x5f: - kbd_log("ATkbc: AMI - alias write to %08X\n", dev->command); - dev->mem[dev->command & 0x1f] = val; - if (dev->command == 0x60) + switch(dev->kbc_cmd) { + /* 0x40 - 0x5F are aliases for 0x60 - 0x7F */ + case 0x40 ... 0x5f: + kbd_log("ATkbc: AMI - alias write to %08X\n", dev->kbc_cmd); + if (dev->kbc_cmd == 0x40) write_cmd(dev, val); + else + dev->mem[(dev->kbc_cmd & 0x1f) + 0x20] = val; return 0; case 0xaf: /* set extended controller RAM */ - kbd_log("ATkbc: AMI - set extended controller RAM\n"); - if (dev->secr_phase == 1) { - dev->mem_addr = val; - dev->want60 = 1; - dev->secr_phase = 2; - } else if (dev->secr_phase == 2) { - dev->mem[dev->mem_addr] = val; + kbd_log("ATkbc: AMI - set extended controller RAM, input phase %i\n", dev->secr_phase); + if (dev->secr_phase == 0) { + dev->mem_index = val; + dev->kbc_in = 1; + dev->secr_phase++; + } else if (dev->secr_phase == 1) { + if (dev->mem_index == 0x20) + write_cmd(dev, val); + else + dev->mem[dev->mem_index] = val; dev->secr_phase = 0; } return 0; + case 0xb8: + kbd_log("ATkbc: AMI MegaKey - memory index %02X\n", val); + dev->mem_index = val; + return 0; + + case 0xbb: + kbd_log("ATkbc: AMI MegaKey - write %02X to memory index %02X\n", val, dev->mem_index); + if (dev->mem_index >= 0x80) { + switch (dev->mem[0x9b] & 0xc0) { + case 0x00: + index = 0x0080; + break; + case 0x40: case 0x80: + index = 0x0000; + break; + case 0xc0: + index = 0x0100; + break; + } + dev->mem[index + dev->mem_index] = val; + } else if (dev->mem_index == 0x60) + write_cmd(dev, val); + else if (dev->mem_index == 0x42) + dev->status = val; + else if (dev->mem_index >= 0x40) + dev->mem[dev->mem_index - 0x40] = val; + else + dev->mem_int[dev->mem_index] = val; + return 0; + + case 0xbd: + kbd_log("ATkbc: AMI MegaKey - write %02X to config index %02X\n", val, dev->mem_index); + switch (dev->mem_index) { + case 0x00: /* STAT8042 */ + dev->status = val; + break; + case 0x01: /* Password_ptr */ + dev->mem[0x1c] = val; + break; + case 0x02: /* Wakeup_Tsk_Reg */ + dev->mem[0x1e] = val; + break; + case 0x03: /* CCB */ + write_cmd(dev, val); + break; + case 0x04: /* Debounce_time */ + dev->mem[0x4d] = val; + break; + case 0x05: /* Pulse_Width */ + dev->mem[0x4e] = val; + break; + case 0x06: /* Pk_sel_byte */ + dev->mem[0x4c] = val; + break; + case 0x07: /* Func_Tsk_Reg */ + dev->mem[0x7e] = val; + break; + case 0x08: /* TypematicRate */ + dev->mem[0x80] = val; + break; + case 0x09: /* Led_Flag_Byte */ + dev->mem[0x81] = val; + break; + case 0x0a: /* Kbms_Command_St */ + dev->mem[0x87] = val; + break; + case 0x0b: /* Delay_Count_Byte */ + dev->mem[0x86] = val; + break; + case 0x0c: /* KBC_Flags */ + dev->mem[0x9b] = val; + break; + case 0x0d: /* SCODE_HK1 */ + dev->mem[0x50] = val; + break; + case 0x0e: /* SCODE_HK2 */ + dev->mem[0x51] = val; + break; + case 0x0f: /* SCODE_HK3 */ + dev->mem[0x52] = val; + break; + case 0x10: /* SCODE_HK4 */ + dev->mem[0x53] = val; + break; + case 0x11: /* SCODE_HK5 */ + dev->mem[0x54] = val; + break; + case 0x12: /* SCODE_HK6 */ + dev->mem[0x55] = val; + break; + case 0x13: /* TASK_HK1 */ + dev->mem[0x56] = val; + break; + case 0x14: /* TASK_HK2 */ + dev->mem[0x57] = val; + break; + case 0x15: /* TASK_HK3 */ + dev->mem[0x58] = val; + break; + case 0x16: /* TASK_HK4 */ + dev->mem[0x59] = val; + break; + case 0x17: /* TASK_HK5 */ + dev->mem[0x5a] = val; + break; + /* The next 4 bytes have uncertain correspondences. */ + case 0x18: /* Batt_Poll_delay_Time */ + dev->mem[0x5b] = val; + break; + case 0x19: /* Batt_Alarm_Reg1 */ + dev->mem[0x5c] = val; + break; + case 0x1a: /* Batt_Alarm_Reg2 */ + dev->mem[0x5d] = val; + break; + case 0x1b: /* Batt_Alarm_Tsk_Reg */ + dev->mem[0x5e] = val; + break; + case 0x1c: /* Kbc_State1 */ + dev->mem[0x9d] = val; + break; + case 0x1d: /* Aux_Config */ + dev->mem[0x75] = val; + break; + case 0x1e: /* Kbc_State3 */ + dev->mem[0x73] = val; + break; + } + return 0; + + case 0xc1: /* write input port */ + kbd_log("ATkbc: AMI MegaKey - write %02X to input port\n", val); + dev->p1 = val; + return 0; + case 0xcb: /* set keyboard mode */ kbd_log("ATkbc: AMI - set keyboard mode\n"); return 0; @@ -1328,62 +2294,50 @@ static uint8_t write64_ami(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; + uint16_t index = 0x00c0; switch (val) { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x05: case 0x06: case 0x07: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0d: case 0x0e: case 0x0f: - case 0x10: case 0x11: case 0x12: case 0x13: - case 0x14: case 0x15: case 0x16: case 0x17: - case 0x18: case 0x19: case 0x1a: case 0x1b: - case 0x1c: case 0x1d: case 0x1e: case 0x1f: + case 0x00 ... 0x1f: kbd_log("ATkbc: AMI - alias read from %08X\n", val); - add_data(dev, dev->mem[val]); + kbc_transmit(dev, dev->mem[val + 0x20]); return 0; - case 0x40: case 0x41: case 0x42: case 0x43: - case 0x44: case 0x45: case 0x46: case 0x47: - case 0x48: case 0x49: case 0x4a: case 0x4b: - 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: case 0x5f: - kbd_log("ATkbc: AMI - alias write to %08X\n", dev->command); - dev->want60 = 1; + case 0x40 ... 0x5f: + kbd_log("ATkbc: AMI - alias write to %08X\n", dev->kbc_cmd); + dev->kbc_in = 1; return 0; case 0xa0: /* copyright message */ - add_data(dev, 0x28); - add_data(dev, 0x00); - break; + kbc_transmit(dev, ami_copr[0]); + dev->kbc_phase = 1; + return 0; case 0xa1: /* get controller version */ kbd_log("ATkbc: AMI - get controller version\n"); - add_data(dev, 'H'); + // kbc_transmit(dev, 'H'); + kbc_transmit(dev, '5'); return 0; case 0xa2: /* clear keyboard controller lines P22/P23 */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - clear KBC lines P22 and P23\n"); - write_output(dev, dev->output_port & 0xf3); - add_data(dev, 0x00); + write_output(dev, dev->p2 & 0xf3); + kbc_transmit(dev, 0x00); return 0; } break; case 0xa3: /* set keyboard controller lines P22/P23 */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - set KBC lines P22 and P23\n"); - write_output(dev, dev->output_port | 0x0c); - add_data(dev, 0x00); + write_output(dev, dev->p2 | 0x0c); + kbc_transmit(dev, 0x00); return 0; } break; case 0xa4: /* write clock = low */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - write clock = low\n"); dev->ami_stat &= 0xfe; return 0; @@ -1391,7 +2345,7 @@ write64_ami(void *priv, uint8_t val) break; case 0xa5: /* write clock = high */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - write clock = high\n"); dev->ami_stat |= 0x01; return 0; @@ -1399,15 +2353,15 @@ write64_ami(void *priv, uint8_t val) break; case 0xa6: /* read clock */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - read clock\n"); - add_data(dev, !!(dev->ami_stat & 1)); + kbc_transmit(dev, !!(dev->ami_stat & 1)); return 0; } break; case 0xa7: /* write cache bad */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - write cache bad\n"); dev->ami_stat &= 0xfd; return 0; @@ -1415,7 +2369,7 @@ write64_ami(void *priv, uint8_t val) break; case 0xa8: /* write cache good */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - write cache good\n"); dev->ami_stat |= 0x02; return 0; @@ -1423,68 +2377,237 @@ write64_ami(void *priv, uint8_t val) break; case 0xa9: /* read cache */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - read cache\n"); - add_data(dev, !!(dev->ami_stat & 2)); + kbc_transmit(dev, !!(dev->ami_stat & 2)); return 0; } break; case 0xaf: /* set extended controller RAM */ kbd_log("ATkbc: set extended controller RAM\n"); - dev->want60 = 1; - dev->secr_phase = 1; + dev->kbc_in = 1; return 0; - case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb0 ... 0xb3: /* set KBC lines P10-P13 (input port bits 0-3) low */ kbd_log("ATkbc: set KBC lines P10-P13 (input port bits 0-3) low\n"); - if (!PCI || (val > 0xb1)) - dev->input_port &= ~(1 << (val & 0x03)); - add_data(dev, 0x00); + if (!(dev->flags & KBC_FLAG_PS2) || (val > 0xb1)) { + dev->p1 &= ~(1 << (val & 0x03)); + } + kbc_transmit(dev, 0x00); return 0; case 0xb4: case 0xb5: /* set KBC lines P22-P23 (output port bits 2-3) low */ kbd_log("ATkbc: set KBC lines P22-P23 (output port bits 2-3) low\n"); - if (! PCI) - write_output(dev, dev->output_port & ~(4 << (val & 0x01))); - add_data(dev, 0x00); + if (!(dev->flags & KBC_FLAG_PS2)) + write_output(dev, dev->p2 & ~(4 << (val & 0x01))); + kbc_transmit(dev, 0x00); return 0; - case 0xb8: case 0xb9: case 0xba: case 0xbb: +#if 0 + case 0xb8 ... 0xbb: +#else + case 0xb9: +#endif /* set KBC lines P10-P13 (input port bits 0-3) high */ kbd_log("ATkbc: set KBC lines P10-P13 (input port bits 0-3) high\n"); - if (!PCI || (val > 0xb9)) { - dev->input_port |= (1 << (val & 0x03)); - add_data(dev, 0x00); + if (!(dev->flags & KBC_FLAG_PS2) || (val > 0xb9)) { + dev->p1 |= (1 << (val & 0x03)); + kbc_transmit(dev, 0x00); } return 0; + case 0xb8: + kbd_log("ATkbc: AMI MegaKey - memory index\n"); + dev->kbc_in = 1; + return 0; + + case 0xba: + kbd_log("ATkbc: AMI MegaKey - read %02X memory from index %02X\n", dev->mem[dev->mem_index], dev->mem_index); + if (dev->mem_index >= 0x80) { + switch (dev->mem[0x9b] & 0xc0) { + case 0x00: + index = 0x0080; + break; + case 0x40: case 0x80: + index = 0x0000; + break; + case 0xc0: + index = 0x0100; + break; + } + kbc_transmit(dev, dev->mem[index + dev->mem_index]); + } else if (dev->mem_index == 0x42) + kbc_transmit(dev, dev->status); + else if (dev->mem_index >= 0x40) + kbc_transmit(dev, dev->mem[dev->mem_index - 0x40]); + else + kbc_transmit(dev, dev->mem_int[dev->mem_index]); + return 0; + + case 0xbb: + kbd_log("ATkbc: AMI MegaKey - write to memory index %02X\n", dev->mem_index); + dev->kbc_in = 1; + return 0; + +#if 0 case 0xbc: case 0xbd: /* set KBC lines P22-P23 (output port bits 2-3) high */ kbd_log("ATkbc: set KBC lines P22-P23 (output port bits 2-3) high\n"); - if (! PCI) - write_output(dev, dev->output_port | (4 << (val & 0x01))); - add_data(dev, 0x00); + if (!(dev->flags & KBC_FLAG_PS2)) + write_output(dev, dev->p2 | (4 << (val & 0x01))); + kbc_transmit(dev, 0x00); + return 0; +#endif + + case 0xbc: + switch (dev->mem_index) { + case 0x00: /* STAT8042 */ + kbc_transmit(dev, dev->status); + break; + case 0x01: /* Password_ptr */ + kbc_transmit(dev, dev->mem[0x1c]); + break; + case 0x02: /* Wakeup_Tsk_Reg */ + kbc_transmit(dev, dev->mem[0x1e]); + break; + case 0x03: /* CCB */ + kbc_transmit(dev, dev->mem[0x20]); + break; + case 0x04: /* Debounce_time */ + kbc_transmit(dev, dev->mem[0x4d]); + break; + case 0x05: /* Pulse_Width */ + kbc_transmit(dev, dev->mem[0x4e]); + break; + case 0x06: /* Pk_sel_byte */ + kbc_transmit(dev, dev->mem[0x4c]); + break; + case 0x07: /* Func_Tsk_Reg */ + kbc_transmit(dev, dev->mem[0x7e]); + break; + case 0x08: /* TypematicRate */ + kbc_transmit(dev, dev->mem[0x80]); + break; + case 0x09: /* Led_Flag_Byte */ + kbc_transmit(dev, dev->mem[0x81]); + break; + case 0x0a: /* Kbms_Command_St */ + kbc_transmit(dev, dev->mem[0x87]); + break; + case 0x0b: /* Delay_Count_Byte */ + kbc_transmit(dev, dev->mem[0x86]); + break; + case 0x0c: /* KBC_Flags */ + kbc_transmit(dev, dev->mem[0x9b]); + break; + case 0x0d: /* SCODE_HK1 */ + kbc_transmit(dev, dev->mem[0x50]); + break; + case 0x0e: /* SCODE_HK2 */ + kbc_transmit(dev, dev->mem[0x51]); + break; + case 0x0f: /* SCODE_HK3 */ + kbc_transmit(dev, dev->mem[0x52]); + break; + case 0x10: /* SCODE_HK4 */ + kbc_transmit(dev, dev->mem[0x53]); + break; + case 0x11: /* SCODE_HK5 */ + kbc_transmit(dev, dev->mem[0x54]); + break; + case 0x12: /* SCODE_HK6 */ + kbc_transmit(dev, dev->mem[0x55]); + break; + case 0x13: /* TASK_HK1 */ + kbc_transmit(dev, dev->mem[0x56]); + break; + case 0x14: /* TASK_HK2 */ + kbc_transmit(dev, dev->mem[0x57]); + break; + case 0x15: /* TASK_HK3 */ + kbc_transmit(dev, dev->mem[0x58]); + break; + case 0x16: /* TASK_HK4 */ + kbc_transmit(dev, dev->mem[0x59]); + break; + case 0x17: /* TASK_HK5 */ + kbc_transmit(dev, dev->mem[0x5a]); + break; + /* The next 4 bytes have uncertain correspondences. */ + case 0x18: /* Batt_Poll_delay_Time */ + kbc_transmit(dev, dev->mem[0x5b]); + break; + case 0x19: /* Batt_Alarm_Reg1 */ + kbc_transmit(dev, dev->mem[0x5c]); + break; + case 0x1a: /* Batt_Alarm_Reg2 */ + kbc_transmit(dev, dev->mem[0x5d]); + break; + case 0x1b: /* Batt_Alarm_Tsk_Reg */ + kbc_transmit(dev, dev->mem[0x5e]); + break; + case 0x1c: /* Kbc_State1 */ + kbc_transmit(dev, dev->mem[0x9d]); + break; + case 0x1d: /* Aux_Config */ + kbc_transmit(dev, dev->mem[0x75]); + break; + case 0x1e: /* Kbc_State3 */ + kbc_transmit(dev, dev->mem[0x73]); + break; + default: + kbc_transmit(dev, 0x00); + break; + } + kbd_log("ATkbc: AMI MegaKey - read from config index %02X\n", dev->mem_index); return 0; - case 0xc8: + case 0xbd: + kbd_log("ATkbc: AMI MegaKey - write to config index %02X\n", dev->mem_index); + dev->kbc_in = 1; + return 0; + + case 0xc1: /* write input port */ + kbd_log("ATkbc: AMI MegaKey - write input port\n"); + dev->kbc_in = 1; + return 0; + + case 0xc4: + /* set KBC line P14 low */ + kbd_log("ATkbc: set KBC line P14 (input port bit 4) low\n"); + dev->p1 &= 0xef; + kbc_transmit(dev, 0x00); + return 0; + case 0xc5: + /* set KBC line P15 low */ + kbd_log("ATkbc: set KBC line P15 (input port bit 5) low\n"); + dev->p1 &= 0xdf; + kbc_transmit(dev, 0x00); + return 0; + + case 0xc8: case 0xc9: /* - * unblock KBC lines P22/P23 + * (un)block KBC lines P22/P23 * (allow command D1 to change bits 2/3 of the output port) */ - kbd_log("ATkbc: AMI - unblock KBC lines P22 and P23\n"); - dev->output_locked = 1; + kbd_log("ATkbc: AMI - %sblock KBC lines P22 and P23\n", (val & 1) ? "" : "un"); + dev->p2_locked = (val & 1); return 0; - case 0xc9: - /* - * block KBC lines P22/P23 - * (disallow command D1 from changing bits 2/3 of the port) - */ - kbd_log("ATkbc: AMI - block KBC lines P22 and P23\n"); - dev->output_locked = 1; + case 0xcc: + /* set KBC line P14 high */ + kbd_log("ATkbc: set KBC line P14 (input port bit 4) high\n"); + dev->p1 |= 0x10; + kbc_transmit(dev, 0x00); + return 0; + case 0xcd: + /* set KBC line P15 high */ + kbd_log("ATkbc: set KBC line P15 (input port bit 5) high\n"); + dev->p1 |= 0x20; + kbc_transmit(dev, 0x00); return 0; case 0xef: /* ??? - sent by AMI486 */ @@ -1505,23 +2628,20 @@ write64_ibm_mca(void *priv, uint8_t val) case 0xc1: /*Copy bits 0 to 3 of input port to status bits 4 to 7*/ kbd_log("ATkbc: copy bits 0 to 3 of input port to status bits 4 to 7\n"); dev->status &= 0x0f; - dev->status |= ((((dev->input_port & 0xfc) | 0x84) & 0x0f) << 4); + dev->status |= ((((dev->p1 & 0xfc) | 0x84) & 0x0f) << 4); return 0; case 0xc2: /*Copy bits 4 to 7 of input port to status bits 4 to 7*/ kbd_log("ATkbc: copy bits 4 to 7 of input port to status bits 4 to 7\n"); dev->status &= 0x0f; - dev->status |= (((dev->input_port & 0xfc) | 0x84) & 0xf0); + dev->status |= (((dev->p1 & 0xfc) | 0x84) & 0xf0); return 0; case 0xaf: kbd_log("ATkbc: bad KBC command AF\n"); return 1; - case 0xf0: case 0xf1: case 0xf2: case 0xf3: - case 0xf4: case 0xf5: case 0xf6: case 0xf7: - case 0xf8: case 0xf9: case 0xfa: case 0xfb: - case 0xfc: case 0xfd: case 0xfe: case 0xff: + case 0xf0 ... 0xff: kbd_log("ATkbc: pulse: %01X\n", (val & 0x03) | 0x0c); pulse_output(dev, (val & 0x03) | 0x0c); return 0; @@ -1536,7 +2656,7 @@ write60_quadtel(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; - switch(dev->command) { + switch(dev->kbc_cmd) { case 0xcf: /*??? - sent by MegaPC BIOS*/ kbd_log("ATkbc: ??? - sent by MegaPC BIOS\n"); return 0; @@ -1545,12 +2665,34 @@ write60_quadtel(void *priv, uint8_t val) return 1; } + static uint8_t write64_olivetti(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; switch (val) { + /* This appears to be a clone of "Read input port", in which case, the bis would be: + 7: M290 (AT KBC): + Keyboard lock (1 = unlocked, 0 = locked); + M300 (PS/2 KBC): + Bus expansion board present (1 = present, 0 = not present); + 6: Usually: + Display (1 = MDA, 0 = CGA, but can have its polarity inverted); + 5: Manufacturing jumper (1 = not installed, 0 = installed (infinite loop)); + 4: RAM on motherboard (1 = 256 kB, 0 = 512 kB - which machine actually uses this?); + 3: Fast Ram check (if inactive keyboard works erratically); + 2: Keyboard fuse present + This appears to be in-line with PS/2: 1 = no power, 0 = keyboard power normal; + 1: M290 (AT KBC): + Unused; + M300 (PS/2 KBC): + Mouse data in; + 0: M290 (AT KBC): + Unused; + M300 (PS/2 KBC): + Key data in. + */ case 0x80: /* Olivetti-specific command */ /* * bit 7: bus expansion board present (M300) / keyboard unlocked (M290) @@ -1559,11 +2701,9 @@ write64_olivetti(void *priv, uint8_t val) * bit 2: keyboard fuse present * bits 0-1: ??? */ - add_to_kbc_queue_front(dev, (0x0c | ((is386) ? 0x00 : 0x80)) & 0xdf, 0, 0x00); - dev->input_port = ((dev->input_port + 1) & 3) | - (dev->input_port & 0xfc); + kbc_transmit(dev, 0x0c | (is386 ? 0x00 : 0x80)); return 0; - } + } return write64_generic(dev, val); } @@ -1581,7 +2721,7 @@ write64_quadtel(void *priv, uint8_t val) case 0xcf: /*??? - sent by MegaPC BIOS*/ kbd_log("ATkbc: ??? - sent by MegaPC BIOS\n"); - dev->want60 = 1; + dev->kbc_in = 1; return 0; } @@ -1594,7 +2734,7 @@ write60_toshiba(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; - switch(dev->command) { + switch(dev->kbc_cmd) { case 0xb6: /* T3100e - set color/mono switch */ kbd_log("ATkbc: T3100e - set color/mono switch\n"); t3100e_mono_set(val); @@ -1637,29 +2777,30 @@ write64_toshiba(void *priv, uint8_t val) case 0xb4: /* T3100e: Get configuration / status */ kbd_log("ATkbc: T3100e: Get configuration / status\n"); - add_data(dev, t3100e_config_get()); + kbc_transmit(dev, t3100e_config_get()); return 0; case 0xb5: /* T3100e: Get colour / mono byte */ kbd_log("ATkbc: T3100e: Get colour / mono byte\n"); - add_data(dev, t3100e_mono_get()); + kbc_transmit(dev, t3100e_mono_get()); return 0; case 0xb6: /* T3100e: Set colour / mono byte */ kbd_log("ATkbc: T3100e: Set colour / mono byte\n"); - dev->want60 = 1; + dev->kbc_in = 1; return 0; case 0xb7: /* T3100e: Emulate PS/2 keyboard */ case 0xb8: /* T3100e: Emulate AT keyboard */ - dev->flags &= ~KBC_TYPE_MASK; + dev->flags &= ~KBC_FLAG_PS2; if (val == 0xb7) { kbd_log("ATkbc: T3100e: Emulate PS/2 keyboard\n"); - dev->flags |= KBC_TYPE_PS2_NOREF; - } else { - kbd_log("ATkbc: T3100e: Emulate AT keyboard\n"); - dev->flags |= KBC_TYPE_ISA; + dev->flags |= KBC_FLAG_PS2; } +#ifdef ENABLE_KEYBOARD_AT_LOG + else + kbd_log("ATkbc: T3100e: Emulate AT keyboard\n"); +#endif return 0; case 0xbb: /* T3100e: Read 'Fn' key. @@ -1669,8 +2810,9 @@ write64_toshiba(void *priv, uint8_t val) kbd_log("ATkbc: T3100e: Read 'Fn' key\n"); if (keyboard_recv(0xb8) || /* Right Alt */ keyboard_recv(0x9d)) /* Right Ctrl */ - add_data(dev, 0x04); - else add_data(dev, 0x00); + kbc_transmit(dev, 0x04); + else + kbc_transmit(dev, 0x00); return 0; case 0xbc: /* T3100e: Reset Fn+Key notification */ @@ -1683,8 +2825,8 @@ write64_toshiba(void *priv, uint8_t val) /* The T3100e returns all bits set except bit 6 which * is set by t3100e_mono_set() */ - dev->input_port = (t3100e_mono_get() & 1) ? 0xff : 0xbf; - add_data(dev, dev->input_port); + dev->p1 = (t3100e_mono_get() & 1) ? 0xff : 0xbf; + kbc_transmit(dev, dev->p1); return 0; } @@ -1697,423 +2839,46 @@ static void kbd_write(uint16_t port, uint8_t val, void *priv) { atkbd_t *dev = (atkbd_t *)priv; - int i = 0, bad = 1; - uint8_t mask, kbc_ven = 0x0; - kbc_ven = dev->flags & KBC_VEN_MASK; - if ((kbc_ven == KBC_VEN_XI8088) && (port == 0x63)) - port = 0x61; - - kbd_log((port == 0x61) ? "" : "ATkbc: write(%04X, %02X)\n", port, val); + kbd_log("[%04X:%08X] ATkbc: write(%04X, %02X)\n", CS, cpu_state.pc, port, val); switch (port) { case 0x60: - dev->status &= ~STAT_CD; - if (dev->want60) { - /* Write data to controller. */ - dev->want60 = 0; + dev->status = (dev->status & ~STAT_CD) | STAT_IFULL; + dev->ib = val; + // kbd_status("Write %02X: %02X, Status = %02X\n", port, val, dev->status); - switch (dev->command) { - case 0x60: case 0x61: case 0x62: case 0x63: - case 0x64: case 0x65: case 0x66: case 0x67: - case 0x68: case 0x69: case 0x6a: case 0x6b: - case 0x6c: case 0x6d: case 0x6e: case 0x6f: - case 0x70: case 0x71: case 0x72: case 0x73: - case 0x74: case 0x75: case 0x76: case 0x77: - case 0x78: case 0x79: case 0x7a: case 0x7b: - case 0x7c: case 0x7d: case 0x7e: case 0x7f: - dev->mem[dev->command & 0x1f] = val; - if (dev->command == 0x60) - write_cmd(dev, val); - break; - - case 0xd1: /* write output port */ - kbd_log("ATkbc: write output port\n"); - if (dev->output_locked) { - /*If keyboard controller lines P22-P23 are blocked, - we force them to remain unchanged.*/ - val &= ~0x0c; - val |= (dev->output_port & 0x0c); - } - write_output(dev, val); - break; - - case 0xd2: /* write to keyboard output buffer */ - kbd_log("ATkbc: write to keyboard output buffer\n"); - add_data_kbd_direct(dev, val); - break; - - case 0xd3: /* write to mouse output buffer */ - kbd_log("ATkbc: write to mouse output buffer\n"); - if (mouse_write && ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) - keyboard_at_adddata_mouse(val); - break; - - case 0xd4: /* write to mouse */ - kbd_log("ATkbc: write to mouse (%02X)\n", val); - - if (val == 0xbb) - break; - - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - set_enable_mouse(dev, 1); - if (mouse_write) - mouse_write(val, mouse_p); - else - add_to_kbc_queue_front(dev, 0xfe, 2, 0x40); - } - break; - - default: - /* - * Run the vendor-specific handler - * if we have one. Otherwise, or if - * it returns an error, log a bad - * controller command. - */ - if (dev->write60_ven) - bad = dev->write60_ven(dev, val); - - if (bad) { - kbd_log("ATkbc: bad controller command %02x data %02x\n", dev->command, val); - add_data_kbd(0xfe); - } - } - } else { - /* Write data to keyboard. */ - dev->mem[0] &= ~0x10; - - if (dev->key_wantdata) { - dev->key_wantdata = 0; - - /* - * Several system BIOSes and OS device drivers - * mess up with this, and repeat the command - * code many times. Fun! - */ - if (val == dev->key_command) { - /* Respond NAK and ignore it. */ - add_data_kbd(0xfe); - dev->key_command = 0x00; - break; - } - - switch (dev->key_command) { - case 0xed: /* set/reset LEDs */ - add_data_kbd_direct(dev, 0xfa); - kbd_log("ATkbd: set LEDs [%02x]\n", val); - break; - - case 0xf0: /* get/set scancode set */ - add_data_kbd_direct(dev, 0xfa); - if (val == 0) { - kbd_log("Get scan code set: %02X\n", keyboard_mode & 3); - add_data_kbd_direct(dev, keyboard_mode & 3); - } else { - if ((val <= 3) && (val != 1)) { - keyboard_mode &= 0xfc; - keyboard_mode |= (val & 3); - kbd_log("Scan code set now: %02X\n", val); - } - set_scancode_map(dev); - } - break; - - case 0xf3: /* set typematic rate/delay */ - add_data_kbd_direct(dev, 0xfa); - break; - - default: - kbd_log("ATkbd: bad keyboard 0060 write %02X command %02X\n", val, dev->key_command); - add_data_kbd_direct(dev, 0xfe); - break; - } - - /* Keyboard command is now done. */ - dev->key_command = 0x00; - } else { - /* No keyboard command in progress. */ - dev->key_command = 0x00; - - set_enable_kbd(dev, 1); - - switch (val) { - case 0x00: - kbd_log("ATkbd: command 00\n"); - add_data_kbd_direct(dev, 0xfa); - break; - - case 0x05: /*??? - sent by NT 4.0*/ - kbd_log("ATkbd: command 05 (NT 4.0)\n"); - add_data_kbd_direct(dev, 0xfe); - break; - - /* Sent by Pentium-era AMI BIOS'es.*/ - case 0x71: case 0x82: - kbd_log("ATkbd: Pentium-era AMI BIOS command %02X\n", val); - break; - - case 0xed: /* set/reset LEDs */ - kbd_log("ATkbd: set/reset leds\n"); - add_data_kbd_direct(dev, 0xfa); - - dev->key_wantdata = 1; - break; - - case 0xee: /* diagnostic echo */ - kbd_log("ATkbd: ECHO\n"); - add_data_kbd_direct(dev, 0xee); - break; - - case 0xef: /* NOP (reserved for future use) */ - kbd_log("ATkbd: NOP\n"); - break; - - case 0xf0: /* get/set scan code set */ - kbd_log("ATkbd: scan code set\n"); - add_data_kbd_direct(dev, 0xfa); - dev->key_wantdata = 1; - break; - - case 0xf2: /* read ID */ - /* Fixed as translation will be done in add_data_kbd(). */ - kbd_log("ATkbd: read keyboard id\n"); - /* TODO: After keyboard type selection is implemented, make this - return the correct keyboard ID for the selected type. */ - add_data_kbd_direct(dev, 0xfa); - add_data_kbd_direct(dev, 0xab); - add_data_kbd_direct(dev, 0x83); - break; - - case 0xf3: /* set typematic rate/delay */ - kbd_log("ATkbd: set typematic rate/delay\n"); - add_data_kbd_direct(dev, 0xfa); - dev->key_wantdata = 1; - break; - - case 0xf4: /* enable keyboard */ - kbd_log("ATkbd: enable keyboard\n"); - add_data_kbd_direct(dev, 0xfa); - keyboard_scan = 1; - break; - - case 0xf5: /* set defaults and disable keyboard */ - case 0xf6: /* set defaults */ - kbd_log("ATkbd: set defaults%s\n", (val == 0xf6) ? "" : " and disable keyboard"); - keyboard_scan = (val == 0xf6); - kbd_log("val = %02X, keyboard_scan = %i, dev->mem[0] = %02X\n", - val, keyboard_scan, dev->mem[0]); - add_data_kbd_direct(dev, 0xfa); - - keyboard_set3_all_break = 0; - keyboard_set3_all_repeat = 0; - memset(keyboard_set3_flags, 0, 512); - keyboard_mode = (keyboard_mode & 0xfc) | 0x02; - set_scancode_map(dev); - break; - - case 0xf7: /* set all keys to repeat */ - kbd_log("ATkbd: set all keys to repeat\n"); - add_data_kbd_direct(dev, 0xfa); - keyboard_set3_all_break = 1; - break; - - case 0xf8: /* set all keys to give make/break codes */ - kbd_log("ATkbd: set all keys to give make/break codes\n"); - add_data_kbd_direct(dev, 0xfa); - keyboard_set3_all_break = 1; - break; - - case 0xf9: /* set all keys to give make codes only */ - kbd_log("ATkbd: set all keys to give make codes only\n"); - add_data_kbd_direct(dev, 0xfa); - keyboard_set3_all_break = 0; - break; - - case 0xfa: /* set all keys to repeat and give make/break codes */ - kbd_log("ATkbd: set all keys to repeat and give make/break codes\n"); - add_data_kbd_direct(dev, 0xfa); - keyboard_set3_all_repeat = 1; - keyboard_set3_all_break = 1; - break; - - case 0xfe: /* resend last scan code */ - kbd_log("ATkbd: reset last scan code\n"); - add_data_kbd_raw(dev, kbd_last_scan_code); - break; - - case 0xff: /* reset */ - kbd_log("ATkbd: kbd reset\n"); - kbc_queue_reset(1); - kbd_last_scan_code = 0x00; - add_data_kbd_direct(dev, 0xfa); - - /* Set scan code set to 2. */ - keyboard_mode = (keyboard_mode & 0xfc) | 0x02; - set_scancode_map(dev); - - dev->reset_delay = RESET_DELAY_TIME; - break; - - default: - kbd_log("ATkbd: bad keyboard command %02X\n", val); - add_data_kbd_direct(dev, 0xfe); - } - - /* If command needs data, remember command. */ - if (dev->key_wantdata == 1) - dev->key_command = val; - } +#if 0 + if ((dev->fast_a20_phase == 1)/* && ((val == 0xdd) || (val == 0xdf))*/) { + dev->status &= ~STAT_IFULL; + write_output(dev, val); + dev->fast_a20_phase = 0; } +#endif break; - - case 0x61: - ppi.pb = (ppi.pb & 0x10) | (val & 0x0f); - - speaker_update(); - speaker_gated = val & 1; - speaker_enable = val & 2; - if (speaker_enable) - was_speaker_enable = 1; - pit_ctr_set_gate(&pit->counters[2], val & 1); - - if (kbc_ven == KBC_VEN_XI8088) - xi8088_turbo_set(!!(val & 0x04)); - break; - case 0x64: - /* Controller command. */ - dev->want60 = 0; - dev->status |= STAT_CD; + dev->status |= (STAT_CD | STAT_IFULL); + dev->ib = val; + // kbd_status("Write %02X: %02X, Status = %02X\n", port, val, dev->status); - switch (val) { - /* Read data from KBC memory. */ - case 0x20: case 0x21: case 0x22: case 0x23: - case 0x24: case 0x25: case 0x26: case 0x27: - case 0x28: case 0x29: case 0x2a: case 0x2b: - case 0x2c: case 0x2d: case 0x2e: case 0x2f: - case 0x30: case 0x31: case 0x32: case 0x33: - case 0x34: case 0x35: case 0x36: case 0x37: - case 0x38: case 0x39: case 0x3a: case 0x3b: - case 0x3c: case 0x3d: case 0x3e: case 0x3f: - add_data(dev, dev->mem[val & 0x1f]); - break; - - /* Write data to KBC memory. */ - case 0x60: case 0x61: case 0x62: case 0x63: - case 0x64: case 0x65: case 0x66: case 0x67: - case 0x68: case 0x69: case 0x6a: case 0x6b: - case 0x6c: case 0x6d: case 0x6e: case 0x6f: - case 0x70: case 0x71: case 0x72: case 0x73: - case 0x74: case 0x75: case 0x76: case 0x77: - case 0x78: case 0x79: case 0x7a: case 0x7b: - case 0x7c: case 0x7d: case 0x7e: case 0x7f: - dev->want60 = 1; - break; - - case 0xaa: /* self-test */ - kbd_log("ATkbc: self-test\n"); - if ((kbc_ven == KBC_VEN_TOSHIBA) || (kbc_ven == KBC_VEN_SAMSUNG)) - dev->status |= STAT_IFULL; - write_output(dev, ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x4b : 0xcf); - - /* Always reinitialize all queues - the real hardware pulls keyboard and mouse - clocks high, which stops keyboard scanning. */ - kbd_log("ATkbc: self-test reinitialization\n"); - dev->out_new = dev->out_delayed = -1; - for (i = 0; i < 3; i++) - kbc_queue_reset(i); - kbd_last_scan_code = 0x00; - dev->status &= ~STAT_OFULL; - dev->last_irq = dev->old_last_irq = 0; - - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) - write_cmd(dev, 0x30 | STAT_SYSFLAG); - else - write_cmd(dev, 0x10 | STAT_SYSFLAG); - add_data(dev, 0x55); - break; - - case 0xab: /* interface test */ - kbd_log("ATkbc: interface test\n"); - add_data(dev, 0x00); /*no error*/ - break; - - case 0xac: /* diagnostic dump */ - kbd_log("ATkbc: diagnostic dump\n"); - for (i = 0; i < 16; i++) - add_data(dev, dev->mem[i]); - add_data(dev, (dev->input_port & 0xf0) | 0x80); - add_data(dev, dev->output_port); - add_data(dev, dev->status); - break; - - case 0xad: /* disable keyboard */ - kbd_log("ATkbc: disable keyboard\n"); - set_enable_kbd(dev, 0); - break; - - case 0xae: /* enable keyboard */ - kbd_log("ATkbc: enable keyboard\n"); - set_enable_kbd(dev, 1); - break; - - case 0xca: /* read keyboard mode */ - kbd_log("ATkbc: AMI - read keyboard mode\n"); - add_data(dev, ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x01 : 0x00); /*ISA mode*/ - break; - - case 0xcb: /* set keyboard mode */ - kbd_log("ATkbc: AMI - set keyboard mode\n"); - dev->want60 = 1; - break; - - case 0xd0: /* read output port */ - kbd_log("ATkbc: read output port\n"); - mask = 0xff; - if (((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) && (dev->mem[0] & 0x10)) - mask &= 0xbf; - add_to_kbc_queue_front(dev, dev->output_port & mask, 0, 0x00); - break; - - case 0xd1: /* write output port */ - kbd_log("ATkbc: write output port\n"); - dev->want60 = 1; - break; - - case 0xd2: /* write keyboard output buffer */ - kbd_log("ATkbc: write keyboard output buffer\n"); - dev->want60 = 1; - break; - - case 0xdd: /* disable A20 address line */ - case 0xdf: /* enable A20 address line */ - kbd_log("ATkbc: %sable A20\n", (val == 0xdd) ? "dis": "en"); - write_output(dev, (dev->output_port & 0xfd) | (val & 0x02)); - break; - - case 0xe0: /* read test inputs */ - kbd_log("ATkbc: read test inputs\n"); - add_data(dev, 0x00); - break; - - default: - /* - * Unrecognized controller command. - * - * If we have a vendor-specific handler, run - * that. Otherwise, or if that handler fails, - * log a bad command. - */ - if (dev->write64_ven) - bad = dev->write64_ven(dev, val); - - kbd_log(bad ? "ATkbc: bad controller command %02X\n" : "", val); +#if 0 + if (val == 0xd1) { + dev->status &= ~STAT_IFULL; + dev->fast_a20_phase = 1; + } else if (val == 0xfe) { + dev->status &= ~STAT_IFULL; + pulse_output(dev, 0x0e); + } else if ((val == 0xad) || (val == 0xae)) { + dev->status &= ~STAT_IFULL; + if (val & 0x01) + dev->mem[0x20] |= 0x10; + else + dev->mem[0x20] &= ~0x10; + } else if (val == 0xa1) { + dev->status &= ~STAT_IFULL; + kbc_send_to_ob(dev, 'H', 0, 0x00); } - - /* If the command needs data, remember the command. */ - if (dev->want60) - dev->command = val; +#endif break; } } @@ -2124,83 +2889,20 @@ kbd_read(uint16_t port, void *priv) { atkbd_t *dev = (atkbd_t *)priv; uint8_t ret = 0xff; - uint8_t kbc_ven = 0x0; - kbc_ven = dev->flags & KBC_VEN_MASK; - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) - cycles -= ISA_CYCLES(8); - - if ((kbc_ven == KBC_VEN_XI8088) && (port == 0x63)) - port = 0x61; + // if (dev->flags & KBC_FLAG_PS2) + // cycles -= ISA_CYCLES(8); switch (port) { case 0x60: - ret = dev->out; + ret = dev->ob; dev->status &= ~STAT_OFULL; picintc(dev->last_irq); dev->last_irq = 0; break; - case 0x61: - ret = ppi.pb & ~0xe0; - if (ppispeakon) - ret |= 0x20; - if ((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) { - if (dev->refresh) - ret |= 0x10; - else - ret &= ~0x10; - } - if (kbc_ven == KBC_VEN_XI8088) { - if (xi8088_turbo_get()) - ret |= 0x04; - else - ret &= ~0x04; - } - break; - - case 0x62: - ret = 0xff; - if (kbc_ven == KBC_VEN_OLIVETTI) { - /* SWA on Olivetti M240 mainboard (off=1) */ - ret = 0x00; - if (ppi.pb & 0x8) { - /* Switches 4, 5 - floppy drives (number) */ - int i, fdd_count = 0; - for (i = 0; i < FDD_NUM; i++) { - if (fdd_get_flags(i)) - fdd_count++; - } - if (!fdd_count) - ret |= 0x00; - else - ret |= ((fdd_count - 1) << 2); - /* Switches 6, 7 - monitor type */ - if (video_is_mda()) - ret |= 0x3; - else if (video_is_cga()) - ret |= 0x2; /* 0x10 would be 40x25 */ - else - ret |= 0x0; - } else { - /* bit 2 always on */ - ret |= 0x4; - /* Switch 8 - 8087 FPU. */ - if (hasfpu) - ret |= 0x02; - } - } - break; case 0x64: - ret = (dev->status & 0xfb); - if (dev->mem[0] & STAT_SYSFLAG) - ret |= STAT_SYSFLAG; - /* Only clear the transmit timeout flag on non-PS/2 controllers, as on - PS/2 controller, it is the keyboard/mouse output source bit. */ - // dev->status &= ~STAT_RTIMEOUT; - if (((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) && - (kbc_ven != KBC_VEN_IBM_MCA)) - dev->status &= ~STAT_TTIMEOUT; + ret = dev->status; break; default: @@ -2208,22 +2910,12 @@ kbd_read(uint16_t port, void *priv) break; } - kbd_log((port == 0x61) ? "" : "ATkbc: read(%04X) = %02X\n", port, ret); + kbd_log("[%04X:%08X] ATkbc: read(%04X) = %02X\n",CS, cpu_state.pc, port, ret); return(ret); } -static void -kbd_refresh(void *priv) -{ - atkbd_t *dev = (atkbd_t *)priv; - - dev->refresh = !dev->refresh; - timer_advance_u64(&dev->refresh_time, PS2_REFRESH_TIME); -} - - static void kbd_reset(void *priv) { @@ -2232,25 +2924,26 @@ kbd_reset(void *priv) uint8_t kbc_ven = 0x0; kbc_ven = dev->flags & KBC_VEN_MASK; - dev->first_write = 1; - // dev->status = STAT_UNLOCKED | STAT_CD; dev->status = STAT_UNLOCKED; - dev->mem[0] = 0x01; - dev->mem[0] |= CCB_TRANSLATE; - dev->wantirq = 0; + dev->mem[0x20] = 0x01; + dev->mem[0x20] |= CCB_TRANSLATE; write_output(dev, 0xcf); - dev->last_irq = dev->old_last_irq = 0; + dev->last_irq = 0; dev->secr_phase = 0; - dev->key_wantdata = 0; + dev->kbd_in = 0; + dev->ami_mode = !!(dev->flags & KBC_FLAG_PS2); /* Set up the correct Video Type bits. */ + dev->p1 = video_is_mda() ? 0xf0 : 0xb0; if ((kbc_ven == KBC_VEN_XI8088) || (kbc_ven == KBC_VEN_ACER)) - dev->input_port = video_is_mda() ? 0xb0 : 0xf0; + dev->p1 ^= 0x40; + if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) + dev->inhibit = ((dev->p1 & 0x80) >> 3); else - dev->input_port = video_is_mda() ? 0xf0 : 0xb0; - kbd_log("ATkbc: input port = %02x\n", dev->input_port); + dev->inhibit = 0x10; + kbd_log("ATkbc: input port = %02x\n", dev->p1); - keyboard_mode = 0x02 | (dev->mem[0] & CCB_TRANSLATE); + keyboard_mode = 0x02 | (dev->mem[0x20] & CCB_TRANSLATE); /* Enable keyboard, disable mouse. */ set_enable_kbd(dev, 1); @@ -2258,16 +2951,18 @@ kbd_reset(void *priv) set_enable_mouse(dev, 0); mouse_scan = 0; - dev->out_new = dev->out_delayed = -1; - for (i = 0; i < 3; i++) - kbc_queue_reset(i); - kbd_last_scan_code = 0; + dev->ob = 0xff; sc_or = 0; + for (i = 1; i <= 2; i++) + kbc_queue_reset(i); + memset(keyboard_set3_flags, 0, 512); set_scancode_map(dev); + + dev->mem[0x31] = 0xfe; } @@ -2289,7 +2984,6 @@ kbd_close(void *priv) /* Stop timers. */ timer_disable(&dev->send_delay_timer); - timer_disable(&dev->refresh_time); keyboard_scan = 0; keyboard_send = NULL; @@ -2313,17 +3007,14 @@ kbd_init(const device_t *info) dev->flags = info->local; video_reset(gfxcard); - kbd_reset(dev); + dev->kbc_poll_phase = KBC_RESET; + kbd_send_to_host(dev, 0xaa); - io_sethandler(0x0060, 5, - kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); + io_sethandler(0x0060, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); + io_sethandler(0x0064, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); keyboard_send = add_data_kbd; timer_add(&dev->send_delay_timer, kbd_poll, dev, 1); - - if ((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) - timer_add(&dev->refresh_time, kbd_refresh, dev, 1); - timer_add(&dev->pulse_cb, pulse_poll, dev, 0); dev->write60_ven = NULL; @@ -2339,12 +3030,14 @@ kbd_init(const device_t *info) break; case KBC_VEN_OLIVETTI: + /* The Olivetti controller is a special case - starts directly in the + main loop instead of the reset loop. */ + dev->kbc_poll_phase = KBC_MAIN_LOOP; dev->write64_ven = write64_olivetti; break; case KBC_VEN_AMI: case KBC_VEN_INTEL_AMI: - case KBC_VEN_SAMSUNG: dev->write60_ven = write60_ami; dev->write64_ven = write64_ami; break; @@ -2364,6 +3057,8 @@ kbd_init(const device_t *info) break; } + kbd_reset(dev); + /* We need this, sadly. */ SavedKbd = dev; @@ -2391,16 +3086,6 @@ const device_t keyboard_at_ami_device = { { NULL }, NULL, NULL, NULL }; -const device_t keyboard_at_samsung_device = { - "PC/AT Keyboard (Samsung)", - 0, - KBC_TYPE_ISA | KBC_VEN_SAMSUNG, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - const device_t keyboard_at_toshiba_device = { "PC/AT Keyboard (Toshiba)", 0, @@ -2432,16 +3117,6 @@ const device_t keyboard_at_ncr_device = { }; const device_t keyboard_ps2_device = { - "PS/2 Keyboard", - 0, - KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_ps2_device = { "PS/2 Keyboard", 0, KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, @@ -2454,7 +3129,7 @@ const device_t keyboard_ps2_ps2_device = { const device_t keyboard_ps2_ps1_device = { "PS/2 Keyboard (IBM PS/1)", 0, - KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1, + KBC_TYPE_PS2_1 | KBC_VEN_IBM_PS1, kbd_init, kbd_close, kbd_reset, @@ -2464,7 +3139,7 @@ const device_t keyboard_ps2_ps1_device = { const device_t keyboard_ps2_ps1_pci_device = { "PS/2 Keyboard (IBM PS/1)", DEVICE_PCI, - KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1, + KBC_TYPE_PS2_1 | KBC_VEN_IBM_PS1, kbd_init, kbd_close, kbd_reset, @@ -2484,7 +3159,7 @@ const device_t keyboard_ps2_xi8088_device = { const device_t keyboard_ps2_ami_device = { "PS/2 Keyboard (AMI)", 0, - KBC_TYPE_PS2_NOREF | KBC_VEN_AMI, + KBC_TYPE_PS2_1 | KBC_VEN_AMI, kbd_init, kbd_close, kbd_reset, @@ -2494,7 +3169,7 @@ const device_t keyboard_ps2_ami_device = { const device_t keyboard_ps2_olivetti_device = { "PS/2 Keyboard (Olivetti)", 0, - KBC_TYPE_PS2_NOREF | KBC_VEN_OLIVETTI, + KBC_TYPE_PS2_1 | KBC_VEN_OLIVETTI, kbd_init, kbd_close, kbd_reset, @@ -2524,7 +3199,7 @@ const device_t keyboard_ps2_mca_2_device = { const device_t keyboard_ps2_quadtel_device = { "PS/2 Keyboard (Quadtel/MegaPC)", 0, - KBC_TYPE_PS2_NOREF | KBC_VEN_QUADTEL, + KBC_TYPE_PS2_1 | KBC_VEN_QUADTEL, kbd_init, kbd_close, kbd_reset, @@ -2534,7 +3209,7 @@ const device_t keyboard_ps2_quadtel_device = { const device_t keyboard_ps2_pci_device = { "PS/2 Keyboard", DEVICE_PCI, - KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC, + KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, kbd_init, kbd_close, kbd_reset, @@ -2544,7 +3219,7 @@ const device_t keyboard_ps2_pci_device = { const device_t keyboard_ps2_ami_pci_device = { "PS/2 Keyboard (AMI)", DEVICE_PCI, - KBC_TYPE_PS2_NOREF | KBC_VEN_AMI, + KBC_TYPE_PS2_1 | KBC_VEN_AMI, kbd_init, kbd_close, kbd_reset, @@ -2554,7 +3229,7 @@ const device_t keyboard_ps2_ami_pci_device = { const device_t keyboard_ps2_intel_ami_pci_device = { "PS/2 Keyboard (AMI)", DEVICE_PCI, - KBC_TYPE_PS2_NOREF | KBC_VEN_INTEL_AMI, + KBC_TYPE_PS2_1 | KBC_VEN_INTEL_AMI, kbd_init, kbd_close, kbd_reset, @@ -2564,7 +3239,7 @@ const device_t keyboard_ps2_intel_ami_pci_device = { const device_t keyboard_ps2_acer_pci_device = { "PS/2 Keyboard (Acer 90M002A)", DEVICE_PCI, - KBC_TYPE_PS2_NOREF | KBC_VEN_ACER, + KBC_TYPE_PS2_1 | KBC_VEN_ACER, kbd_init, kbd_close, kbd_reset, @@ -2575,17 +3250,8 @@ const device_t keyboard_ps2_acer_pci_device = { void keyboard_at_set_mouse(void (*func)(uint8_t val, void *priv), void *priv) { - mouse_write = func; - mouse_p = priv; -} - - -void -keyboard_at_adddata_keyboard_raw(uint8_t val) -{ - atkbd_t *dev = SavedKbd; - - add_data_kbd_queue(dev, 0, val); + // mouse_write = func; + // mouse_p = priv; } @@ -2598,10 +3264,30 @@ keyboard_at_adddata_mouse(uint8_t val) } +void +keyboard_at_adddata_mouse_direct(uint8_t val) +{ + // atkbd_t *dev = SavedKbd; + + return; +} + + +void +keyboard_at_adddata_mouse_cmd(uint8_t val) +{ + // atkbd_t *dev = SavedKbd; + + return; +} + + void keyboard_at_mouse_reset(void) { - kbc_queue_reset(2); + // atkbd_t *dev = SavedKbd; + + return; } @@ -2612,13 +3298,22 @@ keyboard_at_mouse_pos(void) } +int +keyboard_at_fixed_channel(void) +{ + // atkbd_t *dev = SavedKbd; + + return 0x000; +} + + void keyboard_at_set_mouse_scan(uint8_t val) { atkbd_t *dev = SavedKbd; uint8_t temp_mouse_scan = val ? 1 : 0; - if (temp_mouse_scan == !(dev->mem[0] & 0x20)) + if (temp_mouse_scan == !(dev->mem[0x20] & 0x20)) return; set_enable_mouse(dev, val ? 1 : 0); @@ -2632,7 +3327,7 @@ keyboard_at_get_mouse_scan(void) { atkbd_t *dev = SavedKbd; - return((dev->mem[0] & 0x20) ? 0x00 : 0x10); + return((dev->mem[0x20] & 0x20) ? 0x00 : 0x10); } @@ -2641,5 +3336,17 @@ keyboard_at_set_a20_key(int state) { atkbd_t *dev = SavedKbd; - write_output(dev, (dev->output_port & 0xfd) | ((!!state) << 1)); + write_output(dev, (dev->p2 & 0xfd) | ((!!state) << 1)); +} + + +void +keyboard_at_set_mode(int ps2) +{ + atkbd_t *dev = SavedKbd; + + if (ps2) + dev->flags |= KBC_FLAG_PS2; + else + dev->flags &= ~KBC_FLAG_PS2; } From d38a90bbcc4b24f69b1d34701421729afb2bb3d4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 2 Aug 2021 06:59:46 +0200 Subject: [PATCH 24/96] And Makefile.mingw. --- src/win/Makefile.mingw | 1 + 1 file changed, 1 insertion(+) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 4390235a9..42b3fbbbc 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -631,6 +631,7 @@ MCHOBJ := machine.o machine_table.o \ m_at_socket8.o m_at_slot1.o m_at_slot2.o m_at_socket370.o \ m_at_misc.o +ifeq ($(NEW_KBC), y) DEVOBJ := bugger.o cartridge.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o \ ibm_5161.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o \ clock_ics9xxx.o isapnp.o \ From a1e6872a440dbfbbc0d30d9f0631adc4208aa265 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 2 Aug 2021 22:07:23 +0200 Subject: [PATCH 25/96] The Contaq now uses the correct functions for ISA clock dividers. --- src/chipset/contaq_82c59x.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/chipset/contaq_82c59x.c b/src/chipset/contaq_82c59x.c index 19a3d5b44..33f972780 100644 --- a/src/chipset/contaq_82c59x.c +++ b/src/chipset/contaq_82c59x.c @@ -75,16 +75,16 @@ contaq_82c59x_isa_speed_recalc(contaq_82c59x_t *dev) /* TODO: ISA clock dividers for 386 and alt. 486. */ switch (dev->regs[0x10] & 0x03) { case 0x00: - cpu_set_isa_pci_div(4); + cpu_set_isa_speed(cpu_busspeed / 4); break; case 0x01: - cpu_set_isa_pci_div(6); + cpu_set_isa_speed(cpu_busspeed / 6); break; case 0x02: - cpu_set_isa_pci_div(8); + cpu_set_isa_speed(cpu_busspeed / 8); break; case 0x04: - cpu_set_isa_pci_div(5); + cpu_set_isa_speed(cpu_busspeed / 5); break; } } From bee63961d29dc7d06b6221c769a0e9483ddb94b9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 2 Aug 2021 22:10:20 +0200 Subject: [PATCH 26/96] Some Contaq clean-ups. --- src/chipset/contaq_82c59x.c | 120 +++--------------------------------- 1 file changed, 8 insertions(+), 112 deletions(-) diff --git a/src/chipset/contaq_82c59x.c b/src/chipset/contaq_82c59x.c index 33f972780..eb9ed9cdd 100644 --- a/src/chipset/contaq_82c59x.c +++ b/src/chipset/contaq_82c59x.c @@ -205,11 +205,7 @@ contaq_82c59x_write(uint16_t addr, uint8_t val, void *priv) cpu_update_waitstates(); break; - case 0x12: - dev->regs[dev->index] = val; - break; - - case 0x13: + case 0x12: case 0x13: dev->regs[dev->index] = val; break; @@ -223,27 +219,7 @@ contaq_82c59x_write(uint16_t addr, uint8_t val, void *priv) contaq_82c59x_shadow_recalc(dev); break; - case 0x16: - dev->regs[dev->index] = val; - break; - - case 0x17: - dev->regs[dev->index] = val; - break; - - case 0x18: - dev->regs[dev->index] = val; - break; - - case 0x19: - dev->regs[dev->index] = val; - break; - - case 0x1a: - dev->regs[dev->index] = val; - break; - - case 0x1b: + case 0x16 ... 0x1b: dev->regs[dev->index] = val; break; @@ -253,32 +229,12 @@ contaq_82c59x_write(uint16_t addr, uint8_t val, void *priv) contaq_82c59x_isa_speed_recalc(dev); break; - case 0x1d: - dev->regs[dev->index] = val; - break; - - case 0x1e: - dev->regs[dev->index] = val; - break; - - case 0x1f: + case 0x1d ... 0x1f: dev->regs[dev->index] = val; break; /* Green (82C597-specific) registers. */ - case 0x60: - dev->regs[dev->index] = val; - break; - - case 0x61: - dev->regs[dev->index] = val; - break; - - case 0x62: - dev->regs[dev->index] = val; - break; - - case 0x63: + case 0x60 ... 0x63: dev->regs[dev->index] = val; break; @@ -291,23 +247,7 @@ contaq_82c59x_write(uint16_t addr, uint8_t val, void *priv) } break; - case 0x65: - dev->regs[dev->index] = val; - break; - - case 0x66: - dev->regs[dev->index] = val; - break; - - case 0x67: - dev->regs[dev->index] = val; - break; - - case 0x68: - dev->regs[dev->index] = val; - break; - - case 0x69: + case 0x65 ... 0x69: dev->regs[dev->index] = val; break; @@ -316,15 +256,7 @@ contaq_82c59x_write(uint16_t addr, uint8_t val, void *priv) dev->smi_status_set = !!(val & 0x80); break; - case 0x6b: - dev->regs[dev->index] = val; - break; - - case 0x6c: - dev->regs[dev->index] = val; - break; - - case 0x6d: + case 0x6b ... 0x6d: dev->regs[dev->index] = val; break; @@ -338,47 +270,11 @@ contaq_82c59x_write(uint16_t addr, uint8_t val, void *priv) contaq_82c59x_smram_recalc(dev); break; - case 0x71: + case 0x71 ... 0x79: dev->regs[dev->index] = val; break; - case 0x72: - dev->regs[dev->index] = val; - break; - - case 0x73: - dev->regs[dev->index] = val; - break; - - case 0x74: - dev->regs[dev->index] = val; - break; - - case 0x75: - dev->regs[dev->index] = val; - break; - - case 0x76: - dev->regs[dev->index] = val; - break; - - case 0x77: - dev->regs[dev->index] = val; - break; - - case 0x78: - dev->regs[dev->index] = val; - break; - - case 0x79: - dev->regs[dev->index] = val; - break; - - case 0x7b: - dev->regs[dev->index] = val; - break; - - case 0x7c: + case 0x7b: case 0x7c: dev->regs[dev->index] = val; break; } From f8046a8745c9fcfbb3adac2b944c9989687a950c Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 2 Aug 2021 22:12:14 +0200 Subject: [PATCH 27/96] And another Contaq fix. --- src/chipset/contaq_82c59x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chipset/contaq_82c59x.c b/src/chipset/contaq_82c59x.c index eb9ed9cdd..93c841b9b 100644 --- a/src/chipset/contaq_82c59x.c +++ b/src/chipset/contaq_82c59x.c @@ -83,7 +83,7 @@ contaq_82c59x_isa_speed_recalc(contaq_82c59x_t *dev) case 0x02: cpu_set_isa_speed(cpu_busspeed / 8); break; - case 0x04: + case 0x03: cpu_set_isa_speed(cpu_busspeed / 5); break; } From e2a227552ed06d949b635bb4f70e230f7b2b5e3b Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 4 Aug 2021 09:03:27 +0200 Subject: [PATCH 28/96] Change #1 for attempted conflict resolution. --- src/machine/m_at_sockets7.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/machine/m_at_sockets7.c b/src/machine/m_at_sockets7.c index 47ee28a29..2ab21d856 100644 --- a/src/machine/m_at_sockets7.c +++ b/src/machine/m_at_sockets7.c @@ -40,6 +40,7 @@ #include <86box/video.h> #include "cpu.h" #include <86box/machine.h> +#include <86box/snd_ac97.h> #include <86box/clock.h> From 43bfecaa6e04da7502913cc97c851ce2acba045b Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 4 Aug 2021 09:05:20 +0200 Subject: [PATCH 29/96] And another. --- src/machine/m_at_sockets7.c | 139 ------------------------------------ 1 file changed, 139 deletions(-) diff --git a/src/machine/m_at_sockets7.c b/src/machine/m_at_sockets7.c index 2ab21d856..be27801cb 100644 --- a/src/machine/m_at_sockets7.c +++ b/src/machine/m_at_sockets7.c @@ -41,145 +41,6 @@ #include "cpu.h" #include <86box/machine.h> #include <86box/snd_ac97.h> -#include <86box/clock.h> - - -int -machine_at_p5a_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/p5a/1011.005", - 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(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - 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(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 4, 1, 2); - device_add(&ali1541_device); - device_add(&ali1543c_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&sst_flash_39sf020_device); - spd_register(SPD_TYPE_SDRAM, 0xF, 256); - device_add(&w83781d_p5a_device); /* fans: Chassis, CPU, Power; temperatures: MB, unused, CPU */ - - return ret; -} - - -int -machine_at_m579_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/m579/MS6260S_Socket7_ALi_M1542_AMI.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_AGPBRIDGE, 1, 2, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x10, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); - device_add(&ali1541_device); - device_add(&ali1543c_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&sst_flash_29ee010_device); - spd_register(SPD_TYPE_SDRAM, 0x3, 128); - - return ret; -} - - -int -machine_at_ga_5aa_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/ga-5aa/GA-5AA.F7b", - 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_AGPBRIDGE, 1, 2, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - 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); - device_add(&ali1541_device); - device_add(&ali1543c_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&sst_flash_29ee010_device); - spd_register(SPD_TYPE_SDRAM, 0x3, 128); - - return ret; -} - - -int -machine_at_ga_5ax_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/ga-5ax/5AX.F4", - 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_AGPBRIDGE, 1, 2, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - 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(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - device_add(&ali1541_device); - device_add(&ali1543c_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&sst_flash_29ee010_device); - spd_register(SPD_TYPE_SDRAM, 0x3, 128); - - return ret; -} int From 66da8a9905fd31da877fe17e52e680d7e7656e81 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 4 Aug 2021 09:14:47 +0200 Subject: [PATCH 30/96] And another. --- src/machine/machine_table.c | 519 +++++------------------------------- 1 file changed, 61 insertions(+), 458 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 124a1236b..f8a4f3bb7 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -39,12 +39,10 @@ const machine_type_t machine_types[] = { { "8086", MACHINE_TYPE_8086 }, { "80286", MACHINE_TYPE_286 }, { "i386SX", MACHINE_TYPE_386SX }, - { "486SLC", MACHINE_TYPE_486SLC }, { "i386DX", MACHINE_TYPE_386DX }, { "i386DX/i486", MACHINE_TYPE_386DX_486 }, { "i486 (Socket 168 and 1)", MACHINE_TYPE_486 }, - { "i486 (Socket 2)", MACHINE_TYPE_486_S2 }, - { "i486 (Socket 3)", MACHINE_TYPE_486_S3 }, + { "i486 (Socket 2 and 3)", MACHINE_TYPE_486_S3 }, { "i486 (Miscellaneous)", MACHINE_TYPE_486_MISC }, { "Socket 4", MACHINE_TYPE_SOCKET4 }, { "Socket 5", MACHINE_TYPE_SOCKET5 }, @@ -60,49 +58,6 @@ const machine_type_t machine_types[] = { }; -/* Machines to add before machine freeze: - - Jetway J-403TG MR BIOS v2.02; - - Matsonic MS6260S (AMI Super Socket 7 with Aladdin V chipset); - - PCChips M773 (440BX + SMSC with AMI BIOS); - - Rise R418 (was removed on my end, has to be re-added); - - TMC Mycomp PCI54ST; - - Zeos Quadtel 486. - - NOTE: The AMI MegaKey tests were done on a real Intel Advanced/ATX - (thanks, MrKsoft for running my AMIKEY.COM on it), but the - technical specifications of the other Intel machines confirm - that the other boards also have the MegaKey. - - NOTE: The later (ie. not AMI Color) Intel AMI BIOS'es execute a - sequence of commands (B8, BA, BB) during one of the very first - phases of POST, in a way that is only valid on the AMIKey-3 - KBC firmware, that includes the Classic PCI/ED (Ninja) BIOS - which otherwise does not execute any AMI KBC commands, which - indicates that the sequence is a leftover of whatever AMI - BIOS (likely a laptop one since the AMIKey-3 is a laptop KBC - firmware!) Intel forked. - - NOTE: The VIA VT82C42N returns 0x46 ('F') in command 0xA1 (so it - emulates the AMI KF/AMIKey KBC firmware), and 0x42 ('B') in - command 0xAF. - The version on the VIA VT82C686B southbridge also returns - 'F' in command 0xA1, but 0x45 ('E') in command 0xAF. - - NOTE: The AMI MegaKey commands blanked in the technical reference - are CC and and C4, which are Set P14 High and Set P14 Low, - respectively. Also, AMI KBC command C1, mysteriously missing - from the technical references of AMI MegaKey and earlier, is - Write Input Port, same as on AMIKey-3. - - Machines to remove: - - Hedaka HED-919; - - A-Trend ATC-1415; - - ECS Elite UM8810PAIO; - - Shuttle HOT-433A; - - Azza 5IVG (if a more interesting machine with Prime3C is found). -*/ - - const machine_t machines[] = { /* 8088 Machines */ { "[8088] IBM PC (1981)", "ibmpc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 16, 64, 16, 0, machine_pc_init, NULL }, @@ -114,10 +69,10 @@ const machine_t machines[] = { { "[8088] AMI XT clone", "amixt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_amixt_init, NULL }, { "[8088] Columbia Data Products MPC-1600", "mpc1600", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 512, 64, 0, machine_xt_mpc1600_init, NULL }, { "[8088] Compaq Portable", "portable", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_compaq_portable_init, NULL }, - { "[8088] DTK PIM-TB10-Z", "dtk", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_dtk_init, NULL }, + { "[8088] DTK XT clone", "dtk", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_dtk_init, NULL }, { "[8088] Eagle PC Spirit", "pcspirit", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_pcspirit_init, NULL }, { "[8088] Generic XT clone", "genxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_genxt_init, NULL }, - { "[8088] Juko ST", "jukopc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_jukopc_init, NULL }, + { "[8088] Juko XT clone", "jukopc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_jukopc_init, NULL }, { "[8088] Multitech PC-700", "pc700", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_pc700_init, NULL }, { "[8088] NCR PC4i", "pc4i", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_pc4i_init, NULL }, { "[8088] Olivetti M19", "m19", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 4772728, 7159092, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 256, 640, 256, 0, machine_xt_m19_init, m19_get_device }, @@ -132,7 +87,6 @@ const machine_t machines[] = { #if defined(DEV_BRANCH) && defined(USE_LASERXT) { "[8088] VTech Laser Turbo XT", "ltxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_laserxt_init, NULL }, #endif - /* Has a standard PS/2 KBC (so, use IBM PS/2 Type 1). */ { "[8088] Xi8088", "xi8088", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2, 64, 1024, 128, 127, machine_xt_xi8088_init, xi8088_get_device }, { "[8088] Zenith Data Systems Z-151/152/161","zdsz151", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_z151_init, NULL }, { "[8088] Zenith Data Systems Z-159", "zdsz159", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_z159_init, NULL }, @@ -148,7 +102,6 @@ const machine_t machines[] = { { "[8086] Amstrad PPC512/640", "ppc512", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO | MACHINE_MOUSE | MACHINE_NONMI, 512, 640, 128, 63, machine_ppc512_init, ppc512_get_device }, { "[8086] Compaq Deskpro", "deskpro", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_compaq_deskpro_init, NULL }, { "[8086] Olivetti M21/24/24SP", "m24", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO | MACHINE_MOUSE, 128, 640, 128, 0, machine_xt_m24_init, m24_get_device }, - /* Has Olivetti KBC firmware. */ { "[8086] Olivetti M240", "m240", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_m240_init, NULL }, { "[8086] Schetmash Iskra-3104", "iskra3104", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_iskra3104_init, NULL }, { "[8086] Tandy 1000 SL/2", "tandy1000sl2", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 512, 768, 128, 0, machine_tandy1000sl2_init, tandy1k_sl_get_device }, @@ -158,710 +111,360 @@ const machine_t machines[] = { { "[8086] VTech Laser XT3", "lxt3", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_lxt3_init, NULL }, #endif + /* 286 XT machines */ +#if defined(DEV_BRANCH) && defined(USE_HEDAKA) + { "[Citygate D30 XT] Hedaka HED-919", "hed919", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 1024, 64, 0, machine_xt_hed919_init, NULL }, +#endif + /* 286 AT machines */ - /* Has IBM AT KBC firmware. */ { "[ISA] IBM AT", "ibmat", MACHINE_TYPE_286, CPU_PKG_286, 0, 6000000, 8000000, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_ibm_init, NULL }, - /* Has IBM PS/2 Type 1 KBC firmware. */ { "[ISA] IBM PS/1 model 2011", "ibmps1es", MACHINE_TYPE_286, CPU_PKG_286, 0, 10000000, 10000000, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_XTA | MACHINE_VIDEO_FIXED, 512, 16384, 512, 63, machine_ps1_m2011_init, NULL }, - /* Has IBM PS/2 Type 1 KBC firmware. */ { "[ISA] IBM PS/2 model 30-286", "ibmps2_m30_286", MACHINE_TYPE_286, CPU_PKG_286 | CPU_PKG_486SLC_IBM, 0, 10000000, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_XTA | MACHINE_VIDEO_FIXED, 1024, 16384,1024, 127, machine_ps2_m30_286_init, NULL }, - /* Has IBM AT KBC firmware. */ { "[ISA] IBM XT Model 286", "ibmxt286", MACHINE_TYPE_286, CPU_PKG_286, 0, 6000000, 6000000, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 127, machine_at_ibmxt286_init, NULL }, - /* AMI BIOS for a chipset-less machine, most likely has AMI 'F' KBC firmware. */ { "[ISA] AMI IBM AT", "ibmatami", MACHINE_TYPE_286, CPU_PKG_286, 0, 6000000, 8000000, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_ibmatami_init, NULL }, - /* Uses Commodore (CBM) KBC firmware, to be implemented as identical to the - IBM AT KBC firmware unless evidence emerges of any proprietary commands. */ { "[ISA] Commodore PC 30 III", "cmdpc30", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 640, 16384, 128, 127, machine_at_cmdpc_init, NULL }, - /* Uses Compaq KBC firmware. */ { "[ISA] Compaq Portable II", "portableii", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 640, 16384, 128, 127, machine_at_portableii_init, NULL }, - /* Uses Compaq KBC firmware. */ { "[ISA] Compaq Portable III", "portableiii", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_VIDEO, 640, 16384, 128, 127, machine_at_portableiii_init, at_cpqiii_get_device }, - /* Has IBM AT KBC firmware. */ { "[ISA] MR 286 clone", "mr286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 512, 16384, 128, 127, machine_at_mr286_init, NULL }, - /* Has IBM AT KBC firmware. */ { "[ISA] NCR PC8/810/710/3390/3392", "pc8", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_pc8_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_OLIVETTI) - /* Has Olivetti KBC firmware. */ { "[ISA] Olivetti M290", "m290", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 640, 16384, 128, 127, machine_at_m290_init, NULL }, #endif -#if defined(DEV_BRANCH) && defined(USE_OPEN_AT) - /* Has IBM AT KBC firmware. */ + #if defined(DEV_BRANCH) && defined(USE_OPEN_AT) { "[ISA] OpenAT", "openat", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_openat_init, NULL }, #endif - /* Has IBM AT KBC firmware. */ { "[ISA] Phoenix IBM AT", "ibmatpx", MACHINE_TYPE_286, CPU_PKG_286, 0, 6000000, 8000000, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_ibmatpx_init, NULL }, - /* Has Quadtel KBC firmware. */ { "[ISA] Quadtel IBM AT", "ibmatquadtel", MACHINE_TYPE_286, CPU_PKG_286, 0, 6000000, 8000000, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_ibmatquadtel_init, NULL }, - /* This has a Siemens proprietary KBC which is completely undocumented. */ { "[ISA] Siemens PCD-2L", "siemens", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_siemens_init, NULL }, - /* This has Toshiba's proprietary KBC, which is already implemented. */ { "[ISA] Toshiba T3100e", "t3100e", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_VIDEO_FIXED, 1024, 5120, 256, 63, machine_at_t3100e_init, NULL }, - /* Has Quadtel KBC firmware. */ { "[GC103] Quadtel 286 clone", "quadt286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_quadt286_init, NULL }, - /* Most likely has AMI 'F' KBC firmware. */ { "[GC103] Trigem 286M", "tg286m", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 512, 8192, 128, 127, machine_at_tg286m_init, NULL }, - /* This has "AMI KEYBOARD BIOS", most likely 'F'. */ - { "[NEAT] Dataexpert 286", "ami286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_neat_ami_init, NULL }, - /* Has IBM AT KBC firmware. */ + { "[NEAT] AMI 286 clone", "ami286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_neat_ami_init, NULL }, { "[NEAT] NCR 3302", "3302", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_VIDEO, 512, 16384, 128, 127, machine_at_3302_init, NULL }, - /* Has IBM AT KBC firmware. */ { "[NEAT] Phoenix 286 clone", "px286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_px286_init, NULL }, - /* Has Chips & Technologies KBC firmware. */ + { "[SCAT] Award 286 clone", "award286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_award286_init, NULL }, { "[SCAT] GW-286CT GEAR", "gw286ct", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 512, 16384, 128, 127, machine_at_gw286ct_init, NULL }, - /* Has IBM PS/2 Type 1 KBC firmware. */ { "[SCAT] Goldstar GDC-212M", "gdc212m", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_BUS_PS2, 512, 4096, 512, 127, machine_at_gdc212m_init, NULL }, - /* Has a VIA VT82C42N KBC. */ - { "[SCAT] Hyundai Solomon 286KP", "award286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_award286_init, NULL }, - /* Has a VIA VT82C42N KBC. */ { "[SCAT] Hyundai Super-286TR", "super286tr", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_super286tr_init, NULL }, - /* Has IBM PS/2 Type 1 KBC firmware. */ { "[SCAT] Samsung SPC-4200P", "spc4200p", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2, 512, 2048, 128, 127, machine_at_spc4200p_init, NULL }, - /* Has IBM PS/2 Type 1 KBC firmware. */ { "[SCAT] Samsung SPC-4216P", "spc4216p", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2, 1024, 5120,1024, 127, machine_at_spc4216p_init, NULL }, - /* Has IBM PS/2 Type 1 KBC firmware. */ { "[SCAT] Samsung SPC-4620P", "spc4620p", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 5120,1024, 127, machine_at_spc4620p_init, NULL }, - /* Has IBM AT KBC firmware. */ { "[SCAT] Samsung Deskmaster 286", "deskmaster286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_deskmaster286_init, NULL }, /* 286 machines that utilize the MCA bus */ - /* Has IBM PS/2 Type 2 KBC firmware. */ { "[MCA] IBM PS/2 model 50", "ibmps2_m50", MACHINE_TYPE_286, CPU_PKG_286 | CPU_PKG_486SLC_IBM, 0, 10000000, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 10240,1024, 63, machine_ps2_model_50_init, NULL }, /* 386SX machines */ - /* ISA slots available because an official IBM expansion for that existed. */ - /* Has IBM PS/2 Type 1 KBC firmware. */ - { "[ISA] IBM PS/1 model 2121", "ibmps1_2121", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 6144,1024, 63, machine_ps1_m2121_init, NULL }, - /* Has IBM AT KBC firmware. */ - { "[ISA] NCR PC916SX", "pc916sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 128, 127, machine_at_pc916sx_init, NULL }, - /* Has Quadtel KBC firmware. */ - { "[ISA] QTC-SXM KT X20T02/HI", "quadt386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 128, 127, machine_at_quadt386sx_init, NULL }, + { "[ISA] IBM PS/1 model 2121", "ibmps1_2121", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO_FIXED, 2048, 6144,1024, 63, machine_ps1_m2121_init, NULL }, + { "[ISA] IBM PS/1 m.2121+ISA", "ibmps1_2121_isa", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 6144,1024, 63, machine_ps1_m2121_init, NULL }, + { "[ISA] NCR PC916SX", "pc916sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 128, 127, machine_at_pc916sx_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_M6117) - /* Has IBM PS/2 Type 1 KBC firmware. */ { "[ALi M6117] Acrosser AR-B1375", "arb1375", MACHINE_TYPE_386SX, CPU_PKG_M6117, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768,1024, 127, machine_at_arb1375_init, NULL }, - /* Has IBM PS/2 Type 1 KBC firmware. */ { "[ALi M6117] Acrosser PJ-A511M", "pja511m", MACHINE_TYPE_386SX, CPU_PKG_M6117, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768,1024, 127, machine_at_pja511m_init, NULL }, #endif - /* 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. */ - { "[ALi M1217] Flytech 386", "flytech386", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 16384, 1024, 127, machine_at_flytech386_init, at_flytech386_get_device }, - /* 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. */ + { "[ALi M1217] Flytech 386", "flytech386", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 16384, 1024, 127, machine_at_flytech386_init, at_flytech386_get_device }, { "[HT18] AMA-932J", "ama932j", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_VIDEO, 512, 8192, 128, 127, machine_at_ama932j_init, at_ama932j_get_device }, - /* Has an unknown KBC firmware with commands B8 and BB in the style of - Phoenix MultiKey and AMIKey-3(!), but also commands E1 and EA with - unknown functions. */ - { "[Intel 82335 ADI 386SX", "adi386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_adi386sx_init, NULL }, - /* Has an AMI Keyboard BIOS PLUS KBC firmware ('8'). */ + { "[Intel 82335] ADI 386SX", "adi386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_adi386sx_init, NULL }, { "[Intel 82335] Shuttle 386SX", "shuttle386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_shuttle386sx_init, NULL }, - /* Uses Commodore (CBM) KBC firmware, to be implemented as identical to - the IBM PS/2 Type 1 KBC firmware unless evidence emerges of any - proprietary commands. */ { "[NEAT] Commodore SL386SX-16", "cmdsl386sx16", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 8192, 512, 127, machine_at_cmdsl386sx16_init, NULL }, - /* Has IBM AT KBC firmware. */ { "[NEAT] DTK 386SX clone", "dtk386", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_neat_init, NULL }, - /* Has IBM AT KBC firmware. */ + { "[OPTi 283] Olivetti M300-08", "m30008", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 20000000, 20000000, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 16384, 2048, 127, machine_at_m30008_init, at_m30008_get_device }, + { "[OPTi 283] Olivetti M300-15", "m30015", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 25000000, 25000000, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 16384, 2048, 127, machine_at_m30015_init, NULL }, { "[OPTi 291] DTK PPM-3333P", "awardsx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_awardsx_init, NULL }, - /* Uses Commodore (CBM) KBC firmware, to be implemented as identical to - the IBM PS/2 Type 1 KBC firmware unless evidence emerges of any - proprietary commands. */ { "[SCAMP] Commodore SL386SX-25", "cmdsl386sx25", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 8192, 512, 127, machine_at_cmdsl386sx25_init, at_cmdsl386sx25_get_device }, - /* Has IBM PS/2 Type 1 KBC firmware. */ { "[SCAMP] Samsung SPC-6033P", "spc6033p", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 12288, 2048, 127, machine_at_spc6033p_init, at_spc6033p_get_device }, - /* Has an unknown AMI KBC firmware, I'm going to assume 'F' until a - photo or real hardware BIOS string is found. */ { "[SCAT] KMX-C-02", "kmxc02", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 512, 127, machine_at_kmxc02_init, NULL }, - /* Has Quadtel KBC firmware. */ { "[WD76C10] Amstrad MegaPC", "megapc", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 32768, 1024, 127, machine_at_wd76c10_init, NULL }, /* 386SX machines which utilize the MCA bus */ - /* Has IBM PS/2 Type 1 KBC firmware. */ { "[MCA] IBM PS/2 model 55SX", "ibmps2_m55sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 8192, 1024, 63, machine_ps2_model_55sx_init, NULL }, - /* 486SLC machines */ - /* 486SLC machines with just the ISA slot */ - /* Has AMIKey H KBC firmware. */ - { "[OPTi 283] RYC Leopard LX", "rycleopardlx", MACHINE_TYPE_486SLC, CPU_PKG_486SLC_IBM, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 16384, 1024, 127, machine_at_rycleopardlx_init, NULL }, - /* 386DX machines */ { "[ACC 2168] AMI 386DX clone", "acc386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_acc386_init, NULL }, - /* Has an AMI Keyboard BIOS PLUS KBC firmware ('8'). */ { "[C&T 386] ECS 386/32", "ecs386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_ecs386_init, NULL }, { "[C&T 386] Samsung SPC-6000A", "spc6000a", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_spc6000a_init, NULL }, - /* Uses Compaq KBC firmware. */ { "[ISA] Compaq Portable III (386)", "portableiii386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_VIDEO, 1024, 14336, 1024, 127, machine_at_portableiii386_init, at_cpqiii_get_device }, - /* Has IBM AT KBC firmware. */ - { "[ISA] Micronics 09-00021", "micronics386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_micronics386_init, NULL }, - /* Has AMIKey F KBC firmware. */ - { "[SiS 310] ASUS ISA-386C", "asus386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 32768, 1024, 127, machine_at_asus386_init, NULL }, + { "[ISA] Micronics 386 clone", "micronics386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_micronics386_init, NULL }, + { "[SiS 310] ASUS ISA-386C", "asus386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_asus386_init, NULL }, /* 386DX machines which utilize the MCA bus */ - /* Has IBM PS/2 Type 1 KBC firmware. */ { "[MCA] IBM PS/2 model 70 (type 3)", "ibmps2_m70_type3", MACHINE_TYPE_386DX, CPU_PKG_386DX | CPU_PKG_486BL, 0, 0, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 2048, 16384, 2048, 63, machine_ps2_model_70_type3_init, NULL }, - /* Has IBM PS/2 Type 1 KBC firmware. */ { "[MCA] IBM PS/2 model 80", "ibmps2_m80", MACHINE_TYPE_386DX, CPU_PKG_386DX | CPU_PKG_486BL, 0, 0, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 12288, 1024, 63, machine_ps2_model_80_init, NULL }, - /* Has IBM PS/2 Type 1 KBC firmware. */ { "[MCA] IBM PS/2 model 80 (type 3)", "ibmps2_m80_type3", MACHINE_TYPE_386DX, CPU_PKG_386DX | CPU_PKG_486BL, 0, 0, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 2048, 12288, 2048, 63, machine_ps2_model_80_axx_init, NULL }, /* 386DX/486 machines */ - /* The BIOS sends commands C9 without a parameter and D5, both of which are - Phoenix MultiKey commands. */ - { "[OPTi 495] Award 486 clone", "award495", MACHINE_TYPE_386DX_486, CPU_PKG_386DX | CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_init, NULL }, - /* Has AMIKey F KBC firmware. */ - { "[OPTi 495] Dataexpert SX495", "ami495", MACHINE_TYPE_386DX_486, CPU_PKG_386DX | CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_ami_init, NULL }, - /* Has AMIKey F KBC firmware (it's just the MR BIOS for the above machine). */ - { "[OPTi 495] Dataexpert SX495 (MR BIOS)", "mr495", MACHINE_TYPE_386DX_486, CPU_PKG_386DX | CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_mr_init, NULL }, + { "[OPTi 495] Award 486 clone", "award486", MACHINE_TYPE_386DX_486, CPU_PKG_386DX | CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_init, NULL }, + { "[OPTi 495] Dataexpert SX495 (486)", "ami486", MACHINE_TYPE_386DX_486, CPU_PKG_386DX | CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_ami_init, NULL }, + { "[OPTi 495] MR 486 clone", "mr486", MACHINE_TYPE_386DX_486, CPU_PKG_386DX | CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_mr_init, NULL }, /* 486 machines - Socket 1 */ - /* Has JetKey 5 KBC Firmware which looks like it is a clone of AMIKey type F. - It also has those Ex commands also seen on the VIA VT82C42N (the BIOS - supposedly sends command EF. - The board was also seen in 2003 with a -H string - perhaps someone swapped - the KBC? */ { "[ALi M1429] Olystar LIL1429", "ali1429", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_ali1429_init, NULL }, - /* Has JetKey 5 KBC Firmware - but the BIOS string ends in a hardcoded -F, and - the BIOS also explicitly expects command A1 to return a 'F', so it looks like - the JetKey 5 is a clone of AMIKey type F. */ { "[CS4031] AMI 486 CS4031", "cs4031", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_cs4031_init, NULL }, - /* Uses some variant of Phoenix MultiKey/42 as the Intel 8242 chip has a Phoenix - copyright. */ + { "[ETEQ ET6000] Olivetti PCS-46C", "pcs46c", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE | MACHINE_VIDEO, 4096, 32768, 4096, 127, machine_at_pcs46c_init, at_pcs46c_get_device }, { "[OPTi 895] Mylex MVI486", "mvi486", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE_DUAL, 1024, 65536, 1024, 127, machine_at_mvi486_init, NULL }, - /* Has AMI KF KBC firmware. */ - { "[SiS 401] ASUS ISA-486", "isa486", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_isa486_init, NULL }, - /* Has AMIKey H KBC firmware, per the screenshot in "How computers & MS-DOS work". */ - { "[SiS 401] Chaintech 433SC", "sis401", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_sis401_init, NULL }, - /* Has AMIKey F KBC firmware, per a photo of a monitor with the BIOS screen on - eBay. */ - { "[SiS 460] ABIT AV4", "av4", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_av4_init, NULL }, - /* Has a MR (!) KBC firmware, which is a clone of the standard IBM PS/2 KBC firmware. */ - { "[SiS 471] SiS VL-BUS 471 REV. A1", "px471", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024,131072, 1024, 127, machine_at_px471_init, NULL }, - /* The chip is a Lance LT38C41, a clone of the Intel 8041, and the BIOS sends - commands BC, BD, and C9 which exist on both AMIKey and Phoenix MultiKey/42, - but it does not write a byte after C9, which is consistent with AMIKey, so - this must have some form of AMIKey. */ { "[VIA VT82C495] FIC 486-VC-HD", "486vchd", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 64512, 1024, 127, machine_at_486vchd_init, 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. */ { "[VLSI 82C480] HP Vectra 486VL", "vect486vl", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 32768, 2048, 127, machine_at_vect486vl_init, at_vect486vl_get_device }, - /* Has a standard IBM PS/2 KBC firmware or a clone thereof. */ - { "[VLSI 82C481] Siemens Nixdorf D824", "d824", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 32768, 2048, 127, machine_at_d824_init, at_d824_get_device }, - - /* 486 machines - Socket 2 */ - /* 486 machines with just the ISA slot */ - /* Uses some variant of Phoenix MultiKey/42 as the BIOS sends keyboard controller - command C7 (OR input byte with received data byte). */ - { "[ACC 2168] Packard Bell PB410A", "pb410a", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 4096, 36864, 1024, 127, machine_at_pb410a_init, NULL }, - /* Uses an ACER/NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware (V4.01H). */ - { "[ALi M1429G] Acer A1G", "acera1g", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 4096, 36864, 1024, 127, machine_at_acera1g_init, at_acera1g_get_device }, - /* There are two similar BIOS strings with -H, and one with -U, so I'm going to - give it an AMIKey H KBC firmware. */ - { "[ALi M1429G] AMI WinBIOS 486", "win486", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_winbios1429_init, NULL }, - /* Uses an NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware. */ - { "[SiS 461] Acer V10", "acerv10", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 1024, 32768, 1024, 127, machine_at_acerv10_init, 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. */ - { "[SiS 461] IBM PS/ValuePoint 433DX/Si", "valuepoint433", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 65536, 1024, 127, machine_at_valuepoint433_init, 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. */ - { "[SiS 471] ABit AB-AH4", "win471", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_win471_init, NULL }, + { "[VLSI 82C481] Siemens Nixdorf D824", "d824", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 32768, 2048, 127, machine_at_d824_init, at_d824_get_device }, /* 486 machines - Socket 3 */ /* 486 machines with just the ISA slot */ - /* Has AMI MegaKey KBC firmware. */ - { "[Contaq 82C597] Green-B", "green-b", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_green_b_init, NULL }, - /* Has a VIA VT82C42N KBC. */ + { "[ACC 2168] Packard Bell PB410A", "pb410a", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 4096, 36864, 1024, 127, machine_at_pb410a_init, NULL }, + { "[ALi M1429G] Acer A1G", "acera1g", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 4096, 36864, 1024, 127, machine_at_acera1g_init, at_acera1g_get_device }, + { "[ALi M1429] AMI WinBIOS 486", "win486", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_winbios1429_init, NULL }, { "[OPTi 895] Jetway J-403TG", "403tg", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_403tg_init, NULL }, - /* Has JetKey 5 KBC Firmware which looks like it is a clone of AMIKey type F. */ - { "[OPTi 895] Jetway J-403TG Rev D", "403tg_rev_d", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_403tg_rev_d_init, NULL }, - /* Has JetKey 5 KBC Firmware which looks like it is a clone of AMIKey type F. */ - { "[OPTi 895] Jetway J-403TG Rev D (MR BIOS)","403tg_rev_d_mr", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_403tg_rev_d_mr_init, NULL }, - /* Has AMIKey H keyboard BIOS. */ + { "[SiS 401] AMI 486 Clone", "sis401", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_sis401_init, NULL }, + { "[SiS 401] ASUS ISA-486", "isa486", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_isa486_init, NULL }, + { "[SiS 460] ABIT AV4", "av4", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_av4_init, NULL }, + { "[SiS 461] IBM PS/ValuePoint 433DX/Si", "valuepoint433", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 65536, 1024, 127, machine_at_valuepoint433_init, NULL }, + { "[SiS 471] AMI 486 Clone", "ami471", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_ami471_init, NULL }, + { "[SiS 471] AMI WinBIOS 486 clone", "win471", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_win471_init, NULL }, { "[SiS 471] AOpen Vi15G", "vi15g", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_vi15g_init, NULL }, - /* This has an AMIKey-2, which is an updated version of type 'H'. */ - { "[SiS 471] ASUS VL/I-486SV2G (GX4)", "vli486sv2g", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 65536, 1024, 127, machine_at_vli486sv2g_init, NULL }, - /* Has JetKey 5 KBC Firmware which looks like it is a clone of AMIKey type F. */ + { "[SiS 471] ASUS VL/I-486SV2G (GX4)", "vli486sv2g", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE_DUAL, 1024, 65536, 1024, 127, machine_at_vli486sv2g_init, NULL }, { "[SiS 471] DTK PKM-0038S E-2", "dtk486", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_dtk486_init, NULL }, - /* Unknown Epox VLB Socket 3 board, has AMIKey F keyboard BIOS. */ - { "[SiS 471] Epox 486SX/DX Green", "ami471", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_ami471_init, NULL }, + { "[SiS 471] Phoenix SiS 471", "px471", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024,131072, 1024, 127, machine_at_px471_init, NULL }, /* 486 machines which utilize the PCI bus */ - /* Has the ALi M1487/9's on-chip keyboard controller which clones a standard AT - KBC. */ { "[ALi M1489] ABIT AB-PB4", "abpb4", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_abpb4_init, NULL }, - /* Has the ALi M1487/9's on-chip keyboard controller which clones a standard AT - KBC. - The BIOS string always ends in -U, but the BIOS will send AMIKey commands 0xCA - and 0xCB if command 0xA1 returns a letter in the 0x5x or 0x7x ranges, so I'm - going to give it an AMI 'U' KBC. */ { "[ALi M1489] AMI WinBIOS 486 PCI", "win486pci", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_win486pci_init, NULL }, - /* Has IBM PS/2 Type 1 KBC firmware. */ { "[OPTi 802G] IBM PC 330 (type 6573)", "pc330_6573", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3_PC330, 0, 25000000, 33333333, 0, 0, 2.0, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_pc330_6573_init, NULL }, - /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[i420EX] ASUS PVI-486AP4", "486ap4", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_IDE_DUAL, 1024, 131072, 1024, 127, machine_at_486ap4_init, NULL }, - /* This has the Phoenix MultiKey KBC firmware. */ - { "[i420EX] Intel Classic/PCI ED", "ninja", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 131072, 1024, 127, machine_at_ninja_init, NULL }, - /* This has an AMIKey-2, which is an updated version of type 'H'. Also has a - SST 29EE010 Flash chip. */ { "[i420ZX] ASUS PCI/I-486SP3G", "486sp3g", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL | MACHINE_SCSI, 1024, 131072, 1024, 127, machine_at_486sp3g_init, NULL }, - /* I'm going to assume this as an AMIKey-2 like the other two 486SP3's. */ { "[i420TX] ASUS PCI/I-486SP3", "486sp3", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL | MACHINE_SCSI, 1024, 131072, 1024, 127, machine_at_486sp3_init, NULL }, - /* This has the Phoenix MultiKey KBC firmware. */ { "[i420TX] Intel Classic/PCI", "alfredo", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_alfredo_init, NULL }, - /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[SiS 496] ASUS PVI-486SP3C", "486sp3c", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_IDE_DUAL, 1024, 261120, 1024, 255, machine_at_486sp3c_init, NULL }, - /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[SiS 496] Lucky Star LS-486E", "ls486e", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_ls486e_init, NULL }, - /* The BIOS does not send a single non-standard KBC command, so it has a standard PS/2 KBC. */ { "[SiS 496] Micronics M4Li", "m4li", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 131072, 1024, 127, machine_at_m4li_init, NULL }, - /* Has a BestKey KBC which clones AMI type 'H'. */ { "[SiS 496] Rise Computer R418", "r418", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 261120, 1024, 255, machine_at_r418_init, NULL }, - /* This has a Holtek 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. */ { "[SiS 496] Soyo 4SA2", "4sa2", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, CPU_BLOCK(CPU_i486SX, CPU_i486DX, CPU_Am486SX, CPU_Am486DX), 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 261120, 1024, 255, machine_at_4sa2_init, NULL }, - /* According to MrKsoft, his real 4DPS has an AMIKey-2, which is an updated version - of type 'H'. */ { "[SiS 496] Zida Tomato 4DP", "4dps", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 261120, 1024, 255, machine_at_4dps_init, NULL }, - /* Has a VIA VT82C406 KBC+RTC that likely has identical commands to the VT82C42N. */ - { "[VIA VT82C496G] DFI G486VPA", "g486vpa", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_g486vpa_init, NULL }, - /* Has a VIA VT82C42N KBC. */ + { "[UMC 8881] A-Trend ATC-1415", "atc1415", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_atc1415_init, NULL }, + { "[UMC 8881] ECS Elite UM8810PAIO", "ecs486", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_ecs486_init, NULL }, + { "[UMC 8881] Shuttle HOT-433A", "hot433", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 262144, 1024, 255, machine_at_hot433_init, NULL }, { "[VIA VT82C496G] FIC VIP-IO2", "486vipio2", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_486vipio2_init, NULL }, /* 486 machines - Miscellaneous */ + /* 486 machines with just the ISA slot */ + { "[OPTi 283] RYC Leopard LX", "rycleopardlx", MACHINE_TYPE_486_MISC, CPU_PKG_486SLC_IBM, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 16384, 1024, 127, machine_at_rycleopardlx_init, NULL }, + /* 486 machines which utilize the PCI bus */ - /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[STPC Client] ITOX STAR", "itoxstar", MACHINE_TYPE_486_MISC, CPU_PKG_STPC, 0, 66666667, 75000000, 0, 0, 1.0, 1.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 255, machine_at_itoxstar_init, NULL }, - /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[STPC Consumer-II] Acrosser AR-B1479", "arb1479", MACHINE_TYPE_486_MISC, CPU_PKG_STPC, 0, 66666667, 66666667, 0, 0, 2.0, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 32768, 163840, 8192, 255, machine_at_arb1479_init, NULL }, - /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[STPC Elite] Advantech PCM-9340", "pcm9340", MACHINE_TYPE_486_MISC, CPU_PKG_STPC, 0, 66666667, 66666667, 0, 0, 2.0, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 32768, 98304, 8192, 255, machine_at_pcm9340_init, NULL }, - /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[STPC Atlas] AAEON PCM-5330", "pcm5330", MACHINE_TYPE_486_MISC, CPU_PKG_STPC, 0, 66666667, 66666667, 0, 0, 2.0, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 32768, 131072,32768, 255, machine_at_pcm5330_init, NULL }, /* Socket 4 machines */ /* 430LX */ - /* Has AMIKey F KBC firmware (AMIKey). */ { "[i430LX] ASUS P/I-P5MP3", "p5mp3", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE, 2048, 196608, 2048, 127, machine_at_p5mp3_init, NULL }, - /* Has IBM PS/2 Type 1 KBC firmware. */ { "[i430LX] Dell Dimension XPS P60", "dellxp60", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE, 2048, 131072, 2048, 127, machine_at_dellxp60_init, NULL }, - /* Has IBM PS/2 Type 1 KBC firmware. */ { "[i430LX] Dell OptiPlex 560/L", "opti560l", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_opti560l_init, NULL }, - /* This has the Phoenix MultiKey KBC firmware. - This is basically an Intel Batman (*NOT* Batman's Revenge) with a fancier - POST screen */ { "[i430LX] AMBRA DP60 PCI", "ambradp60", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_ambradp60_init, NULL }, - /* Has IBM PS/2 Type 1 KBC firmware. */ { "[i430LX] IBM PS/ValuePoint P60", "valuepointp60", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_valuepointp60_init, NULL }, - /* This has the Phoenix MultiKey KBC firmware. */ - { "[i430LX] Intel Premiere/PCI", "revenge", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_revenge_init, NULL }, - /* Has AMI MegaKey KBC firmware. */ + { "[i430LX] Intel Premiere/PCI", "revenge", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_batman_init, NULL }, { "[i430LX] Micro Star 586MC1", "586mc1", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_586mc1_init, NULL }, - /* This has the Phoenix MultiKey KBC firmware. */ { "[i430LX] Packard Bell PB520R", "pb520r", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 139264, 2048, 127, machine_at_pb520r_init, at_pb520r_get_device }, /* OPTi 596/597 */ - /* This uses an AMI KBC firmware in PS/2 mode (it sends command A5 with the - PS/2 "Load Security" meaning), most likely MegaKey as it sends command AF - (Set Extended Controller RAM) just like the later Intel AMI BIOS'es. */ { "[OPTi 597] AMI Excalibur VLB", "excalibur", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_VLB | MACHINE_IDE, 2048, 65536, 2048, 127, machine_at_excalibur_init, NULL }, - /* OPTi 596/597/822 */ - /* This has AMIKey 'F' KBC firmware. */ - { "[OPTi 597] Supermicro P5VL-PCI", "p5vl", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_VLB, 8192, 131072, 8192, 127, machine_at_p5vl_init, NULL }, - /* SiS 85C50x */ - /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[SiS 85C50x] ASUS PCI/I-P5SP4", "p5sp4", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p5sp4_init, NULL }, /* Socket 5 machines */ /* 430NX */ - /* This has the Phoenix MultiKey KBC firmware. */ { "[i430NX] Intel Premiere/PCI II", "plato", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_plato_init, NULL }, - /* This has the Phoenix MultiKey KBC firmware. - This is basically an Intel Premiere/PCI II with a fancier POST screen. */ { "[i430NX] AMBRA DP90 PCI", "ambradp90", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_ambradp90_init, NULL }, - /* Has AMI MegaKey KBC firmware. */ { "[i430NX] Gigabyte GA-586IP", "430nx", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_430nx_init, NULL }, /* 430FX */ - /* Uses an ACER/NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware (V5.0). */ { "[i430FX] Acer V30", "acerv30", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_acerv30_init, NULL }, - /* Has AMIKey F KBC firmware. */ { "[i430FX] AMI Apollo", "apollo", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_apollo_init, NULL }, - /* Has AMIKey H KBC firmware. */ - { "[i430FX] Dataexpert EXP8551", "exp8551", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_exp8551_init, NULL }, - /* The BIOS does not send a single non-standard KBC command, but the board has a SMC Super I/O - chip with on-chip KBC and AMI MegaKey KBC firmware. */ { "[i430FX] HP Vectra VL 5 Series 4", "vectra54", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 511, machine_at_vectra54_init, at_vectra54_get_device }, - /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the - PC87306 Super I/O chip, command 0xA1 returns '5'. - Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430FX] Intel Advanced/ZP", "zappa", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_zappa_init, NULL }, - /* The BIOS sends KBC command B3 which indicates an AMI (or VIA VT82C42N) KBC. */ { "[i430FX] NEC PowerMate V", "powermatev", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_powermatev_init, NULL }, - /* Has a VIA VT82C42N KBC. */ { "[i430FX] PC Partner MB500N", "mb500n", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_mb500n_init, NULL }, - /* Has AMIKey Z(!) KBC firmware. */ - { "[i430FX] Trigem Hawk", "hawk", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_hawk_init, NULL }, /* OPTi 596/597 */ - /* This uses an AMI KBC firmware in PS/2 mode (it sends command A5 with the - PS/2 "Load Security" meaning), most likely MegaKey as it sends command AF - (Set Extended Controller RAM) just like the later Intel AMI BIOS'es. */ { "[OPTi 597] TMC PAT54PV", "pat54pv", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_K5, CPU_5K86), 50000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_VLB, 2048, 65536, 2048, 127, machine_at_pat54pv_init, NULL }, /* OPTi 596/597/822 */ { "[OPTi 597] Shuttle HOT-543", "hot543", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_VLB, 8192, 131072, 8192, 127, machine_at_hot543_init, NULL }, + { "[OPTi 597] Supermicro P54VL-PCI", "p54vl", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_VLB, 8192, 131072, 8192, 127, machine_at_p54vl_init, NULL }, /* SiS 85C50x */ - /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[SiS 85C50x] ASUS PCI/I-P54SP4", "p54sp4", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_K5, CPU_5K86), 40000000, 66666667, 3380, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p54sp4_init, NULL }, - /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[SiS 85C50x] BCM SQ-588", "sq588", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_PENTIUMMMX), 50000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_sq588_init, NULL }, + /* UMC 889x */ + { "[UMC 889x] Shuttle HOT-539", "hot539", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_K5, CPU_5K86), 40000000, 66666667, 3380, 3600, 1.5, 2.0, MACHINE_PCI | MACHINE_IDE_DUAL, 8192, 262144, 8192, 127, machine_at_hot539_init, NULL }, + /* Socket 7 (Single Voltage) machines */ /* 430FX */ - /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[i430FX] ASUS P/I-P54TP4XE", "p54tp4xe", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3600, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p54tp4xe_init, NULL }, - /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[i430FX] ASUS P/I-P54TP4XE (MR BIOS)", "mr586", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3600, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_mr586_init, NULL }, - /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the - PC87306 Super I/O chip, command 0xA1 returns '5'. - Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430FX] Gateway 2000 Thor", "gw2katx", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_gw2katx_init, NULL }, - /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the - PC87306 Super I/O chip, command 0xA1 returns '5'. - Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430FX] Intel Advanced/ATX", "thor", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_thor_init, NULL }, - /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the - PC87306 Super I/O chip, command 0xA1 returns '5'. - Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430FX] Intel Advanced/ATX (MR BIOS)", "mrthor", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_mrthor_init, NULL }, - /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the - PC87306 Super I/O chip, command 0xA1 returns '5'. - Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430FX] Intel Advanced/EV", "endeavor", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_endeavor_init, at_endeavor_get_device }, - /* This has an AMIKey-2, which is an updated version of type 'H'. */ - { "[i430FX] MSI MS-5119", "ms5119", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_ms5119_init, NULL }, - /* This most likely uses AMI MegaKey KBC firmware as well due to having the same - Super I/O chip (that has the KBC firmware on it) as eg. the Advanced/EV. */ { "[i430FX] Packard Bell PB640", "pb640", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_pb640_init, at_pb640_get_device }, - /* Has an AMI 'H' KBC firmware (1992). */ - { "[i430FX] QDI FMB", "fmb", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_WINCHIP, CPU_WINCHIP2, CPU_Cx6x86, CPU_Cx6x86L, CPU_Cx6x86MX), 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_fmb_init, NULL }, + { "[i430FX] QDI Chariot", "chariot", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_WINCHIP, CPU_WINCHIP2, CPU_Cx6x86, CPU_Cx6x86L, CPU_Cx6x86MX), 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_chariot_init, NULL }, /* 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. */ { "[i430HX] Acer M3A", "acerm3a", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3300, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 196608, 8192, 127, machine_at_acerm3a_init, NULL }, - /* Has AMIKey F KBC firmware. */ { "[i430HX] AOpen AP53", "ap53", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3450, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_ap53_init, NULL }, - /* [TEST] Has a VIA 82C42N KBC, with AMIKey F KBC firmware. */ { "[i430HX] Biostar MB-8500TUC", "8500tuc", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_8500tuc_init, 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. */ { "[i430HX] SuperMicro Super P55T2S", "p55t2s", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3300, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 127, machine_at_p55t2s_init, NULL }, /* 430VX */ - /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the - PC87306 Super I/O chip, command 0xA1 returns '5'. - Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430VX] Gateway 2000 Tigereye", "gw2kte", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_gw2kte_init, NULL }, /* SiS 5511 */ - /* Has AMIKey H KBC firmware (AMIKey-2). */ - { "[SiS 5511] AOpen AP5S", "ap5s", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_ap5s_init, NULL }, + { "[SiS 5511] AOpen AP5S", "ap5s", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_ap5s_init, NULL }, /* Socket 7 (Dual Voltage) machines */ /* 430HX */ - /* Has SST flash and the SMC FDC73C935's on-chip KBC with Phoenix MultiKey firmware. */ { "[i430HX] Acer V35N", "acerv35n", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_Cx6x86MX), 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 196608, 8192, 127, machine_at_acerv35n_init, NULL }, - /* Has AMIKey H KBC firmware (AMIKey-2). */ { "[i430HX] ASUS P/I-P55T2P4", "p55t2p4", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 83333333, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 127, machine_at_p55t2p4_init, NULL }, - /* Has the SMC FDC73C935's on-chip KBC with Phoenix MultiKey firmware. */ { "[i430HX] Micronics M7S-Hi", "m7shi", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 511, machine_at_m7shi_init, NULL }, - /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the - PC87306 Super I/O chip, command 0xA1 returns '5'. - Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430HX] Intel TC430HX", "tc430hx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 255, machine_at_tc430hx_init, NULL }, - /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the - PC87306 Super I/O chip, command 0xA1 returns '5'. - Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430HX] Toshiba Equium 5200D", "equium5200", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 196608, 8192, 127, machine_at_equium5200_init, NULL }, - /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the - PC87306 Super I/O chip, command 0xA1 returns '5'. - Command 0xA0 copyright string: (C)1994 AMI . - Yes, this is an Intel AMI BIOS with a fancy splash screen. */ { "[i430HX] Sony Vaio PCV-240", "pcv240", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 196608, 8192, 127, machine_at_pcv240_init, NULL }, - /* The base board has AMIKey-2 (updated 'H') KBC firmware. */ { "[i430HX] ASUS P/I-P65UP5 (C-P55T2D)", "p65up5_cp55t2d", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_p65up5_cp55t2d_init, NULL }, /* 430VX */ - /* Has AMIKey H KBC firmware (AMIKey-2). */ { "[i430VX] ASUS P/I-P55TVP4", "p55tvp4", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p55tvp4_init, NULL }, - /* The BIOS does not send a single non-standard KBC command, so it must have a standard IBM - PS/2 KBC firmware or a clone thereof. */ { "[i430VX] Azza 5IVG", "5ivg", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_5ivg_init, NULL }, - /* [TEST] Has AMIKey 'F' KBC firmware. */ { "[i430VX] Biostar MB-8500TVX-A", "8500tvxa", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2600, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_8500tvxa_init, NULL }, - /* The BIOS does not send a single non-standard KBC command, but the board has a SMC Super I/O - chip with on-chip KBC and AMI MegaKey KBC firmware. */ { "[i430VX] Compaq Presario 2240", "presario2240", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_presario2240_init, NULL }, - /* This most likely has AMI MegaKey as above. */ { "[i430VX] Compaq Presario 4500", "presario4500", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_presario4500_init, NULL }, - /* The BIOS sends KBC command CB which is an AMI KBC command, so it has an AMI KBC firmware. */ { "[i430VX] Epox P55-VA", "p55va", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p55va_init, NULL }, - /* The BIOS does not send a single non-standard KBC command. */ { "[i430VX] HP Brio 80xx", "brio80xx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 66666667, 66666667, 2200, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_brio80xx_init, NULL }, - /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the - PC87306 Super I/O chip, command 0xA1 returns '5'. - Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430VX] Packard Bell PB680", "pb680", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_pb680_init, NULL }, - /* This has the AMIKey 'H' firmware, possibly AMIKey-2. Photos show it with a BestKey, so it - likely clones the behavior of AMIKey 'H'. */ { "[i430VX] PC Partner MB520N", "mb520n", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2600, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_mb520n_init, NULL }, - /* This has a Holtek 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. */ { "[i430VX] Shuttle HOT-557", "430vx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_GAMEPORT, 8192, 131072, 8192, 127, machine_at_i430vx_init, NULL }, /* 430TX */ - /* The BIOS sends KBC command B8, CA, and CB, so it has an AMI KBC firmware. */ { "[i430TX] ADLink NuPRO-592", "nupro592", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 66666667, 66666667, 1900, 2800, 1.5, 5.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_nupro592_init, NULL }, - /* This has the AMIKey KBC firmware, which is an updated 'F' type (YM430TX is based on the TX97). */ { "[i430TX] ASUS TX97", "tx97", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 75000000, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_tx97_init, NULL }, #if defined(DEV_BRANCH) && defined(NO_SIO) - /* This has the Phoenix MultiKey KBC firmware. */ { "[i430TX] Intel AN430TX", "an430tx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_an430tx_init, NULL }, #endif - /* This has the AMIKey KBC firmware, which is an updated 'F' type. */ { "[i430TX] Intel YM430TX", "ym430tx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_ym430tx_init, NULL }, - /* The BIOS sends KBC command BB and expects it to output a byte, which is AMI KBC behavior. */ { "[i430TX] PC Partner MB540N", "mb540n", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2700, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_mb540n_init, NULL }, - /* [TEST] Has AMIKey 'H' KBC firmware. */ { "[i430TX] SuperMicro Super P5MMS98", "p5mms98", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2100, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_p5mms98_init, NULL }, /* Apollo VPX */ - /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA - VT82C42N. */ { "[VIA VPX] FIC VA-502", "ficva502", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 75000000, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_ficva502_init, NULL }, /* Apollo VP3 */ - /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA - VT82C42N. */ { "[VIA VP3] FIC PA-2012", "ficpa2012", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 55000000, 75000000, 2100, 3520, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 127, machine_at_ficpa2012_init, NULL }, /* SiS 5571 */ - /* Has the SiS 5571 chipset with on-chip KBC. */ { "[SiS 5571] Rise R534F", "r534f", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 393216, 8192, 127, machine_at_r534f_init, NULL }, - /* Has the SiS 5571 chipset with on-chip KBC. */ { "[SiS 5571] MSI MS-5146", "ms5146", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 127, machine_at_ms5146_init, NULL }, + /* SiS 5598 */ + { "[SiS 5598] ASUS SP97-XV", "sp97xv", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2100, 3200, 1.5, 2.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_sp97xv_init, NULL }, + { "[SiS 5598] PC Chips M571", "m571", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 75000000, 2500, 3500, 1.5, 3.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_m571_init, NULL }, + /* ALi ALADDiN IV */ - /* Has the ALi M1543 southbridge with on-chip KBC. */ +#if defined(DEV_BRANCH) && defined(USE_M154X) { "[ALi ALADDiN IV] PC Chips M560", "m560", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 83333333, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_m560_init, NULL }, - /* Has the ALi M1543 southbridge with on-chip KBC. */ { "[ALi ALADDiN IV] MSI MS-5164", "ms5164", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2100, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_ms5164_init, NULL }, +#endif /* Super Socket 7 machines */ - /* ALi ALADDiN V */ - /* Has the ALi M1543C southbridge with on-chip KBC. */ - { "[ALi ALADDiN V] ASUS P5A", "p5a", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 2000, 3200, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,2097152, 8192, 255, machine_at_p5a_init, NULL }, - /* Is the exact same as the Matsonic MS6260S. Has the ALi M1543C southbridge - with on-chip KBC. */ - { "[ALi ALADDiN V] PC Chips M579", "m579", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 2000, 3200, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,2097152, 8192, 255, machine_at_m579_init, NULL }, - /* Has the ALi M1543C southbridge with on-chip KBC. */ - { "[ALi ALADDiN V] Gigabyte GA-5AA", "ga-5aa", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 2000, 3200, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,2097152, 8192, 255, machine_at_ga_5aa_init, NULL }, - /* Has the ALi M1543C southbridge with on-chip KBC. */ - { "[ALi ALADDiN V] Gigabyte GA-5AX", "ga-5ax", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 2000, 3200, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,2097152, 8192, 255, machine_at_ga_5ax_init, NULL }, - /* Apollo MVP3 */ - /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA - VT82C42N. */ { "[VIA MVP3] AOpen AX59 Pro", "ax59pro", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 1300, 3520, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_ax59pro_init, NULL }, - /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA - VT82C42N. */ { "[VIA MVP3] FIC VA-503+", "ficva503p", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 2000, 3200, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_mvp3_init, NULL }, - /* Has the VIA VT82C686A southbridge with on-chip KBC identical to the VIA - VT82C42N. */ { "[VIA MVP3] FIC VA-503A", "ficva503a", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 1800, 3100, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_ficva503a_init, NULL }, /* Socket 8 machines */ /* 450KX */ #if defined(DEV_BRANCH) && defined(USE_I450KX) - /* This has an AMIKey, which is an updated version of type 'F'. */ { "[i450KX] ASUS P/I-P6RP4", "p6rp4", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_p6rp4_init, NULL }, #endif /* 440FX */ - /* Has the SMC FDC73C935's on-chip KBC with Phoenix MultiKey firmware. */ { "[i440FX] Acer V60N", "v60n", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2500, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_v60n_init, NULL }, - /* The base board has AMIKey-2 (updated 'H') KBC firmware. */ { "[i440FX] ASUS P/I-P65UP5 (C-P6ND)", "p65up5_cp6nd", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 127, machine_at_p65up5_cp6nd_init, 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. */ { "[i440FX] Biostar MB-8600TTC", "8600ttc", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 50000000, 66666667, 2900, 3300, 2.0, 5.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 127, machine_at_8500ttc_init, NULL }, { "[i440FX] Gigabyte GA-686NX", "686nx", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 2.0, 5.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_686nx_init, NULL }, - /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the - PC87306 Super I/O chip, command 0xA1 returns '5'. - Command 0xA0 copyright string: (C)1994 AMI . */ { "[i440FX] Intel AP440FX", "ap440fx", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 2.0, 3.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_ap440fx_init, NULL }, - /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the - PC87306 Super I/O chip, command 0xA1 returns '5'. - Command 0xA0 copyright string: (C)1994 AMI . */ { "[i440FX] Intel VS440FX", "vs440fx", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 2.0, 3.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_vs440fx_init, NULL }, - /* Has the SMC FDC73C935's on-chip KBC with Phoenix MultiKey firmware. */ { "[i440FX] Micronics M6Mi", "m6mi", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2900, 3300, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 127, machine_at_m6mi_init, 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. */ { "[i440FX] PC Partner MB600N", "mb600n", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_mb600n_init, NULL }, /* Slot 1 machines */ - /* ALi ALADDiN V */ - /* Has the ALi M1543C southbridge with on-chip KBC. */ - { "[ALi ALADDiN-PRO II] PC Chips M729", "m729", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 50000000, 66666667, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,2097152, 8192, 255, machine_at_m729_init, NULL }, - /* 440FX */ - /* The base board has AMIKey-2 (updated 'H') KBC firmware. */ { "[i440FX] ASUS P/I-P65UP5 (C-PKND)", "p65up5_cpknd", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 50000000, 66666667, 1800, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 127, machine_at_p65up5_cpknd_init, NULL }, - /* This has a Holtek 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. */ { "[i440FX] ASUS KN97", "kn97", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 60000000, 83333333, 1800, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 127, machine_at_kn97_init, NULL }, /* 440LX */ - /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[i440LX] ABIT LX6", "lx6", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 60000000, 100000000, 1500, 3500, 2.0, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_lx6_init, NULL }, - /* Has a SM(S)C FDC37C935 Super I/O chip with on-chip KBC with Phoenix - MultiKey KBC firmware. */ { "[i440LX] Micronics Spitfire", "spitfire", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 66666667, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_spitfire_init, NULL }, /* 440EX */ - /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[i440EX] QDI EXCELLENT II", "p6i440e2", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 83333333, 1800, 3500, 3.0, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 255, machine_at_p6i440e2_init, NULL }, /* 440BX */ - /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[i440BX] ASUS P2B-LS", "p2bls", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 50000000, 112121212, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_p2bls_init, NULL }, - /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[i440BX] ASUS P3B-F", "p3bf", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_p3bf_init, NULL }, - /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[i440BX] ABIT BF6", "bf6", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 133333333, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_bf6_init, NULL }, - /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[i440BX] AOpen AX6BC", "ax6bc", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 112121212, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_ax6bc_init, NULL }, - /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[i440BX] Gigabyte GA-686BX", "686bx", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_686bx_init, NULL }, - /* Has a SM(S)C FDC37M60x Super I/O chip with on-chip KBC with most likely - AMIKey-2 KBC firmware. */ { "[i440BX] HP Vectra VEi 8", "vei8", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_vei8_init, NULL }, - /* Has a National Semiconductors PC87309 Super I/O chip with on-chip KBC - with most likely AMIKey-2 KBC firmware. */ { "[i440BX] Tyan Tsunami ATX", "tsunamiatx", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 112121212, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_SOUND, 8192,1048576, 8192, 255, machine_at_tsunamiatx_init, at_tsunamiatx_get_device }, - /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[i440BX] SuperMicro Super P6SBA", "p6sba", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_p6sba_init, NULL }, +#if defined(DEV_BRANCH) && defined(NO_SIO) + { "[i440BX] Fujitsu ErgoPro x365", "ergox365", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 393216, 8192, 511, machine_at_ergox365_init, NULL }, +#endif /* 440ZX */ - /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[i440ZX] MSI MS-6168", "ms6168", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_SOUND,8192, 524288, 8192, 255, machine_at_ms6168_init, NULL }, - /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[i440ZX] Packard Bell Bora Pro", "borapro", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 66666667, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_SOUND,8192, 524288, 8192, 255, machine_at_borapro_init, NULL }, /* SMSC VictoryBX-66 */ - /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[SMSC VictoryBX-66] A-Trend ATC6310BXII","atc6310bxii", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_atc6310bxii_init, NULL }, /* VIA Apollo Pro */ - /* Has the VIA VT82C596B southbridge with on-chip KBC identical to the VIA - VT82C42N. */ { "[VIA Apollo Pro] FIC KA-6130", "ficka6130", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 255, machine_at_ficka6130_init, NULL }, - /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[VIA Apollo Pro133] ASUS P3V133", "p3v133", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1572864, 8192, 255, machine_at_p3v133_init, NULL }, - /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[VIA Apollo Pro133A] ASUS P3V4X", "p3v4x", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,2097152, 8192, 255, machine_at_p3v4x_init, NULL }, /* Slot 1/2 machines */ /* 440GX */ - /* Has a National Semiconductors PC87309 Super I/O chip with on-chip KBC - with most likely AMIKey-2 KBC firmware. */ { "[i440GX] Freeway FW-6400GX", "fw6400gx", MACHINE_TYPE_SLOT1_2, CPU_PKG_SLOT1 | CPU_PKG_SLOT2, 0, 100000000, 150000000, 1800, 3500, 3.0, 8.0, (MACHINE_AGP & ~MACHINE_AT) | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 16384,2080768,16384, 511, machine_at_fw6400gx_init, NULL }, /* Slot 2 machines */ /* 440GX */ - /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[i440GX] Gigabyte GA-6GXU", "6gxu", MACHINE_TYPE_SLOT2, CPU_PKG_SLOT2, 0, 100000000, 133333333, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 16384,2097152,16384, 511, machine_at_6gxu_init, NULL }, - /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[i440GX] SuperMicro Super S2DGE", "s2dge", MACHINE_TYPE_SLOT2, CPU_PKG_SLOT2, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 16384,2097152,16384, 511, machine_at_s2dge_init, NULL }, /* PGA370 machines */ /* 440LX */ - /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[i440LX] SuperMicro Super 370SLM", "s370slm", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 100000000, 1800, 3500, MACHINE_MULTIPLIER_FIXED, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_s370slm_init, NULL }, /* 440BX */ - /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[i440BX] AEWIN AW-O671R", "awo671r", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, /* limits assumed */ MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 255, machine_at_awo671r_init, NULL }, - /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[i440BX] ASUS CUBX", "cubx", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_cubx_init, NULL }, - /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[i440BX] AmazePC AM-BX133", "ambx133", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, /* limits assumed */ MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_ambx133_init, NULL }, - /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[i440BX] Tyan Trinity 371", "trinity371", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_trinity371_init, NULL }, /* 440ZX */ - /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[i440ZX] Soltek SL-63A1", "63a", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 255, machine_at_63a_init, NULL }, /* SMSC VictoryBX-66 */ - /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[SMSC VictoryBX-66] A-Trend ATC7020BXII","atc7020bxii", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_atc7020bxii_init, NULL }, /* VIA Apollo Pro */ - /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA - VT82C42N. */ { "[VIA Apollo Pro] PC Partner APAS3", "apas3", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_apas3_init, NULL }, - /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[VIA Apollo Pro133] ECS P6BAP", "p6bap", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1572864, 8192, 255, machine_at_p6bap_init, NULL }, - /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[VIA Apollo Pro133A] AEWIN WCF-681", "wcf681", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, /* limits assumed */ MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_wcf681_init, NULL }, - /* Has the VIA VT82C686B southbridge with on-chip KBC identical to the VIA - VT82C42N. */ - { "[VIA Apollo Pro133A] ASUS CUV4X-LS", "cuv4xls", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, (MACHINE_AGP & ~MACHINE_AT) | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 16384,1572864, 8192, 255, machine_at_cuv4xls_init, NULL }, - /* Has the VIA VT82C686B southbridge with on-chip KBC identical to the VIA - VT82C42N. */ - { "[VIA Apollo Pro133A] Acorp 6VIA90AP", "6via90ap", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, MACHINE_MULTIPLIER_FIXED, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1572864, 8192, 255, machine_at_6via90ap_init, NULL }, + { "[VIA Apollo Pro133A] ASUS CUV4X-LS", "cuv4xls", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, (MACHINE_AGP & ~MACHINE_AT) | MACHINE_BUS_PS2 | MACHINE_BUS_AC97 | MACHINE_IDE_DUAL,16384,1572864, 8192, 255, machine_at_cuv4xls_init, NULL }, + { "[VIA Apollo Pro133A] Acorp 6VIA90AP", "6via90ap", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, MACHINE_MULTIPLIER_FIXED, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_GAMEPORT, 8192,1572864, 8192, 255, machine_at_6via90ap_init, NULL }, + { "[VIA Apollo ProMedia] Jetway 603TCF", "603tcf", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_603tcf_init, NULL }, /* Miscellaneous/Fake/Hypervisor machines */ - /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ { "[i440BX] Microsoft Virtual PC 2007", "vpc2007", MACHINE_TYPE_MISC, CPU_PKG_SLOT1, CPU_BLOCK(CPU_PENTIUM2, CPU_CYRIX3S), 0, 0, 0, 0, 0, 0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_vpc2007_init, NULL }, { NULL, NULL, MACHINE_TYPE_NONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL } From 5b81bad4e89548f0ba6cd501fb6fc13691183e72 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 4 Aug 2021 09:19:21 +0200 Subject: [PATCH 31/96] And a restoration. --- src/machine/m_at_sockets7.c | 172 ++++++++++++ src/machine/machine_table.c | 527 +++++++++++++++++++++++++++++++----- 2 files changed, 637 insertions(+), 62 deletions(-) diff --git a/src/machine/m_at_sockets7.c b/src/machine/m_at_sockets7.c index ca6c957e2..ba26fdb99 100644 --- a/src/machine/m_at_sockets7.c +++ b/src/machine/m_at_sockets7.c @@ -41,6 +41,178 @@ #include "cpu.h" #include <86box/machine.h> #include <86box/snd_ac97.h> +#include <86box/clock.h> + + +int +machine_at_p5a_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/p5a/1011.005", + 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(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + 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(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 4, 1, 2); + device_add(&ali1541_device); + device_add(&ali1543c_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0xF, 256); + device_add(&w83781d_p5a_device); /* fans: Chassis, CPU, Power; temperatures: MB, unused, CPU */ + + return ret; +} + + +int +machine_at_m579_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/m579/MS6260S_Socket7_ALi_M1542_AMI.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_AGPBRIDGE, 1, 2, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x10, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); + device_add(&ali1541_device); + device_add(&ali1543c_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sst_flash_29ee010_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 128); + + return ret; +} + + +int +machine_at_ga_5aa_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ga-5aa/GA-5AA.F7b", + 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_AGPBRIDGE, 1, 2, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + 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); + device_add(&ali1541_device); + device_add(&ali1543c_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sst_flash_29ee010_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 128); + + return ret; +} + + +int +machine_at_ga_5ax_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ga-5ax/5AX.F4", + 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_AGPBRIDGE, 1, 2, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + 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(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + device_add(&ali1541_device); + device_add(&ali1543c_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sst_flash_29ee010_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 128); + + return ret; +} + + +int +machine_at_ax59pro_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ax59pro/AX59P236.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(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 0, 0); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + + device_add(&via_mvp3_device); + device_add(&via_vt82c586b_device); + device_add(&keyboard_ps2_pci_device); + device_add(&w83877tf_device); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 256); + + return ret; +} int diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index f8a4f3bb7..b6f7d86ec 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -39,10 +39,12 @@ const machine_type_t machine_types[] = { { "8086", MACHINE_TYPE_8086 }, { "80286", MACHINE_TYPE_286 }, { "i386SX", MACHINE_TYPE_386SX }, + { "486SLC", MACHINE_TYPE_486SLC }, { "i386DX", MACHINE_TYPE_386DX }, { "i386DX/i486", MACHINE_TYPE_386DX_486 }, { "i486 (Socket 168 and 1)", MACHINE_TYPE_486 }, - { "i486 (Socket 2 and 3)", MACHINE_TYPE_486_S3 }, + { "i486 (Socket 2)", MACHINE_TYPE_486_S2 }, + { "i486 (Socket 3)", MACHINE_TYPE_486_S3 }, { "i486 (Miscellaneous)", MACHINE_TYPE_486_MISC }, { "Socket 4", MACHINE_TYPE_SOCKET4 }, { "Socket 5", MACHINE_TYPE_SOCKET5 }, @@ -58,6 +60,53 @@ const machine_type_t machine_types[] = { }; +/* Machines to add before machine freeze: + - Jetway J-403TG MR BIOS v2.02; + - Matsonic MS6260S (AMI Super Socket 7 with Aladdin V chipset); + - PCChips M773 (440BX + SMSC with AMI BIOS); + - Rise R418 (was removed on my end, has to be re-added); + - TMC Mycomp PCI54ST; + - Zeos Quadtel 486. + + NOTE: The AMI MegaKey tests were done on a real Intel Advanced/ATX + (thanks, MrKsoft for running my AMIKEY.COM on it), but the + technical specifications of the other Intel machines confirm + that the other boards also have the MegaKey. + + NOTE: The later (ie. not AMI Color) Intel AMI BIOS'es execute a + sequence of commands (B8, BA, BB) during one of the very first + phases of POST, in a way that is only valid on the AMIKey-3 + KBC firmware, that includes the Classic PCI/ED (Ninja) BIOS + which otherwise does not execute any AMI KBC commands, which + indicates that the sequence is a leftover of whatever AMI + BIOS (likely a laptop one since the AMIKey-3 is a laptop KBC + firmware!) Intel forked. + + NOTE: The VIA VT82C42N returns 0x46 ('F') in command 0xA1 (so it + emulates the AMI KF/AMIKey KBC firmware), and 0x42 ('B') in + command 0xAF. + The version on the VIA VT82C686B southbridge also returns + 'F' in command 0xA1, but 0x45 ('E') in command 0xAF. + The version on the VIA VT82C586B southbridge also returns + 'F' in command 0xA1, but 0x44 ('D') in command 0xAF. + The version on the VIA VT82C586A southbridge also returns + 'F' in command 0xA1, but 0x43 ('C') in command 0xAF. + + NOTE: The AMI MegaKey commands blanked in the technical reference + are CC and and C4, which are Set P14 High and Set P14 Low, + respectively. Also, AMI KBC command C1, mysteriously missing + from the technical references of AMI MegaKey and earlier, is + Write Input Port, same as on AMIKey-3. + + Machines to remove: + - Hedaka HED-919; + - A-Trend ATC-1415; + - ECS Elite UM8810PAIO; + - Shuttle HOT-433A; + - Azza 5IVG (if a more interesting machine with Prime3C is found). +*/ + + const machine_t machines[] = { /* 8088 Machines */ { "[8088] IBM PC (1981)", "ibmpc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 16, 64, 16, 0, machine_pc_init, NULL }, @@ -69,10 +118,10 @@ const machine_t machines[] = { { "[8088] AMI XT clone", "amixt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_amixt_init, NULL }, { "[8088] Columbia Data Products MPC-1600", "mpc1600", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 512, 64, 0, machine_xt_mpc1600_init, NULL }, { "[8088] Compaq Portable", "portable", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_compaq_portable_init, NULL }, - { "[8088] DTK XT clone", "dtk", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_dtk_init, NULL }, + { "[8088] DTK PIM-TB10-Z", "dtk", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_dtk_init, NULL }, { "[8088] Eagle PC Spirit", "pcspirit", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_pcspirit_init, NULL }, { "[8088] Generic XT clone", "genxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_genxt_init, NULL }, - { "[8088] Juko XT clone", "jukopc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_jukopc_init, NULL }, + { "[8088] Juko ST", "jukopc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_jukopc_init, NULL }, { "[8088] Multitech PC-700", "pc700", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_pc700_init, NULL }, { "[8088] NCR PC4i", "pc4i", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_pc4i_init, NULL }, { "[8088] Olivetti M19", "m19", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 4772728, 7159092, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 256, 640, 256, 0, machine_xt_m19_init, m19_get_device }, @@ -87,6 +136,7 @@ const machine_t machines[] = { #if defined(DEV_BRANCH) && defined(USE_LASERXT) { "[8088] VTech Laser Turbo XT", "ltxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_laserxt_init, NULL }, #endif + /* Has a standard PS/2 KBC (so, use IBM PS/2 Type 1). */ { "[8088] Xi8088", "xi8088", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2, 64, 1024, 128, 127, machine_xt_xi8088_init, xi8088_get_device }, { "[8088] Zenith Data Systems Z-151/152/161","zdsz151", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_z151_init, NULL }, { "[8088] Zenith Data Systems Z-159", "zdsz159", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_z159_init, NULL }, @@ -102,6 +152,7 @@ const machine_t machines[] = { { "[8086] Amstrad PPC512/640", "ppc512", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO | MACHINE_MOUSE | MACHINE_NONMI, 512, 640, 128, 63, machine_ppc512_init, ppc512_get_device }, { "[8086] Compaq Deskpro", "deskpro", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_compaq_deskpro_init, NULL }, { "[8086] Olivetti M21/24/24SP", "m24", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO | MACHINE_MOUSE, 128, 640, 128, 0, machine_xt_m24_init, m24_get_device }, + /* Has Olivetti KBC firmware. */ { "[8086] Olivetti M240", "m240", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_m240_init, NULL }, { "[8086] Schetmash Iskra-3104", "iskra3104", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_iskra3104_init, NULL }, { "[8086] Tandy 1000 SL/2", "tandy1000sl2", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 512, 768, 128, 0, machine_tandy1000sl2_init, tandy1k_sl_get_device }, @@ -111,360 +162,712 @@ const machine_t machines[] = { { "[8086] VTech Laser XT3", "lxt3", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_lxt3_init, NULL }, #endif - /* 286 XT machines */ -#if defined(DEV_BRANCH) && defined(USE_HEDAKA) - { "[Citygate D30 XT] Hedaka HED-919", "hed919", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 1024, 64, 0, machine_xt_hed919_init, NULL }, -#endif - /* 286 AT machines */ + /* Has IBM AT KBC firmware. */ { "[ISA] IBM AT", "ibmat", MACHINE_TYPE_286, CPU_PKG_286, 0, 6000000, 8000000, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_ibm_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[ISA] IBM PS/1 model 2011", "ibmps1es", MACHINE_TYPE_286, CPU_PKG_286, 0, 10000000, 10000000, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_XTA | MACHINE_VIDEO_FIXED, 512, 16384, 512, 63, machine_ps1_m2011_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[ISA] IBM PS/2 model 30-286", "ibmps2_m30_286", MACHINE_TYPE_286, CPU_PKG_286 | CPU_PKG_486SLC_IBM, 0, 10000000, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_XTA | MACHINE_VIDEO_FIXED, 1024, 16384,1024, 127, machine_ps2_m30_286_init, NULL }, + /* Has IBM AT KBC firmware. */ { "[ISA] IBM XT Model 286", "ibmxt286", MACHINE_TYPE_286, CPU_PKG_286, 0, 6000000, 6000000, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 127, machine_at_ibmxt286_init, NULL }, + /* AMI BIOS for a chipset-less machine, most likely has AMI 'F' KBC firmware. */ { "[ISA] AMI IBM AT", "ibmatami", MACHINE_TYPE_286, CPU_PKG_286, 0, 6000000, 8000000, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_ibmatami_init, NULL }, + /* Uses Commodore (CBM) KBC firmware, to be implemented as identical to the + IBM AT KBC firmware unless evidence emerges of any proprietary commands. */ { "[ISA] Commodore PC 30 III", "cmdpc30", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 640, 16384, 128, 127, machine_at_cmdpc_init, NULL }, + /* Uses Compaq KBC firmware. */ { "[ISA] Compaq Portable II", "portableii", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 640, 16384, 128, 127, machine_at_portableii_init, NULL }, + /* Uses Compaq KBC firmware. */ { "[ISA] Compaq Portable III", "portableiii", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_VIDEO, 640, 16384, 128, 127, machine_at_portableiii_init, at_cpqiii_get_device }, + /* Has IBM AT KBC firmware. */ { "[ISA] MR 286 clone", "mr286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 512, 16384, 128, 127, machine_at_mr286_init, NULL }, + /* Has IBM AT KBC firmware. */ { "[ISA] NCR PC8/810/710/3390/3392", "pc8", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_pc8_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_OLIVETTI) + /* Has Olivetti KBC firmware. */ { "[ISA] Olivetti M290", "m290", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 640, 16384, 128, 127, machine_at_m290_init, NULL }, #endif - #if defined(DEV_BRANCH) && defined(USE_OPEN_AT) +#if defined(DEV_BRANCH) && defined(USE_OPEN_AT) + /* Has IBM AT KBC firmware. */ { "[ISA] OpenAT", "openat", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_openat_init, NULL }, #endif + /* Has IBM AT KBC firmware. */ { "[ISA] Phoenix IBM AT", "ibmatpx", MACHINE_TYPE_286, CPU_PKG_286, 0, 6000000, 8000000, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_ibmatpx_init, NULL }, + /* Has Quadtel KBC firmware. */ { "[ISA] Quadtel IBM AT", "ibmatquadtel", MACHINE_TYPE_286, CPU_PKG_286, 0, 6000000, 8000000, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_ibmatquadtel_init, NULL }, + /* This has a Siemens proprietary KBC which is completely undocumented. */ { "[ISA] Siemens PCD-2L", "siemens", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_siemens_init, NULL }, + /* This has Toshiba's proprietary KBC, which is already implemented. */ { "[ISA] Toshiba T3100e", "t3100e", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_VIDEO_FIXED, 1024, 5120, 256, 63, machine_at_t3100e_init, NULL }, + /* Has Quadtel KBC firmware. */ { "[GC103] Quadtel 286 clone", "quadt286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_quadt286_init, NULL }, + /* Most likely has AMI 'F' KBC firmware. */ { "[GC103] Trigem 286M", "tg286m", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 512, 8192, 128, 127, machine_at_tg286m_init, NULL }, - { "[NEAT] AMI 286 clone", "ami286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_neat_ami_init, NULL }, + /* This has "AMI KEYBOARD BIOS", most likely 'F'. */ + { "[NEAT] Dataexpert 286", "ami286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_neat_ami_init, NULL }, + /* Has IBM AT KBC firmware. */ { "[NEAT] NCR 3302", "3302", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_VIDEO, 512, 16384, 128, 127, machine_at_3302_init, NULL }, + /* Has IBM AT KBC firmware. */ { "[NEAT] Phoenix 286 clone", "px286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_px286_init, NULL }, - { "[SCAT] Award 286 clone", "award286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_award286_init, NULL }, + /* Has Chips & Technologies KBC firmware. */ { "[SCAT] GW-286CT GEAR", "gw286ct", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 512, 16384, 128, 127, machine_at_gw286ct_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[SCAT] Goldstar GDC-212M", "gdc212m", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_BUS_PS2, 512, 4096, 512, 127, machine_at_gdc212m_init, NULL }, + /* Has a VIA VT82C42N KBC. */ + { "[SCAT] Hyundai Solomon 286KP", "award286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_award286_init, NULL }, + /* Has a VIA VT82C42N KBC. */ { "[SCAT] Hyundai Super-286TR", "super286tr", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_super286tr_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[SCAT] Samsung SPC-4200P", "spc4200p", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2, 512, 2048, 128, 127, machine_at_spc4200p_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[SCAT] Samsung SPC-4216P", "spc4216p", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2, 1024, 5120,1024, 127, machine_at_spc4216p_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[SCAT] Samsung SPC-4620P", "spc4620p", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 5120,1024, 127, machine_at_spc4620p_init, NULL }, + /* Has IBM AT KBC firmware. */ { "[SCAT] Samsung Deskmaster 286", "deskmaster286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_deskmaster286_init, NULL }, /* 286 machines that utilize the MCA bus */ + /* Has IBM PS/2 Type 2 KBC firmware. */ { "[MCA] IBM PS/2 model 50", "ibmps2_m50", MACHINE_TYPE_286, CPU_PKG_286 | CPU_PKG_486SLC_IBM, 0, 10000000, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 10240,1024, 63, machine_ps2_model_50_init, NULL }, /* 386SX machines */ - { "[ISA] IBM PS/1 model 2121", "ibmps1_2121", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO_FIXED, 2048, 6144,1024, 63, machine_ps1_m2121_init, NULL }, - { "[ISA] IBM PS/1 m.2121+ISA", "ibmps1_2121_isa", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 6144,1024, 63, machine_ps1_m2121_init, NULL }, - { "[ISA] NCR PC916SX", "pc916sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 128, 127, machine_at_pc916sx_init, NULL }, + /* ISA slots available because an official IBM expansion for that existed. */ + /* Has IBM PS/2 Type 1 KBC firmware. */ + { "[ISA] IBM PS/1 model 2121", "ibmps1_2121", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 6144,1024, 63, machine_ps1_m2121_init, NULL }, + /* Has IBM AT KBC firmware. */ + { "[ISA] NCR PC916SX", "pc916sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 128, 127, machine_at_pc916sx_init, NULL }, + /* Has Quadtel KBC firmware. */ + { "[ISA] QTC-SXM KT X20T02/HI", "quadt386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 128, 127, machine_at_quadt386sx_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_M6117) + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[ALi M6117] Acrosser AR-B1375", "arb1375", MACHINE_TYPE_386SX, CPU_PKG_M6117, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768,1024, 127, machine_at_arb1375_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[ALi M6117] Acrosser PJ-A511M", "pja511m", MACHINE_TYPE_386SX, CPU_PKG_M6117, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768,1024, 127, machine_at_pja511m_init, NULL }, #endif - { "[ALi M1217] Flytech 386", "flytech386", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 16384, 1024, 127, machine_at_flytech386_init, at_flytech386_get_device }, + /* 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. */ + { "[ALi M1217] Flytech 386", "flytech386", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 16384, 1024, 127, machine_at_flytech386_init, at_flytech386_get_device }, + /* 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. */ { "[HT18] AMA-932J", "ama932j", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_VIDEO, 512, 8192, 128, 127, machine_at_ama932j_init, at_ama932j_get_device }, - { "[Intel 82335] ADI 386SX", "adi386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_adi386sx_init, NULL }, + /* Has an unknown KBC firmware with commands B8 and BB in the style of + Phoenix MultiKey and AMIKey-3(!), but also commands E1 and EA with + unknown functions. */ + { "[Intel 82335 ADI 386SX", "adi386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_adi386sx_init, NULL }, + /* Has an AMI Keyboard BIOS PLUS KBC firmware ('8'). */ { "[Intel 82335] Shuttle 386SX", "shuttle386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_shuttle386sx_init, NULL }, + /* Uses Commodore (CBM) KBC firmware, to be implemented as identical to + the IBM PS/2 Type 1 KBC firmware unless evidence emerges of any + proprietary commands. */ { "[NEAT] Commodore SL386SX-16", "cmdsl386sx16", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 8192, 512, 127, machine_at_cmdsl386sx16_init, NULL }, + /* Has IBM AT KBC firmware. */ { "[NEAT] DTK 386SX clone", "dtk386", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_neat_init, NULL }, - { "[OPTi 283] Olivetti M300-08", "m30008", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 20000000, 20000000, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 16384, 2048, 127, machine_at_m30008_init, at_m30008_get_device }, - { "[OPTi 283] Olivetti M300-15", "m30015", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 25000000, 25000000, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 16384, 2048, 127, machine_at_m30015_init, NULL }, + /* Has IBM AT KBC firmware. */ { "[OPTi 291] DTK PPM-3333P", "awardsx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_awardsx_init, NULL }, + /* Uses Commodore (CBM) KBC firmware, to be implemented as identical to + the IBM PS/2 Type 1 KBC firmware unless evidence emerges of any + proprietary commands. */ { "[SCAMP] Commodore SL386SX-25", "cmdsl386sx25", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 8192, 512, 127, machine_at_cmdsl386sx25_init, at_cmdsl386sx25_get_device }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[SCAMP] Samsung SPC-6033P", "spc6033p", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 12288, 2048, 127, machine_at_spc6033p_init, at_spc6033p_get_device }, + /* Has an unknown AMI KBC firmware, I'm going to assume 'F' until a + photo or real hardware BIOS string is found. */ { "[SCAT] KMX-C-02", "kmxc02", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 512, 127, machine_at_kmxc02_init, NULL }, + /* Has Quadtel KBC firmware. */ { "[WD76C10] Amstrad MegaPC", "megapc", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 32768, 1024, 127, machine_at_wd76c10_init, NULL }, /* 386SX machines which utilize the MCA bus */ + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[MCA] IBM PS/2 model 55SX", "ibmps2_m55sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 8192, 1024, 63, machine_ps2_model_55sx_init, NULL }, + /* 486SLC machines */ + /* 486SLC machines with just the ISA slot */ + /* Has AMIKey H KBC firmware. */ + { "[OPTi 283] RYC Leopard LX", "rycleopardlx", MACHINE_TYPE_486SLC, CPU_PKG_486SLC_IBM, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 16384, 1024, 127, machine_at_rycleopardlx_init, NULL }, + /* 386DX machines */ { "[ACC 2168] AMI 386DX clone", "acc386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_acc386_init, NULL }, + /* Has an AMI Keyboard BIOS PLUS KBC firmware ('8'). */ { "[C&T 386] ECS 386/32", "ecs386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_ecs386_init, NULL }, { "[C&T 386] Samsung SPC-6000A", "spc6000a", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_spc6000a_init, NULL }, + /* Uses Compaq KBC firmware. */ { "[ISA] Compaq Portable III (386)", "portableiii386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_VIDEO, 1024, 14336, 1024, 127, machine_at_portableiii386_init, at_cpqiii_get_device }, - { "[ISA] Micronics 386 clone", "micronics386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_micronics386_init, NULL }, - { "[SiS 310] ASUS ISA-386C", "asus386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_asus386_init, NULL }, + /* Has IBM AT KBC firmware. */ + { "[ISA] Micronics 09-00021", "micronics386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_micronics386_init, NULL }, + /* Has AMIKey F KBC firmware. */ + { "[SiS 310] ASUS ISA-386C", "asus386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 32768, 1024, 127, machine_at_asus386_init, NULL }, /* 386DX machines which utilize the MCA bus */ + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[MCA] IBM PS/2 model 70 (type 3)", "ibmps2_m70_type3", MACHINE_TYPE_386DX, CPU_PKG_386DX | CPU_PKG_486BL, 0, 0, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 2048, 16384, 2048, 63, machine_ps2_model_70_type3_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[MCA] IBM PS/2 model 80", "ibmps2_m80", MACHINE_TYPE_386DX, CPU_PKG_386DX | CPU_PKG_486BL, 0, 0, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 12288, 1024, 63, machine_ps2_model_80_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[MCA] IBM PS/2 model 80 (type 3)", "ibmps2_m80_type3", MACHINE_TYPE_386DX, CPU_PKG_386DX | CPU_PKG_486BL, 0, 0, 0, 0, 0, 0, 0, MACHINE_MCA | MACHINE_BUS_PS2 | MACHINE_VIDEO, 2048, 12288, 2048, 63, machine_ps2_model_80_axx_init, NULL }, /* 386DX/486 machines */ - { "[OPTi 495] Award 486 clone", "award486", MACHINE_TYPE_386DX_486, CPU_PKG_386DX | CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_init, NULL }, - { "[OPTi 495] Dataexpert SX495 (486)", "ami486", MACHINE_TYPE_386DX_486, CPU_PKG_386DX | CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_ami_init, NULL }, - { "[OPTi 495] MR 486 clone", "mr486", MACHINE_TYPE_386DX_486, CPU_PKG_386DX | CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_mr_init, NULL }, + /* The BIOS sends commands C9 without a parameter and D5, both of which are + Phoenix MultiKey commands. */ + { "[OPTi 495] Award 486 clone", "award495", MACHINE_TYPE_386DX_486, CPU_PKG_386DX | CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_init, NULL }, + /* Has AMIKey F KBC firmware. */ + { "[OPTi 495] Dataexpert SX495", "ami495", MACHINE_TYPE_386DX_486, CPU_PKG_386DX | CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_ami_init, NULL }, + /* Has AMIKey F KBC firmware (it's just the MR BIOS for the above machine). */ + { "[OPTi 495] Dataexpert SX495 (MR BIOS)", "mr495", MACHINE_TYPE_386DX_486, CPU_PKG_386DX | CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_mr_init, NULL }, /* 486 machines - Socket 1 */ + /* Has JetKey 5 KBC Firmware which looks like it is a clone of AMIKey type F. + It also has those Ex commands also seen on the VIA VT82C42N (the BIOS + supposedly sends command EF. + The board was also seen in 2003 with a -H string - perhaps someone swapped + the KBC? */ { "[ALi M1429] Olystar LIL1429", "ali1429", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_ali1429_init, NULL }, + /* Has JetKey 5 KBC Firmware - but the BIOS string ends in a hardcoded -F, and + the BIOS also explicitly expects command A1 to return a 'F', so it looks like + the JetKey 5 is a clone of AMIKey type F. */ { "[CS4031] AMI 486 CS4031", "cs4031", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_cs4031_init, NULL }, - { "[ETEQ ET6000] Olivetti PCS-46C", "pcs46c", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE | MACHINE_VIDEO, 4096, 32768, 4096, 127, machine_at_pcs46c_init, at_pcs46c_get_device }, + /* Uses some variant of Phoenix MultiKey/42 as the Intel 8242 chip has a Phoenix + copyright. */ { "[OPTi 895] Mylex MVI486", "mvi486", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE_DUAL, 1024, 65536, 1024, 127, machine_at_mvi486_init, NULL }, + /* Has AMI KF KBC firmware. */ + { "[SiS 401] ASUS ISA-486", "isa486", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_isa486_init, NULL }, + /* Has AMIKey H KBC firmware, per the screenshot in "How computers & MS-DOS work". */ + { "[SiS 401] Chaintech 433SC", "sis401", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_sis401_init, NULL }, + /* Has AMIKey F KBC firmware, per a photo of a monitor with the BIOS screen on + eBay. */ + { "[SiS 460] ABIT AV4", "av4", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_av4_init, NULL }, + /* Has a MR (!) KBC firmware, which is a clone of the standard IBM PS/2 KBC firmware. */ + { "[SiS 471] SiS VL-BUS 471 REV. A1", "px471", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024,131072, 1024, 127, machine_at_px471_init, NULL }, + /* The chip is a Lance LT38C41, a clone of the Intel 8041, and the BIOS sends + commands BC, BD, and C9 which exist on both AMIKey and Phoenix MultiKey/42, + but it does not write a byte after C9, which is consistent with AMIKey, so + this must have some form of AMIKey. */ { "[VIA VT82C495] FIC 486-VC-HD", "486vchd", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 64512, 1024, 127, machine_at_486vchd_init, 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. */ { "[VLSI 82C480] HP Vectra 486VL", "vect486vl", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 32768, 2048, 127, machine_at_vect486vl_init, at_vect486vl_get_device }, - { "[VLSI 82C481] Siemens Nixdorf D824", "d824", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 32768, 2048, 127, machine_at_d824_init, at_d824_get_device }, + /* Has a standard IBM PS/2 KBC firmware or a clone thereof. */ + { "[VLSI 82C481] Siemens Nixdorf D824", "d824", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 32768, 2048, 127, machine_at_d824_init, at_d824_get_device }, + + /* 486 machines - Socket 2 */ + /* 486 machines with just the ISA slot */ + /* Uses some variant of Phoenix MultiKey/42 as the BIOS sends keyboard controller + command C7 (OR input byte with received data byte). */ + { "[ACC 2168] Packard Bell PB410A", "pb410a", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 4096, 36864, 1024, 127, machine_at_pb410a_init, NULL }, + /* Uses an ACER/NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware (V4.01H). */ + { "[ALi M1429G] Acer A1G", "acera1g", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 4096, 36864, 1024, 127, machine_at_acera1g_init, at_acera1g_get_device }, + /* There are two similar BIOS strings with -H, and one with -U, so I'm going to + give it an AMIKey H KBC firmware. */ + { "[ALi M1429G] AMI WinBIOS 486", "win486", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_winbios1429_init, NULL }, + /* Uses an Intel KBC with Phoenix MultiKey KBC firmware. */ + { "[SiS 461] DEC DECpc LPV", "decpc_lpv", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 1024, 32768, 1024, 127, machine_at_decpc_lpv_init, NULL }, + /* Uses an NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware. */ + { "[SiS 461] Acer V10", "acerv10", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 1024, 32768, 1024, 127, machine_at_acerv10_init, 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. */ + { "[SiS 461] IBM PS/ValuePoint 433DX/Si", "valuepoint433", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 65536, 1024, 127, machine_at_valuepoint433_init, 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. */ + { "[SiS 471] ABit AB-AH4", "win471", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_win471_init, NULL }, /* 486 machines - Socket 3 */ /* 486 machines with just the ISA slot */ - { "[ACC 2168] Packard Bell PB410A", "pb410a", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 4096, 36864, 1024, 127, machine_at_pb410a_init, NULL }, - { "[ALi M1429G] Acer A1G", "acera1g", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 4096, 36864, 1024, 127, machine_at_acera1g_init, at_acera1g_get_device }, - { "[ALi M1429] AMI WinBIOS 486", "win486", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_winbios1429_init, NULL }, + /* Has AMI MegaKey KBC firmware. */ + { "[Contaq 82C597] Green-B", "green-b", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_green_b_init, NULL }, + /* Has a VIA VT82C42N KBC. */ { "[OPTi 895] Jetway J-403TG", "403tg", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_403tg_init, NULL }, - { "[SiS 401] AMI 486 Clone", "sis401", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_sis401_init, NULL }, - { "[SiS 401] ASUS ISA-486", "isa486", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_isa486_init, NULL }, - { "[SiS 460] ABIT AV4", "av4", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_av4_init, NULL }, - { "[SiS 461] IBM PS/ValuePoint 433DX/Si", "valuepoint433", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 65536, 1024, 127, machine_at_valuepoint433_init, NULL }, - { "[SiS 471] AMI 486 Clone", "ami471", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_ami471_init, NULL }, - { "[SiS 471] AMI WinBIOS 486 clone", "win471", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_win471_init, NULL }, + /* Has JetKey 5 KBC Firmware which looks like it is a clone of AMIKey type F. */ + { "[OPTi 895] Jetway J-403TG Rev D", "403tg_rev_d", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_403tg_rev_d_init, NULL }, + /* Has JetKey 5 KBC Firmware which looks like it is a clone of AMIKey type F. */ + { "[OPTi 895] Jetway J-403TG Rev D (MR BIOS)","403tg_rev_d_mr", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_403tg_rev_d_mr_init, NULL }, + /* Has AMIKey H keyboard BIOS. */ { "[SiS 471] AOpen Vi15G", "vi15g", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_vi15g_init, NULL }, - { "[SiS 471] ASUS VL/I-486SV2G (GX4)", "vli486sv2g", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE_DUAL, 1024, 65536, 1024, 127, machine_at_vli486sv2g_init, NULL }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ + { "[SiS 471] ASUS VL/I-486SV2G (GX4)", "vli486sv2g", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 65536, 1024, 127, machine_at_vli486sv2g_init, NULL }, + /* Has JetKey 5 KBC Firmware which looks like it is a clone of AMIKey type F. */ { "[SiS 471] DTK PKM-0038S E-2", "dtk486", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_dtk486_init, NULL }, - { "[SiS 471] Phoenix SiS 471", "px471", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024,131072, 1024, 127, machine_at_px471_init, NULL }, + /* Unknown Epox VLB Socket 3 board, has AMIKey F keyboard BIOS. */ + { "[SiS 471] Epox 486SX/DX Green", "ami471", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_ami471_init, NULL }, /* 486 machines which utilize the PCI bus */ + /* Has the ALi M1487/9's on-chip keyboard controller which clones a standard AT + KBC. */ { "[ALi M1489] ABIT AB-PB4", "abpb4", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_abpb4_init, NULL }, + /* Has the ALi M1487/9's on-chip keyboard controller which clones a standard AT + KBC. + The BIOS string always ends in -U, but the BIOS will send AMIKey commands 0xCA + and 0xCB if command 0xA1 returns a letter in the 0x5x or 0x7x ranges, so I'm + going to give it an AMI 'U' KBC. */ { "[ALi M1489] AMI WinBIOS 486 PCI", "win486pci", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_win486pci_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[OPTi 802G] IBM PC 330 (type 6573)", "pc330_6573", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3_PC330, 0, 25000000, 33333333, 0, 0, 2.0, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_pc330_6573_init, NULL }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[i420EX] ASUS PVI-486AP4", "486ap4", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_IDE_DUAL, 1024, 131072, 1024, 127, machine_at_486ap4_init, NULL }, + /* This has the Phoenix MultiKey KBC firmware. */ + { "[i420EX] Intel Classic/PCI ED", "ninja", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 131072, 1024, 127, machine_at_ninja_init, NULL }, + /* This has an AMIKey-2, which is an updated version of type 'H'. Also has a + SST 29EE010 Flash chip. */ { "[i420ZX] ASUS PCI/I-486SP3G", "486sp3g", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL | MACHINE_SCSI, 1024, 131072, 1024, 127, machine_at_486sp3g_init, NULL }, + /* I'm going to assume this as an AMIKey-2 like the other two 486SP3's. */ { "[i420TX] ASUS PCI/I-486SP3", "486sp3", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL | MACHINE_SCSI, 1024, 131072, 1024, 127, machine_at_486sp3_init, NULL }, + /* This has the Phoenix MultiKey KBC firmware. */ { "[i420TX] Intel Classic/PCI", "alfredo", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_alfredo_init, NULL }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[SiS 496] ASUS PVI-486SP3C", "486sp3c", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_IDE_DUAL, 1024, 261120, 1024, 255, machine_at_486sp3c_init, NULL }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[SiS 496] Lucky Star LS-486E", "ls486e", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_ls486e_init, NULL }, + /* The BIOS does not send a single non-standard KBC command, so it has a standard PS/2 KBC. */ { "[SiS 496] Micronics M4Li", "m4li", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 131072, 1024, 127, machine_at_m4li_init, NULL }, + /* Has a BestKey KBC which clones AMI type 'H'. */ { "[SiS 496] Rise Computer R418", "r418", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 261120, 1024, 255, machine_at_r418_init, NULL }, + /* This has a Holtek 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. */ { "[SiS 496] Soyo 4SA2", "4sa2", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, CPU_BLOCK(CPU_i486SX, CPU_i486DX, CPU_Am486SX, CPU_Am486DX), 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 261120, 1024, 255, machine_at_4sa2_init, NULL }, + /* According to MrKsoft, his real 4DPS has an AMIKey-2, which is an updated version + of type 'H'. */ { "[SiS 496] Zida Tomato 4DP", "4dps", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 261120, 1024, 255, machine_at_4dps_init, NULL }, - { "[UMC 8881] A-Trend ATC-1415", "atc1415", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_atc1415_init, NULL }, - { "[UMC 8881] ECS Elite UM8810PAIO", "ecs486", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_ecs486_init, NULL }, - { "[UMC 8881] Shuttle HOT-433A", "hot433", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 262144, 1024, 255, machine_at_hot433_init, NULL }, + /* Has a VIA VT82C406 KBC+RTC that likely has identical commands to the VT82C42N. */ + { "[VIA VT82C496G] DFI G486VPA", "g486vpa", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_g486vpa_init, NULL }, + /* Has a VIA VT82C42N KBC. */ { "[VIA VT82C496G] FIC VIP-IO2", "486vipio2", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_486vipio2_init, NULL }, /* 486 machines - Miscellaneous */ - /* 486 machines with just the ISA slot */ - { "[OPTi 283] RYC Leopard LX", "rycleopardlx", MACHINE_TYPE_486_MISC, CPU_PKG_486SLC_IBM, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 16384, 1024, 127, machine_at_rycleopardlx_init, NULL }, - /* 486 machines which utilize the PCI bus */ + /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[STPC Client] ITOX STAR", "itoxstar", MACHINE_TYPE_486_MISC, CPU_PKG_STPC, 0, 66666667, 75000000, 0, 0, 1.0, 1.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 255, machine_at_itoxstar_init, NULL }, + /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[STPC Consumer-II] Acrosser AR-B1479", "arb1479", MACHINE_TYPE_486_MISC, CPU_PKG_STPC, 0, 66666667, 66666667, 0, 0, 2.0, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 32768, 163840, 8192, 255, machine_at_arb1479_init, NULL }, + /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[STPC Elite] Advantech PCM-9340", "pcm9340", MACHINE_TYPE_486_MISC, CPU_PKG_STPC, 0, 66666667, 66666667, 0, 0, 2.0, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 32768, 98304, 8192, 255, machine_at_pcm9340_init, NULL }, + /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[STPC Atlas] AAEON PCM-5330", "pcm5330", MACHINE_TYPE_486_MISC, CPU_PKG_STPC, 0, 66666667, 66666667, 0, 0, 2.0, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 32768, 131072,32768, 255, machine_at_pcm5330_init, NULL }, /* Socket 4 machines */ /* 430LX */ + /* Has AMIKey F KBC firmware (AMIKey). */ { "[i430LX] ASUS P/I-P5MP3", "p5mp3", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE, 2048, 196608, 2048, 127, machine_at_p5mp3_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[i430LX] Dell Dimension XPS P60", "dellxp60", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE, 2048, 131072, 2048, 127, machine_at_dellxp60_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[i430LX] Dell OptiPlex 560/L", "opti560l", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_opti560l_init, NULL }, + /* This has the Phoenix MultiKey KBC firmware. + This is basically an Intel Batman (*NOT* Batman's Revenge) with a fancier + POST screen */ { "[i430LX] AMBRA DP60 PCI", "ambradp60", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_ambradp60_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ { "[i430LX] IBM PS/ValuePoint P60", "valuepointp60", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_valuepointp60_init, NULL }, - { "[i430LX] Intel Premiere/PCI", "revenge", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_batman_init, NULL }, + /* This has the Phoenix MultiKey KBC firmware. */ + { "[i430LX] Intel Premiere/PCI", "revenge", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_revenge_init, NULL }, + /* Has AMI MegaKey KBC firmware. */ { "[i430LX] Micro Star 586MC1", "586mc1", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_586mc1_init, NULL }, + /* This has the Phoenix MultiKey KBC firmware. */ { "[i430LX] Packard Bell PB520R", "pb520r", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 139264, 2048, 127, machine_at_pb520r_init, at_pb520r_get_device }, /* OPTi 596/597 */ + /* This uses an AMI KBC firmware in PS/2 mode (it sends command A5 with the + PS/2 "Load Security" meaning), most likely MegaKey as it sends command AF + (Set Extended Controller RAM) just like the later Intel AMI BIOS'es. */ { "[OPTi 597] AMI Excalibur VLB", "excalibur", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_VLB | MACHINE_IDE, 2048, 65536, 2048, 127, machine_at_excalibur_init, NULL }, + /* OPTi 596/597/822 */ + /* This has AMIKey 'F' KBC firmware. */ + { "[OPTi 597] Supermicro P5VL-PCI", "p5vl", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_VLB, 8192, 131072, 8192, 127, machine_at_p5vl_init, NULL }, + /* SiS 85C50x */ + /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[SiS 85C50x] ASUS PCI/I-P5SP4", "p5sp4", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p5sp4_init, NULL }, /* Socket 5 machines */ /* 430NX */ + /* This has the Phoenix MultiKey KBC firmware. */ { "[i430NX] Intel Premiere/PCI II", "plato", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_plato_init, NULL }, + /* This has the Phoenix MultiKey KBC firmware. + This is basically an Intel Premiere/PCI II with a fancier POST screen. */ { "[i430NX] AMBRA DP90 PCI", "ambradp90", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_ambradp90_init, NULL }, + /* Has AMI MegaKey KBC firmware. */ { "[i430NX] Gigabyte GA-586IP", "430nx", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_430nx_init, NULL }, /* 430FX */ + /* Uses an ACER/NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware (V5.0). */ { "[i430FX] Acer V30", "acerv30", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_acerv30_init, NULL }, + /* Has AMIKey F KBC firmware. */ { "[i430FX] AMI Apollo", "apollo", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_apollo_init, NULL }, + /* Has AMIKey H KBC firmware. */ + { "[i430FX] Dataexpert EXP8551", "exp8551", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_exp8551_init, NULL }, + /* The BIOS does not send a single non-standard KBC command, but the board has a SMC Super I/O + chip with on-chip KBC and AMI MegaKey KBC firmware. */ { "[i430FX] HP Vectra VL 5 Series 4", "vectra54", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 511, machine_at_vectra54_init, at_vectra54_get_device }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430FX] Intel Advanced/ZP", "zappa", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_zappa_init, NULL }, + /* The BIOS sends KBC command B3 which indicates an AMI (or VIA VT82C42N) KBC. */ { "[i430FX] NEC PowerMate V", "powermatev", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_powermatev_init, NULL }, + /* Has a VIA VT82C42N KBC. */ { "[i430FX] PC Partner MB500N", "mb500n", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_mb500n_init, NULL }, + /* Has AMIKey Z(!) KBC firmware. */ + { "[i430FX] Trigem Hawk", "hawk", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_hawk_init, NULL }, /* OPTi 596/597 */ + /* This uses an AMI KBC firmware in PS/2 mode (it sends command A5 with the + PS/2 "Load Security" meaning), most likely MegaKey as it sends command AF + (Set Extended Controller RAM) just like the later Intel AMI BIOS'es. */ { "[OPTi 597] TMC PAT54PV", "pat54pv", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_K5, CPU_5K86), 50000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_VLB, 2048, 65536, 2048, 127, machine_at_pat54pv_init, NULL }, /* OPTi 596/597/822 */ { "[OPTi 597] Shuttle HOT-543", "hot543", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_VLB, 8192, 131072, 8192, 127, machine_at_hot543_init, NULL }, - { "[OPTi 597] Supermicro P54VL-PCI", "p54vl", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_VLB, 8192, 131072, 8192, 127, machine_at_p54vl_init, NULL }, /* SiS 85C50x */ + /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[SiS 85C50x] ASUS PCI/I-P54SP4", "p54sp4", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_K5, CPU_5K86), 40000000, 66666667, 3380, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p54sp4_init, NULL }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[SiS 85C50x] BCM SQ-588", "sq588", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_PENTIUMMMX), 50000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_sq588_init, NULL }, - /* UMC 889x */ - { "[UMC 889x] Shuttle HOT-539", "hot539", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_K5, CPU_5K86), 40000000, 66666667, 3380, 3600, 1.5, 2.0, MACHINE_PCI | MACHINE_IDE_DUAL, 8192, 262144, 8192, 127, machine_at_hot539_init, NULL }, - /* Socket 7 (Single Voltage) machines */ /* 430FX */ + /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[i430FX] ASUS P/I-P54TP4XE", "p54tp4xe", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3600, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p54tp4xe_init, NULL }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[i430FX] ASUS P/I-P54TP4XE (MR BIOS)", "mr586", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3600, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_mr586_init, NULL }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430FX] Gateway 2000 Thor", "gw2katx", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_gw2katx_init, NULL }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430FX] Intel Advanced/ATX", "thor", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_thor_init, NULL }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430FX] Intel Advanced/ATX (MR BIOS)", "mrthor", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_mrthor_init, NULL }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430FX] Intel Advanced/EV", "endeavor", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_endeavor_init, at_endeavor_get_device }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ + { "[i430FX] MSI MS-5119", "ms5119", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_ms5119_init, NULL }, + /* This most likely uses AMI MegaKey KBC firmware as well due to having the same + Super I/O chip (that has the KBC firmware on it) as eg. the Advanced/EV. */ { "[i430FX] Packard Bell PB640", "pb640", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_pb640_init, at_pb640_get_device }, - { "[i430FX] QDI Chariot", "chariot", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_WINCHIP, CPU_WINCHIP2, CPU_Cx6x86, CPU_Cx6x86L, CPU_Cx6x86MX), 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_chariot_init, NULL }, + /* Has an AMI 'H' KBC firmware (1992). */ + { "[i430FX] QDI FMB", "fmb", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_WINCHIP, CPU_WINCHIP2, CPU_Cx6x86, CPU_Cx6x86L, CPU_Cx6x86MX), 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_fmb_init, NULL }, /* 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. */ { "[i430HX] Acer M3A", "acerm3a", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3300, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 196608, 8192, 127, machine_at_acerm3a_init, NULL }, + /* Has AMIKey F KBC firmware. */ { "[i430HX] AOpen AP53", "ap53", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3450, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_ap53_init, NULL }, + /* [TEST] Has a VIA 82C42N KBC, with AMIKey F KBC firmware. */ { "[i430HX] Biostar MB-8500TUC", "8500tuc", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_8500tuc_init, 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. */ { "[i430HX] SuperMicro Super P55T2S", "p55t2s", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3300, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 127, machine_at_p55t2s_init, NULL }, /* 430VX */ + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430VX] Gateway 2000 Tigereye", "gw2kte", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_gw2kte_init, NULL }, /* SiS 5511 */ - { "[SiS 5511] AOpen AP5S", "ap5s", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_ap5s_init, NULL }, + /* Has AMIKey H KBC firmware (AMIKey-2). */ + { "[SiS 5511] AOpen AP5S", "ap5s", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_ap5s_init, NULL }, /* Socket 7 (Dual Voltage) machines */ /* 430HX */ + /* Has SST flash and the SMC FDC73C935's on-chip KBC with Phoenix MultiKey firmware. */ { "[i430HX] Acer V35N", "acerv35n", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_Cx6x86MX), 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 196608, 8192, 127, machine_at_acerv35n_init, NULL }, + /* Has AMIKey H KBC firmware (AMIKey-2). */ { "[i430HX] ASUS P/I-P55T2P4", "p55t2p4", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 83333333, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 127, machine_at_p55t2p4_init, NULL }, + /* Has the SMC FDC73C935's on-chip KBC with Phoenix MultiKey firmware. */ { "[i430HX] Micronics M7S-Hi", "m7shi", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 511, machine_at_m7shi_init, NULL }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430HX] Intel TC430HX", "tc430hx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 255, machine_at_tc430hx_init, NULL }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430HX] Toshiba Equium 5200D", "equium5200", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 196608, 8192, 127, machine_at_equium5200_init, NULL }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . + Yes, this is an Intel AMI BIOS with a fancy splash screen. */ { "[i430HX] Sony Vaio PCV-240", "pcv240", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 196608, 8192, 127, machine_at_pcv240_init, NULL }, + /* The base board has AMIKey-2 (updated 'H') KBC firmware. */ { "[i430HX] ASUS P/I-P65UP5 (C-P55T2D)", "p65up5_cp55t2d", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_p65up5_cp55t2d_init, NULL }, /* 430VX */ + /* Has AMIKey H KBC firmware (AMIKey-2). */ { "[i430VX] ASUS P/I-P55TVP4", "p55tvp4", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p55tvp4_init, NULL }, + /* The BIOS does not send a single non-standard KBC command, so it must have a standard IBM + PS/2 KBC firmware or a clone thereof. */ { "[i430VX] Azza 5IVG", "5ivg", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_5ivg_init, NULL }, + /* [TEST] Has AMIKey 'F' KBC firmware. */ { "[i430VX] Biostar MB-8500TVX-A", "8500tvxa", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2600, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_8500tvxa_init, NULL }, + /* The BIOS does not send a single non-standard KBC command, but the board has a SMC Super I/O + chip with on-chip KBC and AMI MegaKey KBC firmware. */ { "[i430VX] Compaq Presario 2240", "presario2240", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_presario2240_init, NULL }, + /* This most likely has AMI MegaKey as above. */ { "[i430VX] Compaq Presario 4500", "presario4500", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_presario4500_init, NULL }, + /* The BIOS sends KBC command CB which is an AMI KBC command, so it has an AMI KBC firmware. */ { "[i430VX] Epox P55-VA", "p55va", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p55va_init, NULL }, + /* The BIOS does not send a single non-standard KBC command. */ { "[i430VX] HP Brio 80xx", "brio80xx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 66666667, 66666667, 2200, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_brio80xx_init, NULL }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i430VX] Packard Bell PB680", "pb680", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_pb680_init, NULL }, + /* This has the AMIKey 'H' firmware, possibly AMIKey-2. Photos show it with a BestKey, so it + likely clones the behavior of AMIKey 'H'. */ { "[i430VX] PC Partner MB520N", "mb520n", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2600, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_mb520n_init, NULL }, + /* This has a Holtek 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. */ { "[i430VX] Shuttle HOT-557", "430vx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_GAMEPORT, 8192, 131072, 8192, 127, machine_at_i430vx_init, NULL }, /* 430TX */ + /* The BIOS sends KBC command B8, CA, and CB, so it has an AMI KBC firmware. */ { "[i430TX] ADLink NuPRO-592", "nupro592", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 66666667, 66666667, 1900, 2800, 1.5, 5.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_nupro592_init, NULL }, + /* This has the AMIKey KBC firmware, which is an updated 'F' type (YM430TX is based on the TX97). */ { "[i430TX] ASUS TX97", "tx97", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 75000000, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_tx97_init, NULL }, #if defined(DEV_BRANCH) && defined(NO_SIO) + /* This has the Phoenix MultiKey KBC firmware. */ { "[i430TX] Intel AN430TX", "an430tx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_an430tx_init, NULL }, #endif + /* This has the AMIKey KBC firmware, which is an updated 'F' type. */ { "[i430TX] Intel YM430TX", "ym430tx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_ym430tx_init, NULL }, + /* The BIOS sends KBC command BB and expects it to output a byte, which is AMI KBC behavior. */ { "[i430TX] PC Partner MB540N", "mb540n", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2700, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_mb540n_init, NULL }, + /* [TEST] Has AMIKey 'H' KBC firmware. */ { "[i430TX] SuperMicro Super P5MMS98", "p5mms98", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2100, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_p5mms98_init, NULL }, /* Apollo VPX */ + /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA + VT82C42N. */ { "[VIA VPX] FIC VA-502", "ficva502", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 75000000, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_ficva502_init, NULL }, /* Apollo VP3 */ + /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA + VT82C42N. */ { "[VIA VP3] FIC PA-2012", "ficpa2012", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 55000000, 75000000, 2100, 3520, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 127, machine_at_ficpa2012_init, NULL }, /* SiS 5571 */ + /* Has the SiS 5571 chipset with on-chip KBC. */ { "[SiS 5571] Rise R534F", "r534f", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 393216, 8192, 127, machine_at_r534f_init, NULL }, + /* Has the SiS 5571 chipset with on-chip KBC. */ { "[SiS 5571] MSI MS-5146", "ms5146", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 127, machine_at_ms5146_init, NULL }, - /* SiS 5598 */ - { "[SiS 5598] ASUS SP97-XV", "sp97xv", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2100, 3200, 1.5, 2.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_sp97xv_init, NULL }, - { "[SiS 5598] PC Chips M571", "m571", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 75000000, 2500, 3500, 1.5, 3.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_m571_init, NULL }, - - /* ALi ALADDiN IV */ -#if defined(DEV_BRANCH) && defined(USE_M154X) - { "[ALi ALADDiN IV] PC Chips M560", "m560", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 83333333, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_m560_init, NULL }, - { "[ALi ALADDiN IV] MSI MS-5164", "ms5164", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2100, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_ms5164_init, NULL }, -#endif + /* ALi ALADDiN IV+ */ + /* Has the ALi M1543 southbridge with on-chip KBC. */ + { "[ALi ALADDiN IV+] PC Chips M560", "m560", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 83333333, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_m560_init, NULL }, + /* Has the ALi M1543 southbridge with on-chip KBC. */ + { "[ALi ALADDiN IV+] MSI MS-5164", "ms5164", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 2100, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_ms5164_init, NULL }, /* Super Socket 7 machines */ + /* ALi ALADDiN V */ + /* Has the ALi M1543C southbridge with on-chip KBC. */ + { "[ALi ALADDiN V] ASUS P5A", "p5a", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 2000, 3200, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,2097152, 8192, 255, machine_at_p5a_init, NULL }, + /* Is the exact same as the Matsonic MS6260S. Has the ALi M1543C southbridge + with on-chip KBC. */ + { "[ALi ALADDiN V] PC Chips M579", "m579", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 2000, 3200, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,2097152, 8192, 255, machine_at_m579_init, NULL }, + /* Has the ALi M1543C southbridge with on-chip KBC. */ + { "[ALi ALADDiN V] Gigabyte GA-5AA", "ga-5aa", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 2000, 3200, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,2097152, 8192, 255, machine_at_ga_5aa_init, NULL }, + /* Has the ALi M1543C southbridge with on-chip KBC. */ + { "[ALi ALADDiN V] Gigabyte GA-5AX", "ga-5ax", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 2000, 3200, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,2097152, 8192, 255, machine_at_ga_5ax_init, NULL }, + /* Apollo MVP3 */ + /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA + VT82C42N. */ { "[VIA MVP3] AOpen AX59 Pro", "ax59pro", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 1300, 3520, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_ax59pro_init, NULL }, + /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA + VT82C42N. */ { "[VIA MVP3] FIC VA-503+", "ficva503p", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 2000, 3200, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_mvp3_init, NULL }, + /* Has the VIA VT82C686A southbridge with on-chip KBC identical to the VIA + VT82C42N. */ { "[VIA MVP3] FIC VA-503A", "ficva503a", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 1800, 3100, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_ficva503a_init, NULL }, /* Socket 8 machines */ /* 450KX */ #if defined(DEV_BRANCH) && defined(USE_I450KX) + /* This has an AMIKey, which is an updated version of type 'F'. */ { "[i450KX] ASUS P/I-P6RP4", "p6rp4", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_p6rp4_init, NULL }, #endif /* 440FX */ + /* Has the SMC FDC73C935's on-chip KBC with Phoenix MultiKey firmware. */ { "[i440FX] Acer V60N", "v60n", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2500, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_v60n_init, NULL }, + /* The base board has AMIKey-2 (updated 'H') KBC firmware. */ { "[i440FX] ASUS P/I-P65UP5 (C-P6ND)", "p65up5_cp6nd", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 127, machine_at_p65up5_cp6nd_init, 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. */ { "[i440FX] Biostar MB-8600TTC", "8600ttc", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 50000000, 66666667, 2900, 3300, 2.0, 5.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 127, machine_at_8500ttc_init, NULL }, { "[i440FX] Gigabyte GA-686NX", "686nx", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 2.0, 5.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_686nx_init, NULL }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i440FX] Intel AP440FX", "ap440fx", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 2.0, 3.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_ap440fx_init, NULL }, + /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the + PC87306 Super I/O chip, command 0xA1 returns '5'. + Command 0xA0 copyright string: (C)1994 AMI . */ { "[i440FX] Intel VS440FX", "vs440fx", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 2.0, 3.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_vs440fx_init, NULL }, + /* Has the SMC FDC73C935's on-chip KBC with Phoenix MultiKey firmware. */ { "[i440FX] Micronics M6Mi", "m6mi", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2900, 3300, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 127, machine_at_m6mi_init, 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. */ { "[i440FX] PC Partner MB600N", "mb600n", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_mb600n_init, NULL }, /* Slot 1 machines */ + /* ALi ALADDiN V */ + /* Has the ALi M1543C southbridge with on-chip KBC. */ + { "[ALi ALADDiN-PRO II] PC Chips M729", "m729", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 50000000, 66666667, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024,2097152, 8192, 255, machine_at_m729_init, NULL }, + /* 440FX */ + /* The base board has AMIKey-2 (updated 'H') KBC firmware. */ { "[i440FX] ASUS P/I-P65UP5 (C-PKND)", "p65up5_cpknd", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 50000000, 66666667, 1800, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 127, machine_at_p65up5_cpknd_init, NULL }, + /* This has a Holtek 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. */ { "[i440FX] ASUS KN97", "kn97", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 60000000, 83333333, 1800, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 127, machine_at_kn97_init, NULL }, /* 440LX */ + /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440LX] ABIT LX6", "lx6", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 60000000, 100000000, 1500, 3500, 2.0, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_lx6_init, NULL }, + /* Has a SM(S)C FDC37C935 Super I/O chip with on-chip KBC with Phoenix + MultiKey KBC firmware. */ { "[i440LX] Micronics Spitfire", "spitfire", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 66666667, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_spitfire_init, NULL }, /* 440EX */ + /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440EX] QDI EXCELLENT II", "p6i440e2", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 83333333, 1800, 3500, 3.0, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 255, machine_at_p6i440e2_init, NULL }, /* 440BX */ + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] ASUS P2B-LS", "p2bls", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 50000000, 112121212, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_p2bls_init, NULL }, + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] ASUS P3B-F", "p3bf", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_p3bf_init, NULL }, + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] ABIT BF6", "bf6", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 133333333, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_bf6_init, NULL }, + /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] AOpen AX6BC", "ax6bc", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 112121212, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_ax6bc_init, NULL }, + /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] Gigabyte GA-686BX", "686bx", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_686bx_init, NULL }, + /* Has a SM(S)C FDC37M60x Super I/O chip with on-chip KBC with most likely + AMIKey-2 KBC firmware. */ { "[i440BX] HP Vectra VEi 8", "vei8", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_vei8_init, NULL }, + /* Has a National Semiconductors PC87309 Super I/O chip with on-chip KBC + with most likely AMIKey-2 KBC firmware. */ { "[i440BX] Tyan Tsunami ATX", "tsunamiatx", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 112121212, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_SOUND, 8192,1048576, 8192, 255, machine_at_tsunamiatx_init, at_tsunamiatx_get_device }, + /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] SuperMicro Super P6SBA", "p6sba", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_p6sba_init, NULL }, -#if defined(DEV_BRANCH) && defined(NO_SIO) - { "[i440BX] Fujitsu ErgoPro x365", "ergox365", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 393216, 8192, 511, machine_at_ergox365_init, NULL }, -#endif /* 440ZX */ + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440ZX] MSI MS-6168", "ms6168", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_SOUND,8192, 524288, 8192, 255, machine_at_ms6168_init, NULL }, + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440ZX] Packard Bell Bora Pro", "borapro", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 66666667, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_SOUND,8192, 524288, 8192, 255, machine_at_borapro_init, NULL }, /* SMSC VictoryBX-66 */ + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[SMSC VictoryBX-66] A-Trend ATC6310BXII","atc6310bxii", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_atc6310bxii_init, NULL }, /* VIA Apollo Pro */ + /* Has the VIA VT82C596B southbridge with on-chip KBC identical to the VIA + VT82C42N. */ { "[VIA Apollo Pro] FIC KA-6130", "ficka6130", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 255, machine_at_ficka6130_init, NULL }, + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[VIA Apollo Pro133] ASUS P3V133", "p3v133", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1572864, 8192, 255, machine_at_p3v133_init, NULL }, + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[VIA Apollo Pro133A] ASUS P3V4X", "p3v4x", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,2097152, 8192, 255, machine_at_p3v4x_init, NULL }, /* Slot 1/2 machines */ /* 440GX */ + /* Has a National Semiconductors PC87309 Super I/O chip with on-chip KBC + with most likely AMIKey-2 KBC firmware. */ { "[i440GX] Freeway FW-6400GX", "fw6400gx", MACHINE_TYPE_SLOT1_2, CPU_PKG_SLOT1 | CPU_PKG_SLOT2, 0, 100000000, 150000000, 1800, 3500, 3.0, 8.0, (MACHINE_AGP & ~MACHINE_AT) | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 16384,2080768,16384, 511, machine_at_fw6400gx_init, NULL }, /* Slot 2 machines */ /* 440GX */ + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440GX] Gigabyte GA-6GXU", "6gxu", MACHINE_TYPE_SLOT2, CPU_PKG_SLOT2, 0, 100000000, 133333333, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 16384,2097152,16384, 511, machine_at_6gxu_init, NULL }, + /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440GX] SuperMicro Super S2DGE", "s2dge", MACHINE_TYPE_SLOT2, CPU_PKG_SLOT2, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 16384,2097152,16384, 511, machine_at_s2dge_init, NULL }, /* PGA370 machines */ /* 440LX */ + /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440LX] SuperMicro Super 370SLM", "s370slm", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 100000000, 1800, 3500, MACHINE_MULTIPLIER_FIXED, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_s370slm_init, NULL }, /* 440BX */ + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] AEWIN AW-O671R", "awo671r", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, /* limits assumed */ MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 255, machine_at_awo671r_init, NULL }, + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] ASUS CUBX", "cubx", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_cubx_init, NULL }, + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] AmazePC AM-BX133", "ambx133", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, /* limits assumed */ MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_ambx133_init, NULL }, + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] Tyan Trinity 371", "trinity371", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_trinity371_init, NULL }, /* 440ZX */ + /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440ZX] Soltek SL-63A1", "63a", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 255, machine_at_63a_init, NULL }, /* SMSC VictoryBX-66 */ + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[SMSC VictoryBX-66] A-Trend ATC7020BXII","atc7020bxii", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_atc7020bxii_init, NULL }, /* VIA Apollo Pro */ + /* Has the VIA VT82C586B southbridge with on-chip KBC identical to the VIA + VT82C42N. */ { "[VIA Apollo Pro] PC Partner APAS3", "apas3", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 100000000, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_apas3_init, NULL }, + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[VIA Apollo Pro133] ECS P6BAP", "p6bap", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1572864, 8192, 255, machine_at_p6bap_init, NULL }, + /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[VIA Apollo Pro133A] AEWIN WCF-681", "wcf681", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, /* limits assumed */ MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_wcf681_init, NULL }, + /* Has the VIA VT82C686B southbridge with on-chip KBC identical to the VIA + VT82C42N. */ { "[VIA Apollo Pro133A] ASUS CUV4X-LS", "cuv4xls", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, (MACHINE_AGP & ~MACHINE_AT) | MACHINE_BUS_PS2 | MACHINE_BUS_AC97 | MACHINE_IDE_DUAL,16384,1572864, 8192, 255, machine_at_cuv4xls_init, NULL }, + /* Has the VIA VT82C686B southbridge with on-chip KBC identical to the VIA + VT82C42N. */ { "[VIA Apollo Pro133A] Acorp 6VIA90AP", "6via90ap", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, MACHINE_MULTIPLIER_FIXED, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_GAMEPORT, 8192,1572864, 8192, 255, machine_at_6via90ap_init, NULL }, - { "[VIA Apollo ProMedia] Jetway 603TCF", "603tcf", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_603tcf_init, NULL }, /* Miscellaneous/Fake/Hypervisor machines */ + /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ { "[i440BX] Microsoft Virtual PC 2007", "vpc2007", MACHINE_TYPE_MISC, CPU_PKG_SLOT1, CPU_BLOCK(CPU_PENTIUM2, CPU_CYRIX3S), 0, 0, 0, 0, 0, 0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_vpc2007_init, NULL }, { NULL, NULL, MACHINE_TYPE_NONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL } From 996803083291348ed997c224a4b4378086aa1c73 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 4 Aug 2021 09:43:53 +0200 Subject: [PATCH 32/96] The missing DEC LPC stuff. --- src/include/86box/machine.h | 1 + src/machine/m_at_386dx_486.c | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 38d7b3cbf..89613c2ca 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -312,6 +312,7 @@ extern int machine_at_cs4031_init(const machine_t *); extern int machine_at_pb410a_init(const machine_t *); +extern int machine_at_decpc_lpv_init(const machine_t *); extern int machine_at_acerv10_init(const machine_t *); extern int machine_at_acera1g_init(const machine_t *); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 4497b1b97..598d61146 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -454,6 +454,29 @@ machine_at_acerv10_init(const machine_t *model) } +int +machine_at_decpc_lpv_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/decpc_lpv/bios.bin-5f2c71ca0a0a5135083487.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&sis_85c461_device); + /* TODO: Phoenix MultiKey KBC */ + device_add(&keyboard_ps2_ami_pci_device); + device_add(&ide_isa_2ch_device); + device_add(&fdc37c663_device); + /* TODO: On-board S3 805 with AT&T 490 RAM DAC. */ + + return ret; +} + static void machine_at_ali1429_common_init(const machine_t *model) { From 8f486a6c0632ee592deebf678f56a30eb7263ff5 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 4 Aug 2021 09:56:22 +0200 Subject: [PATCH 33/96] Fixed the double definition of the AX95 Pro init function. --- src/machine/m_at_sockets7.c | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/src/machine/m_at_sockets7.c b/src/machine/m_at_sockets7.c index ba26fdb99..e9487ecfe 100644 --- a/src/machine/m_at_sockets7.c +++ b/src/machine/m_at_sockets7.c @@ -215,39 +215,6 @@ machine_at_ax59pro_init(const machine_t *model) } -int -machine_at_ax59pro_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/ax59pro/AX59P236.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(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 0, 0); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); - - device_add(&via_mvp3_device); - device_add(&via_vt82c586b_device); - device_add(&keyboard_ps2_pci_device); - device_add(&w83877tf_device); - device_add(&sst_flash_39sf020_device); - spd_register(SPD_TYPE_SDRAM, 0x7, 256); - - return ret; -} - - int machine_at_mvp3_init(const machine_t *model) { From 5ecf3ac6cb83b87d2f76d12c1a756768ac38f7a3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 5 Aug 2021 18:16:17 +0200 Subject: [PATCH 34/96] Merged the ALi M1217 into the M6117 (that's based on the M1217), moved the M6117 out of the Dev branch, removed the broken M6117 Acrosser, and added three M1217 machines. This finishes the ALi work. --- src/chipset/CMakeLists.txt | 8 +- src/chipset/ali1217.c | 145 ----------------------------------- src/chipset/ali6117.c | 43 ++++++++--- src/include/86box/chipset.h | 2 - src/include/86box/machine.h | 8 +- src/machine/m_at_286_386sx.c | 61 ++++++++++++--- src/machine/machine_table.c | 17 ++-- src/win/Makefile.mingw | 13 +--- 8 files changed, 102 insertions(+), 195 deletions(-) delete mode 100644 src/chipset/ali1217.c diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 14ca76962..c015e900d 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -13,8 +13,8 @@ # Copyright 2020,2021 David Hrdlička. # -add_library(chipset OBJECT acc2168.c cs8230.c ali1217.c ali1429.c ali1489.c ali1531.c ali1541.c - ali1543.c ali1621.c headland.c intel_82335.c contaq_82c59x.c cs4031.c intel_420ex.c +add_library(chipset OBJECT acc2168.c cs8230.c ali1429.c ali1489.c ali1531.c ali1541.c ali1543.c + ali1621.c ali6117.c headland.c intel_82335.c contaq_82c59x.c cs4031.c intel_420ex.c intel_4x0.c intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c opti495.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 sis_85c310.c @@ -25,10 +25,6 @@ if(I450KX) target_sources(chipset PRIVATE intel_i450kx.c) endif() -if(M6117) - target_sources(chipset PRIVATE ali6117.c) -endif() - if(OLIVETTI) target_sources(chipset PRIVATE olivetti_eva.c) endif() \ No newline at end of file diff --git a/src/chipset/ali1217.c b/src/chipset/ali1217.c deleted file mode 100644 index ab05ac0a0..000000000 --- a/src/chipset/ali1217.c +++ /dev/null @@ -1,145 +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 ALi M1217 chipset. - * - * Note: This chipset has no datasheet, everything were done via - * reverse engineering the BIOS of various machines using it. - * - * Authors: Tiseno100 - * - * Copyright 2021 Tiseno100 - * - */ - -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include "cpu.h" -#include <86box/timer.h> -#include <86box/io.h> -#include <86box/device.h> -#include <86box/mem.h> -#include <86box/port_92.h> -#include <86box/chipset.h> - - -#ifdef ENABLE_ALI1217_LOG -int ali1217_do_log = ENABLE_ALI1217_LOG; -static void -ali1217_log(const char *fmt, ...) -{ - va_list ap; - - if (ali1217_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -#define ali1217_log(fmt, ...) -#endif - -typedef struct -{ - uint8_t index, regs[256]; - int cfg_locked; -} ali1217_t; - -static void ali1217_shadow_recalc(int reg_15, ali1217_t *dev) -{ - for (uint8_t i = 0; i < 4; i++) - mem_set_mem_state_both((reg_15 ? 0xe0000 : 0xc0000) + (i << 15), 0x8000, ((dev->regs[0x14 + reg_15] & (1 << (i * 2))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x14 + reg_15] & (1 << ((i * 2) + 1))) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); - - flushmmucache_nopc(); -} - -static void -ali1217_write(uint16_t addr, uint8_t val, void *priv) -{ - ali1217_t *dev = (ali1217_t *)priv; - - switch (addr) - { - case 0x22: - dev->index = val; - break; - case 0x23: - if (dev->index != 0x13) - ali1217_log("ALi M1217: dev->regs[%02x] = %02x\n", dev->index, val); - else - dev->cfg_locked = !(val == 0xc5); - - if (!dev->cfg_locked) - { - dev->regs[dev->index] = val; - - if ((dev->index == 0x14) || (dev->index == 0x15)) - ali1217_shadow_recalc(dev->index & 1, dev); - } - break; - } -} - -static uint8_t -ali1217_read(uint16_t addr, void *priv) -{ - ali1217_t *dev = (ali1217_t *)priv; - - return (addr == 0x23) ? dev->regs[dev->index] : 0xff; -} - -static void -ali1217_close(void *priv) -{ - ali1217_t *dev = (ali1217_t *)priv; - - free(dev); -} - -static void * -ali1217_init(const device_t *info) -{ - ali1217_t *dev = (ali1217_t *)malloc(sizeof(ali1217_t)); - memset(dev, 0, sizeof(ali1217_t)); - - device_add(&port_92_device); - - dev->cfg_locked = 1; - - /* - - ALi M1217 Ports - - 22h Index Port - 23h Data Port - - */ - io_sethandler(0x0022, 0x0002, ali1217_read, NULL, NULL, ali1217_write, NULL, NULL, dev); - - return dev; -} - -const device_t ali1217_device = { - "ALi M1217", - 0, - 0, - ali1217_init, - ali1217_close, - NULL, - {NULL}, - NULL, - NULL, - NULL}; diff --git a/src/chipset/ali6117.c b/src/chipset/ali6117.c index ae4a30e61..e7196f952 100644 --- a/src/chipset/ali6117.c +++ b/src/chipset/ali6117.c @@ -109,7 +109,7 @@ ali6117_recalcmapping(ali6117_t *dev) } } - flushmmucache(); + flushmmucache_nopc(); } @@ -127,12 +127,16 @@ ali6117_reg_write(uint16_t addr, uint8_t val, void *priv) else if (dev->unlocked) { ali6117_log("ALI6117: regs[%02X] = %02X\n", dev->reg_offset, val); - switch (dev->reg_offset) { + if (!(dev->local & 0x08) || (dev->reg_offset < 0x30)) switch (dev->reg_offset) { case 0x30: case 0x34: case 0x35: case 0x3e: case 0x3f: case 0x46: case 0x4c: case 0x6a: case 0x73: return; /* read-only registers */ + case 0x10: + refresh_at_enable = !(val & 0x02) || !!(dev->regs[0x20] & 0x80); + break; + case 0x12: val &= 0xf7; /* FALL-THROUGH */ @@ -184,7 +188,7 @@ ali6117_reg_write(uint16_t addr, uint8_t val, void *priv) case 0x20: val &= 0xbf; - refresh_at_enable = !!(val & 0x80); + refresh_at_enable = !(dev->regs[0x10] & 0x02) || !!(val & 0x80); break; case 0x31: @@ -311,13 +315,17 @@ ali6117_reset(void *priv) dev->regs[0x1b] = 0xf0; dev->regs[0x1d] = 0xff; dev->regs[0x20] = 0x80; - dev->regs[0x30] = 0x08; - dev->regs[0x31] = 0x01; - dev->regs[0x34] = 0x04; /* enable internal RTC */ - dev->regs[0x35] = 0x20; /* enable internal KBC */ - dev->regs[0x36] = dev->local & 0x4; /* M6117D ID */ + if (dev->local & 0x08) { + dev->regs[0x30] = 0x08; + dev->regs[0x31] = 0x01; + dev->regs[0x34] = 0x04; /* enable internal RTC */ + dev->regs[0x35] = 0x20; /* enable internal KBC */ + dev->regs[0x36] = dev->local & 0x07; /* M6117D ID */ + } cpu_set_isa_speed(7159091); + + refresh_at_enable = 1; } @@ -361,13 +369,28 @@ ali6117_init(const device_t *info) ali6117_setup(dev); ali6117_reset(dev); - pic_elcr_io_handler(0); - refresh_at_enable = 0; + if (!(dev->local & 0x08)) + pic_elcr_io_handler(0); return dev; } +const device_t ali1217_device = +{ + "ALi M1217", + DEVICE_AT, + 0x8, + ali6117_init, + ali6117_close, + ali6117_reset, + { NULL }, + NULL, + NULL, + NULL +}; + + const device_t ali6117d_device = { "ALi M6117D", diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index c94205277..4ecff681e 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -30,9 +30,7 @@ extern const device_t ali1541_device; extern const device_t ali1543_device; extern const device_t ali1543c_device; extern const device_t ali1621_device; -#if defined(DEV_BRANCH) && defined(USE_M6117) extern const device_t ali6117d_device; -#endif /* AMD */ extern const device_t amd640_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 89613c2ca..f482d63d7 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -279,13 +279,13 @@ extern int machine_at_cmdsl386sx16_init(const machine_t *); extern int machine_at_cmdsl386sx25_init(const machine_t *); extern int machine_at_spc6033p_init(const machine_t *); extern int machine_at_wd76c10_init(const machine_t *); +extern int machine_at_arb1374_init(const machine_t *); +extern int machine_at_sbc_350a_init(const machine_t *); extern int machine_at_flytech386_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_awardsx_init(const machine_t *); -#if defined(DEV_BRANCH) && defined(USE_M6117) -extern int machine_at_arb1375_init(const machine_t *); -extern int machine_at_pja511m_init(const machine_t *); -#endif extern int machine_at_pc916sx_init(const machine_t *); diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 347448b6b..81321a2d7 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -678,6 +678,49 @@ machine_at_awardsx_init(const machine_t *model) return ret; } + +int +machine_at_arb1374_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/arb1374/1374s.rom", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&ali1217_device); + device_add(&w83787f_ide_en_device); + device_add(&keyboard_ps2_ami_device); + + return ret; +} + + +int +machine_at_sbc_350a_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/sbc_350a/350a.rom", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&ali1217_device); + device_add(&sio_detect_device); + device_add(&keyboard_at_device); + + return ret; +} + + int machine_at_flytech386_init(const machine_t *model) { @@ -701,30 +744,31 @@ machine_at_flytech386_init(const machine_t *model) return ret; } + const device_t * at_flytech386_get_device(void) { return &tvga8900d_device; } -#if defined(DEV_BRANCH) && defined(USE_M6117) + int -machine_at_arb1375_init(const machine_t *model) +machine_at_mr1217_init(const machine_t *model) { int ret; - ret = bios_load_linear("roms/machines/arb1375/a1375v25.u11-a", - 0x000e0000, 131072, 0); + ret = bios_load_linear("roms/machines/mr1217/mrbios.BIN", + 0x000f0000, 65536, 0); if (bios_only || !ret) return ret; machine_at_common_init(model); - device_add(&fdc37c669_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&ali6117d_device); - device_add(&sst_flash_29ee010_device); + device_add(&ali1217_device); + device_add(&fdc_at_device); + device_add(&ide_isa_device); + device_add(&keyboard_ps2_device); return ret; } @@ -752,7 +796,6 @@ machine_at_pja511m_init(const machine_t *model) return ret; } -#endif /* * Current bugs: diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index b6f7d86ec..2d5039fb2 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -239,16 +239,19 @@ const machine_t machines[] = { { "[ISA] NCR PC916SX", "pc916sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 128, 127, machine_at_pc916sx_init, NULL }, /* Has Quadtel KBC firmware. */ { "[ISA] QTC-SXM KT X20T02/HI", "quadt386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 128, 127, machine_at_quadt386sx_init, NULL }, -#if defined(DEV_BRANCH) && defined(USE_M6117) - /* Has IBM PS/2 Type 1 KBC firmware. */ - { "[ALi M6117] Acrosser AR-B1375", "arb1375", MACHINE_TYPE_386SX, CPU_PKG_M6117, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768,1024, 127, machine_at_arb1375_init, NULL }, - /* Has IBM PS/2 Type 1 KBC firmware. */ - { "[ALi M6117] Acrosser PJ-A511M", "pja511m", MACHINE_TYPE_386SX, CPU_PKG_M6117, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768,1024, 127, machine_at_pja511m_init, NULL }, -#endif + /* This has an AMIKey-2, which is an updated version of type 'H'. */ + { "[ALi M1217] Acrosser AR-B1374", "arb1374", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768,1024, 127, machine_at_arb1374_init, NULL }, + /* Has the AMIKey KBC firmware, which is an updated 'F' type. */ + { "[ALi M1217] AAEON SBC-350A", "sbc-350a", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 16384, 1024, 127, machine_at_sbc_350a_init, 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. */ { "[ALi M1217] Flytech 386", "flytech386", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 16384, 1024, 127, machine_at_flytech386_init, at_flytech386_get_device }, + /* I'm going to assume this has a standard/generic IBM-compatible AT KBC + firmware until the board is identified. */ + { "[ALi M1217] MR 386SX clone", "mr1217", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 16384, 1024, 127, machine_at_mr1217_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ + { "[ALi M6117] Acrosser PJ-A511M", "pja511m", MACHINE_TYPE_386SX, CPU_PKG_M6117, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768,1024, 127, machine_at_pja511m_init, NULL }, /* 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. */ @@ -256,7 +259,7 @@ const machine_t machines[] = { /* Has an unknown KBC firmware with commands B8 and BB in the style of Phoenix MultiKey and AMIKey-3(!), but also commands E1 and EA with unknown functions. */ - { "[Intel 82335 ADI 386SX", "adi386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_adi386sx_init, NULL }, + { "[Intel 82335 ADI 386SX", "adi386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_adi386sx_init, NULL }, /* Has an AMI Keyboard BIOS PLUS KBC firmware ('8'). */ { "[Intel 82335] Shuttle 386SX", "shuttle386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_shuttle386sx_init, NULL }, /* Uses Commodore (CBM) KBC firmware, to be implemented as identical to diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 543e15d60..9b01db329 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -75,9 +75,6 @@ ifeq ($(DEV_BUILD), y) ifndef SIO_DETECT SIO_DETECT := y endif - ifndef M6117 - M6117 := y - endif ifndef VGAWONDER VGAWONDER := y endif @@ -145,9 +142,6 @@ else ifndef SIO_DETECT SIO_DETECT := n endif - ifndef M6117 - M6117 := n - endif ifndef VGAWONDER VGAWONDER := n endif @@ -551,11 +545,6 @@ OPTS += -DUSE_SIO_DETECT DEVBROBJ += sio_detect.o endif -ifeq ($(M6117), y) -OPTS += -DUSE_M6117 -DEVBROBJ += ali6117.o -endif - ifeq ($(VGAWONDER), y) OPTS += -DUSE_VGAWONDER endif @@ -602,7 +591,7 @@ CPUOBJ := cpu.o cpu_table.o fpu.o x86.o \ CHIPSETOBJ := acc2168.o \ contaq_82c59x.o \ cs4031.o cs8230.o \ - ali1217.o ali1429.o ali1489.o ali1531.o ali1541.o ali1543.o ali1621.o \ + ali1429.o ali1489.o ali1531.o ali1541.o ali1543.o ali1621.o ali6117.o \ gc100.o headland.o \ intel_82335.o intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \ neat.o \ From 89f35be8065791c0efec682b2eadf066e8a721ab Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 5 Aug 2021 18:23:59 +0200 Subject: [PATCH 35/96] Fixed some compile-breaking mistakes. --- src/machine/m_at_286_386sx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 81321a2d7..091723b3c 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -714,7 +714,7 @@ machine_at_sbc_350a_init(const machine_t *model) machine_at_common_init(model); device_add(&ali1217_device); - device_add(&sio_detect_device); + device_add(&fdc37c665_ide_device); device_add(&keyboard_at_device); return ret; From df00d0ac58dd8594cf6304453584e768dc98bc0c Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 7 Aug 2021 12:28:33 +0200 Subject: [PATCH 36/96] Added three ALi M1487/89 machines and that 430VX machine with Award 4.50PG BIOS. --- src/chipset/ali1489.c | 2 +- src/device/keyboard_at.c | 7 ++- src/include/86box/machine.h | 4 ++ src/machine/m_at_386dx_486.c | 85 +++++++++++++++++++++++++++++++++++ src/machine/m_at_socket7_3v.c | 30 +++++++++++++ src/machine/machine_table.c | 12 +++++ src/sio/sio_detect.c | 2 +- 7 files changed, 139 insertions(+), 3 deletions(-) diff --git a/src/chipset/ali1489.c b/src/chipset/ali1489.c index 03c1f4519..6c90cf7d0 100644 --- a/src/chipset/ali1489.c +++ b/src/chipset/ali1489.c @@ -105,7 +105,7 @@ ali1489_shadow_recalc(ali1489_t *dev) } } - flushmmucache(); + flushmmucache_nopc(); } diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 92690db1f..13356127b 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -2315,7 +2315,7 @@ write64_ami(void *priv, uint8_t val) case 0xa1: /* get controller version */ kbd_log("ATkbc: AMI - get controller version\n"); // kbc_transmit(dev, 'H'); - kbc_transmit(dev, '5'); + kbc_transmit(dev, 'Z'); return 0; case 0xa2: /* clear keyboard controller lines P22/P23 */ @@ -2878,6 +2878,11 @@ kbd_write(uint16_t port, uint8_t val, void *priv) dev->status &= ~STAT_IFULL; kbc_send_to_ob(dev, 'H', 0, 0x00); } +#else + if (val == 0xa1) { + dev->status &= ~STAT_IFULL; + kbc_send_to_ob(dev, 'H', 0, 0x00); + } #endif break; } diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index f482d63d7..a04b423ef 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -360,6 +360,9 @@ extern int machine_at_g486vpa_init(const machine_t *); extern int machine_at_486vipio2_init(const machine_t *); extern int machine_at_abpb4_init(const machine_t *); extern int machine_at_win486pci_init(const machine_t *); +extern int machine_at_ms4145_init(const machine_t *); +extern int machine_at_sbc_490_init(const machine_t *); +extern int machine_at_tf_486_init(const machine_t *); extern int machine_at_itoxstar_init(const machine_t *); extern int machine_at_arb1479_init(const machine_t *); @@ -451,6 +454,7 @@ extern int machine_at_ap53_init(const machine_t *); 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_gw2kte_init(const machine_t *); extern int machine_at_ap5s_init(const machine_t *); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 598d61146..f9f19514c 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -1320,6 +1320,91 @@ machine_at_win486pci_init(const machine_t *model) } +int +machine_at_ms4145_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ms4145/AG56S.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(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(&ali1489_device); + device_add(&w83787f_device); + device_add(&keyboard_at_ami_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + + +int +machine_at_sbc_490_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/sbc-490/07159589.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(0x01, PCI_CARD_VIDEO, 4, 1, 2, 3); + 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, 2, 3, 4); + + device_add(&ali1489_device); + device_add(&fdc37c665_device); + device_add(&keyboard_ps2_ami_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + + +int +machine_at_tf_486_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/tf-486/tf486v10.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(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + + device_add(&ali1489_device); + device_add(&w83977ef_device); + device_add(&keyboard_ps2_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + + int machine_at_itoxstar_init(const machine_t *model) { diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index f31aeed33..1b1f7c7be 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -449,6 +449,36 @@ machine_at_p55t2s_init(const machine_t *model) } +int +machine_at_p5vxb_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/p5vxb/P5VXB10.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(0x05, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x06, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x08, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); + device_add(&i430vx_device); + device_add(&piix3_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83877f_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + + int machine_at_gw2kte_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 2d5039fb2..5a5ae8b21 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -397,6 +397,8 @@ const machine_t machines[] = { { "[SiS 471] Epox 486SX/DX Green", "ami471", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_ami471_init, NULL }, /* 486 machines which utilize the PCI bus */ + /* This has an AMIKey-2, which is an updated version of type 'H'. */ + { "[ALi M1489] AAEON SBC-490", "sbc-490", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_sbc_490_init, NULL }, /* Has the ALi M1487/9's on-chip keyboard controller which clones a standard AT KBC. */ { "[ALi M1489] ABIT AB-PB4", "abpb4", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_abpb4_init, NULL }, @@ -406,6 +408,14 @@ const machine_t machines[] = { and 0xCB if command 0xA1 returns a letter in the 0x5x or 0x7x ranges, so I'm going to give it an AMI 'U' KBC. */ { "[ALi M1489] AMI WinBIOS 486 PCI", "win486pci", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_win486pci_init, NULL }, + /* Has the ALi M1487/9's on-chip keyboard controller which clones a standard AT + KBC. + The known BIOS string ends in -E, and the BIOS returns whatever command 0xA1 + returns (but only if command 0xA1 is instant response), so said ALi keyboard + controller likely returns 'E'. */ + { "[ALi M1489] MSI MS-4145", "ms4145", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_ms4145_init, NULL }, + /* Has an ALi M5042 keyboard controller with Phoenix MultiKey/42 v1.40 firmware. */ + { "[ALi M1489] ESA TF-486", "tf-486", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_tf_486_init, NULL }, /* Has IBM PS/2 Type 1 KBC firmware. */ { "[OPTi 802G] IBM PC 330 (type 6573)", "pc330_6573", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3_PC330, 0, 25000000, 33333333, 0, 0, 2.0, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_pc330_6573_init, NULL }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ @@ -578,6 +588,8 @@ const machine_t machines[] = { { "[i430HX] SuperMicro Super P55T2S", "p55t2s", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3300, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 127, machine_at_p55t2s_init, NULL }, /* 430VX */ + /* Has AMIKey H KBC firmware (AMIKey-2). */ + { "[i430VX] ECS P5VX-B", "p5vxb", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p5vxb_init, NULL }, /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . */ diff --git a/src/sio/sio_detect.c b/src/sio/sio_detect.c index 7a0f8821e..8df3864c3 100644 --- a/src/sio/sio_detect.c +++ b/src/sio/sio_detect.c @@ -53,7 +53,7 @@ sio_detect_read(uint16_t port, void *priv) pclog("sio_detect_read : port=%04x = %02X\n", port, dev->regs[port & 1]); - return dev->regs[port & 1]; + return 0xff /*dev->regs[port & 1]*/; } From 1060e62747a3c0ab5d0ffc07a09c7dc1d5fed9dc Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 9 Aug 2021 07:46:02 +0200 Subject: [PATCH 37/96] Some AT / PS/2 KBC fixes, fixes the QDI Excellent II. --- src/device/keyboard_at.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 13356127b..eebfd2c63 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -673,7 +673,7 @@ kbd_status(const char *fmt, ...) } -// #define ENABLE_KEYBOARD_AT_LOG 1 +#define ENABLE_KEYBOARD_AT_LOG 1 #ifdef ENABLE_KEYBOARD_AT_LOG int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG; @@ -1184,7 +1184,7 @@ write_output(atkbd_t *dev, uint8_t val) uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; kbd_log("ATkbc: write output port: %02X (old: %02X)\n", val, dev->p2); - if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) + if (!(dev->flags & KBC_FLAG_PS2)) val |= ((dev->mem[0x20] << 4) & 0x30); dev->kbd_inhibit = (val & 0x40); @@ -1245,12 +1245,15 @@ write_cmd(atkbd_t *dev, uint8_t val) The AMIKEY firmware apparently uses this bit for something else. */ if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) { keyboard_mode &= ~CCB_PCMODE; - /* Update the output port to mirror the KBD DIS and AUX DIS bits, if active. */ - write_output(dev, dev->p2); kbd_log("ATkbc: mouse interrupt is now %s\n", (val & 0x02) ? "enabled" : "disabled"); } + if (!(dev->flags & KBC_FLAG_PS2)) { + /* Update the output port to mirror the KBD DIS and AUX DIS bits, if active. */ + write_output(dev, dev->p2); + } + kbd_log("Command byte now: %02X (%02X)\n", dev->mem[0x20], val); dev->status = (dev->status & ~STAT_SYSFLAG) | (val & STAT_SYSFLAG); @@ -2058,6 +2061,8 @@ write64_generic(void *priv, uint8_t val) P6RP4: Bit 2 must be 1 or CMOS setup is disabled. */ kbd_log("ATkbc: read input port\n"); + kbc_transmit(dev, 0b10011100); + return 0; fixed_bits = 4; /* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */ if (kbc_ven == KBC_VEN_INTEL_AMI) @@ -2879,10 +2884,11 @@ kbd_write(uint16_t port, uint8_t val, void *priv) kbc_send_to_ob(dev, 'H', 0, 0x00); } #else - if (val == 0xa1) { + /* if (val == 0xa1) { dev->status &= ~STAT_IFULL; kbc_send_to_ob(dev, 'H', 0, 0x00); - } + } */ + kbc_process(dev); #endif break; } From c26811308a11f7acf3b60a4e3c56c4016d4508f0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 9 Aug 2021 07:51:23 +0200 Subject: [PATCH 38/96] Removed excess logging. --- src/device/keyboard_at.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index eebfd2c63..31118bdc4 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -673,7 +673,6 @@ kbd_status(const char *fmt, ...) } -#define ENABLE_KEYBOARD_AT_LOG 1 #ifdef ENABLE_KEYBOARD_AT_LOG int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG; From d0cebfdc30f87e9b6f3d46ffcd9e97f47f43fef0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 9 Aug 2021 09:54:49 +0200 Subject: [PATCH 39/96] Reverted a KBC change that should not have been there. --- src/device/keyboard_at.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 31118bdc4..7f5ee51db 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -2060,8 +2060,6 @@ write64_generic(void *priv, uint8_t val) P6RP4: Bit 2 must be 1 or CMOS setup is disabled. */ kbd_log("ATkbc: read input port\n"); - kbc_transmit(dev, 0b10011100); - return 0; fixed_bits = 4; /* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */ if (kbc_ven == KBC_VEN_INTEL_AMI) From 80b75ee433a97eb78f9def63a2d2f023ba9a717e Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 9 Aug 2021 09:58:01 +0200 Subject: [PATCH 40/96] CPU changes. --- src/cpu/386_ops.h | 91 +++++++++++++++++++++++++++++++++++++++++++ src/cpu/cpu.c | 14 ++++++- src/cpu/cpu.h | 1 + src/cpu/cpu_table.c | 6 +-- src/cpu/x86.c | 11 ++---- src/cpu/x86_ops.h | 2 + src/cpu/x86_ops_msr.h | 2 - 7 files changed, 112 insertions(+), 15 deletions(-) diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index 613d8842e..5b472298b 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -641,6 +641,97 @@ const OpFn OP_TABLE(c486_0f)[1024] = /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opSMINT, ILLEGAL, + +/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, +/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, 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*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,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, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*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, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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, opRDSHR_a16, opWRSHR_a16, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opSMINT, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, +/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, 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*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,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, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*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, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a32, opRSDC_a32, opSVLDT_a32, opRSLDT_a32, opSVTS_a32, opRSTS_a32, opSMINT, ILLEGAL, + +/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, +/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, 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*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,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, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*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, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opSMINT, ILLEGAL, + +/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, +/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, 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*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,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, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*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, +}; + +const OpFn OP_TABLE(stpc_0f)[1024] = +{ + /*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, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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, opRDTSC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 290c14a86..b8709254a 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -809,10 +809,17 @@ cpu_set(void) case CPU_Cx486S: case CPU_Cx486DX: + case CPU_STPC: #ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_c486_0f, dynarec_ops_386, dynarec_ops_c486_0f); + if (cpu_s->cpu_type == CPU_STPC) + x86_setopcodes(ops_386, ops_stpc_0f, dynarec_ops_386, dynarec_ops_stpc_0f); + else + x86_setopcodes(ops_386, ops_c486_0f, dynarec_ops_386, dynarec_ops_c486_0f); #else - x86_setopcodes(ops_386, ops_c486_0f); + if (cpu_s->cpu_type == CPU_STPC) + x86_setopcodes(ops_386, ops_stpc_0f); + else + x86_setopcodes(ops_386, ops_c486_0f); #endif timing_rr = 1; /* register dest - register src */ @@ -846,6 +853,9 @@ cpu_set(void) timing_jmp_pm_gate = 37; timing_misaligned = 3; + + if (cpu_s->cpu_type == CPU_STPC) + cpu_features = CPU_FEATURE_RDTSC; break; case CPU_Cx5x86: diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 2aecdf13e..e4bf676bb 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -54,6 +54,7 @@ enum { CPU_Am486DX, CPU_Am486DXL, CPU_Cx486DX, + CPU_STPC, CPU_i486SX_SLENH, CPU_i486DX_SLENH, CPU_ENH_Am486DX, diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 57aa3f7ca..707c9299b 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -576,8 +576,8 @@ const cpu_family_t cpu_families[] = { .name = "STPC-DX", .internal_name = "stpc_dx", .cpus = (const CPU[]) { - {"66", CPU_Cx486DX, fpus_internal, 66666666, 1.0, 3300, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, - {"75", CPU_Cx486DX, fpus_internal, 75000000, 1.0, 3300, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"66", CPU_STPC, fpus_internal, 66666666, 1.0, 3300, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, + {"75", CPU_STPC, fpus_internal, 75000000, 1.0, 3300, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, {"", 0} } }, { @@ -586,7 +586,7 @@ const cpu_family_t cpu_families[] = { .name = "STPC-DX2", .internal_name = "stpc_dx2", .cpus = (const CPU[]) { - {"133", CPU_Cx486DX, fpus_internal, 133333333, 2.0, 3300, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, + {"133", CPU_STPC, fpus_internal, 133333333, 2.0, 3300, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, {"", 0} } }, { diff --git a/src/cpu/x86.c b/src/cpu/x86.c index a80eb2d21..e652c5d27 100644 --- a/src/cpu/x86.c +++ b/src/cpu/x86.c @@ -26,7 +26,6 @@ #include "cpu.h" #include "x86.h" #include <86box/machine.h> -#include <86box/device.h> #include <86box/io.h> #include <86box/mem.h> #include <86box/rom.h> @@ -240,10 +239,8 @@ reset_common(int hard) leave_smm(); /* Needed for the ALi M1533. */ - if (soft_reset_pci && !hard) { + if (soft_reset_pci && !hard) pci_reset(); - device_reset_all_pci(); - } use32 = 0; cpu_cur_status = 0; @@ -267,7 +264,7 @@ reset_common(int hard) } else { loadcs(0xFFFF); cpu_state.pc = 0; - rammask = is286 ? 0xffffff : 0xfffff; + rammask = 0xfffff; } } idt.base = 0; @@ -310,10 +307,8 @@ reset_common(int hard) shadowbios = shadowbios_write = 0; alt_access = cpu_end_block_after_ins = 0; - if (hard) { + if (hard) reset_on_hlt = hlt_reset_pending = 0; - soft_reset_pci = 0; - } if (!is286) reset_808x(hard); diff --git a/src/cpu/x86_ops.h b/src/cpu/x86_ops.h index dc0d62782..2c8812570 100644 --- a/src/cpu/x86_ops.h +++ b/src/cpu/x86_ops.h @@ -80,6 +80,7 @@ extern const OpFn dynarec_ops_386_0f[1024]; extern const OpFn dynarec_ops_486_0f[1024]; extern const OpFn dynarec_ops_c486_0f[1024]; +extern const OpFn dynarec_ops_stpc_0f[1024]; extern const OpFn dynarec_ops_ibm486_0f[1024]; extern const OpFn dynarec_ops_winchip_0f[1024]; @@ -178,6 +179,7 @@ extern const OpFn ops_386_0f[1024]; extern const OpFn ops_486_0f[1024]; extern const OpFn ops_c486_0f[1024]; +extern const OpFn ops_stpc_0f[1024]; extern const OpFn ops_ibm486_0f[1024]; extern const OpFn ops_winchip_0f[1024]; diff --git a/src/cpu/x86_ops_msr.h b/src/cpu/x86_ops_msr.h index 227677268..6624218e4 100644 --- a/src/cpu/x86_ops_msr.h +++ b/src/cpu/x86_ops_msr.h @@ -1,13 +1,11 @@ static int opRDTSC(uint32_t fetchdat) { -#if 0 if (!cpu_has_feature(CPU_FEATURE_RDTSC)) { cpu_state.pc = cpu_state.oldpc; x86illegal(); return 1; } -#endif if ((cr4 & CR4_TSD) && CPL) { x86gpf("RDTSC when TSD set and CPL != 0", 0); From ee4b86065f08c5acce8ca3382ac700c6c15fbd00 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 10 Aug 2021 15:45:49 +0200 Subject: [PATCH 41/96] More CPU changes. --- src/cpu/386_common.c | 1 + src/cpu/cpu.c | 7 ++++--- src/cpu/cpu_table.c | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index fbb67df1c..099e6d72e 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -306,6 +306,7 @@ enum SMMRAM_Fields_AMD_K { }; +#define ENABLE_386_COMMON_LOG 1 #ifdef ENABLE_386_COMMON_LOG int x386_common_do_log = ENABLE_386_COMMON_LOG; diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index b8709254a..5da0778ab 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -375,7 +375,7 @@ cpu_set(void) is_am486dxl = (cpu_s->cpu_type == CPU_Am486DXL); cpu_isintel = !strcmp(cpu_f->manufacturer, "Intel"); - cpu_iscyrix = !strcmp(cpu_f->manufacturer, "Cyrix"); + cpu_iscyrix = !strcmp(cpu_f->manufacturer, "Cyrix") || !strcmp(cpu_f->manufacturer, "ST"); /* SL-Enhanced Intel 486s have the same SMM save state table layout as Pentiums, and the WinChip datasheet claims those are Pentium-compatible as well. AMD Am486DXL/DXL2 also has compatible SMM, or would if not for it's different SMBase*/ @@ -385,7 +385,8 @@ cpu_set(void) is_k6 = (cpu_s->cpu_type >= CPU_K6) && !strcmp(cpu_f->manufacturer, "AMD"); /* The Samuel 2 datasheet claims it's Celeron-compatible. */ is_p6 = (cpu_isintel && (cpu_s->cpu_type >= CPU_PENTIUMPRO)) || !strcmp(cpu_f->manufacturer, "VIA"); - is_cxsmm = !strcmp(cpu_f->manufacturer, "Cyrix") && (cpu_s->cpu_type >= CPU_Cx486S); + is_cxsmm = (!strcmp(cpu_f->manufacturer, "Cyrix") || !strcmp(cpu_f->manufacturer, "ST")) && + (cpu_s->cpu_type >= CPU_Cx486S); hasfpu = (fpu_type != FPU_NONE); hascache = (cpu_s->cpu_type >= CPU_486SLC) || (cpu_s->cpu_type == CPU_IBM386SLC) || @@ -2962,7 +2963,7 @@ cpu_read(uint16_t addr, void *priv) if ((cyrix_addr & 0xf0) == 0xc0) return 0xff; - if (cyrix_addr == 0x20 && cpu_s->cpu_type == CPU_Cx5x86) + if (cyrix_addr == 0x20 && (cpu_s->cpu_type == CPU_Cx5x86)) return 0xff; } diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 707c9299b..e40d64400 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -586,7 +586,7 @@ const cpu_family_t cpu_families[] = { .name = "STPC-DX2", .internal_name = "stpc_dx2", .cpus = (const CPU[]) { - {"133", CPU_STPC, fpus_internal, 133333333, 2.0, 3300, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, + {"133", CPU_STPC, fpus_internal, 133333333, 2.0, 3300, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, {"", 0} } }, { From ed89a93fe2a241d7200212c941ba622f57f27854 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 10 Aug 2021 15:47:02 +0200 Subject: [PATCH 42/96] Removed the M6117 CPU's from the Dev branch. --- src/cpu/cpu_table.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index e40d64400..a3417c920 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -184,7 +184,6 @@ const cpu_family_t cpu_families[] = { {"", 0} } }, -#if defined(DEV_BRANCH) && defined(USE_M6117) { .package = CPU_PKG_M6117, .manufacturer = "ALi", @@ -196,7 +195,6 @@ const cpu_family_t cpu_families[] = { {"", 0} } }, -#endif { .package = CPU_PKG_386SLC_IBM, .manufacturer = "IBM", From 5c8d06ab356257182ca4798926e27774d19975da Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 10 Aug 2021 15:48:58 +0200 Subject: [PATCH 43/96] Temporary revert of keyboard_at.c. --- src/device/keyboard_at.c | 2796 ++++++++++++++------------------------ 1 file changed, 1042 insertions(+), 1754 deletions(-) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 7f5ee51db..1c44880a3 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -57,7 +57,9 @@ #define STAT_IFULL 0x02 #define STAT_OFULL 0x01 -#define RESET_DELAY_TIME 1000 /* 100 ms */ +#define PS2_REFRESH_TIME (16 * TIMER_USEC) + +#define RESET_DELAY_TIME (100 * 10) /* 600ms */ #define CCB_UNUSED 0x80 #define CCB_TRANSLATE 0x40 @@ -72,136 +74,49 @@ #define MODE_MASK 0x6c #define KBC_TYPE_ISA 0x00 /* AT ISA-based chips */ -#define KBC_TYPE_PS2_1 0x04 /* PS2 type, no refresh */ -/* This only differs in that translation is forced off. */ -#define KBC_TYPE_PS2_2 0x05 /* PS2 on PS/2, type 2 */ -#define KBC_TYPE_MASK 0x07 +#define KBC_TYPE_PS2_NOREF 0x01 /* PS2 type, no refresh */ +#define KBC_TYPE_PS2_1 0x02 /* PS2 on PS/2, type 1 */ +#define KBC_TYPE_PS2_2 0x03 /* PS2 on PS/2, type 2 */ +#define KBC_TYPE_MASK 0x03 -#define KBC_FLAG_PS2 0x04 - -/* We need to redefine this: - Currently, we use bits 3-7 for vendor, we should instead use bits 4-7 - for vendor, 0-3 for revision/variant, and have a dev->ps2 flag controlling - controller mode, normally set according to the flags, but togglable on - AMIKey: - 0000 0000 0x00 IBM, AT - 0000 0001 0x01 MR - 0000 0010 0x02 Xi8088, clone of IBM PS/2 type 1 - 0001 0000 0x10 Olivetti - 0010 0000 0x20 Toshiba - 0011 0000 0x30 Quadtel - 0100 0000 0x40 Phoenix MultiKey/42 - 0101 0000 0x50 AMI KF - 0101 0001 0x51 AMI KH - 0101 0010 0x52 AMIKey - 0101 0011 0x53 AMIKey-2 - 0101 0100 0x54 JetKey (clone of AMI KF/AMIKey) - 0110 0000 0x60 Award - 0110 0001 0x61 Award 286 (has some AMI commands apparently) - 0111 0000 0x70 Siemens -*/ - -/* Standard IBM controller */ #define KBC_VEN_GENERIC 0x00 -/* All commands are standard PS/2 */ +#define KBC_VEN_AMI 0x04 #define KBC_VEN_IBM_MCA 0x08 -/* Standard IBM commands, differs in input port bits */ -#define KBC_VEN_IBM_PS1 0x10 -/* Olivetti - proprietary commands and port 62h with switches - readout */ -#define KBC_VEN_OLIVETTI 0x20 -/* Toshiba T3100e - has a bunch of proprietary commands, also sets - IFULL on command AA */ -#define KBC_VEN_TOSHIBA 0x28 -/* Standard IBM commands, uses input port as a switches readout */ -#define KBC_VEN_NCR 0x30 -/* Xi8088 - standard IBM commands, has a turbo bit on port 61h, and the - polarity of the video type bit in the input port is inverted */ -#define KBC_VEN_XI8088 0x38 -/* QuadtelKey - currently guesswork */ -#define KBC_VEN_QUADTEL 0x40 -/* Phoenix MultiKey/42 - not yet implemented */ -#define KBC_VEN_PHOENIX 0x48 -/* Generic commands, XI8088-like input port handling of video type, - maybe we just need a flag for that? */ -#define KBC_VEN_ACER 0x50 -/* AMI KF/KH/AMIKey/AMIKey-2 */ -#define KBC_VEN_AMI 0xf0 -/* Standard AMI commands, differs in input port bits */ -#define KBC_VEN_INTEL_AMI 0xf8 -#define KBC_VEN_MASK 0xf8 - - -/* Flags should be fully 32-bit: - Bits 7- 0: Vendor and revision/variant; - Bits 15- 8: Input port mask; - Bits 23-16: Input port bits that are always on; - Bits 31-24: Flags: - Bit 0: Invert P1 video type bit polarity; - Bit 1: Is PS/2; - Bit 2: Translation forced always off. - - So for example, the IBM PS/2 type 1 controller flags would be: 00000010 00000000 11111111 00000000 = 0200ff00 . */ +#define KBC_VEN_QUADTEL 0x0c +#define KBC_VEN_TOSHIBA 0x10 +#define KBC_VEN_XI8088 0x14 +#define KBC_VEN_IBM_PS1 0x18 +#define KBC_VEN_ACER 0x1c +#define KBC_VEN_INTEL_AMI 0x20 +#define KBC_VEN_OLIVETTI 0x24 +#define KBC_VEN_NCR 0x28 +#define KBC_VEN_SAMSUNG 0x2c +#define KBC_VEN_MASK 0x3c typedef struct { - uint8_t status, ib, ob, p1, p2, old_p2, p2_locked, fast_a20_phase, - secr_phase, mem_index, ami_stat, ami_mode, - kbc_in, kbc_cmd, kbc_in_cmd, kbc_poll_phase, kbc_to_send, - kbc_send_pending, kbc_channel, kbc_stat_hi, kbc_wait_for_response, inhibit, - kbd_in, kbd_cmd, kbd_in_cmd, kbd_written, kbd_data, kbd_poll_phase, kbd_inhibit, - mouse_in, mouse_cmd, mouse_in_cmd, mouse_written, mouse_data, mouse_poll_phase, mouse_inhibit, - kbc_written[3], kbc_data[3]; + uint8_t command, status, old_status, out, old_out, secr_phase, + mem_addr, input_port, output_port, old_output_port, + key_command, output_locked, ami_stat, want60, + wantirq, key_wantdata, refresh, first_write; - uint8_t mem_int[0x40], mem[0x240]; + uint8_t mem[0x100]; - uint16_t last_irq, kbc_phase, kbd_phase, mouse_phase; + int last_irq, old_last_irq, + reset_delay, + out_new, out_delayed; uint32_t flags; - pc_timer_t pulse_cb, send_delay_timer; + pc_timer_t refresh_time, pulse_cb; uint8_t (*write60_ven)(void *p, uint8_t val); uint8_t (*write64_ven)(void *p, uint8_t val); + + pc_timer_t send_delay_timer; } atkbd_t; -enum -{ - CHANNEL_KBC = 0, - CHANNEL_KBD, - CHANNEL_MOUSE -}; - -enum -{ - KBD_MAIN_LOOP = 0, - KBD_CMD_PROCESS -}; - -enum -{ - MOUSE_MAIN_LOOP_1 = 0, - MOUSE_CMD_PROCESS, - MOUSE_CMD_END, - MOUSE_MAIN_LOOP_2 -}; - -enum { - KBC_MAIN_LOOP = 0, - KBC_RESET = 1, - KBC_WAIT = 4, - KBC_WAIT_FOR_KBD, - KBC_WAIT_FOR_MOUSE, - KBC_WAIT_FOR_BOTH -}; - - -static void kbd_cmd_process(atkbd_t *dev); - -static void kbc_wait(atkbd_t *dev, uint8_t flags); - - /* bit 0 = repeat, bit 1 = makes break code? */ uint8_t keyboard_set3_flags[512]; uint8_t keyboard_set3_all_repeat; @@ -210,9 +125,9 @@ uint8_t keyboard_set3_all_break; /* Bits 0 - 1 = scan code set, bit 6 = translate or not. */ uint8_t keyboard_mode = 0x42; -uint8_t * ami_copr = (uint8_t *) "(C)1994 AMI"; - +static uint8_t key_ctrl_queue[16]; +static int key_ctrl_queue_start = 0, key_ctrl_queue_end = 0; static uint8_t key_queue[16]; static int key_queue_start = 0, key_queue_end = 0; uint8_t mouse_queue[16]; @@ -653,26 +568,9 @@ static const scancode scancode_set3[512] = { }; -#define UISTR_LEN 256 -static char kbd_str[UISTR_LEN]; /* UI output string */ static void add_data_kbd(uint16_t val); -extern void ui_sb_bugui(char *__str); - - -static void -kbd_status(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vsprintf(kbd_str, fmt, ap); - ui_sb_bugui(kbd_str); - va_end(ap); -} - - #ifdef ENABLE_KEYBOARD_AT_LOG int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG; @@ -733,6 +631,9 @@ kbc_queue_reset(uint8_t channel) } else if (channel == 1) { key_queue_start = key_queue_end = 0; memset(key_queue, 0x00, sizeof(key_queue)); + } else { + key_ctrl_queue_start = key_ctrl_queue_end = 0; + memset(key_ctrl_queue, 0x00, sizeof(key_ctrl_queue)); } } @@ -740,6 +641,15 @@ kbc_queue_reset(uint8_t channel) static void kbc_queue_add(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) { + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + + if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) + stat_hi |= ((dev->input_port & 0x80) ? 0x10 : 0x00); + else + stat_hi |= 0x10; + + dev->status = (dev->status & 0x0f) | stat_hi; + if (channel == 2) { kbd_log("ATkbc: mouse_queue[%02X] = %02X;\n", mouse_queue_end, val); mouse_queue[mouse_queue_end] = val; @@ -748,1045 +658,83 @@ kbc_queue_add(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); key_queue[key_queue_end] = val; key_queue_end = (key_queue_end + 1) & 0xf; - } else - fatal("Adding %02X to invalid channel %02X\n", val, channel); + } else { + kbd_log("ATkbc: key_ctrl_queue[%02X] = %02X;\n", key_ctrl_queue_end, val); + key_ctrl_queue[key_ctrl_queue_end] = val; + key_ctrl_queue_end = (key_ctrl_queue_end + 1) & 0xf; + } +} + + +static void +add_to_kbc_queue_front(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) +{ + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + + if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) + stat_hi |= ((dev->input_port & 0x80) ? 0x10 : 0x00); + else + stat_hi |= 0x10; + + kbd_log("ATkbc: Adding %02X to front...\n", val); + dev->wantirq = 0; + if (channel == 2) { + if (dev->mem[0] & 0x02) + picint(0x1000); + dev->last_irq = 0x1000; + } else { + if (dev->mem[0] & 0x01) + picint(2); + dev->last_irq = 2; + } + dev->out = val; + if (channel == 2) + dev->status = (dev->status & ~STAT_IFULL) | (STAT_OFULL | STAT_MFULL) | stat_hi; + else + dev->status = (dev->status & ~(STAT_IFULL | STAT_MFULL)) | STAT_OFULL | stat_hi; } static void add_data_kbd_queue(atkbd_t *dev, int direct, uint8_t val) { - if ((!keyboard_scan && !direct) || (key_queue_end >= 16)) { - kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i\n", !keyboard_scan, (key_queue_end >= 16)); + if ((!keyboard_scan && !direct) || (dev->reset_delay > 0) || (key_queue_end >= 16)) { + kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i, %i\n", !keyboard_scan, (dev->reset_delay > 0), (key_queue_end >= 16)); return; } - - kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); + kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); kbc_queue_add(dev, val, 1, 0x00); kbd_last_scan_code = val; } -static void -kbc_send(atkbd_t *dev, uint8_t val, uint8_t channel) -{ - dev->kbc_written[channel] = 1; - dev->kbc_data[channel] = val; -} - static void -kbd_send_to_host(atkbd_t *dev, uint8_t val) +add_data_kbd_direct(atkbd_t *dev, uint8_t val) { - kbc_send(dev, val, CHANNEL_KBD); -} + int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); + int translate = (keyboard_mode & 0x40); + uint8_t send; - -static void -kbd_chip_reset(atkbd_t *dev) -{ - kbc_queue_reset(1); - dev->kbc_written[1] = 0x00; - kbd_last_scan_code = 0x00; - - /* Set scan code set to 2. */ - keyboard_mode = (keyboard_mode & 0xfc) | 0x02; - set_scancode_map(dev); - - dev->kbd_phase = 0; - dev->kbd_in = 0; -} - - -static void -kbd_command(atkbd_t *dev) -{ - uint8_t val = dev->kbd_data; - - if ((dev->kbd_phase > 0) && (dev->kbd_cmd == 0xff)) { - dev->kbd_phase++; - if (dev->kbd_phase == RESET_DELAY_TIME) { - kbd_send_to_host(dev, 0xaa); - dev->kbd_phase = 0; - dev->kbd_cmd = 0x00; - } - return; - } - - if (dev->kbd_phase == 2) { - dev->kbd_phase = 0; - - switch (dev->kbd_cmd) { - case 0xf2: - kbd_send_to_host(dev, 0x83); - break; - default: - fatal("Invalid command for phase 2: %02X\n", dev->kbd_cmd); - break; - } - - /* Keyboard command is now done. */ - if (dev->kbd_phase == 0) - dev->kbd_cmd = 0x00; - return; - } else if (dev->kbd_phase == 1) { - dev->kbd_phase = 0; - - switch (dev->kbd_cmd) { - case 0xf0: - kbd_log("Get scan code set: %02X\n", keyboard_mode & 3); - kbd_send_to_host(dev, keyboard_mode & 3); - break; - case 0xf2: - kbd_send_to_host(dev, 0xab); - dev->kbd_phase = 2; - break; - default: - fatal("Invalid command for phase 1: %02X\n", dev->kbd_cmd); - break; - } - - /* Keyboard command is now done. */ - if (dev->kbd_phase == 0) - dev->kbd_cmd = 0x00; - return; - } - - if (dev->kbd_in && (val < 0xed)) { - dev->kbd_in = 0; - dev->kbd_phase = 0; - - switch (dev->kbd_cmd) { - case 0xed: /* set/reset LEDs */ - kbd_log("ATkbd: set LEDs [%02x]\n", val); - kbd_send_to_host(dev, 0xfa); - break; - - case 0xf0: /* get/set scancode set */ - kbd_send_to_host(dev, 0xfa); - if (val == 0) - dev->kbd_phase = 1; - else { - if ((val <= 3) && (val != 1)) { - keyboard_mode &= 0xfc; - keyboard_mode |= (val & 3); - kbd_log("Scan code set now: %02X\n", val); - } - set_scancode_map(dev); - } - break; - - case 0xf3: /* set typematic rate/delay */ - kbd_send_to_host(dev, 0xfa); - break; - - default: - kbd_log("ATkbd: bad keyboard 0060 write %02X command %02X\n", val, dev->kbd_cmd); - kbd_send_to_host(dev, 0xfe); - break; - } - - /* Keyboard command is now done. */ - if (dev->kbd_phase == 0) - dev->kbd_cmd = 0x00; - } else { - /* No keyboard command in progress. */ - dev->kbd_in = 0; - dev->kbd_cmd = 0x00; - dev->kbd_phase = 0; - - switch (val) { - case 0x00: - kbd_log("ATkbd: command 00\n"); - kbd_send_to_host(dev, 0xfa); - break; - - case 0x05: /*??? - sent by NT 4.0*/ - kbd_log("ATkbd: command 05 (NT 4.0)\n"); - kbd_send_to_host(dev, 0xfe); - break; - - case 0xed: /* set/reset LEDs */ - kbd_log("ATkbd: set/reset leds\n"); - kbd_send_to_host(dev, 0xfa); - - dev->kbd_in = 1; - break; - - case 0xee: /* diagnostic echo */ - kbd_log("ATkbd: ECHO\n"); - kbd_send_to_host(dev, 0xee); - break; - - case 0xef: /* NOP (reserved for future use) */ - kbd_log("ATkbd: NOP\n"); - break; - - case 0xf0: /* get/set scan code set */ - kbd_log("ATkbd: scan code set\n"); - kbd_send_to_host(dev, 0xfa); - dev->kbd_in = 1; - break; - - case 0xf2: /* read ID */ - /* Fixed as translation will be done in add_data_kbd(). */ - kbd_log("ATkbd: read keyboard id\n"); - /* TODO: After keyboard type selection is implemented, make this - return the correct keyboard ID for the selected type. */ - kbd_send_to_host(dev, 0xfa); - dev->kbd_phase = 1; - break; - - case 0xf3: /* set typematic rate/delay */ - kbd_log("ATkbd: set typematic rate/delay\n"); - kbd_send_to_host(dev, 0xfa); - dev->kbd_in = 1; - break; - - case 0xf4: /* enable keyboard */ - kbd_log("ATkbd: enable keyboard\n"); - kbd_send_to_host(dev, 0xfa); - keyboard_scan = 1; - break; - - case 0xf5: /* set defaults and disable keyboard */ - case 0xf6: /* set defaults */ - kbd_log("ATkbd: set defaults%s\n", (val == 0xf6) ? "" : " and disable keyboard"); - keyboard_scan = (val == 0xf6); - kbd_log("val = %02X, keyboard_scan = %i, dev->mem[0x20] = %02X\n", - val, keyboard_scan, dev->mem[0x20]); - kbd_send_to_host(dev, 0xfa); - - keyboard_set3_all_break = 0; - keyboard_set3_all_repeat = 0; - memset(keyboard_set3_flags, 0, 512); - keyboard_mode = (keyboard_mode & 0xfc) | 0x02; - set_scancode_map(dev); - break; - - case 0xf7: /* set all keys to repeat */ - kbd_log("ATkbd: set all keys to repeat\n"); - kbd_send_to_host(dev, 0xfa); - keyboard_set3_all_break = 1; - break; - - case 0xf8: /* set all keys to give make/break codes */ - kbd_log("ATkbd: set all keys to give make/break codes\n"); - kbd_send_to_host(dev, 0xfa); - keyboard_set3_all_break = 1; - break; - - case 0xf9: /* set all keys to give make codes only */ - kbd_log("ATkbd: set all keys to give make codes only\n"); - kbd_send_to_host(dev, 0xfa); - keyboard_set3_all_break = 0; - break; - - case 0xfa: /* set all keys to repeat and give make/break codes */ - kbd_log("ATkbd: set all keys to repeat and give make/break codes\n"); - kbd_send_to_host(dev, 0xfa); - keyboard_set3_all_repeat = 1; - keyboard_set3_all_break = 1; - break; - - case 0xfe: /* resend last scan code */ - kbd_log("ATkbd: reset last scan code\n"); - kbd_send_to_host(dev, kbd_last_scan_code); - break; - - case 0xff: /* reset */ - kbd_log("ATkbd: kbd reset\n"); - kbd_chip_reset(dev); - kbd_send_to_host(dev, 0xfa); - dev->kbd_phase = 1; - break; - - default: - kbd_log("ATkbd: bad keyboard command %02X\n", val); - kbd_send_to_host(dev, 0xfe); - } - - /* If command needs data, remember command. */ - if ((dev->kbd_in == 1) || (dev->kbd_phase > 0)) - dev->kbd_cmd = val; - } -} - - -static void -kbd_do_command(atkbd_t *dev) -{ - kbd_command(dev); - if (dev->kbd_written) - dev->kbd_poll_phase = KBD_CMD_PROCESS; - else if ((dev->kbd_phase == 0) && !dev->kbd_in) { - dev->kbd_in_cmd = 0; - if (dev->kbd_data != 0xf5) - keyboard_scan = 1; - dev->kbd_poll_phase = KBD_MAIN_LOOP; - } else { - keyboard_scan = 0; - dev->kbd_in_cmd = 1; - dev->kbd_poll_phase = KBD_CMD_PROCESS; - } -} - - -static void -kbd_nack(atkbd_t *dev) -{ - kbd_send_to_host(dev, 0xfe); - dev->kbd_poll_phase = KBD_MAIN_LOOP; -} - - -static void -kbd_main_loop(atkbd_t *dev) -{ - uint8_t scan = !dev->kbd_inhibit && keyboard_scan; - - if (dev->kbd_written) { - dev->kbd_written = 0; - kbd_cmd_process(dev); - } else if (scan && (key_queue_start != key_queue_end)) { - /* Scan here. */ - kbd_log("ATkbd: Get %02X from FIFO\n", key_queue[key_queue_start]); - kbd_send_to_host(dev, key_queue[key_queue_start]); - key_queue_start = (key_queue_start + 1) & 0xf; - } -} - - -static void -kbd_cmd_process(atkbd_t *dev) -{ - uint8_t written = dev->kbd_written; - - /* We want data, nothing has been written yet, return. */ - if (dev->kbd_in && !dev->kbd_written) + if (dev->reset_delay) return; - dev->kbd_written = 0; + translate = translate || (keyboard_mode & 0x40) || xt_mode; + translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); - if (!written && !keyboard_scan && dev->kbd_in_cmd && (dev->kbd_phase > 0)) { - kbd_log("ATkbd: Keyboard not written, not scanning, in command, and phase > 0\n"); - kbd_do_command(dev); - } else if (dev->kbd_data == 0xfe) { - kbd_log("ATkbd: Send last byte %02X\n", kbd_last_scan_code); - kbd_send_to_host(dev, kbd_last_scan_code); - dev->kbd_poll_phase = KBD_MAIN_LOOP; - } else if (dev->kbd_data == 0xee) { - kbd_log("ATkbd: Echo EE\n"); - kbd_send_to_host(dev, 0xee); - dev->kbd_poll_phase = KBD_MAIN_LOOP; - } else if (dev->kbd_data >= 0xed) { - kbd_log("ATkbd: Command %02X\n", dev->kbd_data); - if (!keyboard_scan && dev->kbd_in_cmd && (dev->kbd_cmd == 0xed)) { - kbd_log("ATkbd: Not scanning, in command, old command is ED\n"); - keyboard_scan = 1; - dev->kbd_in_cmd = 0; - } - kbd_do_command(dev); - } else { - if (!keyboard_scan && dev->kbd_in_cmd) { - if ((dev->kbd_cmd == 0xf3) && (dev->kbd_data & 0x80)) { - kbd_log("ATkbd: Command F3 data %02X has bit 7 set\n", dev->kbd_data); - kbd_nack(dev); - } else { - kbd_log("ATkbd: Command %02X data %02X\n", dev->kbd_cmd, dev->kbd_data); - kbd_do_command(dev); - } - } else { - kbd_log("ATkbd: Scanning or not in command, NACK\n"); - kbd_nack(dev); - } - } -} + if (translate) + send = nont_to_t[val]; + else + send = val; - -/* Keyboard processing */ -static void -kbd_process(atkbd_t *dev) -{ - /* The real 8048 keyboard firmware stops transmitting if host wants to transmit. */ - if (dev->kbc_written[1] && dev->kbd_written) - dev->kbc_written[1] = 0; - - /* The host has either acknowledged the transmitted byte or we have not transmitted anything (yet). */ - if (!dev->kbc_written[1]) switch (dev->kbd_poll_phase) { - case KBD_MAIN_LOOP: - kbd_main_loop(dev); - break; - case KBD_CMD_PROCESS: - kbd_cmd_process(dev); - break; - } + add_data_kbd_queue(dev, 1, send); } static void -kbc_send_to_ob(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) +add_data_kbd_raw(atkbd_t *dev, uint8_t val) { - uint8_t ch = (channel > 0) ? channel : 1; - uint8_t do_irq = (dev->mem[0x20] & ch); - int translate = (channel == 1) && (keyboard_mode & 0x60); - - if ((channel == 2) && !(dev->flags & KBC_FLAG_PS2)) - return; - - stat_hi |= dev->inhibit; - - if (!dev->kbc_send_pending) { - dev->kbc_send_pending = 1; - dev->kbc_to_send = val; - dev->kbc_channel = channel; - dev->kbc_stat_hi = stat_hi; - return; - } - - if (translate) { - /* Allow for scan code translation. */ - if (val == 0xf0) { - kbd_log("ATkbd: translate is on, F0 prefix detected\n"); - sc_or = 0x80; - return; - } - - /* Skip break code if translated make code has bit 7 set. */ - if ((sc_or == 0x80) && (val & 0x80)) { - kbd_log("ATkbd: translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val); - sc_or = 0; - return; - } - } - - dev->last_irq = (ch == 2) ? 0x1000 : 0x0002; - if (do_irq) { - kbd_log("[%04X:%08X] ATKbc: IRQ %i\n", CS, cpu_state.pc, (ch == 2) ? 12 : 1); - picint(dev->last_irq); - } - kbd_log("ATkbc: %02X coming from channel %i (%i)\n", val, channel, do_irq); - dev->ob = translate ? (nont_to_t[val] | sc_or) : val; - - dev->status = (dev->status & 0x0f) | (stat_hi | (dev->mem[0x20] & STAT_SYSFLAG) | STAT_OFULL); - if (ch == 2) - dev->status |= STAT_MFULL; - - if (translate && (sc_or == 0x80)) - sc_or = 0; -} - - -static void -write_output(atkbd_t *dev, uint8_t val) -{ - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - kbd_log("ATkbc: write output port: %02X (old: %02X)\n", val, dev->p2); - - if (!(dev->flags & KBC_FLAG_PS2)) - val |= ((dev->mem[0x20] << 4) & 0x30); - - dev->kbd_inhibit = (val & 0x40); - dev->mouse_inhibit = (val & 0x08); - - if ((dev->p2 ^ val) & 0x20) { /*IRQ 12*/ - if (val & 0x20) { - kbd_log("ATkbc: write_output(): IRQ 12\n"); - picint(1 << 12); - } else - picintc(1 << 12); - } - if ((dev->p2 ^ val) & 0x10) { /*IRQ 1*/ - if (val & 0x10) { - kbd_log("ATkbc: write_output(): IRQ 1\n"); - picint(1 << 1); - } else - picintc(1 << 1); - } - if ((dev->p2 ^ val) & 0x02) { /*A20 enable change*/ - mem_a20_key = val & 0x02; - mem_a20_recalc(); - flushmmucache(); - } - if ((dev->p2 ^ val) & 0x01) { /*Reset*/ - if (! (val & 0x01)) { - /* Pin 0 selected. */ - softresetx86(); /*Pulse reset!*/ - cpu_set_edx(); - smbase = is_am486dxl ? 0x00060000 : 0x00030000; - } - } - /* Mask off the A20 stuff because we use mem_a20_key directly for that. */ - dev->p2 = val; -} - - -static void -write_cmd(atkbd_t *dev, uint8_t val) -{ - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - kbd_log("ATkbc: write command byte: %02X (old: %02X)\n", val, dev->mem[0x20]); - - /* PS/2 type 2 keyboard controllers always force the XLAT bit to 0. */ - if ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2) - val &= ~CCB_TRANSLATE; - - dev->mem[0x20] = val; - - /* Scan code translate ON/OFF. */ - keyboard_mode &= 0x93; - keyboard_mode |= (val & MODE_MASK); - - kbd_log("ATkbc: keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled"); - - /* ISA AT keyboard controllers use bit 5 for keyboard mode (1 = PC/XT, 2 = AT); - PS/2 (and EISA/PCI) keyboard controllers use it as the PS/2 mouse enable switch. - The AMIKEY firmware apparently uses this bit for something else. */ - if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) { - keyboard_mode &= ~CCB_PCMODE; - - kbd_log("ATkbc: mouse interrupt is now %s\n", (val & 0x02) ? "enabled" : "disabled"); - } - - if (!(dev->flags & KBC_FLAG_PS2)) { - /* Update the output port to mirror the KBD DIS and AUX DIS bits, if active. */ - write_output(dev, dev->p2); - } - - kbd_log("Command byte now: %02X (%02X)\n", dev->mem[0x20], val); - - dev->status = (dev->status & ~STAT_SYSFLAG) | (val & STAT_SYSFLAG); -} - - -static void -pulse_output(atkbd_t *dev, uint8_t mask) -{ - if (mask != 0x0f) { - dev->old_p2 = dev->p2 & ~(0xf0 | mask); - kbd_log("pulse_output(): Output port now: %02X\n", dev->p2 & (0xf0 | mask | (dev->mem[0x20] & 0x30))); - write_output(dev, dev->p2 & (0xf0 | mask | (dev->mem[0x20] & 0x30))); - timer_set_delay_u64(&dev->pulse_cb, 6ULL * TIMER_USEC); - } -} - - -static void -set_enable_kbd(atkbd_t *dev, uint8_t enable) -{ - dev->mem[0x20] &= 0xef; - dev->mem[0x20] |= (enable ? 0x00 : 0x10); -} - - -static void -set_enable_mouse(atkbd_t *dev, uint8_t enable) -{ - dev->mem[0x20] &= 0xdf; - dev->mem[0x20] |= (enable ? 0x00 : 0x20); -} - - -static void -kbc_transmit(atkbd_t *dev, uint8_t val) -{ - kbc_send_to_ob(dev, val, 0, 0x00); -} - - -static void -kbc_command(atkbd_t *dev) -{ - uint8_t mask, val = dev->ib; - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - int bad = 1; - - if ((dev->kbc_phase > 0) && (dev->kbc_cmd == 0xac)) { - if (dev-> kbc_phase < 16) - kbc_transmit(dev, dev->mem[dev->kbc_phase]); - else if (dev-> kbc_phase == 16) - kbc_transmit(dev, (dev->p1 & 0xf0) | 0x80); - else if (dev-> kbc_phase == 17) - kbc_transmit(dev, dev->p2); - else if (dev-> kbc_phase == 18) - kbc_transmit(dev, dev->status); - - dev->kbc_phase++; - if (dev->kbc_phase == 19) { - dev->kbc_phase = 0; - dev->kbc_cmd = 0x00; - } - return; - } else if ((dev->kbc_phase > 0) && (dev->kbc_cmd == 0xa0) && (kbc_ven >= KBC_VEN_AMI)) { - val = ami_copr[dev->kbc_phase]; - kbc_transmit(dev, val); - if (val == 0x00) { - dev->kbc_phase = 0; - dev->kbc_cmd = 0x00; - } else - dev->kbc_phase++; - return; - } else if ((dev->kbc_in > 0) && (dev->kbc_cmd == 0xa5) && (dev->flags & KBC_FLAG_PS2)) { - /* load security */ - kbd_log("ATkbc: load security\n"); - dev->mem[0x50 + dev->kbc_in - 0x01] = val; - if ((dev->kbc_in == 0x80) && (val != 0x00)) { - /* Security string too long, set it to 0x00. */ - dev->mem[0x50] = 0x00; - dev->kbc_in = 0; - dev->kbc_cmd = 0; - } else if (val == 0x00) { - /* Security string finished. */ - dev->kbc_in = 0; - dev->kbc_cmd = 0; - } else /* Increase pointer and request another byte. */ - dev->kbc_in++; - return; - } - - /* If the written port is 64, go straight to the beginning of the command. */ - if (!(dev->status & STAT_CD) && dev->kbc_in) { - /* Write data to controller. */ - dev->kbc_in = 0; - dev->kbc_phase = 0; - - switch (dev->kbc_cmd) { - case 0x60 ... 0x7f: - if (dev->kbc_cmd == 0x60) - write_cmd(dev, val); - else - dev->mem[(dev->kbc_cmd & 0x1f) + 0x20] = val; - break; - - case 0xc7: /* or input port with system data */ - dev->p1 |= val; - break; - - case 0xcb: /* set keyboard mode */ - kbd_log("New AMIKey mode: %02X\n", val); - dev->ami_mode = val; - dev->flags &= ~KBC_FLAG_PS2; - if (val & 1) - dev->flags |= KBC_FLAG_PS2; - break; - - case 0xd1: /* write output port */ - kbd_log("ATkbc: write output port\n"); - if (dev->p2_locked) { - /*If keyboard controller lines P22-P23 are blocked, - we force them to remain unchanged.*/ - val &= ~0x0c; - val |= (dev->p2 & 0x0c); - } - write_output(dev, val); - break; - - case 0xd2: /* write to keyboard output buffer */ - kbd_log("ATkbc: write to keyboard output buffer\n"); - // kbc_send_to_ob(dev, val, 1, 0x00); - /* Should be channel 1, but we send to 0 to avoid translation, - since bytes output using this command do *NOT* get translated. */ - kbc_send_to_ob(dev, val, 0, 0x00); - break; - - case 0xd3: /* write to mouse output buffer */ - kbd_log("ATkbc: write to mouse output buffer\n"); - if (dev->flags & KBC_FLAG_PS2) - kbc_send_to_ob(dev, val, 2, 0x00); - break; - - case 0xd4: /* write to mouse */ - kbd_log("ATkbc: write to mouse (%02X)\n", val); - - if (dev->flags & KBC_FLAG_PS2) { - set_enable_mouse(dev, 1); - dev->mem[0x20] &= ~0x20; - if (mouse_write && !dev->kbc_written[2]) { - kbd_log("ATkbc: Sending %02X to mouse...\n", dev->ib); - dev->mouse_data = val; - dev->mouse_written = 1; - dev->kbc_wait_for_response = 2; - } else - kbc_send_to_ob(dev, 0xfe, 2, 0x40); - } - break; - - default: - /* - * Run the vendor-specific handler - * if we have one. Otherwise, or if - * it returns an error, log a bad - * controller command. - */ - if (dev->write60_ven) - bad = dev->write60_ven(dev, val); - -#ifdef ENABLE_KEYBOARD_AT_LOG - if (bad) - kbd_log("ATkbc: bad controller command %02x data %02x\n", dev->kbc_cmd, val); -#endif - } - } else { - /* Controller command. */ - kbd_log("ATkbc: Controller command: %02X\n", val); - dev->kbc_in = 0; - dev->kbc_phase = 0; - - switch (val) { - /* Read data from KBC memory. */ - case 0x20 ... 0x3f: - kbc_transmit(dev, dev->mem[(val & 0x1f) + 0x20]); - break; - - /* Write data to KBC memory. */ - case 0x60 ... 0x7f: - dev->kbc_in = 1; - break; - - case 0xaa: /* self-test */ - kbd_log("ATkbc: self-test\n"); - write_output(dev, (dev->flags & KBC_FLAG_PS2) ? 0x4b : 0xcf); - - /* Always reinitialize all queues - the real hardware pulls keyboard and mouse - clocks high, which stops keyboard scanning. */ - kbd_log("ATkbc: self-test reinitialization\n"); - dev->kbd_in_cmd = dev->mouse_in_cmd = 0; - dev->status &= ~STAT_OFULL; - dev->last_irq = 0; - dev->kbc_phase = 0; - - /* Phoenix MultiKey should have 0x60 | STAT_SYSFLAG. */ - if (dev->flags & KBC_FLAG_PS2) - write_cmd(dev, 0x30 | STAT_SYSFLAG); - else - write_cmd(dev, 0x10 | STAT_SYSFLAG); - kbc_transmit(dev, 0x55); - break; - - case 0xab: /* interface test */ - kbd_log("ATkbc: interface test\n"); - /* No error. */ - kbc_transmit(dev, 0x00); - break; - - case 0xac: /* diagnostic dump */ - kbd_log("ATkbc: diagnostic dump\n"); - kbc_transmit(dev, dev->mem[0x20]); - dev->kbc_phase = 1; - break; - - case 0xad: /* disable keyboard */ - kbd_log("ATkbc: disable keyboard\n"); - set_enable_kbd(dev, 0); - break; - - case 0xae: /* enable keyboard */ - kbd_log("ATkbc: enable keyboard\n"); - set_enable_kbd(dev, 1); - break; - - case 0xc7: /* or input port with system data */ - kbd_log("ATkbc: Phoenix - or input port with system data\n"); - dev->kbc_in = 1; - break; - - case 0xca: /* read keyboard mode */ - kbd_log("ATkbc: AMI - read keyboard mode\n"); - kbc_transmit(dev, dev->ami_mode); - break; - - case 0xcb: /* set keyboard mode */ - kbd_log("ATkbc: AMI - set keyboard mode\n"); - dev->kbc_in = 1; - break; - - case 0xd0: /* read output port */ - kbd_log("ATkbc: read output port\n"); - mask = 0xff; - if (dev->mem[0x20] & 0x10) - mask &= 0xbf; - if ((dev->flags & KBC_FLAG_PS2) && (dev->mem[0x20] & 0x20)) - mask &= 0xf7; - kbc_transmit(dev, dev->p2 & mask); - break; - - case 0xd1: /* write output port */ - kbd_log("ATkbc: write output port\n"); - dev->kbc_in = 1; - break; - - case 0xd2: /* write keyboard output buffer */ - kbd_log("ATkbc: write keyboard output buffer\n"); - if (dev->flags & KBC_FLAG_PS2) - dev->kbc_in = 1; - else - kbc_transmit(dev, 0x00); /* NCR */ - break; - - case 0xdd: /* disable A20 address line */ - case 0xdf: /* enable A20 address line */ - kbd_log("ATkbc: %sable A20\n", (val == 0xdd) ? "dis": "en"); - write_output(dev, (dev->p2 & 0xfd) | (val & 0x02)); - break; - - case 0xe0: /* read test inputs */ - kbd_log("ATkbc: read test inputs\n"); - kbc_transmit(dev, 0x00); - break; - - case 0xe1: case 0xea: - kbd_log("ATkbc: setting P23-P21 to %01X\n", val & 0x0e); - write_output(dev, (dev->p2 & 0xf1) | (val & 0x0e)); - break; - - default: - /* - * Unrecognized controller command. - * - * If we have a vendor-specific handler, run - * that. Otherwise, or if that handler fails, - * log a bad command. - */ - if (dev->write64_ven) - bad = dev->write64_ven(dev, val); - - kbd_log(bad ? "ATkbc: bad controller command %02X\n" : "", val); - } - - /* If the command needs data, remember the command. */ - if (dev->kbc_in || (dev->kbc_phase > 0)) - dev->kbc_cmd = val; - } -} - - -static void -kbc_dev_data_to_ob(atkbd_t *dev, uint8_t channel) -{ - dev->kbc_written[channel] = 0; - kbd_log("ATkbd: Forwarding %02X from channel %i...\n", dev->kbc_data[channel], channel); - kbc_send_to_ob(dev, dev->kbc_data[channel], channel, 0x00); -} - - -static void -kbc_main_loop_scan(atkbd_t *dev) -{ - uint8_t port_dis = dev->mem[0x20] & 0x30; - uint8_t ps2 = (dev->flags & KBC_FLAG_PS2); - - if (!ps2) - port_dis |= 0x20; - - if (!(dev->status & STAT_OFULL)) { - if (port_dis & 0x20) { - if (!(port_dis & 0x10)) { - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Main loop\n" - "ATkbc: Scan: AUX DIS, KBD EN\n"); - // kbd_log("ATkbc: Scan: AUX DIS, KBD EN\n"); - /* Enable communication with keyboard. */ - dev->p2 &= 0xbf; - dev->kbd_inhibit = 0; - kbc_wait(dev, 1); - } -#ifdef ENABLE_KEYBOARD_AT_LOG - else { - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Main loop\n" - "ATkbc: Scan: AUX DIS, KBD DIS\n"); - // kbd_log("ATkbc: Scan: AUX DIS, KBD DIS\n"); - } -#endif - } else { - /* Enable communication with mouse. */ - dev->p2 &= 0xf7; - dev->mouse_inhibit = 0; - if (dev->mem[0x20] & 0x10) { - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Main loop\n" - "ATkbc: Scan: AUX EN , KBD DIS\n"); - // kbd_log("ATkbc: Scan: AUX EN , KBD DIS\n"); - kbc_wait(dev, 2); - } else { - /* Enable communication with keyboard. */ - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Main loop\n" - "ATkbc: Scan: AUX EN , KBD EN\n"); - // kbd_log("ATkbc: Scan: AUX EN , KBD EN\n"); - dev->p2 &= 0xbf; - dev->kbd_inhibit = 0; - kbc_wait(dev, 3); - } - } - } -#ifdef ENABLE_KEYBOARD_AT_LOG - else { - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Main loop\n" - "ATkbc: Scan: IBF not full and OBF full, do nothing\n"); - // kbd_log("ATkbc: Scan: IBF not full and OBF full, do nothing\n"); - } -#endif -} - - -static void -kbc_process_ib(atkbd_t *dev) -{ - dev->status &= ~STAT_IFULL; - - if (dev->status & STAT_CD) { - dev->kbc_in_cmd = 1; - kbc_command(dev); - - if ((dev->kbc_phase == 0) && !dev->kbc_in) - dev->kbc_in_cmd = 0; - else - return; - } else { - dev->mem[0x20] &= ~0x10; - dev->kbd_data = dev->ib; - dev->kbd_written = 1; - dev->kbc_wait_for_response = 1; - } - - dev->kbc_poll_phase = KBC_MAIN_LOOP; - if (!dev->kbc_wait_for_response) - kbc_main_loop_scan(dev); -} - - -static void -kbc_wait(atkbd_t *dev, uint8_t flags) -{ - if ((flags & 1) && dev->kbc_written[1]) { - /* Disable communication with mouse. */ - dev->p2 |= 0x08; - dev->mouse_inhibit = 1; - /* Send keyboard byte to host. */ - kbc_dev_data_to_ob(dev, CHANNEL_KBD); - dev->kbc_poll_phase = KBC_MAIN_LOOP; - } else if ((flags & 2) && dev->kbc_written[2]) { - /* Disable communication with keyboard. */ - dev->p2 |= 0x40; - dev->kbd_inhibit = 1; - /* Send mouse byte to host. */ - kbc_dev_data_to_ob(dev, CHANNEL_MOUSE); - dev->kbc_poll_phase = KBC_MAIN_LOOP; - } else if (dev->status & STAT_IFULL) { - /* Disable communication with keyboard and mouse. */ - dev->p2 |= 0x48; - dev->kbd_inhibit = dev->mouse_inhibit = 1; - kbc_process_ib(dev); - } else - dev->kbc_poll_phase = KBC_WAIT | flags; -} - - -/* Controller processing */ -static void -kbc_process(atkbd_t *dev) -{ - // kbd_log("ATkbc: kbc_process()\n"); - - /* If we're waiting for the response from the keyboard or mouse, do nothing - until the device has repsonded back. */ - if (dev->kbc_wait_for_response > 0) { - if (dev->kbc_written[dev->kbc_wait_for_response]) - dev->kbc_wait_for_response = 0; - else - return; - } - - if (dev->kbc_send_pending) { - kbd_log("ATkbc: Sending delayed %02X on channel %i with high status %02X\n", - dev->kbc_to_send, dev->kbc_channel, dev->kbc_stat_hi); - kbc_send_to_ob(dev, dev->kbc_to_send, dev->kbc_channel, dev->kbc_stat_hi); - dev->kbc_send_pending = 0; - } - - if (dev->kbc_poll_phase == KBC_RESET) { - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Reset loop()\n"); - - if (dev->status & STAT_IFULL) { - dev->status &= ~STAT_IFULL; - - if ((dev->status & STAT_CD) && (dev->ib == 0xaa)) { - dev->kbc_in_cmd = 1; - kbc_command(dev); - - if ((dev->kbc_phase == 0) && !dev->kbc_in) - dev->kbc_in_cmd = 0; - - dev->kbc_poll_phase = KBC_MAIN_LOOP; - } - } - - return; - } - - if (dev->kbc_in_cmd || (dev->kbc_phase > 0) || dev->kbc_in) { - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: In a command\n"); - if (!dev->kbc_in && (dev->status & STAT_OFULL)) { - kbd_log("ATkbc: !dev->kbc_in && (dev->status & STAT_OFULL)\n"); - return; /* We do not want input and we're waiting for the host to read the data - we transmitted, but it has not done that yet, do nothing. */ - } else if (dev->kbc_in && !(dev->status & STAT_IFULL)) { - kbd_log("ATkbc: dev->kbc_in && !(dev->status & STAT_IFULL)\n"); - return; /* We want input and the host has not provided us with any yet, do nothing. */ - } -#ifdef ENABLE_KEYBOARD_AT_LOG - else - kbd_log("ATkbc: Normal condition\n"); -#endif - - if (dev->status & STAT_IFULL) { - dev->status &= ~STAT_IFULL; - - if (dev->status & STAT_CD) { - kbd_log("ATkbc: Resetting command\n"); - dev->kbc_phase = 0; - dev->kbc_in = 0; - } - } - - /* Process command. */ - kbc_command(dev); - - if ((dev->kbc_phase == 0) && !dev->kbc_in) - dev->kbc_in_cmd = 0; - else - return; - - if (!(dev->status & STAT_OFULL)) - kbc_main_loop_scan(dev); - /* Make absolutely sure to do nothing if OBF is full and IBF is empty. */ - } else if (!(dev->status & STAT_OFULL) || (dev->status & STAT_IFULL)) switch (dev->kbc_poll_phase) { - case KBC_MAIN_LOOP: - // kbd_log("ATkbc: Main loop\n"); - if (dev->status & STAT_IFULL) { - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Main loop\n" - "ATkbc: IBF full, process\n"); - kbc_process_ib(dev); - } else - kbc_main_loop_scan(dev); - break; - case KBC_WAIT_FOR_KBD: - case KBC_WAIT_FOR_MOUSE: - case KBC_WAIT_FOR_BOTH: - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Scan: Phase %i\n", dev->kbc_poll_phase); - kbc_wait(dev, dev->kbc_poll_phase & 3); - break; - default: - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Scan: Invalid phase %i\n", dev->kbc_poll_phase); - break; - } + add_data_kbd_queue(dev, 1, val); } @@ -1794,29 +742,105 @@ static void kbd_poll(void *priv) { atkbd_t *dev = (atkbd_t *)priv; +#ifdef ENABLE_KEYBOARD_AT_LOG + const uint8_t channels[4] = { 1, 2, 0, 0 }; +#endif timer_advance_u64(&dev->send_delay_timer, (100ULL * TIMER_USEC)); - /* We process all three devices at the same time, in an arbitrary order. */ + if (dev->out_new != -1 && !dev->last_irq) { + dev->wantirq = 0; + if (dev->out_new & 0x100) { + if (dev->mem[0] & 0x02) + picint(0x1000); + kbd_log("ATkbc: %02X coming from channel 2\n"); + dev->out = dev->out_new & 0xff; + dev->out_new = -1; + dev->status = (dev->status & ~STAT_IFULL) | (STAT_OFULL | STAT_MFULL); + dev->last_irq = 0x1000; + } else { + if (dev->mem[0] & 0x01) + picint(2); + kbd_log("ATkbc: %02X coming from channel %i\n", dev->out_new & 0xff, channels[(dev->out_new >> 8) & 0x03]); + dev->out = dev->out_new & 0xff; + dev->out_new = -1; + dev->status = (dev->status & ~(STAT_IFULL | STAT_MFULL)) | STAT_OFULL; + dev->last_irq = 2; + } + } - /* Keyboard processing */ - kbd_process(dev); + if (dev->out_new == -1 && !(dev->status & STAT_OFULL) && key_ctrl_queue_start != key_ctrl_queue_end) { + kbd_log("ATkbc: %02X on channel 0\n", key_ctrl_queue[key_ctrl_queue_start]); + dev->out_new = key_ctrl_queue[key_ctrl_queue_start] | 0x200; + key_ctrl_queue_start = (key_ctrl_queue_start + 1) & 0xf; + } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && dev->out_delayed != -1) { + kbd_log("ATkbc: %02X delayed on channel %i\n", dev->out_delayed & 0xff, channels[(dev->out_delayed >> 8) & 0x03]); + dev->out_new = dev->out_delayed; + dev->out_delayed = -1; + } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && mouse_queue_start != mouse_queue_end) { + kbd_log("ATkbc: %02X on channel 2\n", mouse_queue[mouse_queue_start]); + dev->out_new = mouse_queue[mouse_queue_start] | 0x100; + mouse_queue_start = (mouse_queue_start + 1) & 0xf; + } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && !(dev->mem[0] & 0x10) && key_queue_start != key_queue_end) { + kbd_log("ATkbc: %02X on channel 1\n", key_queue[key_queue_start]); + dev->out_new = key_queue[key_queue_start]; + key_queue_start = (key_queue_start + 1) & 0xf; + } - /* TODO: Mouse processing */ - // mouse_process(dev); + if (dev->reset_delay) { + dev->reset_delay--; + if (!dev->reset_delay) { + kbd_log("ATkbc: Sending AA on keyboard reset...\n"); + add_data_kbd_direct(dev, 0xaa); + } + } +} - /* Controller processing */ - kbc_process(dev); + +static void +add_data(atkbd_t *dev, uint8_t val) +{ + kbd_log("ATkbc: add to queue\n"); + + kbd_log("ATkbc: key_ctrl_queue[%02X] = %02X;\n", key_ctrl_queue_end, val); + kbc_queue_add(dev, val, 0, 0x00); + + if (!(dev->out_new & 0x300)) { + dev->out_delayed = dev->out_new; + dev->out_new = -1; + } } static void add_data_vals(atkbd_t *dev, uint8_t *val, uint8_t len) { + int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); + int translate = (keyboard_mode & 0x40); int i; + uint8_t or = 0; + uint8_t send; - for (i = 0; i < len; i++) - add_data_kbd_queue(dev, 0, val[i]); + if (dev->reset_delay) + return; + + translate = translate || (keyboard_mode & 0x40) || xt_mode; + translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); + + for (i = 0; i < len; i++) { + if (translate) { + if (val[i] == 0xf0) { + or = 0x80; + continue; + } + send = nont_to_t[val[i]] | or; + if (or == 0x80) + or = 0; + } else + send = val[i]; + + add_data_kbd_queue(dev, 0, send); + } } @@ -1824,21 +848,56 @@ static void add_data_kbd(uint16_t val) { atkbd_t *dev = SavedKbd; + int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); + int translate = (keyboard_mode & 0x40); uint8_t fake_shift[4]; uint8_t num_lock = 0, shift_states = 0; uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - if (dev->kbd_in || (dev->kbd_phase > 0)) + if (dev->reset_delay) return; + translate = translate || (keyboard_mode & 0x40) || xt_mode; + translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); + keyboard_get_states(NULL, &num_lock, NULL); shift_states = keyboard_get_shift() & STATE_SHIFT_MASK; - /* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */ - if ((dev != NULL) && (kbc_ven == KBC_VEN_TOSHIBA) && (keyboard_recv(0xb8) || keyboard_recv(0x9d)) && - (val >= 0x4f) && (val <= 0x54) && (val != 0x4e)) - t3100e_notify_set((val + 2) & 0x0f); + /* Allow for scan code translation. */ + if (translate && (val == 0xf0)) { + kbd_log("ATkbd: translate is on, F0 prefix detected\n"); + sc_or = 0x80; + return; + } + /* Skip break code if translated make code has bit 7 set. */ + if (translate && (sc_or == 0x80) && (val & 0x80)) { + kbd_log("ATkbd: translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val); + sc_or = 0; + return; + } + + /* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */ + if ((dev != NULL) && (kbc_ven == KBC_VEN_TOSHIBA) && + (keyboard_recv(0xb8) || keyboard_recv(0x9d))) switch (val) { + case 0x4f: t3100e_notify_set(0x01); break; /* End */ + case 0x50: t3100e_notify_set(0x02); break; /* Down */ + case 0x51: t3100e_notify_set(0x03); break; /* PgDn */ + case 0x52: t3100e_notify_set(0x04); break; /* Ins */ + case 0x53: t3100e_notify_set(0x05); break; /* Del */ + case 0x54: t3100e_notify_set(0x06); break; /* SysRQ */ + case 0x45: t3100e_notify_set(0x07); break; /* NumLock */ + case 0x46: t3100e_notify_set(0x08); break; /* ScrLock */ + case 0x47: t3100e_notify_set(0x09); break; /* Home */ + case 0x48: t3100e_notify_set(0x0a); break; /* Up */ + case 0x49: t3100e_notify_set(0x0b); break; /* PgUp */ + case 0x4A: t3100e_notify_set(0x0c); break; /* Keypad -*/ + case 0x4B: t3100e_notify_set(0x0d); break; /* Left */ + case 0x4C: t3100e_notify_set(0x0e); break; /* KP 5 */ + case 0x4D: t3100e_notify_set(0x0f); break; /* Right */ + } + + kbd_log("ATkbd: translate is %s, ", translate ? "on" : "off"); switch(val) { case FAKE_LSHIFT_ON: kbd_log("fake left shift on, scan code: "); @@ -1971,7 +1030,18 @@ add_data_kbd(uint16_t val) break; default: - add_data_kbd_queue(dev, 0, val); +#ifdef ENABLE_KEYBOARD_AT_LOG + kbd_log("scan code: "); + if (translate) { + kbd_log("%02X (original: ", (nont_to_t[val] | sc_or)); + if (sc_or == 0x80) + kbd_log("F0 "); + kbd_log("%02X)\n", val); + } else + kbd_log("%02X\n", val); +#endif + + add_data_kbd_queue(dev, 0, translate ? (nont_to_t[val] | sc_or) : val); break; } @@ -1980,13 +1050,124 @@ add_data_kbd(uint16_t val) } +static void +write_output(atkbd_t *dev, uint8_t val) +{ + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + kbd_log("ATkbc: write output port: %02X (old: %02X)\n", val, dev->output_port); + + if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF)) + val |= ((dev->mem[0] << 4) & 0x10); + + if ((dev->output_port ^ val) & 0x20) { /*IRQ 12*/ + if (val & 0x20) + picint(1 << 12); + else + picintc(1 << 12); + } + if ((dev->output_port ^ val) & 0x10) { /*IRQ 1*/ + if (val & 0x10) + picint(1 << 1); + else + picintc(1 << 1); + } + if ((dev->output_port ^ val) & 0x02) { /*A20 enable change*/ + mem_a20_key = val & 0x02; + mem_a20_recalc(); + flushmmucache(); + } + if ((dev->output_port ^ val) & 0x01) { /*Reset*/ + if (! (val & 0x01)) { + /* Pin 0 selected. */ + softresetx86(); /*Pulse reset!*/ + cpu_set_edx(); + smbase = is_am486dxl ? 0x00060000 : 0x00030000; + } + } + /* Mask off the A20 stuff because we use mem_a20_key directly for that. */ + dev->output_port = val; +} + + +static void +write_cmd(atkbd_t *dev, uint8_t val) +{ + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + kbd_log("ATkbc: write command byte: %02X (old: %02X)\n", val, dev->mem[0]); + + if ((val & 1) && (dev->status & STAT_OFULL)) + dev->wantirq = 1; + if (!(val & 1) && dev->wantirq) + dev->wantirq = 0; + + /* PS/2 type 2 keyboard controllers always force the XLAT bit to 0. */ + if ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2) { + val &= ~CCB_TRANSLATE; + dev->mem[0] &= ~CCB_TRANSLATE; + } + + /* Scan code translate ON/OFF. */ + keyboard_mode &= 0x93; + keyboard_mode |= (val & MODE_MASK); + + kbd_log("ATkbc: keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled"); + + /* ISA AT keyboard controllers use bit 5 for keyboard mode (1 = PC/XT, 2 = AT); + PS/2 (and EISA/PCI) keyboard controllers use it as the PS/2 mouse enable switch. + The AMIKEY firmware apparently uses this bit for something else. */ + if ((kbc_ven == KBC_VEN_AMI) || + ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) { + keyboard_mode &= ~CCB_PCMODE; + + kbd_log("ATkbc: mouse interrupt is now %s\n", (val & 0x02) ? "enabled" : "disabled"); + } + + if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF)) { + /* Update the output port to mirror the KBD DIS and AUX DIS bits, if active. */ + write_output(dev, dev->output_port); + } + + kbd_log("Command byte now: %02X (%02X)\n", dev->mem[0], val); + + dev->status = (dev->status & ~STAT_SYSFLAG) | (val & STAT_SYSFLAG); +} + + +static void +pulse_output(atkbd_t *dev, uint8_t mask) +{ + if (mask != 0x0f) { + dev->old_output_port = dev->output_port & ~(0xf0 | mask); + kbd_log("pulse_output(): Output port now: %02X\n", dev->output_port & (0xf0 | mask)); + write_output(dev, dev->output_port & (0xf0 | mask)); + timer_set_delay_u64(&dev->pulse_cb, 6ULL * TIMER_USEC); + } +} + + static void pulse_poll(void *priv) { atkbd_t *dev = (atkbd_t *)priv; - kbd_log("pulse_poll(): Output port now: %02X\n", dev->p2 | dev->old_p2); - write_output(dev, dev->p2 | dev->old_p2); + kbd_log("pulse_poll(): Output port now: %02X\n", dev->output_port | dev->old_output_port); + write_output(dev, dev->output_port | dev->old_output_port); +} + + +static void +set_enable_kbd(atkbd_t *dev, uint8_t enable) +{ + dev->mem[0] &= 0xef; + dev->mem[0] |= (enable ? 0x00 : 0x10); +} + + +static void +set_enable_mouse(atkbd_t *dev, uint8_t enable) +{ + dev->mem[0] &= 0xdf; + dev->mem[0] |= (enable ? 0x00 : 0x20); } @@ -1995,70 +1176,49 @@ write64_generic(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; uint8_t current_drive, fixed_bits; - uint8_t kbc_ven = 0x0; - kbc_ven = dev->flags & KBC_VEN_MASK; + uint8_t kbc_ven = 0x0; + kbc_ven = dev->flags & KBC_VEN_MASK; + switch (val) { case 0xa4: /* check if password installed */ - if (dev->flags & KBC_FLAG_PS2) { + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: check if password installed\n"); - kbc_transmit(dev, (dev->mem[0x50] == 0x00) ? 0xf1 : 0xfa); - return 0; - } - break; - - case 0xa5: /* load security */ - if (dev->flags & KBC_FLAG_PS2) { - kbd_log("ATkbc: load security\n"); - dev->kbc_in = 1; + add_data(dev, 0xf1); return 0; } break; case 0xa7: /* disable mouse port */ - if (dev->flags & KBC_FLAG_PS2) { + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: disable mouse port\n"); - // kbc_transmit(dev, 0); + set_enable_mouse(dev, 0); return 0; } break; case 0xa8: /*Enable mouse port*/ - if (dev->flags & KBC_FLAG_PS2) { + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: enable mouse port\n"); - // kbc_transmit(dev, 1); + set_enable_mouse(dev, 1); return 0; } break; case 0xa9: /*Test mouse port*/ kbd_log("ATkbc: test mouse port\n"); - if (dev->flags & KBC_FLAG_PS2) { - /* No error, this is testing the channel 2 interface. */ - kbc_transmit(dev, 0x00); + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + add_data(dev, 0x00); /* no error, this is testing the channel 2 interface */ return 0; } break; case 0xaf: /* read keyboard version */ kbd_log("ATkbc: read keyboard version\n"); - kbc_transmit(dev, 0x00); + add_data(dev, 0x00); return 0; case 0xc0: /* read input port */ - /* IBM PS/1: - Bit 2 and 4 ignored (we return always 0), - Bit 6 must 1 for 5.25" floppy drive, 0 for 3.5". - Intel AMI: - Bit 2 ignored (we return always 1), - Bit 4 must be 1, - Bit 6 must be 1 or else error in SMM. - Acer: - Bit 2 must be 0 (and Acer V10 disables CMOS setup if it's 1), - Bit 4 must be 0, - Bit 6 ignored. - P6RP4: - Bit 2 must be 1 or CMOS setup is disabled. */ kbd_log("ATkbc: read input port\n"); fixed_bits = 4; /* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */ @@ -2066,8 +1226,11 @@ write64_generic(void *priv, uint8_t val) fixed_bits |= 0x40; if (kbc_ven == KBC_VEN_IBM_PS1) { current_drive = fdc_get_current_drive(); - kbc_transmit(dev, dev->p1 | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00)); - dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc) | (fdd_is_525(current_drive) ? 0x40 : 0x00); + add_to_kbc_queue_front(dev, dev->input_port | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00), + 0, 0x00); + dev->input_port = ((dev->input_port + 1) & 3) | + (dev->input_port & 0xfc) | + (fdd_is_525(current_drive) ? 0x40 : 0x00); } else if (kbc_ven == KBC_VEN_NCR) { /* switch settings * bit 7: keyboard disable @@ -2079,34 +1242,39 @@ write64_generic(void *priv, uint8_t val) * bit 1: high/auto speed * bit 0: dma mode */ - kbc_transmit(dev, (dev->p1 | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf); - dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc); + add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf, + 0, 0x00); + dev->input_port = ((dev->input_port + 1) & 3) | + (dev->input_port & 0xfc); } else { - pclog("[%04X:%08X] Reading %02X from input port\n", CS, cpu_state.pc, ((dev->p1 | fixed_bits) & 0xf0) | 0x0c); - if ((dev->flags & KBC_FLAG_PS2) && ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI)) - // kbc_transmit(dev, ((dev->p1 | fixed_bits) & 0xf0) | 0x0c); - kbc_transmit(dev, ((dev->p1 | fixed_bits) & 0xf0) | 0x08); - // kbc_transmit(dev, (dev->p1 | fixed_bits) & (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0xeb : 0xef)); + if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) && + ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI)) + add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits) & + (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0xeb : 0xef), 0, 0x00); else - kbc_transmit(dev, dev->p1 | fixed_bits); - dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc); + add_to_kbc_queue_front(dev, dev->input_port | fixed_bits, 0, 0x00); + dev->input_port = ((dev->input_port + 1) & 3) | + (dev->input_port & 0xfc); } return 0; case 0xd3: /* write mouse output buffer */ - if (dev->flags & KBC_FLAG_PS2) { + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: write mouse output buffer\n"); - dev->kbc_in = 1; + dev->want60 = 1; return 0; } break; case 0xd4: /* write to mouse */ kbd_log("ATkbc: write to mouse\n"); - dev->kbc_in = 1; + dev->want60 = 1; return 0; - case 0xf0 ... 0xff: + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: kbd_log("ATkbc: pulse %01X\n", val & 0x0f); pulse_output(dev, val & 0x0f); return 0; @@ -2121,168 +1289,35 @@ static uint8_t write60_ami(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; - uint16_t index = 0x00c0; - switch(dev->kbc_cmd) { - /* 0x40 - 0x5F are aliases for 0x60 - 0x7F */ - case 0x40 ... 0x5f: - kbd_log("ATkbc: AMI - alias write to %08X\n", dev->kbc_cmd); - if (dev->kbc_cmd == 0x40) + switch(dev->command) { + /* 0x40 - 0x5F are aliases for 0x60-0x7F */ + case 0x40: case 0x41: case 0x42: case 0x43: + case 0x44: case 0x45: case 0x46: case 0x47: + case 0x48: case 0x49: case 0x4a: case 0x4b: + 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: case 0x5f: + kbd_log("ATkbc: AMI - alias write to %08X\n", dev->command); + dev->mem[dev->command & 0x1f] = val; + if (dev->command == 0x60) write_cmd(dev, val); - else - dev->mem[(dev->kbc_cmd & 0x1f) + 0x20] = val; return 0; case 0xaf: /* set extended controller RAM */ - kbd_log("ATkbc: AMI - set extended controller RAM, input phase %i\n", dev->secr_phase); - if (dev->secr_phase == 0) { - dev->mem_index = val; - dev->kbc_in = 1; - dev->secr_phase++; - } else if (dev->secr_phase == 1) { - if (dev->mem_index == 0x20) - write_cmd(dev, val); - else - dev->mem[dev->mem_index] = val; + kbd_log("ATkbc: AMI - set extended controller RAM\n"); + if (dev->secr_phase == 1) { + dev->mem_addr = val; + dev->want60 = 1; + dev->secr_phase = 2; + } else if (dev->secr_phase == 2) { + dev->mem[dev->mem_addr] = val; dev->secr_phase = 0; } return 0; - case 0xb8: - kbd_log("ATkbc: AMI MegaKey - memory index %02X\n", val); - dev->mem_index = val; - return 0; - - case 0xbb: - kbd_log("ATkbc: AMI MegaKey - write %02X to memory index %02X\n", val, dev->mem_index); - if (dev->mem_index >= 0x80) { - switch (dev->mem[0x9b] & 0xc0) { - case 0x00: - index = 0x0080; - break; - case 0x40: case 0x80: - index = 0x0000; - break; - case 0xc0: - index = 0x0100; - break; - } - dev->mem[index + dev->mem_index] = val; - } else if (dev->mem_index == 0x60) - write_cmd(dev, val); - else if (dev->mem_index == 0x42) - dev->status = val; - else if (dev->mem_index >= 0x40) - dev->mem[dev->mem_index - 0x40] = val; - else - dev->mem_int[dev->mem_index] = val; - return 0; - - case 0xbd: - kbd_log("ATkbc: AMI MegaKey - write %02X to config index %02X\n", val, dev->mem_index); - switch (dev->mem_index) { - case 0x00: /* STAT8042 */ - dev->status = val; - break; - case 0x01: /* Password_ptr */ - dev->mem[0x1c] = val; - break; - case 0x02: /* Wakeup_Tsk_Reg */ - dev->mem[0x1e] = val; - break; - case 0x03: /* CCB */ - write_cmd(dev, val); - break; - case 0x04: /* Debounce_time */ - dev->mem[0x4d] = val; - break; - case 0x05: /* Pulse_Width */ - dev->mem[0x4e] = val; - break; - case 0x06: /* Pk_sel_byte */ - dev->mem[0x4c] = val; - break; - case 0x07: /* Func_Tsk_Reg */ - dev->mem[0x7e] = val; - break; - case 0x08: /* TypematicRate */ - dev->mem[0x80] = val; - break; - case 0x09: /* Led_Flag_Byte */ - dev->mem[0x81] = val; - break; - case 0x0a: /* Kbms_Command_St */ - dev->mem[0x87] = val; - break; - case 0x0b: /* Delay_Count_Byte */ - dev->mem[0x86] = val; - break; - case 0x0c: /* KBC_Flags */ - dev->mem[0x9b] = val; - break; - case 0x0d: /* SCODE_HK1 */ - dev->mem[0x50] = val; - break; - case 0x0e: /* SCODE_HK2 */ - dev->mem[0x51] = val; - break; - case 0x0f: /* SCODE_HK3 */ - dev->mem[0x52] = val; - break; - case 0x10: /* SCODE_HK4 */ - dev->mem[0x53] = val; - break; - case 0x11: /* SCODE_HK5 */ - dev->mem[0x54] = val; - break; - case 0x12: /* SCODE_HK6 */ - dev->mem[0x55] = val; - break; - case 0x13: /* TASK_HK1 */ - dev->mem[0x56] = val; - break; - case 0x14: /* TASK_HK2 */ - dev->mem[0x57] = val; - break; - case 0x15: /* TASK_HK3 */ - dev->mem[0x58] = val; - break; - case 0x16: /* TASK_HK4 */ - dev->mem[0x59] = val; - break; - case 0x17: /* TASK_HK5 */ - dev->mem[0x5a] = val; - break; - /* The next 4 bytes have uncertain correspondences. */ - case 0x18: /* Batt_Poll_delay_Time */ - dev->mem[0x5b] = val; - break; - case 0x19: /* Batt_Alarm_Reg1 */ - dev->mem[0x5c] = val; - break; - case 0x1a: /* Batt_Alarm_Reg2 */ - dev->mem[0x5d] = val; - break; - case 0x1b: /* Batt_Alarm_Tsk_Reg */ - dev->mem[0x5e] = val; - break; - case 0x1c: /* Kbc_State1 */ - dev->mem[0x9d] = val; - break; - case 0x1d: /* Aux_Config */ - dev->mem[0x75] = val; - break; - case 0x1e: /* Kbc_State3 */ - dev->mem[0x73] = val; - break; - } - return 0; - - case 0xc1: /* write input port */ - kbd_log("ATkbc: AMI MegaKey - write %02X to input port\n", val); - dev->p1 = val; - return 0; - case 0xcb: /* set keyboard mode */ kbd_log("ATkbc: AMI - set keyboard mode\n"); return 0; @@ -2296,50 +1331,62 @@ static uint8_t write64_ami(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; - uint16_t index = 0x00c0; switch (val) { - case 0x00 ... 0x1f: + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x18: case 0x19: case 0x1a: case 0x1b: + case 0x1c: case 0x1d: case 0x1e: case 0x1f: kbd_log("ATkbc: AMI - alias read from %08X\n", val); - kbc_transmit(dev, dev->mem[val + 0x20]); + add_data(dev, dev->mem[val]); return 0; - case 0x40 ... 0x5f: - kbd_log("ATkbc: AMI - alias write to %08X\n", dev->kbc_cmd); - dev->kbc_in = 1; + case 0x40: case 0x41: case 0x42: case 0x43: + case 0x44: case 0x45: case 0x46: case 0x47: + case 0x48: case 0x49: case 0x4a: case 0x4b: + 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: case 0x5f: + kbd_log("ATkbc: AMI - alias write to %08X\n", dev->command); + dev->want60 = 1; return 0; case 0xa0: /* copyright message */ - kbc_transmit(dev, ami_copr[0]); - dev->kbc_phase = 1; - return 0; + add_data(dev, 0x28); + add_data(dev, 0x00); + break; case 0xa1: /* get controller version */ kbd_log("ATkbc: AMI - get controller version\n"); - // kbc_transmit(dev, 'H'); - kbc_transmit(dev, 'Z'); + add_data(dev, 'H'); return 0; case 0xa2: /* clear keyboard controller lines P22/P23 */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - clear KBC lines P22 and P23\n"); - write_output(dev, dev->p2 & 0xf3); - kbc_transmit(dev, 0x00); + write_output(dev, dev->output_port & 0xf3); + add_data(dev, 0x00); return 0; } break; case 0xa3: /* set keyboard controller lines P22/P23 */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - set KBC lines P22 and P23\n"); - write_output(dev, dev->p2 | 0x0c); - kbc_transmit(dev, 0x00); + write_output(dev, dev->output_port | 0x0c); + add_data(dev, 0x00); return 0; } break; case 0xa4: /* write clock = low */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - write clock = low\n"); dev->ami_stat &= 0xfe; return 0; @@ -2347,7 +1394,7 @@ write64_ami(void *priv, uint8_t val) break; case 0xa5: /* write clock = high */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - write clock = high\n"); dev->ami_stat |= 0x01; return 0; @@ -2355,15 +1402,15 @@ write64_ami(void *priv, uint8_t val) break; case 0xa6: /* read clock */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - read clock\n"); - kbc_transmit(dev, !!(dev->ami_stat & 1)); + add_data(dev, !!(dev->ami_stat & 1)); return 0; } break; case 0xa7: /* write cache bad */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - write cache bad\n"); dev->ami_stat &= 0xfd; return 0; @@ -2371,7 +1418,7 @@ write64_ami(void *priv, uint8_t val) break; case 0xa8: /* write cache good */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - write cache good\n"); dev->ami_stat |= 0x02; return 0; @@ -2379,237 +1426,68 @@ write64_ami(void *priv, uint8_t val) break; case 0xa9: /* read cache */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - read cache\n"); - kbc_transmit(dev, !!(dev->ami_stat & 2)); + add_data(dev, !!(dev->ami_stat & 2)); return 0; } break; case 0xaf: /* set extended controller RAM */ kbd_log("ATkbc: set extended controller RAM\n"); - dev->kbc_in = 1; + dev->want60 = 1; + dev->secr_phase = 1; return 0; - case 0xb0 ... 0xb3: + case 0xb0: case 0xb1: case 0xb2: case 0xb3: /* set KBC lines P10-P13 (input port bits 0-3) low */ kbd_log("ATkbc: set KBC lines P10-P13 (input port bits 0-3) low\n"); - if (!(dev->flags & KBC_FLAG_PS2) || (val > 0xb1)) { - dev->p1 &= ~(1 << (val & 0x03)); - } - kbc_transmit(dev, 0x00); + if (!PCI || (val > 0xb1)) + dev->input_port &= ~(1 << (val & 0x03)); + add_data(dev, 0x00); return 0; case 0xb4: case 0xb5: /* set KBC lines P22-P23 (output port bits 2-3) low */ kbd_log("ATkbc: set KBC lines P22-P23 (output port bits 2-3) low\n"); - if (!(dev->flags & KBC_FLAG_PS2)) - write_output(dev, dev->p2 & ~(4 << (val & 0x01))); - kbc_transmit(dev, 0x00); + if (! PCI) + write_output(dev, dev->output_port & ~(4 << (val & 0x01))); + add_data(dev, 0x00); return 0; -#if 0 - case 0xb8 ... 0xbb: -#else - case 0xb9: -#endif + case 0xb8: case 0xb9: case 0xba: case 0xbb: /* set KBC lines P10-P13 (input port bits 0-3) high */ kbd_log("ATkbc: set KBC lines P10-P13 (input port bits 0-3) high\n"); - if (!(dev->flags & KBC_FLAG_PS2) || (val > 0xb9)) { - dev->p1 |= (1 << (val & 0x03)); - kbc_transmit(dev, 0x00); + if (!PCI || (val > 0xb9)) { + dev->input_port |= (1 << (val & 0x03)); + add_data(dev, 0x00); } return 0; - case 0xb8: - kbd_log("ATkbc: AMI MegaKey - memory index\n"); - dev->kbc_in = 1; - return 0; - - case 0xba: - kbd_log("ATkbc: AMI MegaKey - read %02X memory from index %02X\n", dev->mem[dev->mem_index], dev->mem_index); - if (dev->mem_index >= 0x80) { - switch (dev->mem[0x9b] & 0xc0) { - case 0x00: - index = 0x0080; - break; - case 0x40: case 0x80: - index = 0x0000; - break; - case 0xc0: - index = 0x0100; - break; - } - kbc_transmit(dev, dev->mem[index + dev->mem_index]); - } else if (dev->mem_index == 0x42) - kbc_transmit(dev, dev->status); - else if (dev->mem_index >= 0x40) - kbc_transmit(dev, dev->mem[dev->mem_index - 0x40]); - else - kbc_transmit(dev, dev->mem_int[dev->mem_index]); - return 0; - - case 0xbb: - kbd_log("ATkbc: AMI MegaKey - write to memory index %02X\n", dev->mem_index); - dev->kbc_in = 1; - return 0; - -#if 0 case 0xbc: case 0xbd: /* set KBC lines P22-P23 (output port bits 2-3) high */ kbd_log("ATkbc: set KBC lines P22-P23 (output port bits 2-3) high\n"); - if (!(dev->flags & KBC_FLAG_PS2)) - write_output(dev, dev->p2 | (4 << (val & 0x01))); - kbc_transmit(dev, 0x00); - return 0; -#endif - - case 0xbc: - switch (dev->mem_index) { - case 0x00: /* STAT8042 */ - kbc_transmit(dev, dev->status); - break; - case 0x01: /* Password_ptr */ - kbc_transmit(dev, dev->mem[0x1c]); - break; - case 0x02: /* Wakeup_Tsk_Reg */ - kbc_transmit(dev, dev->mem[0x1e]); - break; - case 0x03: /* CCB */ - kbc_transmit(dev, dev->mem[0x20]); - break; - case 0x04: /* Debounce_time */ - kbc_transmit(dev, dev->mem[0x4d]); - break; - case 0x05: /* Pulse_Width */ - kbc_transmit(dev, dev->mem[0x4e]); - break; - case 0x06: /* Pk_sel_byte */ - kbc_transmit(dev, dev->mem[0x4c]); - break; - case 0x07: /* Func_Tsk_Reg */ - kbc_transmit(dev, dev->mem[0x7e]); - break; - case 0x08: /* TypematicRate */ - kbc_transmit(dev, dev->mem[0x80]); - break; - case 0x09: /* Led_Flag_Byte */ - kbc_transmit(dev, dev->mem[0x81]); - break; - case 0x0a: /* Kbms_Command_St */ - kbc_transmit(dev, dev->mem[0x87]); - break; - case 0x0b: /* Delay_Count_Byte */ - kbc_transmit(dev, dev->mem[0x86]); - break; - case 0x0c: /* KBC_Flags */ - kbc_transmit(dev, dev->mem[0x9b]); - break; - case 0x0d: /* SCODE_HK1 */ - kbc_transmit(dev, dev->mem[0x50]); - break; - case 0x0e: /* SCODE_HK2 */ - kbc_transmit(dev, dev->mem[0x51]); - break; - case 0x0f: /* SCODE_HK3 */ - kbc_transmit(dev, dev->mem[0x52]); - break; - case 0x10: /* SCODE_HK4 */ - kbc_transmit(dev, dev->mem[0x53]); - break; - case 0x11: /* SCODE_HK5 */ - kbc_transmit(dev, dev->mem[0x54]); - break; - case 0x12: /* SCODE_HK6 */ - kbc_transmit(dev, dev->mem[0x55]); - break; - case 0x13: /* TASK_HK1 */ - kbc_transmit(dev, dev->mem[0x56]); - break; - case 0x14: /* TASK_HK2 */ - kbc_transmit(dev, dev->mem[0x57]); - break; - case 0x15: /* TASK_HK3 */ - kbc_transmit(dev, dev->mem[0x58]); - break; - case 0x16: /* TASK_HK4 */ - kbc_transmit(dev, dev->mem[0x59]); - break; - case 0x17: /* TASK_HK5 */ - kbc_transmit(dev, dev->mem[0x5a]); - break; - /* The next 4 bytes have uncertain correspondences. */ - case 0x18: /* Batt_Poll_delay_Time */ - kbc_transmit(dev, dev->mem[0x5b]); - break; - case 0x19: /* Batt_Alarm_Reg1 */ - kbc_transmit(dev, dev->mem[0x5c]); - break; - case 0x1a: /* Batt_Alarm_Reg2 */ - kbc_transmit(dev, dev->mem[0x5d]); - break; - case 0x1b: /* Batt_Alarm_Tsk_Reg */ - kbc_transmit(dev, dev->mem[0x5e]); - break; - case 0x1c: /* Kbc_State1 */ - kbc_transmit(dev, dev->mem[0x9d]); - break; - case 0x1d: /* Aux_Config */ - kbc_transmit(dev, dev->mem[0x75]); - break; - case 0x1e: /* Kbc_State3 */ - kbc_transmit(dev, dev->mem[0x73]); - break; - default: - kbc_transmit(dev, 0x00); - break; - } - kbd_log("ATkbc: AMI MegaKey - read from config index %02X\n", dev->mem_index); + if (! PCI) + write_output(dev, dev->output_port | (4 << (val & 0x01))); + add_data(dev, 0x00); return 0; - case 0xbd: - kbd_log("ATkbc: AMI MegaKey - write to config index %02X\n", dev->mem_index); - dev->kbc_in = 1; - return 0; - - case 0xc1: /* write input port */ - kbd_log("ATkbc: AMI MegaKey - write input port\n"); - dev->kbc_in = 1; - return 0; - - case 0xc4: - /* set KBC line P14 low */ - kbd_log("ATkbc: set KBC line P14 (input port bit 4) low\n"); - dev->p1 &= 0xef; - kbc_transmit(dev, 0x00); - return 0; - case 0xc5: - /* set KBC line P15 low */ - kbd_log("ATkbc: set KBC line P15 (input port bit 5) low\n"); - dev->p1 &= 0xdf; - kbc_transmit(dev, 0x00); - return 0; - - case 0xc8: case 0xc9: + case 0xc8: /* - * (un)block KBC lines P22/P23 + * unblock KBC lines P22/P23 * (allow command D1 to change bits 2/3 of the output port) */ - kbd_log("ATkbc: AMI - %sblock KBC lines P22 and P23\n", (val & 1) ? "" : "un"); - dev->p2_locked = (val & 1); + kbd_log("ATkbc: AMI - unblock KBC lines P22 and P23\n"); + dev->output_locked = 1; return 0; - case 0xcc: - /* set KBC line P14 high */ - kbd_log("ATkbc: set KBC line P14 (input port bit 4) high\n"); - dev->p1 |= 0x10; - kbc_transmit(dev, 0x00); - return 0; - case 0xcd: - /* set KBC line P15 high */ - kbd_log("ATkbc: set KBC line P15 (input port bit 5) high\n"); - dev->p1 |= 0x20; - kbc_transmit(dev, 0x00); + case 0xc9: + /* + * block KBC lines P22/P23 + * (disallow command D1 from changing bits 2/3 of the port) + */ + kbd_log("ATkbc: AMI - block KBC lines P22 and P23\n"); + dev->output_locked = 1; return 0; case 0xef: /* ??? - sent by AMI486 */ @@ -2630,20 +1508,23 @@ write64_ibm_mca(void *priv, uint8_t val) case 0xc1: /*Copy bits 0 to 3 of input port to status bits 4 to 7*/ kbd_log("ATkbc: copy bits 0 to 3 of input port to status bits 4 to 7\n"); dev->status &= 0x0f; - dev->status |= ((((dev->p1 & 0xfc) | 0x84) & 0x0f) << 4); + dev->status |= ((((dev->input_port & 0xfc) | 0x84) & 0x0f) << 4); return 0; case 0xc2: /*Copy bits 4 to 7 of input port to status bits 4 to 7*/ kbd_log("ATkbc: copy bits 4 to 7 of input port to status bits 4 to 7\n"); dev->status &= 0x0f; - dev->status |= (((dev->p1 & 0xfc) | 0x84) & 0xf0); + dev->status |= (((dev->input_port & 0xfc) | 0x84) & 0xf0); return 0; case 0xaf: kbd_log("ATkbc: bad KBC command AF\n"); return 1; - case 0xf0 ... 0xff: + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: kbd_log("ATkbc: pulse: %01X\n", (val & 0x03) | 0x0c); pulse_output(dev, (val & 0x03) | 0x0c); return 0; @@ -2658,7 +1539,7 @@ write60_quadtel(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; - switch(dev->kbc_cmd) { + switch(dev->command) { case 0xcf: /*??? - sent by MegaPC BIOS*/ kbd_log("ATkbc: ??? - sent by MegaPC BIOS\n"); return 0; @@ -2667,34 +1548,12 @@ write60_quadtel(void *priv, uint8_t val) return 1; } - static uint8_t write64_olivetti(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; switch (val) { - /* This appears to be a clone of "Read input port", in which case, the bis would be: - 7: M290 (AT KBC): - Keyboard lock (1 = unlocked, 0 = locked); - M300 (PS/2 KBC): - Bus expansion board present (1 = present, 0 = not present); - 6: Usually: - Display (1 = MDA, 0 = CGA, but can have its polarity inverted); - 5: Manufacturing jumper (1 = not installed, 0 = installed (infinite loop)); - 4: RAM on motherboard (1 = 256 kB, 0 = 512 kB - which machine actually uses this?); - 3: Fast Ram check (if inactive keyboard works erratically); - 2: Keyboard fuse present - This appears to be in-line with PS/2: 1 = no power, 0 = keyboard power normal; - 1: M290 (AT KBC): - Unused; - M300 (PS/2 KBC): - Mouse data in; - 0: M290 (AT KBC): - Unused; - M300 (PS/2 KBC): - Key data in. - */ case 0x80: /* Olivetti-specific command */ /* * bit 7: bus expansion board present (M300) / keyboard unlocked (M290) @@ -2703,9 +1562,11 @@ write64_olivetti(void *priv, uint8_t val) * bit 2: keyboard fuse present * bits 0-1: ??? */ - kbc_transmit(dev, 0x0c | (is386 ? 0x00 : 0x80)); + add_to_kbc_queue_front(dev, (0x0c | ((is386) ? 0x00 : 0x80)) & 0xdf, 0, 0x00); + dev->input_port = ((dev->input_port + 1) & 3) | + (dev->input_port & 0xfc); return 0; - } + } return write64_generic(dev, val); } @@ -2723,7 +1584,7 @@ write64_quadtel(void *priv, uint8_t val) case 0xcf: /*??? - sent by MegaPC BIOS*/ kbd_log("ATkbc: ??? - sent by MegaPC BIOS\n"); - dev->kbc_in = 1; + dev->want60 = 1; return 0; } @@ -2736,7 +1597,7 @@ write60_toshiba(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; - switch(dev->kbc_cmd) { + switch(dev->command) { case 0xb6: /* T3100e - set color/mono switch */ kbd_log("ATkbc: T3100e - set color/mono switch\n"); t3100e_mono_set(val); @@ -2779,30 +1640,29 @@ write64_toshiba(void *priv, uint8_t val) case 0xb4: /* T3100e: Get configuration / status */ kbd_log("ATkbc: T3100e: Get configuration / status\n"); - kbc_transmit(dev, t3100e_config_get()); + add_data(dev, t3100e_config_get()); return 0; case 0xb5: /* T3100e: Get colour / mono byte */ kbd_log("ATkbc: T3100e: Get colour / mono byte\n"); - kbc_transmit(dev, t3100e_mono_get()); + add_data(dev, t3100e_mono_get()); return 0; case 0xb6: /* T3100e: Set colour / mono byte */ kbd_log("ATkbc: T3100e: Set colour / mono byte\n"); - dev->kbc_in = 1; + dev->want60 = 1; return 0; case 0xb7: /* T3100e: Emulate PS/2 keyboard */ case 0xb8: /* T3100e: Emulate AT keyboard */ - dev->flags &= ~KBC_FLAG_PS2; + dev->flags &= ~KBC_TYPE_MASK; if (val == 0xb7) { kbd_log("ATkbc: T3100e: Emulate PS/2 keyboard\n"); - dev->flags |= KBC_FLAG_PS2; - } -#ifdef ENABLE_KEYBOARD_AT_LOG - else + dev->flags |= KBC_TYPE_PS2_NOREF; + } else { kbd_log("ATkbc: T3100e: Emulate AT keyboard\n"); -#endif + dev->flags |= KBC_TYPE_ISA; + } return 0; case 0xbb: /* T3100e: Read 'Fn' key. @@ -2812,9 +1672,8 @@ write64_toshiba(void *priv, uint8_t val) kbd_log("ATkbc: T3100e: Read 'Fn' key\n"); if (keyboard_recv(0xb8) || /* Right Alt */ keyboard_recv(0x9d)) /* Right Ctrl */ - kbc_transmit(dev, 0x04); - else - kbc_transmit(dev, 0x00); + add_data(dev, 0x04); + else add_data(dev, 0x00); return 0; case 0xbc: /* T3100e: Reset Fn+Key notification */ @@ -2827,8 +1686,8 @@ write64_toshiba(void *priv, uint8_t val) /* The T3100e returns all bits set except bit 6 which * is set by t3100e_mono_set() */ - dev->p1 = (t3100e_mono_get() & 1) ? 0xff : 0xbf; - kbc_transmit(dev, dev->p1); + dev->input_port = (t3100e_mono_get() & 1) ? 0xff : 0xbf; + add_data(dev, dev->input_port); return 0; } @@ -2841,52 +1700,423 @@ static void kbd_write(uint16_t port, uint8_t val, void *priv) { atkbd_t *dev = (atkbd_t *)priv; + int i = 0, bad = 1; + uint8_t mask, kbc_ven = 0x0; + kbc_ven = dev->flags & KBC_VEN_MASK; - kbd_log("[%04X:%08X] ATkbc: write(%04X, %02X)\n", CS, cpu_state.pc, port, val); + if ((kbc_ven == KBC_VEN_XI8088) && (port == 0x63)) + port = 0x61; + + kbd_log((port == 0x61) ? "" : "ATkbc: write(%04X, %02X)\n", port, val); switch (port) { case 0x60: - dev->status = (dev->status & ~STAT_CD) | STAT_IFULL; - dev->ib = val; - // kbd_status("Write %02X: %02X, Status = %02X\n", port, val, dev->status); + dev->status &= ~STAT_CD; + if (dev->want60) { + /* Write data to controller. */ + dev->want60 = 0; -#if 0 - if ((dev->fast_a20_phase == 1)/* && ((val == 0xdd) || (val == 0xdf))*/) { - dev->status &= ~STAT_IFULL; - write_output(dev, val); - dev->fast_a20_phase = 0; + switch (dev->command) { + case 0x60: case 0x61: case 0x62: case 0x63: + case 0x64: case 0x65: case 0x66: case 0x67: + case 0x68: case 0x69: case 0x6a: case 0x6b: + case 0x6c: case 0x6d: case 0x6e: case 0x6f: + case 0x70: case 0x71: case 0x72: case 0x73: + case 0x74: case 0x75: case 0x76: case 0x77: + case 0x78: case 0x79: case 0x7a: case 0x7b: + case 0x7c: case 0x7d: case 0x7e: case 0x7f: + dev->mem[dev->command & 0x1f] = val; + if (dev->command == 0x60) + write_cmd(dev, val); + break; + + case 0xd1: /* write output port */ + kbd_log("ATkbc: write output port\n"); + if (dev->output_locked) { + /*If keyboard controller lines P22-P23 are blocked, + we force them to remain unchanged.*/ + val &= ~0x0c; + val |= (dev->output_port & 0x0c); + } + write_output(dev, val); + break; + + case 0xd2: /* write to keyboard output buffer */ + kbd_log("ATkbc: write to keyboard output buffer\n"); + add_to_kbc_queue_front(dev, val, 0, 0x00); + break; + + case 0xd3: /* write to mouse output buffer */ + kbd_log("ATkbc: write to mouse output buffer\n"); + if (mouse_write && ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) + keyboard_at_adddata_mouse(val); + break; + + case 0xd4: /* write to mouse */ + kbd_log("ATkbc: write to mouse (%02X)\n", val); + + if (val == 0xbb) + break; + + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + set_enable_mouse(dev, 1); + if (mouse_write) + mouse_write(val, mouse_p); + else + add_to_kbc_queue_front(dev, 0xfe, 2, 0x40); + } + break; + + default: + /* + * Run the vendor-specific handler + * if we have one. Otherwise, or if + * it returns an error, log a bad + * controller command. + */ + if (dev->write60_ven) + bad = dev->write60_ven(dev, val); + + if (bad) { + kbd_log("ATkbc: bad controller command %02x data %02x\n", dev->command, val); + add_data_kbd(0xfe); + } + } + } else { + /* Write data to keyboard. */ + dev->mem[0] &= ~0x10; + + if (dev->key_wantdata) { + dev->key_wantdata = 0; + + /* + * Several system BIOSes and OS device drivers + * mess up with this, and repeat the command + * code many times. Fun! + */ + if (val == dev->key_command) { + /* Respond NAK and ignore it. */ + add_data_kbd(0xfe); + dev->key_command = 0x00; + break; + } + + switch (dev->key_command) { + case 0xed: /* set/reset LEDs */ + add_data_kbd_direct(dev, 0xfa); + kbd_log("ATkbd: set LEDs [%02x]\n", val); + break; + + case 0xf0: /* get/set scancode set */ + add_data_kbd_direct(dev, 0xfa); + if (val == 0) { + kbd_log("Get scan code set: %02X\n", keyboard_mode & 3); + add_data_kbd_direct(dev, keyboard_mode & 3); + } else { + if ((val <= 3) && (val != 1)) { + keyboard_mode &= 0xfc; + keyboard_mode |= (val & 3); + kbd_log("Scan code set now: %02X\n", val); + } + set_scancode_map(dev); + } + break; + + case 0xf3: /* set typematic rate/delay */ + add_data_kbd_direct(dev, 0xfa); + break; + + default: + kbd_log("ATkbd: bad keyboard 0060 write %02X command %02X\n", val, dev->key_command); + add_data_kbd_direct(dev, 0xfe); + break; + } + + /* Keyboard command is now done. */ + dev->key_command = 0x00; + } else { + /* No keyboard command in progress. */ + dev->key_command = 0x00; + + set_enable_kbd(dev, 1); + + switch (val) { + case 0x00: + kbd_log("ATkbd: command 00\n"); + add_data_kbd_direct(dev, 0xfa); + break; + + case 0x05: /*??? - sent by NT 4.0*/ + kbd_log("ATkbd: command 05 (NT 4.0)\n"); + add_data_kbd_direct(dev, 0xfe); + break; + + /* Sent by Pentium-era AMI BIOS'es.*/ + case 0x71: case 0x82: + kbd_log("ATkbd: Pentium-era AMI BIOS command %02X\n", val); + break; + + case 0xed: /* set/reset LEDs */ + kbd_log("ATkbd: set/reset leds\n"); + add_data_kbd_direct(dev, 0xfa); + + dev->key_wantdata = 1; + break; + + case 0xee: /* diagnostic echo */ + kbd_log("ATkbd: ECHO\n"); + add_data_kbd_direct(dev, 0xee); + break; + + case 0xef: /* NOP (reserved for future use) */ + kbd_log("ATkbd: NOP\n"); + break; + + case 0xf0: /* get/set scan code set */ + kbd_log("ATkbd: scan code set\n"); + add_data_kbd_direct(dev, 0xfa); + dev->key_wantdata = 1; + break; + + case 0xf2: /* read ID */ + /* Fixed as translation will be done in add_data_kbd(). */ + kbd_log("ATkbd: read keyboard id\n"); + /* TODO: After keyboard type selection is implemented, make this + return the correct keyboard ID for the selected type. */ + add_data_kbd_direct(dev, 0xfa); + add_data_kbd_direct(dev, 0xab); + add_data_kbd_direct(dev, 0x83); + break; + + case 0xf3: /* set typematic rate/delay */ + kbd_log("ATkbd: set typematic rate/delay\n"); + add_data_kbd_direct(dev, 0xfa); + dev->key_wantdata = 1; + break; + + case 0xf4: /* enable keyboard */ + kbd_log("ATkbd: enable keyboard\n"); + add_data_kbd_direct(dev, 0xfa); + keyboard_scan = 1; + break; + + case 0xf5: /* set defaults and disable keyboard */ + case 0xf6: /* set defaults */ + kbd_log("ATkbd: set defaults%s\n", (val == 0xf6) ? "" : " and disable keyboard"); + keyboard_scan = (val == 0xf6); + kbd_log("val = %02X, keyboard_scan = %i, dev->mem[0] = %02X\n", + val, keyboard_scan, dev->mem[0]); + add_data_kbd_direct(dev, 0xfa); + + keyboard_set3_all_break = 0; + keyboard_set3_all_repeat = 0; + memset(keyboard_set3_flags, 0, 512); + keyboard_mode = (keyboard_mode & 0xfc) | 0x02; + set_scancode_map(dev); + break; + + case 0xf7: /* set all keys to repeat */ + kbd_log("ATkbd: set all keys to repeat\n"); + add_data_kbd_direct(dev, 0xfa); + keyboard_set3_all_break = 1; + break; + + case 0xf8: /* set all keys to give make/break codes */ + kbd_log("ATkbd: set all keys to give make/break codes\n"); + add_data_kbd_direct(dev, 0xfa); + keyboard_set3_all_break = 1; + break; + + case 0xf9: /* set all keys to give make codes only */ + kbd_log("ATkbd: set all keys to give make codes only\n"); + add_data_kbd_direct(dev, 0xfa); + keyboard_set3_all_break = 0; + break; + + case 0xfa: /* set all keys to repeat and give make/break codes */ + kbd_log("ATkbd: set all keys to repeat and give make/break codes\n"); + add_data_kbd_direct(dev, 0xfa); + keyboard_set3_all_repeat = 1; + keyboard_set3_all_break = 1; + break; + + case 0xfe: /* resend last scan code */ + kbd_log("ATkbd: reset last scan code\n"); + add_data_kbd_raw(dev, kbd_last_scan_code); + break; + + case 0xff: /* reset */ + kbd_log("ATkbd: kbd reset\n"); + kbc_queue_reset(1); + kbd_last_scan_code = 0x00; + add_data_kbd_direct(dev, 0xfa); + + /* Set scan code set to 2. */ + keyboard_mode = (keyboard_mode & 0xfc) | 0x02; + set_scancode_map(dev); + + dev->reset_delay = RESET_DELAY_TIME; + break; + + default: + kbd_log("ATkbd: bad keyboard command %02X\n", val); + add_data_kbd_direct(dev, 0xfe); + } + + /* If command needs data, remember command. */ + if (dev->key_wantdata == 1) + dev->key_command = val; + } } -#endif break; - case 0x64: - dev->status |= (STAT_CD | STAT_IFULL); - dev->ib = val; - // kbd_status("Write %02X: %02X, Status = %02X\n", port, val, dev->status); -#if 0 - if (val == 0xd1) { - dev->status &= ~STAT_IFULL; - dev->fast_a20_phase = 1; - } else if (val == 0xfe) { - dev->status &= ~STAT_IFULL; - pulse_output(dev, 0x0e); - } else if ((val == 0xad) || (val == 0xae)) { - dev->status &= ~STAT_IFULL; - if (val & 0x01) - dev->mem[0x20] |= 0x10; - else - dev->mem[0x20] &= ~0x10; - } else if (val == 0xa1) { - dev->status &= ~STAT_IFULL; - kbc_send_to_ob(dev, 'H', 0, 0x00); + case 0x61: + ppi.pb = (ppi.pb & 0x10) | (val & 0x0f); + + speaker_update(); + speaker_gated = val & 1; + speaker_enable = val & 2; + if (speaker_enable) + was_speaker_enable = 1; + pit_ctr_set_gate(&pit->counters[2], val & 1); + + if (kbc_ven == KBC_VEN_XI8088) + xi8088_turbo_set(!!(val & 0x04)); + break; + + case 0x64: + /* Controller command. */ + dev->want60 = 0; + dev->status |= STAT_CD; + + switch (val) { + /* Read data from KBC memory. */ + case 0x20: case 0x21: case 0x22: case 0x23: + case 0x24: case 0x25: case 0x26: case 0x27: + case 0x28: case 0x29: case 0x2a: case 0x2b: + case 0x2c: case 0x2d: case 0x2e: case 0x2f: + case 0x30: case 0x31: case 0x32: case 0x33: + case 0x34: case 0x35: case 0x36: case 0x37: + case 0x38: case 0x39: case 0x3a: case 0x3b: + case 0x3c: case 0x3d: case 0x3e: case 0x3f: + add_data(dev, dev->mem[val & 0x1f]); + break; + + /* Write data to KBC memory. */ + case 0x60: case 0x61: case 0x62: case 0x63: + case 0x64: case 0x65: case 0x66: case 0x67: + case 0x68: case 0x69: case 0x6a: case 0x6b: + case 0x6c: case 0x6d: case 0x6e: case 0x6f: + case 0x70: case 0x71: case 0x72: case 0x73: + case 0x74: case 0x75: case 0x76: case 0x77: + case 0x78: case 0x79: case 0x7a: case 0x7b: + case 0x7c: case 0x7d: case 0x7e: case 0x7f: + dev->want60 = 1; + break; + + case 0xaa: /* self-test */ + kbd_log("ATkbc: self-test\n"); + if ((kbc_ven == KBC_VEN_TOSHIBA) || (kbc_ven == KBC_VEN_SAMSUNG)) + dev->status |= STAT_IFULL; + write_output(dev, ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x4b : 0xcf); + + /* Always reinitialize all queues - the real hardware pulls keyboard and mouse + clocks high, which stops keyboard scanning. */ + kbd_log("ATkbc: self-test reinitialization\n"); + dev->out_new = dev->out_delayed = -1; + for (i = 0; i < 3; i++) + kbc_queue_reset(i); + kbd_last_scan_code = 0x00; + dev->status &= ~STAT_OFULL; + dev->last_irq = dev->old_last_irq = 0; + + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) + write_cmd(dev, 0x30 | STAT_SYSFLAG); + else + write_cmd(dev, 0x10 | STAT_SYSFLAG); + add_data(dev, 0x55); + break; + + case 0xab: /* interface test */ + kbd_log("ATkbc: interface test\n"); + add_data(dev, 0x00); /*no error*/ + break; + + case 0xac: /* diagnostic dump */ + kbd_log("ATkbc: diagnostic dump\n"); + for (i = 0; i < 16; i++) + add_data(dev, dev->mem[i]); + add_data(dev, (dev->input_port & 0xf0) | 0x80); + add_data(dev, dev->output_port); + add_data(dev, dev->status); + break; + + case 0xad: /* disable keyboard */ + kbd_log("ATkbc: disable keyboard\n"); + set_enable_kbd(dev, 0); + break; + + case 0xae: /* enable keyboard */ + kbd_log("ATkbc: enable keyboard\n"); + set_enable_kbd(dev, 1); + break; + + case 0xca: /* read keyboard mode */ + kbd_log("ATkbc: AMI - read keyboard mode\n"); + add_data(dev, ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x01 : 0x00); /*ISA mode*/ + break; + + case 0xcb: /* set keyboard mode */ + kbd_log("ATkbc: AMI - set keyboard mode\n"); + dev->want60 = 1; + break; + + case 0xd0: /* read output port */ + kbd_log("ATkbc: read output port\n"); + mask = 0xff; + if (((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) && (dev->mem[0] & 0x10)) + mask &= 0xbf; + add_to_kbc_queue_front(dev, dev->output_port & mask, 0, 0x00); + break; + + case 0xd1: /* write output port */ + kbd_log("ATkbc: write output port\n"); + dev->want60 = 1; + break; + + case 0xd2: /* write keyboard output buffer */ + kbd_log("ATkbc: write keyboard output buffer\n"); + dev->want60 = 1; + break; + + case 0xdd: /* disable A20 address line */ + case 0xdf: /* enable A20 address line */ + kbd_log("ATkbc: %sable A20\n", (val == 0xdd) ? "dis": "en"); + write_output(dev, (dev->output_port & 0xfd) | (val & 0x02)); + break; + + case 0xe0: /* read test inputs */ + kbd_log("ATkbc: read test inputs\n"); + add_data(dev, 0x00); + break; + + default: + /* + * Unrecognized controller command. + * + * If we have a vendor-specific handler, run + * that. Otherwise, or if that handler fails, + * log a bad command. + */ + if (dev->write64_ven) + bad = dev->write64_ven(dev, val); + + kbd_log(bad ? "ATkbc: bad controller command %02X\n" : "", val); } -#else - /* if (val == 0xa1) { - dev->status &= ~STAT_IFULL; - kbc_send_to_ob(dev, 'H', 0, 0x00); - } */ - kbc_process(dev); -#endif + + /* If the command needs data, remember the command. */ + if (dev->want60) + dev->command = val; break; } } @@ -2897,20 +2127,83 @@ kbd_read(uint16_t port, void *priv) { atkbd_t *dev = (atkbd_t *)priv; uint8_t ret = 0xff; + uint8_t kbc_ven = 0x0; + kbc_ven = dev->flags & KBC_VEN_MASK; - // if (dev->flags & KBC_FLAG_PS2) - // cycles -= ISA_CYCLES(8); + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) + cycles -= ISA_CYCLES(8); + + if ((kbc_ven == KBC_VEN_XI8088) && (port == 0x63)) + port = 0x61; switch (port) { case 0x60: - ret = dev->ob; + ret = dev->out; dev->status &= ~STAT_OFULL; picintc(dev->last_irq); dev->last_irq = 0; break; + case 0x61: + ret = ppi.pb & ~0xe0; + if (ppispeakon) + ret |= 0x20; + if ((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) { + if (dev->refresh) + ret |= 0x10; + else + ret &= ~0x10; + } + if (kbc_ven == KBC_VEN_XI8088) { + if (xi8088_turbo_get()) + ret |= 0x04; + else + ret &= ~0x04; + } + break; + + case 0x62: + ret = 0xff; + if (kbc_ven == KBC_VEN_OLIVETTI) { + /* SWA on Olivetti M240 mainboard (off=1) */ + ret = 0x00; + if (ppi.pb & 0x8) { + /* Switches 4, 5 - floppy drives (number) */ + int i, fdd_count = 0; + for (i = 0; i < FDD_NUM; i++) { + if (fdd_get_flags(i)) + fdd_count++; + } + if (!fdd_count) + ret |= 0x00; + else + ret |= ((fdd_count - 1) << 2); + /* Switches 6, 7 - monitor type */ + if (video_is_mda()) + ret |= 0x3; + else if (video_is_cga()) + ret |= 0x2; /* 0x10 would be 40x25 */ + else + ret |= 0x0; + } else { + /* bit 2 always on */ + ret |= 0x4; + /* Switch 8 - 8087 FPU. */ + if (hasfpu) + ret |= 0x02; + } + } + break; case 0x64: - ret = dev->status; + ret = (dev->status & 0xfb); + if (dev->mem[0] & STAT_SYSFLAG) + ret |= STAT_SYSFLAG; + /* Only clear the transmit timeout flag on non-PS/2 controllers, as on + PS/2 controller, it is the keyboard/mouse output source bit. */ + // dev->status &= ~STAT_RTIMEOUT; + if (((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) && + (kbc_ven != KBC_VEN_IBM_MCA)) + dev->status &= ~STAT_TTIMEOUT; break; default: @@ -2918,12 +2211,22 @@ kbd_read(uint16_t port, void *priv) break; } - kbd_log("[%04X:%08X] ATkbc: read(%04X) = %02X\n",CS, cpu_state.pc, port, ret); + kbd_log((port == 0x61) ? "" : "ATkbc: read(%04X) = %02X\n", port, ret); return(ret); } +static void +kbd_refresh(void *priv) +{ + atkbd_t *dev = (atkbd_t *)priv; + + dev->refresh = !dev->refresh; + timer_advance_u64(&dev->refresh_time, PS2_REFRESH_TIME); +} + + static void kbd_reset(void *priv) { @@ -2932,26 +2235,25 @@ kbd_reset(void *priv) uint8_t kbc_ven = 0x0; kbc_ven = dev->flags & KBC_VEN_MASK; + dev->first_write = 1; + // dev->status = STAT_UNLOCKED | STAT_CD; dev->status = STAT_UNLOCKED; - dev->mem[0x20] = 0x01; - dev->mem[0x20] |= CCB_TRANSLATE; + dev->mem[0] = 0x01; + dev->mem[0] |= CCB_TRANSLATE; + dev->wantirq = 0; write_output(dev, 0xcf); - dev->last_irq = 0; + dev->last_irq = dev->old_last_irq = 0; dev->secr_phase = 0; - dev->kbd_in = 0; - dev->ami_mode = !!(dev->flags & KBC_FLAG_PS2); + dev->key_wantdata = 0; /* Set up the correct Video Type bits. */ - dev->p1 = video_is_mda() ? 0xf0 : 0xb0; if ((kbc_ven == KBC_VEN_XI8088) || (kbc_ven == KBC_VEN_ACER)) - dev->p1 ^= 0x40; - if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) - dev->inhibit = ((dev->p1 & 0x80) >> 3); + dev->input_port = video_is_mda() ? 0xb0 : 0xf0; else - dev->inhibit = 0x10; - kbd_log("ATkbc: input port = %02x\n", dev->p1); + dev->input_port = video_is_mda() ? 0xf0 : 0xb0; + kbd_log("ATkbc: input port = %02x\n", dev->input_port); - keyboard_mode = 0x02 | (dev->mem[0x20] & CCB_TRANSLATE); + keyboard_mode = 0x02 | (dev->mem[0] & CCB_TRANSLATE); /* Enable keyboard, disable mouse. */ set_enable_kbd(dev, 1); @@ -2959,18 +2261,16 @@ kbd_reset(void *priv) set_enable_mouse(dev, 0); mouse_scan = 0; - dev->ob = 0xff; + dev->out_new = dev->out_delayed = -1; + for (i = 0; i < 3; i++) + kbc_queue_reset(i); + kbd_last_scan_code = 0; sc_or = 0; - for (i = 1; i <= 2; i++) - kbc_queue_reset(i); - memset(keyboard_set3_flags, 0, 512); set_scancode_map(dev); - - dev->mem[0x31] = 0xfe; } @@ -2992,6 +2292,7 @@ kbd_close(void *priv) /* Stop timers. */ timer_disable(&dev->send_delay_timer); + timer_disable(&dev->refresh_time); keyboard_scan = 0; keyboard_send = NULL; @@ -3015,14 +2316,17 @@ kbd_init(const device_t *info) dev->flags = info->local; video_reset(gfxcard); - dev->kbc_poll_phase = KBC_RESET; - kbd_send_to_host(dev, 0xaa); + kbd_reset(dev); - io_sethandler(0x0060, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); - io_sethandler(0x0064, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); + io_sethandler(0x0060, 5, + kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); keyboard_send = add_data_kbd; timer_add(&dev->send_delay_timer, kbd_poll, dev, 1); + + if ((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) + timer_add(&dev->refresh_time, kbd_refresh, dev, 1); + timer_add(&dev->pulse_cb, pulse_poll, dev, 0); dev->write60_ven = NULL; @@ -3038,14 +2342,12 @@ kbd_init(const device_t *info) break; case KBC_VEN_OLIVETTI: - /* The Olivetti controller is a special case - starts directly in the - main loop instead of the reset loop. */ - dev->kbc_poll_phase = KBC_MAIN_LOOP; dev->write64_ven = write64_olivetti; break; case KBC_VEN_AMI: case KBC_VEN_INTEL_AMI: + case KBC_VEN_SAMSUNG: dev->write60_ven = write60_ami; dev->write64_ven = write64_ami; break; @@ -3065,8 +2367,6 @@ kbd_init(const device_t *info) break; } - kbd_reset(dev); - /* We need this, sadly. */ SavedKbd = dev; @@ -3094,6 +2394,16 @@ const device_t keyboard_at_ami_device = { { NULL }, NULL, NULL, NULL }; +const device_t keyboard_at_samsung_device = { + "PC/AT Keyboard (Samsung)", + 0, + KBC_TYPE_ISA | KBC_VEN_SAMSUNG, + kbd_init, + kbd_close, + kbd_reset, + { NULL }, NULL, NULL, NULL +}; + const device_t keyboard_at_toshiba_device = { "PC/AT Keyboard (Toshiba)", 0, @@ -3125,6 +2435,16 @@ const device_t keyboard_at_ncr_device = { }; const device_t keyboard_ps2_device = { + "PS/2 Keyboard", + 0, + KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC, + kbd_init, + kbd_close, + kbd_reset, + { NULL }, NULL, NULL, NULL +}; + +const device_t keyboard_ps2_ps2_device = { "PS/2 Keyboard", 0, KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, @@ -3137,7 +2457,7 @@ const device_t keyboard_ps2_device = { const device_t keyboard_ps2_ps1_device = { "PS/2 Keyboard (IBM PS/1)", 0, - KBC_TYPE_PS2_1 | KBC_VEN_IBM_PS1, + KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1, kbd_init, kbd_close, kbd_reset, @@ -3147,7 +2467,7 @@ const device_t keyboard_ps2_ps1_device = { const device_t keyboard_ps2_ps1_pci_device = { "PS/2 Keyboard (IBM PS/1)", DEVICE_PCI, - KBC_TYPE_PS2_1 | KBC_VEN_IBM_PS1, + KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1, kbd_init, kbd_close, kbd_reset, @@ -3167,7 +2487,7 @@ const device_t keyboard_ps2_xi8088_device = { const device_t keyboard_ps2_ami_device = { "PS/2 Keyboard (AMI)", 0, - KBC_TYPE_PS2_1 | KBC_VEN_AMI, + KBC_TYPE_PS2_NOREF | KBC_VEN_AMI, kbd_init, kbd_close, kbd_reset, @@ -3177,7 +2497,7 @@ const device_t keyboard_ps2_ami_device = { const device_t keyboard_ps2_olivetti_device = { "PS/2 Keyboard (Olivetti)", 0, - KBC_TYPE_PS2_1 | KBC_VEN_OLIVETTI, + KBC_TYPE_PS2_NOREF | KBC_VEN_OLIVETTI, kbd_init, kbd_close, kbd_reset, @@ -3207,7 +2527,7 @@ const device_t keyboard_ps2_mca_2_device = { const device_t keyboard_ps2_quadtel_device = { "PS/2 Keyboard (Quadtel/MegaPC)", 0, - KBC_TYPE_PS2_1 | KBC_VEN_QUADTEL, + KBC_TYPE_PS2_NOREF | KBC_VEN_QUADTEL, kbd_init, kbd_close, kbd_reset, @@ -3217,7 +2537,7 @@ const device_t keyboard_ps2_quadtel_device = { const device_t keyboard_ps2_pci_device = { "PS/2 Keyboard", DEVICE_PCI, - KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, + KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC, kbd_init, kbd_close, kbd_reset, @@ -3227,7 +2547,7 @@ const device_t keyboard_ps2_pci_device = { const device_t keyboard_ps2_ami_pci_device = { "PS/2 Keyboard (AMI)", DEVICE_PCI, - KBC_TYPE_PS2_1 | KBC_VEN_AMI, + KBC_TYPE_PS2_NOREF | KBC_VEN_AMI, kbd_init, kbd_close, kbd_reset, @@ -3237,7 +2557,7 @@ const device_t keyboard_ps2_ami_pci_device = { const device_t keyboard_ps2_intel_ami_pci_device = { "PS/2 Keyboard (AMI)", DEVICE_PCI, - KBC_TYPE_PS2_1 | KBC_VEN_INTEL_AMI, + KBC_TYPE_PS2_NOREF | KBC_VEN_INTEL_AMI, kbd_init, kbd_close, kbd_reset, @@ -3247,7 +2567,7 @@ const device_t keyboard_ps2_intel_ami_pci_device = { const device_t keyboard_ps2_acer_pci_device = { "PS/2 Keyboard (Acer 90M002A)", DEVICE_PCI, - KBC_TYPE_PS2_1 | KBC_VEN_ACER, + KBC_TYPE_PS2_NOREF | KBC_VEN_ACER, kbd_init, kbd_close, kbd_reset, @@ -3258,8 +2578,17 @@ const device_t keyboard_ps2_acer_pci_device = { void keyboard_at_set_mouse(void (*func)(uint8_t val, void *priv), void *priv) { - // mouse_write = func; - // mouse_p = priv; + mouse_write = func; + mouse_p = priv; +} + + +void +keyboard_at_adddata_keyboard_raw(uint8_t val) +{ + atkbd_t *dev = SavedKbd; + + add_data_kbd_queue(dev, 0, val); } @@ -3272,30 +2601,10 @@ keyboard_at_adddata_mouse(uint8_t val) } -void -keyboard_at_adddata_mouse_direct(uint8_t val) -{ - // atkbd_t *dev = SavedKbd; - - return; -} - - -void -keyboard_at_adddata_mouse_cmd(uint8_t val) -{ - // atkbd_t *dev = SavedKbd; - - return; -} - - void keyboard_at_mouse_reset(void) { - // atkbd_t *dev = SavedKbd; - - return; + kbc_queue_reset(2); } @@ -3306,22 +2615,13 @@ keyboard_at_mouse_pos(void) } -int -keyboard_at_fixed_channel(void) -{ - // atkbd_t *dev = SavedKbd; - - return 0x000; -} - - void keyboard_at_set_mouse_scan(uint8_t val) { atkbd_t *dev = SavedKbd; uint8_t temp_mouse_scan = val ? 1 : 0; - if (temp_mouse_scan == !(dev->mem[0x20] & 0x20)) + if (temp_mouse_scan == !(dev->mem[0] & 0x20)) return; set_enable_mouse(dev, val ? 1 : 0); @@ -3335,7 +2635,7 @@ keyboard_at_get_mouse_scan(void) { atkbd_t *dev = SavedKbd; - return((dev->mem[0x20] & 0x20) ? 0x00 : 0x10); + return((dev->mem[0] & 0x20) ? 0x00 : 0x10); } @@ -3344,17 +2644,5 @@ keyboard_at_set_a20_key(int state) { atkbd_t *dev = SavedKbd; - write_output(dev, (dev->p2 & 0xfd) | ((!!state) << 1)); -} - - -void -keyboard_at_set_mode(int ps2) -{ - atkbd_t *dev = SavedKbd; - - if (ps2) - dev->flags |= KBC_FLAG_PS2; - else - dev->flags &= ~KBC_FLAG_PS2; + write_output(dev, (dev->output_port & 0xfd) | ((!!state) << 1)); } From 4b1c0a1597800b29cad69099c1226c2cb37a032a Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 10 Aug 2021 15:49:50 +0200 Subject: [PATCH 44/96] And back. --- src/device/keyboard_at.c | 2805 ++++++++++++++++++++++++-------------- 1 file changed, 1759 insertions(+), 1046 deletions(-) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 1c44880a3..c0507ffb5 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -57,9 +57,7 @@ #define STAT_IFULL 0x02 #define STAT_OFULL 0x01 -#define PS2_REFRESH_TIME (16 * TIMER_USEC) - -#define RESET_DELAY_TIME (100 * 10) /* 600ms */ +#define RESET_DELAY_TIME 1000 /* 100 ms */ #define CCB_UNUSED 0x80 #define CCB_TRANSLATE 0x40 @@ -74,49 +72,136 @@ #define MODE_MASK 0x6c #define KBC_TYPE_ISA 0x00 /* AT ISA-based chips */ -#define KBC_TYPE_PS2_NOREF 0x01 /* PS2 type, no refresh */ -#define KBC_TYPE_PS2_1 0x02 /* PS2 on PS/2, type 1 */ -#define KBC_TYPE_PS2_2 0x03 /* PS2 on PS/2, type 2 */ -#define KBC_TYPE_MASK 0x03 +#define KBC_TYPE_PS2_1 0x04 /* PS2 type, no refresh */ +/* This only differs in that translation is forced off. */ +#define KBC_TYPE_PS2_2 0x05 /* PS2 on PS/2, type 2 */ +#define KBC_TYPE_MASK 0x07 +#define KBC_FLAG_PS2 0x04 + +/* We need to redefine this: + Currently, we use bits 3-7 for vendor, we should instead use bits 4-7 + for vendor, 0-3 for revision/variant, and have a dev->ps2 flag controlling + controller mode, normally set according to the flags, but togglable on + AMIKey: + 0000 0000 0x00 IBM, AT + 0000 0001 0x01 MR + 0000 0010 0x02 Xi8088, clone of IBM PS/2 type 1 + 0001 0000 0x10 Olivetti + 0010 0000 0x20 Toshiba + 0011 0000 0x30 Quadtel + 0100 0000 0x40 Phoenix MultiKey/42 + 0101 0000 0x50 AMI KF + 0101 0001 0x51 AMI KH + 0101 0010 0x52 AMIKey + 0101 0011 0x53 AMIKey-2 + 0101 0100 0x54 JetKey (clone of AMI KF/AMIKey) + 0110 0000 0x60 Award + 0110 0001 0x61 Award 286 (has some AMI commands apparently) + 0111 0000 0x70 Siemens +*/ + +/* Standard IBM controller */ #define KBC_VEN_GENERIC 0x00 -#define KBC_VEN_AMI 0x04 +/* All commands are standard PS/2 */ #define KBC_VEN_IBM_MCA 0x08 -#define KBC_VEN_QUADTEL 0x0c -#define KBC_VEN_TOSHIBA 0x10 -#define KBC_VEN_XI8088 0x14 -#define KBC_VEN_IBM_PS1 0x18 -#define KBC_VEN_ACER 0x1c -#define KBC_VEN_INTEL_AMI 0x20 -#define KBC_VEN_OLIVETTI 0x24 -#define KBC_VEN_NCR 0x28 -#define KBC_VEN_SAMSUNG 0x2c -#define KBC_VEN_MASK 0x3c +/* Standard IBM commands, differs in input port bits */ +#define KBC_VEN_IBM_PS1 0x10 +/* Olivetti - proprietary commands and port 62h with switches + readout */ +#define KBC_VEN_OLIVETTI 0x20 +/* Toshiba T3100e - has a bunch of proprietary commands, also sets + IFULL on command AA */ +#define KBC_VEN_TOSHIBA 0x28 +/* Standard IBM commands, uses input port as a switches readout */ +#define KBC_VEN_NCR 0x30 +/* Xi8088 - standard IBM commands, has a turbo bit on port 61h, and the + polarity of the video type bit in the input port is inverted */ +#define KBC_VEN_XI8088 0x38 +/* QuadtelKey - currently guesswork */ +#define KBC_VEN_QUADTEL 0x40 +/* Phoenix MultiKey/42 - not yet implemented */ +#define KBC_VEN_PHOENIX 0x48 +/* Generic commands, XI8088-like input port handling of video type, + maybe we just need a flag for that? */ +#define KBC_VEN_ACER 0x50 +/* AMI KF/KH/AMIKey/AMIKey-2 */ +#define KBC_VEN_AMI 0xf0 +/* Standard AMI commands, differs in input port bits */ +#define KBC_VEN_INTEL_AMI 0xf8 +#define KBC_VEN_MASK 0xf8 + + +/* Flags should be fully 32-bit: + Bits 7- 0: Vendor and revision/variant; + Bits 15- 8: Input port mask; + Bits 23-16: Input port bits that are always on; + Bits 31-24: Flags: + Bit 0: Invert P1 video type bit polarity; + Bit 1: Is PS/2; + Bit 2: Translation forced always off. + + So for example, the IBM PS/2 type 1 controller flags would be: 00000010 00000000 11111111 00000000 = 0200ff00 . */ typedef struct { - uint8_t command, status, old_status, out, old_out, secr_phase, - mem_addr, input_port, output_port, old_output_port, - key_command, output_locked, ami_stat, want60, - wantirq, key_wantdata, refresh, first_write; + uint8_t status, ib, ob, p1, p2, old_p2, p2_locked, fast_a20_phase, + secr_phase, mem_index, ami_stat, ami_mode, + kbc_in, kbc_cmd, kbc_in_cmd, kbc_poll_phase, kbc_to_send, + kbc_send_pending, kbc_channel, kbc_stat_hi, kbc_wait_for_response, inhibit, + kbd_in, kbd_cmd, kbd_in_cmd, kbd_written, kbd_data, kbd_poll_phase, kbd_inhibit, + mouse_in, mouse_cmd, mouse_in_cmd, mouse_written, mouse_data, mouse_poll_phase, mouse_inhibit, + kbc_written[3], kbc_data[3]; - uint8_t mem[0x100]; + uint8_t mem_int[0x40], mem[0x240]; - int last_irq, old_last_irq, - reset_delay, - out_new, out_delayed; + uint16_t last_irq, kbc_phase, kbd_phase, mouse_phase; uint32_t flags; - pc_timer_t refresh_time, pulse_cb; + pc_timer_t pulse_cb, send_delay_timer; uint8_t (*write60_ven)(void *p, uint8_t val); uint8_t (*write64_ven)(void *p, uint8_t val); - - pc_timer_t send_delay_timer; } atkbd_t; +enum +{ + CHANNEL_KBC = 0, + CHANNEL_KBD, + CHANNEL_MOUSE +}; + +enum +{ + KBD_MAIN_LOOP = 0, + KBD_CMD_PROCESS +}; + +enum +{ + MOUSE_MAIN_LOOP_1 = 0, + MOUSE_CMD_PROCESS, + MOUSE_CMD_END, + MOUSE_MAIN_LOOP_2 +}; + +enum { + KBC_MAIN_LOOP = 0, + KBC_RESET = 1, + KBC_WAIT = 4, + KBC_WAIT_FOR_KBD, + KBC_WAIT_FOR_MOUSE, + KBC_WAIT_FOR_BOTH +}; + + +static void kbd_cmd_process(atkbd_t *dev); + +static void kbc_wait(atkbd_t *dev, uint8_t flags); + + /* bit 0 = repeat, bit 1 = makes break code? */ uint8_t keyboard_set3_flags[512]; uint8_t keyboard_set3_all_repeat; @@ -125,9 +210,9 @@ uint8_t keyboard_set3_all_break; /* Bits 0 - 1 = scan code set, bit 6 = translate or not. */ uint8_t keyboard_mode = 0x42; +uint8_t * ami_copr = (uint8_t *) "(C)1994 AMI"; + -static uint8_t key_ctrl_queue[16]; -static int key_ctrl_queue_start = 0, key_ctrl_queue_end = 0; static uint8_t key_queue[16]; static int key_queue_start = 0, key_queue_end = 0; uint8_t mouse_queue[16]; @@ -568,9 +653,27 @@ static const scancode scancode_set3[512] = { }; +#define UISTR_LEN 256 +static char kbd_str[UISTR_LEN]; /* UI output string */ static void add_data_kbd(uint16_t val); +extern void ui_sb_bugui(char *__str); + + +static void +kbd_status(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsprintf(kbd_str, fmt, ap); + ui_sb_bugui(kbd_str); + va_end(ap); +} + + +#define ENABLE_KEYBOARD_AT_LOG 1 #ifdef ENABLE_KEYBOARD_AT_LOG int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG; @@ -631,9 +734,6 @@ kbc_queue_reset(uint8_t channel) } else if (channel == 1) { key_queue_start = key_queue_end = 0; memset(key_queue, 0x00, sizeof(key_queue)); - } else { - key_ctrl_queue_start = key_ctrl_queue_end = 0; - memset(key_ctrl_queue, 0x00, sizeof(key_ctrl_queue)); } } @@ -641,15 +741,6 @@ kbc_queue_reset(uint8_t channel) static void kbc_queue_add(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) { - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - - if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) - stat_hi |= ((dev->input_port & 0x80) ? 0x10 : 0x00); - else - stat_hi |= 0x10; - - dev->status = (dev->status & 0x0f) | stat_hi; - if (channel == 2) { kbd_log("ATkbc: mouse_queue[%02X] = %02X;\n", mouse_queue_end, val); mouse_queue[mouse_queue_end] = val; @@ -658,83 +749,1045 @@ kbc_queue_add(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); key_queue[key_queue_end] = val; key_queue_end = (key_queue_end + 1) & 0xf; - } else { - kbd_log("ATkbc: key_ctrl_queue[%02X] = %02X;\n", key_ctrl_queue_end, val); - key_ctrl_queue[key_ctrl_queue_end] = val; - key_ctrl_queue_end = (key_ctrl_queue_end + 1) & 0xf; - } -} - - -static void -add_to_kbc_queue_front(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) -{ - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - - if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) - stat_hi |= ((dev->input_port & 0x80) ? 0x10 : 0x00); - else - stat_hi |= 0x10; - - kbd_log("ATkbc: Adding %02X to front...\n", val); - dev->wantirq = 0; - if (channel == 2) { - if (dev->mem[0] & 0x02) - picint(0x1000); - dev->last_irq = 0x1000; - } else { - if (dev->mem[0] & 0x01) - picint(2); - dev->last_irq = 2; - } - dev->out = val; - if (channel == 2) - dev->status = (dev->status & ~STAT_IFULL) | (STAT_OFULL | STAT_MFULL) | stat_hi; - else - dev->status = (dev->status & ~(STAT_IFULL | STAT_MFULL)) | STAT_OFULL | stat_hi; + } else + fatal("Adding %02X to invalid channel %02X\n", val, channel); } static void add_data_kbd_queue(atkbd_t *dev, int direct, uint8_t val) { - if ((!keyboard_scan && !direct) || (dev->reset_delay > 0) || (key_queue_end >= 16)) { - kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i, %i\n", !keyboard_scan, (dev->reset_delay > 0), (key_queue_end >= 16)); + if ((!keyboard_scan && !direct) || (key_queue_end >= 16)) { + kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i\n", !keyboard_scan, (key_queue_end >= 16)); return; } - kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); + + kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); kbc_queue_add(dev, val, 1, 0x00); kbd_last_scan_code = val; } - static void -add_data_kbd_direct(atkbd_t *dev, uint8_t val) +kbc_send(atkbd_t *dev, uint8_t val, uint8_t channel) { - int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); - int translate = (keyboard_mode & 0x40); - uint8_t send; - - if (dev->reset_delay) - return; - - translate = translate || (keyboard_mode & 0x40) || xt_mode; - translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); - - if (translate) - send = nont_to_t[val]; - else - send = val; - - add_data_kbd_queue(dev, 1, send); + dev->kbc_written[channel] = 1; + dev->kbc_data[channel] = val; } static void -add_data_kbd_raw(atkbd_t *dev, uint8_t val) +kbd_send_to_host(atkbd_t *dev, uint8_t val) { - add_data_kbd_queue(dev, 1, val); + kbc_send(dev, val, CHANNEL_KBD); +} + + +static void +kbd_chip_reset(atkbd_t *dev) +{ + kbc_queue_reset(1); + dev->kbc_written[1] = 0x00; + kbd_last_scan_code = 0x00; + + /* Set scan code set to 2. */ + keyboard_mode = (keyboard_mode & 0xfc) | 0x02; + set_scancode_map(dev); + + dev->kbd_phase = 0; + dev->kbd_in = 0; +} + + +static void +kbd_command(atkbd_t *dev) +{ + uint8_t val = dev->kbd_data; + + if ((dev->kbd_phase > 0) && (dev->kbd_cmd == 0xff)) { + dev->kbd_phase++; + if (dev->kbd_phase == RESET_DELAY_TIME) { + kbd_send_to_host(dev, 0xaa); + dev->kbd_phase = 0; + dev->kbd_cmd = 0x00; + } + return; + } + + if (dev->kbd_phase == 2) { + dev->kbd_phase = 0; + + switch (dev->kbd_cmd) { + case 0xf2: + kbd_send_to_host(dev, 0x83); + break; + default: + fatal("Invalid command for phase 2: %02X\n", dev->kbd_cmd); + break; + } + + /* Keyboard command is now done. */ + if (dev->kbd_phase == 0) + dev->kbd_cmd = 0x00; + return; + } else if (dev->kbd_phase == 1) { + dev->kbd_phase = 0; + + switch (dev->kbd_cmd) { + case 0xf0: + kbd_log("Get scan code set: %02X\n", keyboard_mode & 3); + kbd_send_to_host(dev, keyboard_mode & 3); + break; + case 0xf2: + kbd_send_to_host(dev, 0xab); + dev->kbd_phase = 2; + break; + default: + fatal("Invalid command for phase 1: %02X\n", dev->kbd_cmd); + break; + } + + /* Keyboard command is now done. */ + if (dev->kbd_phase == 0) + dev->kbd_cmd = 0x00; + return; + } + + if (dev->kbd_in && (val < 0xed)) { + dev->kbd_in = 0; + dev->kbd_phase = 0; + + switch (dev->kbd_cmd) { + case 0xed: /* set/reset LEDs */ + kbd_log("ATkbd: set LEDs [%02x]\n", val); + kbd_send_to_host(dev, 0xfa); + break; + + case 0xf0: /* get/set scancode set */ + kbd_send_to_host(dev, 0xfa); + if (val == 0) + dev->kbd_phase = 1; + else { + if ((val <= 3) && (val != 1)) { + keyboard_mode &= 0xfc; + keyboard_mode |= (val & 3); + kbd_log("Scan code set now: %02X\n", val); + } + set_scancode_map(dev); + } + break; + + case 0xf3: /* set typematic rate/delay */ + kbd_send_to_host(dev, 0xfa); + break; + + default: + kbd_log("ATkbd: bad keyboard 0060 write %02X command %02X\n", val, dev->kbd_cmd); + kbd_send_to_host(dev, 0xfe); + break; + } + + /* Keyboard command is now done. */ + if (dev->kbd_phase == 0) + dev->kbd_cmd = 0x00; + } else { + /* No keyboard command in progress. */ + dev->kbd_in = 0; + dev->kbd_cmd = 0x00; + dev->kbd_phase = 0; + + switch (val) { + case 0x00: + kbd_log("ATkbd: command 00\n"); + kbd_send_to_host(dev, 0xfa); + break; + + case 0x05: /*??? - sent by NT 4.0*/ + kbd_log("ATkbd: command 05 (NT 4.0)\n"); + kbd_send_to_host(dev, 0xfe); + break; + + case 0xed: /* set/reset LEDs */ + kbd_log("ATkbd: set/reset leds\n"); + kbd_send_to_host(dev, 0xfa); + + dev->kbd_in = 1; + break; + + case 0xee: /* diagnostic echo */ + kbd_log("ATkbd: ECHO\n"); + kbd_send_to_host(dev, 0xee); + break; + + case 0xef: /* NOP (reserved for future use) */ + kbd_log("ATkbd: NOP\n"); + break; + + case 0xf0: /* get/set scan code set */ + kbd_log("ATkbd: scan code set\n"); + kbd_send_to_host(dev, 0xfa); + dev->kbd_in = 1; + break; + + case 0xf2: /* read ID */ + /* Fixed as translation will be done in add_data_kbd(). */ + kbd_log("ATkbd: read keyboard id\n"); + /* TODO: After keyboard type selection is implemented, make this + return the correct keyboard ID for the selected type. */ + kbd_send_to_host(dev, 0xfa); + dev->kbd_phase = 1; + break; + + case 0xf3: /* set typematic rate/delay */ + kbd_log("ATkbd: set typematic rate/delay\n"); + kbd_send_to_host(dev, 0xfa); + dev->kbd_in = 1; + break; + + case 0xf4: /* enable keyboard */ + kbd_log("ATkbd: enable keyboard\n"); + kbd_send_to_host(dev, 0xfa); + keyboard_scan = 1; + break; + + case 0xf5: /* set defaults and disable keyboard */ + case 0xf6: /* set defaults */ + kbd_log("ATkbd: set defaults%s\n", (val == 0xf6) ? "" : " and disable keyboard"); + keyboard_scan = (val == 0xf6); + kbd_log("val = %02X, keyboard_scan = %i, dev->mem[0x20] = %02X\n", + val, keyboard_scan, dev->mem[0x20]); + kbd_send_to_host(dev, 0xfa); + + keyboard_set3_all_break = 0; + keyboard_set3_all_repeat = 0; + memset(keyboard_set3_flags, 0, 512); + keyboard_mode = (keyboard_mode & 0xfc) | 0x02; + set_scancode_map(dev); + break; + + case 0xf7: /* set all keys to repeat */ + kbd_log("ATkbd: set all keys to repeat\n"); + kbd_send_to_host(dev, 0xfa); + keyboard_set3_all_break = 1; + break; + + case 0xf8: /* set all keys to give make/break codes */ + kbd_log("ATkbd: set all keys to give make/break codes\n"); + kbd_send_to_host(dev, 0xfa); + keyboard_set3_all_break = 1; + break; + + case 0xf9: /* set all keys to give make codes only */ + kbd_log("ATkbd: set all keys to give make codes only\n"); + kbd_send_to_host(dev, 0xfa); + keyboard_set3_all_break = 0; + break; + + case 0xfa: /* set all keys to repeat and give make/break codes */ + kbd_log("ATkbd: set all keys to repeat and give make/break codes\n"); + kbd_send_to_host(dev, 0xfa); + keyboard_set3_all_repeat = 1; + keyboard_set3_all_break = 1; + break; + + case 0xfe: /* resend last scan code */ + kbd_log("ATkbd: reset last scan code\n"); + kbd_send_to_host(dev, kbd_last_scan_code); + break; + + case 0xff: /* reset */ + kbd_log("ATkbd: kbd reset\n"); + kbd_chip_reset(dev); + kbd_send_to_host(dev, 0xfa); + dev->kbd_phase = 1; + break; + + default: + kbd_log("ATkbd: bad keyboard command %02X\n", val); + kbd_send_to_host(dev, 0xfe); + } + + /* If command needs data, remember command. */ + if ((dev->kbd_in == 1) || (dev->kbd_phase > 0)) + dev->kbd_cmd = val; + } +} + + +static void +kbd_do_command(atkbd_t *dev) +{ + kbd_command(dev); + if (dev->kbd_written) + dev->kbd_poll_phase = KBD_CMD_PROCESS; + else if ((dev->kbd_phase == 0) && !dev->kbd_in) { + dev->kbd_in_cmd = 0; + if (dev->kbd_data != 0xf5) + keyboard_scan = 1; + dev->kbd_poll_phase = KBD_MAIN_LOOP; + } else { + keyboard_scan = 0; + dev->kbd_in_cmd = 1; + dev->kbd_poll_phase = KBD_CMD_PROCESS; + } +} + + +static void +kbd_nack(atkbd_t *dev) +{ + kbd_send_to_host(dev, 0xfe); + dev->kbd_poll_phase = KBD_MAIN_LOOP; +} + + +static void +kbd_main_loop(atkbd_t *dev) +{ + uint8_t scan = !dev->kbd_inhibit && keyboard_scan; + + if (dev->kbd_written) { + dev->kbd_written = 0; + kbd_cmd_process(dev); + } else if (scan && (key_queue_start != key_queue_end)) { + /* Scan here. */ + kbd_log("ATkbd: Get %02X from FIFO\n", key_queue[key_queue_start]); + kbd_send_to_host(dev, key_queue[key_queue_start]); + key_queue_start = (key_queue_start + 1) & 0xf; + } +} + + +static void +kbd_cmd_process(atkbd_t *dev) +{ + uint8_t written = dev->kbd_written; + + /* We want data, nothing has been written yet, return. */ + if (dev->kbd_in && !dev->kbd_written) + return; + + dev->kbd_written = 0; + + if (!written && !keyboard_scan && dev->kbd_in_cmd && (dev->kbd_phase > 0)) { + kbd_log("ATkbd: Keyboard not written, not scanning, in command, and phase > 0\n"); + kbd_do_command(dev); + } else if (dev->kbd_data == 0xfe) { + kbd_log("ATkbd: Send last byte %02X\n", kbd_last_scan_code); + kbd_send_to_host(dev, kbd_last_scan_code); + dev->kbd_poll_phase = KBD_MAIN_LOOP; + } else if (dev->kbd_data == 0xee) { + kbd_log("ATkbd: Echo EE\n"); + kbd_send_to_host(dev, 0xee); + dev->kbd_poll_phase = KBD_MAIN_LOOP; + } else if (dev->kbd_data >= 0xed) { + kbd_log("ATkbd: Command %02X\n", dev->kbd_data); + if (!keyboard_scan && dev->kbd_in_cmd && (dev->kbd_cmd == 0xed)) { + kbd_log("ATkbd: Not scanning, in command, old command is ED\n"); + keyboard_scan = 1; + dev->kbd_in_cmd = 0; + } + kbd_do_command(dev); + } else { + if (!keyboard_scan && dev->kbd_in_cmd) { + if ((dev->kbd_cmd == 0xf3) && (dev->kbd_data & 0x80)) { + kbd_log("ATkbd: Command F3 data %02X has bit 7 set\n", dev->kbd_data); + kbd_nack(dev); + } else { + kbd_log("ATkbd: Command %02X data %02X\n", dev->kbd_cmd, dev->kbd_data); + kbd_do_command(dev); + } + } else { + kbd_log("ATkbd: Scanning or not in command, NACK\n"); + kbd_nack(dev); + } + } +} + + +/* Keyboard processing */ +static void +kbd_process(atkbd_t *dev) +{ + /* The real 8048 keyboard firmware stops transmitting if host wants to transmit. */ + if (dev->kbc_written[1] && dev->kbd_written) + dev->kbc_written[1] = 0; + + /* The host has either acknowledged the transmitted byte or we have not transmitted anything (yet). */ + if (!dev->kbc_written[1]) switch (dev->kbd_poll_phase) { + case KBD_MAIN_LOOP: + kbd_main_loop(dev); + break; + case KBD_CMD_PROCESS: + kbd_cmd_process(dev); + break; + } +} + + +static void +kbc_send_to_ob(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) +{ + uint8_t ch = (channel > 0) ? channel : 1; + uint8_t do_irq = (dev->mem[0x20] & ch); + int translate = (channel == 1) && (keyboard_mode & 0x60); + + if ((channel == 2) && !(dev->flags & KBC_FLAG_PS2)) + return; + + stat_hi |= dev->inhibit; + + if (!dev->kbc_send_pending) { + dev->kbc_send_pending = 1; + dev->kbc_to_send = val; + dev->kbc_channel = channel; + dev->kbc_stat_hi = stat_hi; + return; + } + + if (translate) { + /* Allow for scan code translation. */ + if (val == 0xf0) { + kbd_log("ATkbd: translate is on, F0 prefix detected\n"); + sc_or = 0x80; + return; + } + + /* Skip break code if translated make code has bit 7 set. */ + if ((sc_or == 0x80) && (val & 0x80)) { + kbd_log("ATkbd: translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val); + sc_or = 0; + return; + } + } + + dev->last_irq = (ch == 2) ? 0x1000 : 0x0002; + if (do_irq) { + kbd_log("[%04X:%08X] ATKbc: IRQ %i\n", CS, cpu_state.pc, (ch == 2) ? 12 : 1); + picint(dev->last_irq); + } + kbd_log("ATkbc: %02X coming from channel %i (%i)\n", val, channel, do_irq); + dev->ob = translate ? (nont_to_t[val] | sc_or) : val; + + dev->status = (dev->status & 0x0f) | (stat_hi | (dev->mem[0x20] & STAT_SYSFLAG) | STAT_OFULL); + if (ch == 2) + dev->status |= STAT_MFULL; + + if (translate && (sc_or == 0x80)) + sc_or = 0; +} + + +static void +write_output(atkbd_t *dev, uint8_t val) +{ + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + kbd_log("ATkbc: write output port: %02X (old: %02X)\n", val, dev->p2); + + if (!(dev->flags & KBC_FLAG_PS2)) + val |= ((dev->mem[0x20] << 4) & 0x30); + + dev->kbd_inhibit = (val & 0x40); + dev->mouse_inhibit = (val & 0x08); + + if ((dev->p2 ^ val) & 0x20) { /*IRQ 12*/ + if (val & 0x20) { + kbd_log("ATkbc: write_output(): IRQ 12\n"); + picint(1 << 12); + } else + picintc(1 << 12); + } + if ((dev->p2 ^ val) & 0x10) { /*IRQ 1*/ + if (val & 0x10) { + kbd_log("ATkbc: write_output(): IRQ 1\n"); + picint(1 << 1); + } else + picintc(1 << 1); + } + if ((dev->p2 ^ val) & 0x02) { /*A20 enable change*/ + mem_a20_key = val & 0x02; + mem_a20_recalc(); + flushmmucache(); + } + if ((dev->p2 ^ val) & 0x01) { /*Reset*/ + if (! (val & 0x01)) { + /* Pin 0 selected. */ + softresetx86(); /*Pulse reset!*/ + cpu_set_edx(); + smbase = is_am486dxl ? 0x00060000 : 0x00030000; + } + } + /* Mask off the A20 stuff because we use mem_a20_key directly for that. */ + dev->p2 = val; +} + + +static void +write_cmd(atkbd_t *dev, uint8_t val) +{ + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + kbd_log("ATkbc: write command byte: %02X (old: %02X)\n", val, dev->mem[0x20]); + + /* PS/2 type 2 keyboard controllers always force the XLAT bit to 0. */ + if ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2) + val &= ~CCB_TRANSLATE; + + dev->mem[0x20] = val; + + /* Scan code translate ON/OFF. */ + keyboard_mode &= 0x93; + keyboard_mode |= (val & MODE_MASK); + + kbd_log("ATkbc: keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled"); + + /* ISA AT keyboard controllers use bit 5 for keyboard mode (1 = PC/XT, 2 = AT); + PS/2 (and EISA/PCI) keyboard controllers use it as the PS/2 mouse enable switch. + The AMIKEY firmware apparently uses this bit for something else. */ + if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) { + keyboard_mode &= ~CCB_PCMODE; + + kbd_log("ATkbc: mouse interrupt is now %s\n", (val & 0x02) ? "enabled" : "disabled"); + } + + if (!(dev->flags & KBC_FLAG_PS2)) { + /* Update the output port to mirror the KBD DIS and AUX DIS bits, if active. */ + write_output(dev, dev->p2); + } + + kbd_log("Command byte now: %02X (%02X)\n", dev->mem[0x20], val); + + dev->status = (dev->status & ~STAT_SYSFLAG) | (val & STAT_SYSFLAG); +} + + +static void +pulse_output(atkbd_t *dev, uint8_t mask) +{ + if (mask != 0x0f) { + dev->old_p2 = dev->p2 & ~(0xf0 | mask); + kbd_log("pulse_output(): Output port now: %02X\n", dev->p2 & (0xf0 | mask | (dev->mem[0x20] & 0x30))); + write_output(dev, dev->p2 & (0xf0 | mask | (dev->mem[0x20] & 0x30))); + timer_set_delay_u64(&dev->pulse_cb, 6ULL * TIMER_USEC); + } +} + + +static void +set_enable_kbd(atkbd_t *dev, uint8_t enable) +{ + dev->mem[0x20] &= 0xef; + dev->mem[0x20] |= (enable ? 0x00 : 0x10); +} + + +static void +set_enable_mouse(atkbd_t *dev, uint8_t enable) +{ + dev->mem[0x20] &= 0xdf; + dev->mem[0x20] |= (enable ? 0x00 : 0x20); +} + + +static void +kbc_transmit(atkbd_t *dev, uint8_t val) +{ + kbc_send_to_ob(dev, val, 0, 0x00); +} + + +static void +kbc_command(atkbd_t *dev) +{ + uint8_t mask, val = dev->ib; + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + int bad = 1; + + if ((dev->kbc_phase > 0) && (dev->kbc_cmd == 0xac)) { + if (dev-> kbc_phase < 16) + kbc_transmit(dev, dev->mem[dev->kbc_phase]); + else if (dev-> kbc_phase == 16) + kbc_transmit(dev, (dev->p1 & 0xf0) | 0x80); + else if (dev-> kbc_phase == 17) + kbc_transmit(dev, dev->p2); + else if (dev-> kbc_phase == 18) + kbc_transmit(dev, dev->status); + + dev->kbc_phase++; + if (dev->kbc_phase == 19) { + dev->kbc_phase = 0; + dev->kbc_cmd = 0x00; + } + return; + } else if ((dev->kbc_phase > 0) && (dev->kbc_cmd == 0xa0) && (kbc_ven >= KBC_VEN_AMI)) { + val = ami_copr[dev->kbc_phase]; + kbc_transmit(dev, val); + if (val == 0x00) { + dev->kbc_phase = 0; + dev->kbc_cmd = 0x00; + } else + dev->kbc_phase++; + return; + } else if ((dev->kbc_in > 0) && (dev->kbc_cmd == 0xa5) && (dev->flags & KBC_FLAG_PS2)) { + /* load security */ + kbd_log("ATkbc: load security\n"); + dev->mem[0x50 + dev->kbc_in - 0x01] = val; + if ((dev->kbc_in == 0x80) && (val != 0x00)) { + /* Security string too long, set it to 0x00. */ + dev->mem[0x50] = 0x00; + dev->kbc_in = 0; + dev->kbc_cmd = 0; + } else if (val == 0x00) { + /* Security string finished. */ + dev->kbc_in = 0; + dev->kbc_cmd = 0; + } else /* Increase pointer and request another byte. */ + dev->kbc_in++; + return; + } + + /* If the written port is 64, go straight to the beginning of the command. */ + if (!(dev->status & STAT_CD) && dev->kbc_in) { + /* Write data to controller. */ + dev->kbc_in = 0; + dev->kbc_phase = 0; + + switch (dev->kbc_cmd) { + case 0x60 ... 0x7f: + if (dev->kbc_cmd == 0x60) + write_cmd(dev, val); + else + dev->mem[(dev->kbc_cmd & 0x1f) + 0x20] = val; + break; + + case 0xc7: /* or input port with system data */ + dev->p1 |= val; + break; + + case 0xcb: /* set keyboard mode */ + kbd_log("New AMIKey mode: %02X\n", val); + dev->ami_mode = val; + dev->flags &= ~KBC_FLAG_PS2; + if (val & 1) + dev->flags |= KBC_FLAG_PS2; + break; + + case 0xd1: /* write output port */ + kbd_log("ATkbc: write output port\n"); + if (dev->p2_locked) { + /*If keyboard controller lines P22-P23 are blocked, + we force them to remain unchanged.*/ + val &= ~0x0c; + val |= (dev->p2 & 0x0c); + } + write_output(dev, val); + break; + + case 0xd2: /* write to keyboard output buffer */ + kbd_log("ATkbc: write to keyboard output buffer\n"); + // kbc_send_to_ob(dev, val, 1, 0x00); + /* Should be channel 1, but we send to 0 to avoid translation, + since bytes output using this command do *NOT* get translated. */ + kbc_send_to_ob(dev, val, 0, 0x00); + break; + + case 0xd3: /* write to mouse output buffer */ + kbd_log("ATkbc: write to mouse output buffer\n"); + if (dev->flags & KBC_FLAG_PS2) + kbc_send_to_ob(dev, val, 2, 0x00); + break; + + case 0xd4: /* write to mouse */ + kbd_log("ATkbc: write to mouse (%02X)\n", val); + + if (dev->flags & KBC_FLAG_PS2) { + set_enable_mouse(dev, 1); + dev->mem[0x20] &= ~0x20; + if (mouse_write && !dev->kbc_written[2]) { + kbd_log("ATkbc: Sending %02X to mouse...\n", dev->ib); + dev->mouse_data = val; + dev->mouse_written = 1; + dev->kbc_wait_for_response = 2; + } else + kbc_send_to_ob(dev, 0xfe, 2, 0x40); + } + break; + + default: + /* + * Run the vendor-specific handler + * if we have one. Otherwise, or if + * it returns an error, log a bad + * controller command. + */ + if (dev->write60_ven) + bad = dev->write60_ven(dev, val); + +#ifdef ENABLE_KEYBOARD_AT_LOG + if (bad) + kbd_log("ATkbc: bad controller command %02x data %02x\n", dev->kbc_cmd, val); +#endif + } + } else { + /* Controller command. */ + kbd_log("ATkbc: Controller command: %02X\n", val); + dev->kbc_in = 0; + dev->kbc_phase = 0; + + switch (val) { + /* Read data from KBC memory. */ + case 0x20 ... 0x3f: + kbc_transmit(dev, dev->mem[(val & 0x1f) + 0x20]); + break; + + /* Write data to KBC memory. */ + case 0x60 ... 0x7f: + dev->kbc_in = 1; + break; + + case 0xaa: /* self-test */ + kbd_log("ATkbc: self-test\n"); + write_output(dev, (dev->flags & KBC_FLAG_PS2) ? 0x4b : 0xcf); + + /* Always reinitialize all queues - the real hardware pulls keyboard and mouse + clocks high, which stops keyboard scanning. */ + kbd_log("ATkbc: self-test reinitialization\n"); + dev->kbd_in_cmd = dev->mouse_in_cmd = 0; + dev->status &= ~STAT_OFULL; + dev->last_irq = 0; + dev->kbc_phase = 0; + + /* Phoenix MultiKey should have 0x60 | STAT_SYSFLAG. */ + if (dev->flags & KBC_FLAG_PS2) + write_cmd(dev, 0x30 | STAT_SYSFLAG); + else + write_cmd(dev, 0x10 | STAT_SYSFLAG); + kbc_transmit(dev, 0x55); + break; + + case 0xab: /* interface test */ + kbd_log("ATkbc: interface test\n"); + /* No error. */ + kbc_transmit(dev, 0x00); + break; + + case 0xac: /* diagnostic dump */ + kbd_log("ATkbc: diagnostic dump\n"); + kbc_transmit(dev, dev->mem[0x20]); + dev->kbc_phase = 1; + break; + + case 0xad: /* disable keyboard */ + kbd_log("ATkbc: disable keyboard\n"); + set_enable_kbd(dev, 0); + break; + + case 0xae: /* enable keyboard */ + kbd_log("ATkbc: enable keyboard\n"); + set_enable_kbd(dev, 1); + break; + + case 0xc7: /* or input port with system data */ + kbd_log("ATkbc: Phoenix - or input port with system data\n"); + dev->kbc_in = 1; + break; + + case 0xca: /* read keyboard mode */ + kbd_log("ATkbc: AMI - read keyboard mode\n"); + kbc_transmit(dev, dev->ami_mode); + break; + + case 0xcb: /* set keyboard mode */ + kbd_log("ATkbc: AMI - set keyboard mode\n"); + dev->kbc_in = 1; + break; + + case 0xd0: /* read output port */ + kbd_log("ATkbc: read output port\n"); + mask = 0xff; + if (dev->mem[0x20] & 0x10) + mask &= 0xbf; + if ((dev->flags & KBC_FLAG_PS2) && (dev->mem[0x20] & 0x20)) + mask &= 0xf7; + kbc_transmit(dev, dev->p2 & mask); + break; + + case 0xd1: /* write output port */ + kbd_log("ATkbc: write output port\n"); + dev->kbc_in = 1; + break; + + case 0xd2: /* write keyboard output buffer */ + kbd_log("ATkbc: write keyboard output buffer\n"); + if (dev->flags & KBC_FLAG_PS2) + dev->kbc_in = 1; + else + kbc_transmit(dev, 0x00); /* NCR */ + break; + + case 0xdd: /* disable A20 address line */ + case 0xdf: /* enable A20 address line */ + kbd_log("ATkbc: %sable A20\n", (val == 0xdd) ? "dis": "en"); + write_output(dev, (dev->p2 & 0xfd) | (val & 0x02)); + break; + + case 0xe0: /* read test inputs */ + kbd_log("ATkbc: read test inputs\n"); + kbc_transmit(dev, 0x00); + break; + + case 0xe1: case 0xea: + kbd_log("ATkbc: setting P23-P21 to %01X\n", val & 0x0e); + write_output(dev, (dev->p2 & 0xf1) | (val & 0x0e)); + break; + + default: + /* + * Unrecognized controller command. + * + * If we have a vendor-specific handler, run + * that. Otherwise, or if that handler fails, + * log a bad command. + */ + if (dev->write64_ven) + bad = dev->write64_ven(dev, val); + + kbd_log(bad ? "ATkbc: bad controller command %02X\n" : "", val); + } + + /* If the command needs data, remember the command. */ + if (dev->kbc_in || (dev->kbc_phase > 0)) + dev->kbc_cmd = val; + } +} + + +static void +kbc_dev_data_to_ob(atkbd_t *dev, uint8_t channel) +{ + dev->kbc_written[channel] = 0; + kbd_log("ATkbd: Forwarding %02X from channel %i...\n", dev->kbc_data[channel], channel); + kbc_send_to_ob(dev, dev->kbc_data[channel], channel, 0x00); +} + + +static void +kbc_main_loop_scan(atkbd_t *dev) +{ + uint8_t port_dis = dev->mem[0x20] & 0x30; + uint8_t ps2 = (dev->flags & KBC_FLAG_PS2); + + if (!ps2) + port_dis |= 0x20; + + if (!(dev->status & STAT_OFULL)) { + if (port_dis & 0x20) { + if (!(port_dis & 0x10)) { + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Main loop\n" + "ATkbc: Scan: AUX DIS, KBD EN\n"); + // kbd_log("ATkbc: Scan: AUX DIS, KBD EN\n"); + /* Enable communication with keyboard. */ + dev->p2 &= 0xbf; + dev->kbd_inhibit = 0; + kbc_wait(dev, 1); + } +#ifdef ENABLE_KEYBOARD_AT_LOG + else { + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Main loop\n" + "ATkbc: Scan: AUX DIS, KBD DIS\n"); + // kbd_log("ATkbc: Scan: AUX DIS, KBD DIS\n"); + } +#endif + } else { + /* Enable communication with mouse. */ + dev->p2 &= 0xf7; + dev->mouse_inhibit = 0; + if (dev->mem[0x20] & 0x10) { + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Main loop\n" + "ATkbc: Scan: AUX EN , KBD DIS\n"); + // kbd_log("ATkbc: Scan: AUX EN , KBD DIS\n"); + kbc_wait(dev, 2); + } else { + /* Enable communication with keyboard. */ + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Main loop\n" + "ATkbc: Scan: AUX EN , KBD EN\n"); + // kbd_log("ATkbc: Scan: AUX EN , KBD EN\n"); + dev->p2 &= 0xbf; + dev->kbd_inhibit = 0; + kbc_wait(dev, 3); + } + } + } +#ifdef ENABLE_KEYBOARD_AT_LOG + else { + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Main loop\n" + "ATkbc: Scan: IBF not full and OBF full, do nothing\n"); + // kbd_log("ATkbc: Scan: IBF not full and OBF full, do nothing\n"); + } +#endif +} + + +static void +kbc_process_ib(atkbd_t *dev) +{ + dev->status &= ~STAT_IFULL; + + if (dev->status & STAT_CD) { + dev->kbc_in_cmd = 1; + kbc_command(dev); + + if ((dev->kbc_phase == 0) && !dev->kbc_in) + dev->kbc_in_cmd = 0; + else + return; + } else { + dev->mem[0x20] &= ~0x10; + dev->kbd_data = dev->ib; + dev->kbd_written = 1; + dev->kbc_wait_for_response = 1; + } + + dev->kbc_poll_phase = KBC_MAIN_LOOP; + if (!dev->kbc_wait_for_response) + kbc_main_loop_scan(dev); +} + + +static void +kbc_wait(atkbd_t *dev, uint8_t flags) +{ + if ((flags & 1) && dev->kbc_written[1]) { + /* Disable communication with mouse. */ + dev->p2 |= 0x08; + dev->mouse_inhibit = 1; + /* Send keyboard byte to host. */ + kbc_dev_data_to_ob(dev, CHANNEL_KBD); + dev->kbc_poll_phase = KBC_MAIN_LOOP; + } else if ((flags & 2) && dev->kbc_written[2]) { + /* Disable communication with keyboard. */ + dev->p2 |= 0x40; + dev->kbd_inhibit = 1; + /* Send mouse byte to host. */ + kbc_dev_data_to_ob(dev, CHANNEL_MOUSE); + dev->kbc_poll_phase = KBC_MAIN_LOOP; + } else if (dev->status & STAT_IFULL) { + /* Disable communication with keyboard and mouse. */ + dev->p2 |= 0x48; + dev->kbd_inhibit = dev->mouse_inhibit = 1; + kbc_process_ib(dev); + } else + dev->kbc_poll_phase = KBC_WAIT | flags; +} + + +/* Controller processing */ +static void +kbc_process(atkbd_t *dev) +{ + // kbd_log("ATkbc: kbc_process()\n"); + + /* If we're waiting for the response from the keyboard or mouse, do nothing + until the device has repsonded back. */ + if (dev->kbc_wait_for_response > 0) { + if (dev->kbc_written[dev->kbc_wait_for_response]) + dev->kbc_wait_for_response = 0; + else + return; + } + + if (dev->kbc_send_pending) { + kbd_log("ATkbc: Sending delayed %02X on channel %i with high status %02X\n", + dev->kbc_to_send, dev->kbc_channel, dev->kbc_stat_hi); + kbc_send_to_ob(dev, dev->kbc_to_send, dev->kbc_channel, dev->kbc_stat_hi); + dev->kbc_send_pending = 0; + } + + if (dev->kbc_poll_phase == KBC_RESET) { + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Reset loop()\n"); + + if (dev->status & STAT_IFULL) { + dev->status &= ~STAT_IFULL; + + if ((dev->status & STAT_CD) && (dev->ib == 0xaa)) { + dev->kbc_in_cmd = 1; + kbc_command(dev); + + if ((dev->kbc_phase == 0) && !dev->kbc_in) + dev->kbc_in_cmd = 0; + + dev->kbc_poll_phase = KBC_MAIN_LOOP; + } + } + + return; + } + + if (dev->kbc_in_cmd || (dev->kbc_phase > 0) || dev->kbc_in) { + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: In a command\n"); + if (!dev->kbc_in && (dev->status & STAT_OFULL)) { + kbd_log("ATkbc: !dev->kbc_in && (dev->status & STAT_OFULL)\n"); + return; /* We do not want input and we're waiting for the host to read the data + we transmitted, but it has not done that yet, do nothing. */ + } else if (dev->kbc_in && !(dev->status & STAT_IFULL)) { + kbd_log("ATkbc: dev->kbc_in && !(dev->status & STAT_IFULL)\n"); + return; /* We want input and the host has not provided us with any yet, do nothing. */ + } +#ifdef ENABLE_KEYBOARD_AT_LOG + else + kbd_log("ATkbc: Normal condition\n"); +#endif + + if (dev->status & STAT_IFULL) { + dev->status &= ~STAT_IFULL; + + if (dev->status & STAT_CD) { + kbd_log("ATkbc: Resetting command\n"); + dev->kbc_phase = 0; + dev->kbc_in = 0; + } + } + + /* Process command. */ + kbc_command(dev); + + if ((dev->kbc_phase == 0) && !dev->kbc_in) + dev->kbc_in_cmd = 0; + else + return; + + if (!(dev->status & STAT_OFULL)) + kbc_main_loop_scan(dev); + /* Make absolutely sure to do nothing if OBF is full and IBF is empty. */ + } else if (!(dev->status & STAT_OFULL) || (dev->status & STAT_IFULL)) switch (dev->kbc_poll_phase) { + case KBC_MAIN_LOOP: + // kbd_log("ATkbc: Main loop\n"); + if (dev->status & STAT_IFULL) { + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Main loop\n" + "ATkbc: IBF full, process\n"); + kbc_process_ib(dev); + } else + kbc_main_loop_scan(dev); + break; + case KBC_WAIT_FOR_KBD: + case KBC_WAIT_FOR_MOUSE: + case KBC_WAIT_FOR_BOTH: + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Scan: Phase %i\n", dev->kbc_poll_phase); + kbc_wait(dev, dev->kbc_poll_phase & 3); + break; + default: + kbd_log("ATkbc: kbc_process()\n" + "ATkbc: Scan: Invalid phase %i\n", dev->kbc_poll_phase); + break; + } } @@ -742,105 +1795,29 @@ static void kbd_poll(void *priv) { atkbd_t *dev = (atkbd_t *)priv; -#ifdef ENABLE_KEYBOARD_AT_LOG - const uint8_t channels[4] = { 1, 2, 0, 0 }; -#endif timer_advance_u64(&dev->send_delay_timer, (100ULL * TIMER_USEC)); - if (dev->out_new != -1 && !dev->last_irq) { - dev->wantirq = 0; - if (dev->out_new & 0x100) { - if (dev->mem[0] & 0x02) - picint(0x1000); - kbd_log("ATkbc: %02X coming from channel 2\n"); - dev->out = dev->out_new & 0xff; - dev->out_new = -1; - dev->status = (dev->status & ~STAT_IFULL) | (STAT_OFULL | STAT_MFULL); - dev->last_irq = 0x1000; - } else { - if (dev->mem[0] & 0x01) - picint(2); - kbd_log("ATkbc: %02X coming from channel %i\n", dev->out_new & 0xff, channels[(dev->out_new >> 8) & 0x03]); - dev->out = dev->out_new & 0xff; - dev->out_new = -1; - dev->status = (dev->status & ~(STAT_IFULL | STAT_MFULL)) | STAT_OFULL; - dev->last_irq = 2; - } - } + /* We process all three devices at the same time, in an arbitrary order. */ - if (dev->out_new == -1 && !(dev->status & STAT_OFULL) && key_ctrl_queue_start != key_ctrl_queue_end) { - kbd_log("ATkbc: %02X on channel 0\n", key_ctrl_queue[key_ctrl_queue_start]); - dev->out_new = key_ctrl_queue[key_ctrl_queue_start] | 0x200; - key_ctrl_queue_start = (key_ctrl_queue_start + 1) & 0xf; - } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && dev->out_delayed != -1) { - kbd_log("ATkbc: %02X delayed on channel %i\n", dev->out_delayed & 0xff, channels[(dev->out_delayed >> 8) & 0x03]); - dev->out_new = dev->out_delayed; - dev->out_delayed = -1; - } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && mouse_queue_start != mouse_queue_end) { - kbd_log("ATkbc: %02X on channel 2\n", mouse_queue[mouse_queue_start]); - dev->out_new = mouse_queue[mouse_queue_start] | 0x100; - mouse_queue_start = (mouse_queue_start + 1) & 0xf; - } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && !(dev->mem[0] & 0x10) && key_queue_start != key_queue_end) { - kbd_log("ATkbc: %02X on channel 1\n", key_queue[key_queue_start]); - dev->out_new = key_queue[key_queue_start]; - key_queue_start = (key_queue_start + 1) & 0xf; - } + /* Keyboard processing */ + kbd_process(dev); - if (dev->reset_delay) { - dev->reset_delay--; - if (!dev->reset_delay) { - kbd_log("ATkbc: Sending AA on keyboard reset...\n"); - add_data_kbd_direct(dev, 0xaa); - } - } -} + /* TODO: Mouse processing */ + // mouse_process(dev); - -static void -add_data(atkbd_t *dev, uint8_t val) -{ - kbd_log("ATkbc: add to queue\n"); - - kbd_log("ATkbc: key_ctrl_queue[%02X] = %02X;\n", key_ctrl_queue_end, val); - kbc_queue_add(dev, val, 0, 0x00); - - if (!(dev->out_new & 0x300)) { - dev->out_delayed = dev->out_new; - dev->out_new = -1; - } + /* Controller processing */ + kbc_process(dev); } static void add_data_vals(atkbd_t *dev, uint8_t *val, uint8_t len) { - int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); - int translate = (keyboard_mode & 0x40); int i; - uint8_t or = 0; - uint8_t send; - if (dev->reset_delay) - return; - - translate = translate || (keyboard_mode & 0x40) || xt_mode; - translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); - - for (i = 0; i < len; i++) { - if (translate) { - if (val[i] == 0xf0) { - or = 0x80; - continue; - } - send = nont_to_t[val[i]] | or; - if (or == 0x80) - or = 0; - } else - send = val[i]; - - add_data_kbd_queue(dev, 0, send); - } + for (i = 0; i < len; i++) + add_data_kbd_queue(dev, 0, val[i]); } @@ -848,56 +1825,21 @@ static void add_data_kbd(uint16_t val) { atkbd_t *dev = SavedKbd; - int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); - int translate = (keyboard_mode & 0x40); uint8_t fake_shift[4]; uint8_t num_lock = 0, shift_states = 0; uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - if (dev->reset_delay) + if (dev->kbd_in || (dev->kbd_phase > 0)) return; - translate = translate || (keyboard_mode & 0x40) || xt_mode; - translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); - keyboard_get_states(NULL, &num_lock, NULL); shift_states = keyboard_get_shift() & STATE_SHIFT_MASK; - /* Allow for scan code translation. */ - if (translate && (val == 0xf0)) { - kbd_log("ATkbd: translate is on, F0 prefix detected\n"); - sc_or = 0x80; - return; - } - - /* Skip break code if translated make code has bit 7 set. */ - if (translate && (sc_or == 0x80) && (val & 0x80)) { - kbd_log("ATkbd: translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val); - sc_or = 0; - return; - } - /* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */ - if ((dev != NULL) && (kbc_ven == KBC_VEN_TOSHIBA) && - (keyboard_recv(0xb8) || keyboard_recv(0x9d))) switch (val) { - case 0x4f: t3100e_notify_set(0x01); break; /* End */ - case 0x50: t3100e_notify_set(0x02); break; /* Down */ - case 0x51: t3100e_notify_set(0x03); break; /* PgDn */ - case 0x52: t3100e_notify_set(0x04); break; /* Ins */ - case 0x53: t3100e_notify_set(0x05); break; /* Del */ - case 0x54: t3100e_notify_set(0x06); break; /* SysRQ */ - case 0x45: t3100e_notify_set(0x07); break; /* NumLock */ - case 0x46: t3100e_notify_set(0x08); break; /* ScrLock */ - case 0x47: t3100e_notify_set(0x09); break; /* Home */ - case 0x48: t3100e_notify_set(0x0a); break; /* Up */ - case 0x49: t3100e_notify_set(0x0b); break; /* PgUp */ - case 0x4A: t3100e_notify_set(0x0c); break; /* Keypad -*/ - case 0x4B: t3100e_notify_set(0x0d); break; /* Left */ - case 0x4C: t3100e_notify_set(0x0e); break; /* KP 5 */ - case 0x4D: t3100e_notify_set(0x0f); break; /* Right */ - } + if ((dev != NULL) && (kbc_ven == KBC_VEN_TOSHIBA) && (keyboard_recv(0xb8) || keyboard_recv(0x9d)) && + (val >= 0x4f) && (val <= 0x54) && (val != 0x4e)) + t3100e_notify_set((val + 2) & 0x0f); - kbd_log("ATkbd: translate is %s, ", translate ? "on" : "off"); switch(val) { case FAKE_LSHIFT_ON: kbd_log("fake left shift on, scan code: "); @@ -1030,18 +1972,7 @@ add_data_kbd(uint16_t val) break; default: -#ifdef ENABLE_KEYBOARD_AT_LOG - kbd_log("scan code: "); - if (translate) { - kbd_log("%02X (original: ", (nont_to_t[val] | sc_or)); - if (sc_or == 0x80) - kbd_log("F0 "); - kbd_log("%02X)\n", val); - } else - kbd_log("%02X\n", val); -#endif - - add_data_kbd_queue(dev, 0, translate ? (nont_to_t[val] | sc_or) : val); + add_data_kbd_queue(dev, 0, val); break; } @@ -1050,124 +1981,13 @@ add_data_kbd(uint16_t val) } -static void -write_output(atkbd_t *dev, uint8_t val) -{ - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - kbd_log("ATkbc: write output port: %02X (old: %02X)\n", val, dev->output_port); - - if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF)) - val |= ((dev->mem[0] << 4) & 0x10); - - if ((dev->output_port ^ val) & 0x20) { /*IRQ 12*/ - if (val & 0x20) - picint(1 << 12); - else - picintc(1 << 12); - } - if ((dev->output_port ^ val) & 0x10) { /*IRQ 1*/ - if (val & 0x10) - picint(1 << 1); - else - picintc(1 << 1); - } - if ((dev->output_port ^ val) & 0x02) { /*A20 enable change*/ - mem_a20_key = val & 0x02; - mem_a20_recalc(); - flushmmucache(); - } - if ((dev->output_port ^ val) & 0x01) { /*Reset*/ - if (! (val & 0x01)) { - /* Pin 0 selected. */ - softresetx86(); /*Pulse reset!*/ - cpu_set_edx(); - smbase = is_am486dxl ? 0x00060000 : 0x00030000; - } - } - /* Mask off the A20 stuff because we use mem_a20_key directly for that. */ - dev->output_port = val; -} - - -static void -write_cmd(atkbd_t *dev, uint8_t val) -{ - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - kbd_log("ATkbc: write command byte: %02X (old: %02X)\n", val, dev->mem[0]); - - if ((val & 1) && (dev->status & STAT_OFULL)) - dev->wantirq = 1; - if (!(val & 1) && dev->wantirq) - dev->wantirq = 0; - - /* PS/2 type 2 keyboard controllers always force the XLAT bit to 0. */ - if ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2) { - val &= ~CCB_TRANSLATE; - dev->mem[0] &= ~CCB_TRANSLATE; - } - - /* Scan code translate ON/OFF. */ - keyboard_mode &= 0x93; - keyboard_mode |= (val & MODE_MASK); - - kbd_log("ATkbc: keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled"); - - /* ISA AT keyboard controllers use bit 5 for keyboard mode (1 = PC/XT, 2 = AT); - PS/2 (and EISA/PCI) keyboard controllers use it as the PS/2 mouse enable switch. - The AMIKEY firmware apparently uses this bit for something else. */ - if ((kbc_ven == KBC_VEN_AMI) || - ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) { - keyboard_mode &= ~CCB_PCMODE; - - kbd_log("ATkbc: mouse interrupt is now %s\n", (val & 0x02) ? "enabled" : "disabled"); - } - - if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF)) { - /* Update the output port to mirror the KBD DIS and AUX DIS bits, if active. */ - write_output(dev, dev->output_port); - } - - kbd_log("Command byte now: %02X (%02X)\n", dev->mem[0], val); - - dev->status = (dev->status & ~STAT_SYSFLAG) | (val & STAT_SYSFLAG); -} - - -static void -pulse_output(atkbd_t *dev, uint8_t mask) -{ - if (mask != 0x0f) { - dev->old_output_port = dev->output_port & ~(0xf0 | mask); - kbd_log("pulse_output(): Output port now: %02X\n", dev->output_port & (0xf0 | mask)); - write_output(dev, dev->output_port & (0xf0 | mask)); - timer_set_delay_u64(&dev->pulse_cb, 6ULL * TIMER_USEC); - } -} - - static void pulse_poll(void *priv) { atkbd_t *dev = (atkbd_t *)priv; - kbd_log("pulse_poll(): Output port now: %02X\n", dev->output_port | dev->old_output_port); - write_output(dev, dev->output_port | dev->old_output_port); -} - - -static void -set_enable_kbd(atkbd_t *dev, uint8_t enable) -{ - dev->mem[0] &= 0xef; - dev->mem[0] |= (enable ? 0x00 : 0x10); -} - - -static void -set_enable_mouse(atkbd_t *dev, uint8_t enable) -{ - dev->mem[0] &= 0xdf; - dev->mem[0] |= (enable ? 0x00 : 0x20); + kbd_log("pulse_poll(): Output port now: %02X\n", dev->p2 | dev->old_p2); + write_output(dev, dev->p2 | dev->old_p2); } @@ -1176,49 +1996,70 @@ write64_generic(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; uint8_t current_drive, fixed_bits; - uint8_t kbc_ven = 0x0; - kbc_ven = dev->flags & KBC_VEN_MASK; - + uint8_t kbc_ven = 0x0; + kbc_ven = dev->flags & KBC_VEN_MASK; switch (val) { case 0xa4: /* check if password installed */ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + if (dev->flags & KBC_FLAG_PS2) { kbd_log("ATkbc: check if password installed\n"); - add_data(dev, 0xf1); + kbc_transmit(dev, (dev->mem[0x50] == 0x00) ? 0xf1 : 0xfa); + return 0; + } + break; + + case 0xa5: /* load security */ + if (dev->flags & KBC_FLAG_PS2) { + kbd_log("ATkbc: load security\n"); + dev->kbc_in = 1; return 0; } break; case 0xa7: /* disable mouse port */ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + if (dev->flags & KBC_FLAG_PS2) { kbd_log("ATkbc: disable mouse port\n"); - set_enable_mouse(dev, 0); + // kbc_transmit(dev, 0); return 0; } break; case 0xa8: /*Enable mouse port*/ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + if (dev->flags & KBC_FLAG_PS2) { kbd_log("ATkbc: enable mouse port\n"); - set_enable_mouse(dev, 1); + // kbc_transmit(dev, 1); return 0; } break; case 0xa9: /*Test mouse port*/ kbd_log("ATkbc: test mouse port\n"); - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - add_data(dev, 0x00); /* no error, this is testing the channel 2 interface */ + if (dev->flags & KBC_FLAG_PS2) { + /* No error, this is testing the channel 2 interface. */ + kbc_transmit(dev, 0x00); return 0; } break; case 0xaf: /* read keyboard version */ kbd_log("ATkbc: read keyboard version\n"); - add_data(dev, 0x00); + kbc_transmit(dev, 0x00); return 0; case 0xc0: /* read input port */ + /* IBM PS/1: + Bit 2 and 4 ignored (we return always 0), + Bit 6 must 1 for 5.25" floppy drive, 0 for 3.5". + Intel AMI: + Bit 2 ignored (we return always 1), + Bit 4 must be 1, + Bit 6 must be 1 or else error in SMM. + Acer: + Bit 2 must be 0 (and Acer V10 disables CMOS setup if it's 1), + Bit 4 must be 0, + Bit 6 ignored. + P6RP4: + Bit 2 must be 1 or CMOS setup is disabled. */ kbd_log("ATkbc: read input port\n"); fixed_bits = 4; /* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */ @@ -1226,11 +2067,8 @@ write64_generic(void *priv, uint8_t val) fixed_bits |= 0x40; if (kbc_ven == KBC_VEN_IBM_PS1) { current_drive = fdc_get_current_drive(); - add_to_kbc_queue_front(dev, dev->input_port | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00), - 0, 0x00); - dev->input_port = ((dev->input_port + 1) & 3) | - (dev->input_port & 0xfc) | - (fdd_is_525(current_drive) ? 0x40 : 0x00); + kbc_transmit(dev, dev->p1 | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00)); + dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc) | (fdd_is_525(current_drive) ? 0x40 : 0x00); } else if (kbc_ven == KBC_VEN_NCR) { /* switch settings * bit 7: keyboard disable @@ -1242,39 +2080,34 @@ write64_generic(void *priv, uint8_t val) * bit 1: high/auto speed * bit 0: dma mode */ - add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf, - 0, 0x00); - dev->input_port = ((dev->input_port + 1) & 3) | - (dev->input_port & 0xfc); + kbc_transmit(dev, (dev->p1 | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf); + dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc); } else { - if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) && - ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI)) - add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits) & - (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0xeb : 0xef), 0, 0x00); + pclog("[%04X:%08X] Reading %02X from input port\n", CS, cpu_state.pc, ((dev->p1 | fixed_bits) & 0xf0) | 0x0c); + if ((dev->flags & KBC_FLAG_PS2) && ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI)) + // kbc_transmit(dev, ((dev->p1 | fixed_bits) & 0xf0) | 0x0c); + kbc_transmit(dev, ((dev->p1 | fixed_bits) & 0xf0) | 0x08); + // kbc_transmit(dev, (dev->p1 | fixed_bits) & (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0xeb : 0xef)); else - add_to_kbc_queue_front(dev, dev->input_port | fixed_bits, 0, 0x00); - dev->input_port = ((dev->input_port + 1) & 3) | - (dev->input_port & 0xfc); + kbc_transmit(dev, dev->p1 | fixed_bits); + dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc); } return 0; case 0xd3: /* write mouse output buffer */ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + if (dev->flags & KBC_FLAG_PS2) { kbd_log("ATkbc: write mouse output buffer\n"); - dev->want60 = 1; + dev->kbc_in = 1; return 0; } break; case 0xd4: /* write to mouse */ kbd_log("ATkbc: write to mouse\n"); - dev->want60 = 1; + dev->kbc_in = 1; return 0; - case 0xf0: case 0xf1: case 0xf2: case 0xf3: - case 0xf4: case 0xf5: case 0xf6: case 0xf7: - case 0xf8: case 0xf9: case 0xfa: case 0xfb: - case 0xfc: case 0xfd: case 0xfe: case 0xff: + case 0xf0 ... 0xff: kbd_log("ATkbc: pulse %01X\n", val & 0x0f); pulse_output(dev, val & 0x0f); return 0; @@ -1289,35 +2122,168 @@ static uint8_t write60_ami(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; + uint16_t index = 0x00c0; - switch(dev->command) { - /* 0x40 - 0x5F are aliases for 0x60-0x7F */ - case 0x40: case 0x41: case 0x42: case 0x43: - case 0x44: case 0x45: case 0x46: case 0x47: - case 0x48: case 0x49: case 0x4a: case 0x4b: - 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: case 0x5f: - kbd_log("ATkbc: AMI - alias write to %08X\n", dev->command); - dev->mem[dev->command & 0x1f] = val; - if (dev->command == 0x60) + switch(dev->kbc_cmd) { + /* 0x40 - 0x5F are aliases for 0x60 - 0x7F */ + case 0x40 ... 0x5f: + kbd_log("ATkbc: AMI - alias write to %08X\n", dev->kbc_cmd); + if (dev->kbc_cmd == 0x40) write_cmd(dev, val); + else + dev->mem[(dev->kbc_cmd & 0x1f) + 0x20] = val; return 0; case 0xaf: /* set extended controller RAM */ - kbd_log("ATkbc: AMI - set extended controller RAM\n"); - if (dev->secr_phase == 1) { - dev->mem_addr = val; - dev->want60 = 1; - dev->secr_phase = 2; - } else if (dev->secr_phase == 2) { - dev->mem[dev->mem_addr] = val; + kbd_log("ATkbc: AMI - set extended controller RAM, input phase %i\n", dev->secr_phase); + if (dev->secr_phase == 0) { + dev->mem_index = val; + dev->kbc_in = 1; + dev->secr_phase++; + } else if (dev->secr_phase == 1) { + if (dev->mem_index == 0x20) + write_cmd(dev, val); + else + dev->mem[dev->mem_index] = val; dev->secr_phase = 0; } return 0; + case 0xb8: + kbd_log("ATkbc: AMI MegaKey - memory index %02X\n", val); + dev->mem_index = val; + return 0; + + case 0xbb: + kbd_log("ATkbc: AMI MegaKey - write %02X to memory index %02X\n", val, dev->mem_index); + if (dev->mem_index >= 0x80) { + switch (dev->mem[0x9b] & 0xc0) { + case 0x00: + index = 0x0080; + break; + case 0x40: case 0x80: + index = 0x0000; + break; + case 0xc0: + index = 0x0100; + break; + } + dev->mem[index + dev->mem_index] = val; + } else if (dev->mem_index == 0x60) + write_cmd(dev, val); + else if (dev->mem_index == 0x42) + dev->status = val; + else if (dev->mem_index >= 0x40) + dev->mem[dev->mem_index - 0x40] = val; + else + dev->mem_int[dev->mem_index] = val; + return 0; + + case 0xbd: + kbd_log("ATkbc: AMI MegaKey - write %02X to config index %02X\n", val, dev->mem_index); + switch (dev->mem_index) { + case 0x00: /* STAT8042 */ + dev->status = val; + break; + case 0x01: /* Password_ptr */ + dev->mem[0x1c] = val; + break; + case 0x02: /* Wakeup_Tsk_Reg */ + dev->mem[0x1e] = val; + break; + case 0x03: /* CCB */ + write_cmd(dev, val); + break; + case 0x04: /* Debounce_time */ + dev->mem[0x4d] = val; + break; + case 0x05: /* Pulse_Width */ + dev->mem[0x4e] = val; + break; + case 0x06: /* Pk_sel_byte */ + dev->mem[0x4c] = val; + break; + case 0x07: /* Func_Tsk_Reg */ + dev->mem[0x7e] = val; + break; + case 0x08: /* TypematicRate */ + dev->mem[0x80] = val; + break; + case 0x09: /* Led_Flag_Byte */ + dev->mem[0x81] = val; + break; + case 0x0a: /* Kbms_Command_St */ + dev->mem[0x87] = val; + break; + case 0x0b: /* Delay_Count_Byte */ + dev->mem[0x86] = val; + break; + case 0x0c: /* KBC_Flags */ + dev->mem[0x9b] = val; + break; + case 0x0d: /* SCODE_HK1 */ + dev->mem[0x50] = val; + break; + case 0x0e: /* SCODE_HK2 */ + dev->mem[0x51] = val; + break; + case 0x0f: /* SCODE_HK3 */ + dev->mem[0x52] = val; + break; + case 0x10: /* SCODE_HK4 */ + dev->mem[0x53] = val; + break; + case 0x11: /* SCODE_HK5 */ + dev->mem[0x54] = val; + break; + case 0x12: /* SCODE_HK6 */ + dev->mem[0x55] = val; + break; + case 0x13: /* TASK_HK1 */ + dev->mem[0x56] = val; + break; + case 0x14: /* TASK_HK2 */ + dev->mem[0x57] = val; + break; + case 0x15: /* TASK_HK3 */ + dev->mem[0x58] = val; + break; + case 0x16: /* TASK_HK4 */ + dev->mem[0x59] = val; + break; + case 0x17: /* TASK_HK5 */ + dev->mem[0x5a] = val; + break; + /* The next 4 bytes have uncertain correspondences. */ + case 0x18: /* Batt_Poll_delay_Time */ + dev->mem[0x5b] = val; + break; + case 0x19: /* Batt_Alarm_Reg1 */ + dev->mem[0x5c] = val; + break; + case 0x1a: /* Batt_Alarm_Reg2 */ + dev->mem[0x5d] = val; + break; + case 0x1b: /* Batt_Alarm_Tsk_Reg */ + dev->mem[0x5e] = val; + break; + case 0x1c: /* Kbc_State1 */ + dev->mem[0x9d] = val; + break; + case 0x1d: /* Aux_Config */ + dev->mem[0x75] = val; + break; + case 0x1e: /* Kbc_State3 */ + dev->mem[0x73] = val; + break; + } + return 0; + + case 0xc1: /* write input port */ + kbd_log("ATkbc: AMI MegaKey - write %02X to input port\n", val); + dev->p1 = val; + return 0; + case 0xcb: /* set keyboard mode */ kbd_log("ATkbc: AMI - set keyboard mode\n"); return 0; @@ -1331,62 +2297,50 @@ static uint8_t write64_ami(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; + uint16_t index = 0x00c0; switch (val) { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x05: case 0x06: case 0x07: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0d: case 0x0e: case 0x0f: - case 0x10: case 0x11: case 0x12: case 0x13: - case 0x14: case 0x15: case 0x16: case 0x17: - case 0x18: case 0x19: case 0x1a: case 0x1b: - case 0x1c: case 0x1d: case 0x1e: case 0x1f: + case 0x00 ... 0x1f: kbd_log("ATkbc: AMI - alias read from %08X\n", val); - add_data(dev, dev->mem[val]); + kbc_transmit(dev, dev->mem[val + 0x20]); return 0; - case 0x40: case 0x41: case 0x42: case 0x43: - case 0x44: case 0x45: case 0x46: case 0x47: - case 0x48: case 0x49: case 0x4a: case 0x4b: - 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: case 0x5f: - kbd_log("ATkbc: AMI - alias write to %08X\n", dev->command); - dev->want60 = 1; + case 0x40 ... 0x5f: + kbd_log("ATkbc: AMI - alias write to %08X\n", dev->kbc_cmd); + dev->kbc_in = 1; return 0; case 0xa0: /* copyright message */ - add_data(dev, 0x28); - add_data(dev, 0x00); - break; + kbc_transmit(dev, ami_copr[0]); + dev->kbc_phase = 1; + return 0; case 0xa1: /* get controller version */ kbd_log("ATkbc: AMI - get controller version\n"); - add_data(dev, 'H'); + // kbc_transmit(dev, 'H'); + kbc_transmit(dev, 'Z'); return 0; case 0xa2: /* clear keyboard controller lines P22/P23 */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - clear KBC lines P22 and P23\n"); - write_output(dev, dev->output_port & 0xf3); - add_data(dev, 0x00); + write_output(dev, dev->p2 & 0xf3); + kbc_transmit(dev, 0x00); return 0; } break; case 0xa3: /* set keyboard controller lines P22/P23 */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - set KBC lines P22 and P23\n"); - write_output(dev, dev->output_port | 0x0c); - add_data(dev, 0x00); + write_output(dev, dev->p2 | 0x0c); + kbc_transmit(dev, 0x00); return 0; } break; case 0xa4: /* write clock = low */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - write clock = low\n"); dev->ami_stat &= 0xfe; return 0; @@ -1394,7 +2348,7 @@ write64_ami(void *priv, uint8_t val) break; case 0xa5: /* write clock = high */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - write clock = high\n"); dev->ami_stat |= 0x01; return 0; @@ -1402,15 +2356,15 @@ write64_ami(void *priv, uint8_t val) break; case 0xa6: /* read clock */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - read clock\n"); - add_data(dev, !!(dev->ami_stat & 1)); + kbc_transmit(dev, !!(dev->ami_stat & 1)); return 0; } break; case 0xa7: /* write cache bad */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - write cache bad\n"); dev->ami_stat &= 0xfd; return 0; @@ -1418,7 +2372,7 @@ write64_ami(void *priv, uint8_t val) break; case 0xa8: /* write cache good */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - write cache good\n"); dev->ami_stat |= 0x02; return 0; @@ -1426,68 +2380,237 @@ write64_ami(void *priv, uint8_t val) break; case 0xa9: /* read cache */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (!(dev->flags & KBC_FLAG_PS2)) { kbd_log("ATkbc: AMI - read cache\n"); - add_data(dev, !!(dev->ami_stat & 2)); + kbc_transmit(dev, !!(dev->ami_stat & 2)); return 0; } break; case 0xaf: /* set extended controller RAM */ kbd_log("ATkbc: set extended controller RAM\n"); - dev->want60 = 1; - dev->secr_phase = 1; + dev->kbc_in = 1; return 0; - case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb0 ... 0xb3: /* set KBC lines P10-P13 (input port bits 0-3) low */ kbd_log("ATkbc: set KBC lines P10-P13 (input port bits 0-3) low\n"); - if (!PCI || (val > 0xb1)) - dev->input_port &= ~(1 << (val & 0x03)); - add_data(dev, 0x00); + if (!(dev->flags & KBC_FLAG_PS2) || (val > 0xb1)) { + dev->p1 &= ~(1 << (val & 0x03)); + } + kbc_transmit(dev, 0x00); return 0; case 0xb4: case 0xb5: /* set KBC lines P22-P23 (output port bits 2-3) low */ kbd_log("ATkbc: set KBC lines P22-P23 (output port bits 2-3) low\n"); - if (! PCI) - write_output(dev, dev->output_port & ~(4 << (val & 0x01))); - add_data(dev, 0x00); + if (!(dev->flags & KBC_FLAG_PS2)) + write_output(dev, dev->p2 & ~(4 << (val & 0x01))); + kbc_transmit(dev, 0x00); return 0; - case 0xb8: case 0xb9: case 0xba: case 0xbb: +#if 0 + case 0xb8 ... 0xbb: +#else + case 0xb9: +#endif /* set KBC lines P10-P13 (input port bits 0-3) high */ kbd_log("ATkbc: set KBC lines P10-P13 (input port bits 0-3) high\n"); - if (!PCI || (val > 0xb9)) { - dev->input_port |= (1 << (val & 0x03)); - add_data(dev, 0x00); + if (!(dev->flags & KBC_FLAG_PS2) || (val > 0xb9)) { + dev->p1 |= (1 << (val & 0x03)); + kbc_transmit(dev, 0x00); } return 0; + case 0xb8: + kbd_log("ATkbc: AMI MegaKey - memory index\n"); + dev->kbc_in = 1; + return 0; + + case 0xba: + kbd_log("ATkbc: AMI MegaKey - read %02X memory from index %02X\n", dev->mem[dev->mem_index], dev->mem_index); + if (dev->mem_index >= 0x80) { + switch (dev->mem[0x9b] & 0xc0) { + case 0x00: + index = 0x0080; + break; + case 0x40: case 0x80: + index = 0x0000; + break; + case 0xc0: + index = 0x0100; + break; + } + kbc_transmit(dev, dev->mem[index + dev->mem_index]); + } else if (dev->mem_index == 0x42) + kbc_transmit(dev, dev->status); + else if (dev->mem_index >= 0x40) + kbc_transmit(dev, dev->mem[dev->mem_index - 0x40]); + else + kbc_transmit(dev, dev->mem_int[dev->mem_index]); + return 0; + + case 0xbb: + kbd_log("ATkbc: AMI MegaKey - write to memory index %02X\n", dev->mem_index); + dev->kbc_in = 1; + return 0; + +#if 0 case 0xbc: case 0xbd: /* set KBC lines P22-P23 (output port bits 2-3) high */ kbd_log("ATkbc: set KBC lines P22-P23 (output port bits 2-3) high\n"); - if (! PCI) - write_output(dev, dev->output_port | (4 << (val & 0x01))); - add_data(dev, 0x00); + if (!(dev->flags & KBC_FLAG_PS2)) + write_output(dev, dev->p2 | (4 << (val & 0x01))); + kbc_transmit(dev, 0x00); + return 0; +#endif + + case 0xbc: + switch (dev->mem_index) { + case 0x00: /* STAT8042 */ + kbc_transmit(dev, dev->status); + break; + case 0x01: /* Password_ptr */ + kbc_transmit(dev, dev->mem[0x1c]); + break; + case 0x02: /* Wakeup_Tsk_Reg */ + kbc_transmit(dev, dev->mem[0x1e]); + break; + case 0x03: /* CCB */ + kbc_transmit(dev, dev->mem[0x20]); + break; + case 0x04: /* Debounce_time */ + kbc_transmit(dev, dev->mem[0x4d]); + break; + case 0x05: /* Pulse_Width */ + kbc_transmit(dev, dev->mem[0x4e]); + break; + case 0x06: /* Pk_sel_byte */ + kbc_transmit(dev, dev->mem[0x4c]); + break; + case 0x07: /* Func_Tsk_Reg */ + kbc_transmit(dev, dev->mem[0x7e]); + break; + case 0x08: /* TypematicRate */ + kbc_transmit(dev, dev->mem[0x80]); + break; + case 0x09: /* Led_Flag_Byte */ + kbc_transmit(dev, dev->mem[0x81]); + break; + case 0x0a: /* Kbms_Command_St */ + kbc_transmit(dev, dev->mem[0x87]); + break; + case 0x0b: /* Delay_Count_Byte */ + kbc_transmit(dev, dev->mem[0x86]); + break; + case 0x0c: /* KBC_Flags */ + kbc_transmit(dev, dev->mem[0x9b]); + break; + case 0x0d: /* SCODE_HK1 */ + kbc_transmit(dev, dev->mem[0x50]); + break; + case 0x0e: /* SCODE_HK2 */ + kbc_transmit(dev, dev->mem[0x51]); + break; + case 0x0f: /* SCODE_HK3 */ + kbc_transmit(dev, dev->mem[0x52]); + break; + case 0x10: /* SCODE_HK4 */ + kbc_transmit(dev, dev->mem[0x53]); + break; + case 0x11: /* SCODE_HK5 */ + kbc_transmit(dev, dev->mem[0x54]); + break; + case 0x12: /* SCODE_HK6 */ + kbc_transmit(dev, dev->mem[0x55]); + break; + case 0x13: /* TASK_HK1 */ + kbc_transmit(dev, dev->mem[0x56]); + break; + case 0x14: /* TASK_HK2 */ + kbc_transmit(dev, dev->mem[0x57]); + break; + case 0x15: /* TASK_HK3 */ + kbc_transmit(dev, dev->mem[0x58]); + break; + case 0x16: /* TASK_HK4 */ + kbc_transmit(dev, dev->mem[0x59]); + break; + case 0x17: /* TASK_HK5 */ + kbc_transmit(dev, dev->mem[0x5a]); + break; + /* The next 4 bytes have uncertain correspondences. */ + case 0x18: /* Batt_Poll_delay_Time */ + kbc_transmit(dev, dev->mem[0x5b]); + break; + case 0x19: /* Batt_Alarm_Reg1 */ + kbc_transmit(dev, dev->mem[0x5c]); + break; + case 0x1a: /* Batt_Alarm_Reg2 */ + kbc_transmit(dev, dev->mem[0x5d]); + break; + case 0x1b: /* Batt_Alarm_Tsk_Reg */ + kbc_transmit(dev, dev->mem[0x5e]); + break; + case 0x1c: /* Kbc_State1 */ + kbc_transmit(dev, dev->mem[0x9d]); + break; + case 0x1d: /* Aux_Config */ + kbc_transmit(dev, dev->mem[0x75]); + break; + case 0x1e: /* Kbc_State3 */ + kbc_transmit(dev, dev->mem[0x73]); + break; + default: + kbc_transmit(dev, 0x00); + break; + } + kbd_log("ATkbc: AMI MegaKey - read from config index %02X\n", dev->mem_index); return 0; - case 0xc8: + case 0xbd: + kbd_log("ATkbc: AMI MegaKey - write to config index %02X\n", dev->mem_index); + dev->kbc_in = 1; + return 0; + + case 0xc1: /* write input port */ + kbd_log("ATkbc: AMI MegaKey - write input port\n"); + dev->kbc_in = 1; + return 0; + + case 0xc4: + /* set KBC line P14 low */ + kbd_log("ATkbc: set KBC line P14 (input port bit 4) low\n"); + dev->p1 &= 0xef; + kbc_transmit(dev, 0x00); + return 0; + case 0xc5: + /* set KBC line P15 low */ + kbd_log("ATkbc: set KBC line P15 (input port bit 5) low\n"); + dev->p1 &= 0xdf; + kbc_transmit(dev, 0x00); + return 0; + + case 0xc8: case 0xc9: /* - * unblock KBC lines P22/P23 + * (un)block KBC lines P22/P23 * (allow command D1 to change bits 2/3 of the output port) */ - kbd_log("ATkbc: AMI - unblock KBC lines P22 and P23\n"); - dev->output_locked = 1; + kbd_log("ATkbc: AMI - %sblock KBC lines P22 and P23\n", (val & 1) ? "" : "un"); + dev->p2_locked = (val & 1); return 0; - case 0xc9: - /* - * block KBC lines P22/P23 - * (disallow command D1 from changing bits 2/3 of the port) - */ - kbd_log("ATkbc: AMI - block KBC lines P22 and P23\n"); - dev->output_locked = 1; + case 0xcc: + /* set KBC line P14 high */ + kbd_log("ATkbc: set KBC line P14 (input port bit 4) high\n"); + dev->p1 |= 0x10; + kbc_transmit(dev, 0x00); + return 0; + case 0xcd: + /* set KBC line P15 high */ + kbd_log("ATkbc: set KBC line P15 (input port bit 5) high\n"); + dev->p1 |= 0x20; + kbc_transmit(dev, 0x00); return 0; case 0xef: /* ??? - sent by AMI486 */ @@ -1508,23 +2631,20 @@ write64_ibm_mca(void *priv, uint8_t val) case 0xc1: /*Copy bits 0 to 3 of input port to status bits 4 to 7*/ kbd_log("ATkbc: copy bits 0 to 3 of input port to status bits 4 to 7\n"); dev->status &= 0x0f; - dev->status |= ((((dev->input_port & 0xfc) | 0x84) & 0x0f) << 4); + dev->status |= ((((dev->p1 & 0xfc) | 0x84) & 0x0f) << 4); return 0; case 0xc2: /*Copy bits 4 to 7 of input port to status bits 4 to 7*/ kbd_log("ATkbc: copy bits 4 to 7 of input port to status bits 4 to 7\n"); dev->status &= 0x0f; - dev->status |= (((dev->input_port & 0xfc) | 0x84) & 0xf0); + dev->status |= (((dev->p1 & 0xfc) | 0x84) & 0xf0); return 0; case 0xaf: kbd_log("ATkbc: bad KBC command AF\n"); return 1; - case 0xf0: case 0xf1: case 0xf2: case 0xf3: - case 0xf4: case 0xf5: case 0xf6: case 0xf7: - case 0xf8: case 0xf9: case 0xfa: case 0xfb: - case 0xfc: case 0xfd: case 0xfe: case 0xff: + case 0xf0 ... 0xff: kbd_log("ATkbc: pulse: %01X\n", (val & 0x03) | 0x0c); pulse_output(dev, (val & 0x03) | 0x0c); return 0; @@ -1539,7 +2659,7 @@ write60_quadtel(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; - switch(dev->command) { + switch(dev->kbc_cmd) { case 0xcf: /*??? - sent by MegaPC BIOS*/ kbd_log("ATkbc: ??? - sent by MegaPC BIOS\n"); return 0; @@ -1548,12 +2668,34 @@ write60_quadtel(void *priv, uint8_t val) return 1; } + static uint8_t write64_olivetti(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; switch (val) { + /* This appears to be a clone of "Read input port", in which case, the bis would be: + 7: M290 (AT KBC): + Keyboard lock (1 = unlocked, 0 = locked); + M300 (PS/2 KBC): + Bus expansion board present (1 = present, 0 = not present); + 6: Usually: + Display (1 = MDA, 0 = CGA, but can have its polarity inverted); + 5: Manufacturing jumper (1 = not installed, 0 = installed (infinite loop)); + 4: RAM on motherboard (1 = 256 kB, 0 = 512 kB - which machine actually uses this?); + 3: Fast Ram check (if inactive keyboard works erratically); + 2: Keyboard fuse present + This appears to be in-line with PS/2: 1 = no power, 0 = keyboard power normal; + 1: M290 (AT KBC): + Unused; + M300 (PS/2 KBC): + Mouse data in; + 0: M290 (AT KBC): + Unused; + M300 (PS/2 KBC): + Key data in. + */ case 0x80: /* Olivetti-specific command */ /* * bit 7: bus expansion board present (M300) / keyboard unlocked (M290) @@ -1562,11 +2704,9 @@ write64_olivetti(void *priv, uint8_t val) * bit 2: keyboard fuse present * bits 0-1: ??? */ - add_to_kbc_queue_front(dev, (0x0c | ((is386) ? 0x00 : 0x80)) & 0xdf, 0, 0x00); - dev->input_port = ((dev->input_port + 1) & 3) | - (dev->input_port & 0xfc); + kbc_transmit(dev, 0x0c | (is386 ? 0x00 : 0x80)); return 0; - } + } return write64_generic(dev, val); } @@ -1584,7 +2724,7 @@ write64_quadtel(void *priv, uint8_t val) case 0xcf: /*??? - sent by MegaPC BIOS*/ kbd_log("ATkbc: ??? - sent by MegaPC BIOS\n"); - dev->want60 = 1; + dev->kbc_in = 1; return 0; } @@ -1597,7 +2737,7 @@ write60_toshiba(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; - switch(dev->command) { + switch(dev->kbc_cmd) { case 0xb6: /* T3100e - set color/mono switch */ kbd_log("ATkbc: T3100e - set color/mono switch\n"); t3100e_mono_set(val); @@ -1640,29 +2780,30 @@ write64_toshiba(void *priv, uint8_t val) case 0xb4: /* T3100e: Get configuration / status */ kbd_log("ATkbc: T3100e: Get configuration / status\n"); - add_data(dev, t3100e_config_get()); + kbc_transmit(dev, t3100e_config_get()); return 0; case 0xb5: /* T3100e: Get colour / mono byte */ kbd_log("ATkbc: T3100e: Get colour / mono byte\n"); - add_data(dev, t3100e_mono_get()); + kbc_transmit(dev, t3100e_mono_get()); return 0; case 0xb6: /* T3100e: Set colour / mono byte */ kbd_log("ATkbc: T3100e: Set colour / mono byte\n"); - dev->want60 = 1; + dev->kbc_in = 1; return 0; case 0xb7: /* T3100e: Emulate PS/2 keyboard */ case 0xb8: /* T3100e: Emulate AT keyboard */ - dev->flags &= ~KBC_TYPE_MASK; + dev->flags &= ~KBC_FLAG_PS2; if (val == 0xb7) { kbd_log("ATkbc: T3100e: Emulate PS/2 keyboard\n"); - dev->flags |= KBC_TYPE_PS2_NOREF; - } else { - kbd_log("ATkbc: T3100e: Emulate AT keyboard\n"); - dev->flags |= KBC_TYPE_ISA; + dev->flags |= KBC_FLAG_PS2; } +#ifdef ENABLE_KEYBOARD_AT_LOG + else + kbd_log("ATkbc: T3100e: Emulate AT keyboard\n"); +#endif return 0; case 0xbb: /* T3100e: Read 'Fn' key. @@ -1672,8 +2813,9 @@ write64_toshiba(void *priv, uint8_t val) kbd_log("ATkbc: T3100e: Read 'Fn' key\n"); if (keyboard_recv(0xb8) || /* Right Alt */ keyboard_recv(0x9d)) /* Right Ctrl */ - add_data(dev, 0x04); - else add_data(dev, 0x00); + kbc_transmit(dev, 0x04); + else + kbc_transmit(dev, 0x00); return 0; case 0xbc: /* T3100e: Reset Fn+Key notification */ @@ -1686,8 +2828,8 @@ write64_toshiba(void *priv, uint8_t val) /* The T3100e returns all bits set except bit 6 which * is set by t3100e_mono_set() */ - dev->input_port = (t3100e_mono_get() & 1) ? 0xff : 0xbf; - add_data(dev, dev->input_port); + dev->p1 = (t3100e_mono_get() & 1) ? 0xff : 0xbf; + kbc_transmit(dev, dev->p1); return 0; } @@ -1700,423 +2842,52 @@ static void kbd_write(uint16_t port, uint8_t val, void *priv) { atkbd_t *dev = (atkbd_t *)priv; - int i = 0, bad = 1; - uint8_t mask, kbc_ven = 0x0; - kbc_ven = dev->flags & KBC_VEN_MASK; - if ((kbc_ven == KBC_VEN_XI8088) && (port == 0x63)) - port = 0x61; - - kbd_log((port == 0x61) ? "" : "ATkbc: write(%04X, %02X)\n", port, val); + kbd_log("[%04X:%08X] ATkbc: write(%04X, %02X)\n", CS, cpu_state.pc, port, val); switch (port) { case 0x60: - dev->status &= ~STAT_CD; - if (dev->want60) { - /* Write data to controller. */ - dev->want60 = 0; + dev->status = (dev->status & ~STAT_CD) | STAT_IFULL; + dev->ib = val; + // kbd_status("Write %02X: %02X, Status = %02X\n", port, val, dev->status); - switch (dev->command) { - case 0x60: case 0x61: case 0x62: case 0x63: - case 0x64: case 0x65: case 0x66: case 0x67: - case 0x68: case 0x69: case 0x6a: case 0x6b: - case 0x6c: case 0x6d: case 0x6e: case 0x6f: - case 0x70: case 0x71: case 0x72: case 0x73: - case 0x74: case 0x75: case 0x76: case 0x77: - case 0x78: case 0x79: case 0x7a: case 0x7b: - case 0x7c: case 0x7d: case 0x7e: case 0x7f: - dev->mem[dev->command & 0x1f] = val; - if (dev->command == 0x60) - write_cmd(dev, val); - break; - - case 0xd1: /* write output port */ - kbd_log("ATkbc: write output port\n"); - if (dev->output_locked) { - /*If keyboard controller lines P22-P23 are blocked, - we force them to remain unchanged.*/ - val &= ~0x0c; - val |= (dev->output_port & 0x0c); - } - write_output(dev, val); - break; - - case 0xd2: /* write to keyboard output buffer */ - kbd_log("ATkbc: write to keyboard output buffer\n"); - add_to_kbc_queue_front(dev, val, 0, 0x00); - break; - - case 0xd3: /* write to mouse output buffer */ - kbd_log("ATkbc: write to mouse output buffer\n"); - if (mouse_write && ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) - keyboard_at_adddata_mouse(val); - break; - - case 0xd4: /* write to mouse */ - kbd_log("ATkbc: write to mouse (%02X)\n", val); - - if (val == 0xbb) - break; - - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - set_enable_mouse(dev, 1); - if (mouse_write) - mouse_write(val, mouse_p); - else - add_to_kbc_queue_front(dev, 0xfe, 2, 0x40); - } - break; - - default: - /* - * Run the vendor-specific handler - * if we have one. Otherwise, or if - * it returns an error, log a bad - * controller command. - */ - if (dev->write60_ven) - bad = dev->write60_ven(dev, val); - - if (bad) { - kbd_log("ATkbc: bad controller command %02x data %02x\n", dev->command, val); - add_data_kbd(0xfe); - } - } - } else { - /* Write data to keyboard. */ - dev->mem[0] &= ~0x10; - - if (dev->key_wantdata) { - dev->key_wantdata = 0; - - /* - * Several system BIOSes and OS device drivers - * mess up with this, and repeat the command - * code many times. Fun! - */ - if (val == dev->key_command) { - /* Respond NAK and ignore it. */ - add_data_kbd(0xfe); - dev->key_command = 0x00; - break; - } - - switch (dev->key_command) { - case 0xed: /* set/reset LEDs */ - add_data_kbd_direct(dev, 0xfa); - kbd_log("ATkbd: set LEDs [%02x]\n", val); - break; - - case 0xf0: /* get/set scancode set */ - add_data_kbd_direct(dev, 0xfa); - if (val == 0) { - kbd_log("Get scan code set: %02X\n", keyboard_mode & 3); - add_data_kbd_direct(dev, keyboard_mode & 3); - } else { - if ((val <= 3) && (val != 1)) { - keyboard_mode &= 0xfc; - keyboard_mode |= (val & 3); - kbd_log("Scan code set now: %02X\n", val); - } - set_scancode_map(dev); - } - break; - - case 0xf3: /* set typematic rate/delay */ - add_data_kbd_direct(dev, 0xfa); - break; - - default: - kbd_log("ATkbd: bad keyboard 0060 write %02X command %02X\n", val, dev->key_command); - add_data_kbd_direct(dev, 0xfe); - break; - } - - /* Keyboard command is now done. */ - dev->key_command = 0x00; - } else { - /* No keyboard command in progress. */ - dev->key_command = 0x00; - - set_enable_kbd(dev, 1); - - switch (val) { - case 0x00: - kbd_log("ATkbd: command 00\n"); - add_data_kbd_direct(dev, 0xfa); - break; - - case 0x05: /*??? - sent by NT 4.0*/ - kbd_log("ATkbd: command 05 (NT 4.0)\n"); - add_data_kbd_direct(dev, 0xfe); - break; - - /* Sent by Pentium-era AMI BIOS'es.*/ - case 0x71: case 0x82: - kbd_log("ATkbd: Pentium-era AMI BIOS command %02X\n", val); - break; - - case 0xed: /* set/reset LEDs */ - kbd_log("ATkbd: set/reset leds\n"); - add_data_kbd_direct(dev, 0xfa); - - dev->key_wantdata = 1; - break; - - case 0xee: /* diagnostic echo */ - kbd_log("ATkbd: ECHO\n"); - add_data_kbd_direct(dev, 0xee); - break; - - case 0xef: /* NOP (reserved for future use) */ - kbd_log("ATkbd: NOP\n"); - break; - - case 0xf0: /* get/set scan code set */ - kbd_log("ATkbd: scan code set\n"); - add_data_kbd_direct(dev, 0xfa); - dev->key_wantdata = 1; - break; - - case 0xf2: /* read ID */ - /* Fixed as translation will be done in add_data_kbd(). */ - kbd_log("ATkbd: read keyboard id\n"); - /* TODO: After keyboard type selection is implemented, make this - return the correct keyboard ID for the selected type. */ - add_data_kbd_direct(dev, 0xfa); - add_data_kbd_direct(dev, 0xab); - add_data_kbd_direct(dev, 0x83); - break; - - case 0xf3: /* set typematic rate/delay */ - kbd_log("ATkbd: set typematic rate/delay\n"); - add_data_kbd_direct(dev, 0xfa); - dev->key_wantdata = 1; - break; - - case 0xf4: /* enable keyboard */ - kbd_log("ATkbd: enable keyboard\n"); - add_data_kbd_direct(dev, 0xfa); - keyboard_scan = 1; - break; - - case 0xf5: /* set defaults and disable keyboard */ - case 0xf6: /* set defaults */ - kbd_log("ATkbd: set defaults%s\n", (val == 0xf6) ? "" : " and disable keyboard"); - keyboard_scan = (val == 0xf6); - kbd_log("val = %02X, keyboard_scan = %i, dev->mem[0] = %02X\n", - val, keyboard_scan, dev->mem[0]); - add_data_kbd_direct(dev, 0xfa); - - keyboard_set3_all_break = 0; - keyboard_set3_all_repeat = 0; - memset(keyboard_set3_flags, 0, 512); - keyboard_mode = (keyboard_mode & 0xfc) | 0x02; - set_scancode_map(dev); - break; - - case 0xf7: /* set all keys to repeat */ - kbd_log("ATkbd: set all keys to repeat\n"); - add_data_kbd_direct(dev, 0xfa); - keyboard_set3_all_break = 1; - break; - - case 0xf8: /* set all keys to give make/break codes */ - kbd_log("ATkbd: set all keys to give make/break codes\n"); - add_data_kbd_direct(dev, 0xfa); - keyboard_set3_all_break = 1; - break; - - case 0xf9: /* set all keys to give make codes only */ - kbd_log("ATkbd: set all keys to give make codes only\n"); - add_data_kbd_direct(dev, 0xfa); - keyboard_set3_all_break = 0; - break; - - case 0xfa: /* set all keys to repeat and give make/break codes */ - kbd_log("ATkbd: set all keys to repeat and give make/break codes\n"); - add_data_kbd_direct(dev, 0xfa); - keyboard_set3_all_repeat = 1; - keyboard_set3_all_break = 1; - break; - - case 0xfe: /* resend last scan code */ - kbd_log("ATkbd: reset last scan code\n"); - add_data_kbd_raw(dev, kbd_last_scan_code); - break; - - case 0xff: /* reset */ - kbd_log("ATkbd: kbd reset\n"); - kbc_queue_reset(1); - kbd_last_scan_code = 0x00; - add_data_kbd_direct(dev, 0xfa); - - /* Set scan code set to 2. */ - keyboard_mode = (keyboard_mode & 0xfc) | 0x02; - set_scancode_map(dev); - - dev->reset_delay = RESET_DELAY_TIME; - break; - - default: - kbd_log("ATkbd: bad keyboard command %02X\n", val); - add_data_kbd_direct(dev, 0xfe); - } - - /* If command needs data, remember command. */ - if (dev->key_wantdata == 1) - dev->key_command = val; - } +#if 0 + if ((dev->fast_a20_phase == 1)/* && ((val == 0xdd) || (val == 0xdf))*/) { + dev->status &= ~STAT_IFULL; + write_output(dev, val); + dev->fast_a20_phase = 0; } +#endif break; - - case 0x61: - ppi.pb = (ppi.pb & 0x10) | (val & 0x0f); - - speaker_update(); - speaker_gated = val & 1; - speaker_enable = val & 2; - if (speaker_enable) - was_speaker_enable = 1; - pit_ctr_set_gate(&pit->counters[2], val & 1); - - if (kbc_ven == KBC_VEN_XI8088) - xi8088_turbo_set(!!(val & 0x04)); - break; - case 0x64: - /* Controller command. */ - dev->want60 = 0; - dev->status |= STAT_CD; + dev->status |= (STAT_CD | STAT_IFULL); + dev->ib = val; + // kbd_status("Write %02X: %02X, Status = %02X\n", port, val, dev->status); - switch (val) { - /* Read data from KBC memory. */ - case 0x20: case 0x21: case 0x22: case 0x23: - case 0x24: case 0x25: case 0x26: case 0x27: - case 0x28: case 0x29: case 0x2a: case 0x2b: - case 0x2c: case 0x2d: case 0x2e: case 0x2f: - case 0x30: case 0x31: case 0x32: case 0x33: - case 0x34: case 0x35: case 0x36: case 0x37: - case 0x38: case 0x39: case 0x3a: case 0x3b: - case 0x3c: case 0x3d: case 0x3e: case 0x3f: - add_data(dev, dev->mem[val & 0x1f]); - break; - - /* Write data to KBC memory. */ - case 0x60: case 0x61: case 0x62: case 0x63: - case 0x64: case 0x65: case 0x66: case 0x67: - case 0x68: case 0x69: case 0x6a: case 0x6b: - case 0x6c: case 0x6d: case 0x6e: case 0x6f: - case 0x70: case 0x71: case 0x72: case 0x73: - case 0x74: case 0x75: case 0x76: case 0x77: - case 0x78: case 0x79: case 0x7a: case 0x7b: - case 0x7c: case 0x7d: case 0x7e: case 0x7f: - dev->want60 = 1; - break; - - case 0xaa: /* self-test */ - kbd_log("ATkbc: self-test\n"); - if ((kbc_ven == KBC_VEN_TOSHIBA) || (kbc_ven == KBC_VEN_SAMSUNG)) - dev->status |= STAT_IFULL; - write_output(dev, ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x4b : 0xcf); - - /* Always reinitialize all queues - the real hardware pulls keyboard and mouse - clocks high, which stops keyboard scanning. */ - kbd_log("ATkbc: self-test reinitialization\n"); - dev->out_new = dev->out_delayed = -1; - for (i = 0; i < 3; i++) - kbc_queue_reset(i); - kbd_last_scan_code = 0x00; - dev->status &= ~STAT_OFULL; - dev->last_irq = dev->old_last_irq = 0; - - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) - write_cmd(dev, 0x30 | STAT_SYSFLAG); - else - write_cmd(dev, 0x10 | STAT_SYSFLAG); - add_data(dev, 0x55); - break; - - case 0xab: /* interface test */ - kbd_log("ATkbc: interface test\n"); - add_data(dev, 0x00); /*no error*/ - break; - - case 0xac: /* diagnostic dump */ - kbd_log("ATkbc: diagnostic dump\n"); - for (i = 0; i < 16; i++) - add_data(dev, dev->mem[i]); - add_data(dev, (dev->input_port & 0xf0) | 0x80); - add_data(dev, dev->output_port); - add_data(dev, dev->status); - break; - - case 0xad: /* disable keyboard */ - kbd_log("ATkbc: disable keyboard\n"); - set_enable_kbd(dev, 0); - break; - - case 0xae: /* enable keyboard */ - kbd_log("ATkbc: enable keyboard\n"); - set_enable_kbd(dev, 1); - break; - - case 0xca: /* read keyboard mode */ - kbd_log("ATkbc: AMI - read keyboard mode\n"); - add_data(dev, ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x01 : 0x00); /*ISA mode*/ - break; - - case 0xcb: /* set keyboard mode */ - kbd_log("ATkbc: AMI - set keyboard mode\n"); - dev->want60 = 1; - break; - - case 0xd0: /* read output port */ - kbd_log("ATkbc: read output port\n"); - mask = 0xff; - if (((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) && (dev->mem[0] & 0x10)) - mask &= 0xbf; - add_to_kbc_queue_front(dev, dev->output_port & mask, 0, 0x00); - break; - - case 0xd1: /* write output port */ - kbd_log("ATkbc: write output port\n"); - dev->want60 = 1; - break; - - case 0xd2: /* write keyboard output buffer */ - kbd_log("ATkbc: write keyboard output buffer\n"); - dev->want60 = 1; - break; - - case 0xdd: /* disable A20 address line */ - case 0xdf: /* enable A20 address line */ - kbd_log("ATkbc: %sable A20\n", (val == 0xdd) ? "dis": "en"); - write_output(dev, (dev->output_port & 0xfd) | (val & 0x02)); - break; - - case 0xe0: /* read test inputs */ - kbd_log("ATkbc: read test inputs\n"); - add_data(dev, 0x00); - break; - - default: - /* - * Unrecognized controller command. - * - * If we have a vendor-specific handler, run - * that. Otherwise, or if that handler fails, - * log a bad command. - */ - if (dev->write64_ven) - bad = dev->write64_ven(dev, val); - - kbd_log(bad ? "ATkbc: bad controller command %02X\n" : "", val); +#if 0 + if (val == 0xd1) { + dev->status &= ~STAT_IFULL; + dev->fast_a20_phase = 1; + } else if (val == 0xfe) { + dev->status &= ~STAT_IFULL; + pulse_output(dev, 0x0e); + } else if ((val == 0xad) || (val == 0xae)) { + dev->status &= ~STAT_IFULL; + if (val & 0x01) + dev->mem[0x20] |= 0x10; + else + dev->mem[0x20] &= ~0x10; + } else if (val == 0xa1) { + dev->status &= ~STAT_IFULL; + kbc_send_to_ob(dev, 'H', 0, 0x00); } - - /* If the command needs data, remember the command. */ - if (dev->want60) - dev->command = val; +#else + /* if (val == 0xa1) { + dev->status &= ~STAT_IFULL; + kbc_send_to_ob(dev, 'H', 0, 0x00); + } */ + kbc_process(dev); +#endif break; } } @@ -2127,83 +2898,20 @@ kbd_read(uint16_t port, void *priv) { atkbd_t *dev = (atkbd_t *)priv; uint8_t ret = 0xff; - uint8_t kbc_ven = 0x0; - kbc_ven = dev->flags & KBC_VEN_MASK; - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) - cycles -= ISA_CYCLES(8); - - if ((kbc_ven == KBC_VEN_XI8088) && (port == 0x63)) - port = 0x61; + // if (dev->flags & KBC_FLAG_PS2) + // cycles -= ISA_CYCLES(8); switch (port) { case 0x60: - ret = dev->out; + ret = dev->ob; dev->status &= ~STAT_OFULL; picintc(dev->last_irq); dev->last_irq = 0; break; - case 0x61: - ret = ppi.pb & ~0xe0; - if (ppispeakon) - ret |= 0x20; - if ((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) { - if (dev->refresh) - ret |= 0x10; - else - ret &= ~0x10; - } - if (kbc_ven == KBC_VEN_XI8088) { - if (xi8088_turbo_get()) - ret |= 0x04; - else - ret &= ~0x04; - } - break; - - case 0x62: - ret = 0xff; - if (kbc_ven == KBC_VEN_OLIVETTI) { - /* SWA on Olivetti M240 mainboard (off=1) */ - ret = 0x00; - if (ppi.pb & 0x8) { - /* Switches 4, 5 - floppy drives (number) */ - int i, fdd_count = 0; - for (i = 0; i < FDD_NUM; i++) { - if (fdd_get_flags(i)) - fdd_count++; - } - if (!fdd_count) - ret |= 0x00; - else - ret |= ((fdd_count - 1) << 2); - /* Switches 6, 7 - monitor type */ - if (video_is_mda()) - ret |= 0x3; - else if (video_is_cga()) - ret |= 0x2; /* 0x10 would be 40x25 */ - else - ret |= 0x0; - } else { - /* bit 2 always on */ - ret |= 0x4; - /* Switch 8 - 8087 FPU. */ - if (hasfpu) - ret |= 0x02; - } - } - break; case 0x64: - ret = (dev->status & 0xfb); - if (dev->mem[0] & STAT_SYSFLAG) - ret |= STAT_SYSFLAG; - /* Only clear the transmit timeout flag on non-PS/2 controllers, as on - PS/2 controller, it is the keyboard/mouse output source bit. */ - // dev->status &= ~STAT_RTIMEOUT; - if (((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) && - (kbc_ven != KBC_VEN_IBM_MCA)) - dev->status &= ~STAT_TTIMEOUT; + ret = dev->status; break; default: @@ -2211,22 +2919,12 @@ kbd_read(uint16_t port, void *priv) break; } - kbd_log((port == 0x61) ? "" : "ATkbc: read(%04X) = %02X\n", port, ret); + kbd_log("[%04X:%08X] ATkbc: read(%04X) = %02X\n",CS, cpu_state.pc, port, ret); return(ret); } -static void -kbd_refresh(void *priv) -{ - atkbd_t *dev = (atkbd_t *)priv; - - dev->refresh = !dev->refresh; - timer_advance_u64(&dev->refresh_time, PS2_REFRESH_TIME); -} - - static void kbd_reset(void *priv) { @@ -2235,25 +2933,26 @@ kbd_reset(void *priv) uint8_t kbc_ven = 0x0; kbc_ven = dev->flags & KBC_VEN_MASK; - dev->first_write = 1; - // dev->status = STAT_UNLOCKED | STAT_CD; dev->status = STAT_UNLOCKED; - dev->mem[0] = 0x01; - dev->mem[0] |= CCB_TRANSLATE; - dev->wantirq = 0; + dev->mem[0x20] = 0x01; + dev->mem[0x20] |= CCB_TRANSLATE; write_output(dev, 0xcf); - dev->last_irq = dev->old_last_irq = 0; + dev->last_irq = 0; dev->secr_phase = 0; - dev->key_wantdata = 0; + dev->kbd_in = 0; + dev->ami_mode = !!(dev->flags & KBC_FLAG_PS2); /* Set up the correct Video Type bits. */ + dev->p1 = video_is_mda() ? 0xf0 : 0xb0; if ((kbc_ven == KBC_VEN_XI8088) || (kbc_ven == KBC_VEN_ACER)) - dev->input_port = video_is_mda() ? 0xb0 : 0xf0; + dev->p1 ^= 0x40; + if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) + dev->inhibit = ((dev->p1 & 0x80) >> 3); else - dev->input_port = video_is_mda() ? 0xf0 : 0xb0; - kbd_log("ATkbc: input port = %02x\n", dev->input_port); + dev->inhibit = 0x10; + kbd_log("ATkbc: input port = %02x\n", dev->p1); - keyboard_mode = 0x02 | (dev->mem[0] & CCB_TRANSLATE); + keyboard_mode = 0x02 | (dev->mem[0x20] & CCB_TRANSLATE); /* Enable keyboard, disable mouse. */ set_enable_kbd(dev, 1); @@ -2261,16 +2960,18 @@ kbd_reset(void *priv) set_enable_mouse(dev, 0); mouse_scan = 0; - dev->out_new = dev->out_delayed = -1; - for (i = 0; i < 3; i++) - kbc_queue_reset(i); - kbd_last_scan_code = 0; + dev->ob = 0xff; sc_or = 0; + for (i = 1; i <= 2; i++) + kbc_queue_reset(i); + memset(keyboard_set3_flags, 0, 512); set_scancode_map(dev); + + dev->mem[0x31] = 0xfe; } @@ -2292,7 +2993,6 @@ kbd_close(void *priv) /* Stop timers. */ timer_disable(&dev->send_delay_timer); - timer_disable(&dev->refresh_time); keyboard_scan = 0; keyboard_send = NULL; @@ -2316,17 +3016,14 @@ kbd_init(const device_t *info) dev->flags = info->local; video_reset(gfxcard); - kbd_reset(dev); + dev->kbc_poll_phase = KBC_RESET; + kbd_send_to_host(dev, 0xaa); - io_sethandler(0x0060, 5, - kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); + io_sethandler(0x0060, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); + io_sethandler(0x0064, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); keyboard_send = add_data_kbd; timer_add(&dev->send_delay_timer, kbd_poll, dev, 1); - - if ((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) - timer_add(&dev->refresh_time, kbd_refresh, dev, 1); - timer_add(&dev->pulse_cb, pulse_poll, dev, 0); dev->write60_ven = NULL; @@ -2342,12 +3039,14 @@ kbd_init(const device_t *info) break; case KBC_VEN_OLIVETTI: + /* The Olivetti controller is a special case - starts directly in the + main loop instead of the reset loop. */ + dev->kbc_poll_phase = KBC_MAIN_LOOP; dev->write64_ven = write64_olivetti; break; case KBC_VEN_AMI: case KBC_VEN_INTEL_AMI: - case KBC_VEN_SAMSUNG: dev->write60_ven = write60_ami; dev->write64_ven = write64_ami; break; @@ -2367,6 +3066,8 @@ kbd_init(const device_t *info) break; } + kbd_reset(dev); + /* We need this, sadly. */ SavedKbd = dev; @@ -2394,16 +3095,6 @@ const device_t keyboard_at_ami_device = { { NULL }, NULL, NULL, NULL }; -const device_t keyboard_at_samsung_device = { - "PC/AT Keyboard (Samsung)", - 0, - KBC_TYPE_ISA | KBC_VEN_SAMSUNG, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - const device_t keyboard_at_toshiba_device = { "PC/AT Keyboard (Toshiba)", 0, @@ -2435,16 +3126,6 @@ const device_t keyboard_at_ncr_device = { }; const device_t keyboard_ps2_device = { - "PS/2 Keyboard", - 0, - KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_ps2_device = { "PS/2 Keyboard", 0, KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, @@ -2457,7 +3138,7 @@ const device_t keyboard_ps2_ps2_device = { const device_t keyboard_ps2_ps1_device = { "PS/2 Keyboard (IBM PS/1)", 0, - KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1, + KBC_TYPE_PS2_1 | KBC_VEN_IBM_PS1, kbd_init, kbd_close, kbd_reset, @@ -2467,7 +3148,7 @@ const device_t keyboard_ps2_ps1_device = { const device_t keyboard_ps2_ps1_pci_device = { "PS/2 Keyboard (IBM PS/1)", DEVICE_PCI, - KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1, + KBC_TYPE_PS2_1 | KBC_VEN_IBM_PS1, kbd_init, kbd_close, kbd_reset, @@ -2487,7 +3168,7 @@ const device_t keyboard_ps2_xi8088_device = { const device_t keyboard_ps2_ami_device = { "PS/2 Keyboard (AMI)", 0, - KBC_TYPE_PS2_NOREF | KBC_VEN_AMI, + KBC_TYPE_PS2_1 | KBC_VEN_AMI, kbd_init, kbd_close, kbd_reset, @@ -2497,7 +3178,7 @@ const device_t keyboard_ps2_ami_device = { const device_t keyboard_ps2_olivetti_device = { "PS/2 Keyboard (Olivetti)", 0, - KBC_TYPE_PS2_NOREF | KBC_VEN_OLIVETTI, + KBC_TYPE_PS2_1 | KBC_VEN_OLIVETTI, kbd_init, kbd_close, kbd_reset, @@ -2527,7 +3208,7 @@ const device_t keyboard_ps2_mca_2_device = { const device_t keyboard_ps2_quadtel_device = { "PS/2 Keyboard (Quadtel/MegaPC)", 0, - KBC_TYPE_PS2_NOREF | KBC_VEN_QUADTEL, + KBC_TYPE_PS2_1 | KBC_VEN_QUADTEL, kbd_init, kbd_close, kbd_reset, @@ -2537,7 +3218,7 @@ const device_t keyboard_ps2_quadtel_device = { const device_t keyboard_ps2_pci_device = { "PS/2 Keyboard", DEVICE_PCI, - KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC, + KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, kbd_init, kbd_close, kbd_reset, @@ -2547,7 +3228,7 @@ const device_t keyboard_ps2_pci_device = { const device_t keyboard_ps2_ami_pci_device = { "PS/2 Keyboard (AMI)", DEVICE_PCI, - KBC_TYPE_PS2_NOREF | KBC_VEN_AMI, + KBC_TYPE_PS2_1 | KBC_VEN_AMI, kbd_init, kbd_close, kbd_reset, @@ -2557,7 +3238,7 @@ const device_t keyboard_ps2_ami_pci_device = { const device_t keyboard_ps2_intel_ami_pci_device = { "PS/2 Keyboard (AMI)", DEVICE_PCI, - KBC_TYPE_PS2_NOREF | KBC_VEN_INTEL_AMI, + KBC_TYPE_PS2_1 | KBC_VEN_INTEL_AMI, kbd_init, kbd_close, kbd_reset, @@ -2567,7 +3248,7 @@ const device_t keyboard_ps2_intel_ami_pci_device = { const device_t keyboard_ps2_acer_pci_device = { "PS/2 Keyboard (Acer 90M002A)", DEVICE_PCI, - KBC_TYPE_PS2_NOREF | KBC_VEN_ACER, + KBC_TYPE_PS2_1 | KBC_VEN_ACER, kbd_init, kbd_close, kbd_reset, @@ -2578,17 +3259,8 @@ const device_t keyboard_ps2_acer_pci_device = { void keyboard_at_set_mouse(void (*func)(uint8_t val, void *priv), void *priv) { - mouse_write = func; - mouse_p = priv; -} - - -void -keyboard_at_adddata_keyboard_raw(uint8_t val) -{ - atkbd_t *dev = SavedKbd; - - add_data_kbd_queue(dev, 0, val); + // mouse_write = func; + // mouse_p = priv; } @@ -2601,10 +3273,30 @@ keyboard_at_adddata_mouse(uint8_t val) } +void +keyboard_at_adddata_mouse_direct(uint8_t val) +{ + // atkbd_t *dev = SavedKbd; + + return; +} + + +void +keyboard_at_adddata_mouse_cmd(uint8_t val) +{ + // atkbd_t *dev = SavedKbd; + + return; +} + + void keyboard_at_mouse_reset(void) { - kbc_queue_reset(2); + // atkbd_t *dev = SavedKbd; + + return; } @@ -2615,13 +3307,22 @@ keyboard_at_mouse_pos(void) } +int +keyboard_at_fixed_channel(void) +{ + // atkbd_t *dev = SavedKbd; + + return 0x000; +} + + void keyboard_at_set_mouse_scan(uint8_t val) { atkbd_t *dev = SavedKbd; uint8_t temp_mouse_scan = val ? 1 : 0; - if (temp_mouse_scan == !(dev->mem[0] & 0x20)) + if (temp_mouse_scan == !(dev->mem[0x20] & 0x20)) return; set_enable_mouse(dev, val ? 1 : 0); @@ -2635,7 +3336,7 @@ keyboard_at_get_mouse_scan(void) { atkbd_t *dev = SavedKbd; - return((dev->mem[0] & 0x20) ? 0x00 : 0x10); + return((dev->mem[0x20] & 0x20) ? 0x00 : 0x10); } @@ -2644,5 +3345,17 @@ keyboard_at_set_a20_key(int state) { atkbd_t *dev = SavedKbd; - write_output(dev, (dev->output_port & 0xfd) | ((!!state) << 1)); + write_output(dev, (dev->p2 & 0xfd) | ((!!state) << 1)); +} + + +void +keyboard_at_set_mode(int ps2) +{ + atkbd_t *dev = SavedKbd; + + if (ps2) + dev->flags |= KBC_FLAG_PS2; + else + dev->flags &= ~KBC_FLAG_PS2; } From 4a6f5ed045821ac30411c2aaf23c997cbf4021bc Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 10 Aug 2021 15:55:33 +0200 Subject: [PATCH 45/96] Disabled keyboard logging. --- src/device/keyboard_at.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index c0507ffb5..7f5ee51db 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -673,7 +673,6 @@ kbd_status(const char *fmt, ...) } -#define ENABLE_KEYBOARD_AT_LOG 1 #ifdef ENABLE_KEYBOARD_AT_LOG int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG; From 80bc644692633cd27f026ab17240fce0328c759e Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 12 Aug 2021 11:10:16 +0200 Subject: [PATCH 46/96] ALi and SMC fixes. --- src/chipset/ali1489.c | 10 +++++++--- src/sio/sio_fdc37c66x.c | 15 +++++++++++---- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/chipset/ali1489.c b/src/chipset/ali1489.c index 6c90cf7d0..330792b78 100644 --- a/src/chipset/ali1489.c +++ b/src/chipset/ali1489.c @@ -74,6 +74,9 @@ typedef struct } ali1489_t; +static void ali1489_ide_handler(ali1489_t *dev); + + static void ali1489_shadow_recalc(ali1489_t *dev) { @@ -121,8 +124,7 @@ ali1489_smram_recalc(ali1489_t *dev) smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, (dev->regs[0x19] & 0x08), 1); break; case 0x20: - if ((dev->regs[0x14] & 0x03) == 0x00) - smram_enable(dev->smram, 0xe0000, 0xe0000, 0x10000, (dev->regs[0x19] & 0x08), 1); + smram_enable(dev->smram, 0xe0000, 0xe0000, 0x10000, (dev->regs[0x19] & 0x08), 1); break; case 0x30: if ((dev->regs[0x35] & 0xc0) == 0x80) @@ -203,6 +205,8 @@ ali1489_defaults(ali1489_t *dev) 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); + + ali1489_ide_handler(dev); } @@ -459,7 +463,7 @@ ali1489_ide_handler(ali1489_t *dev) { ide_pri_disable(); ide_sec_disable(); - if (dev->regs[0x01] & 0x01) { + if (dev->ide_regs[0x01] & 0x01) { ide_pri_enable(); if (!(dev->ide_regs[0x35] & 0x40)) ide_sec_enable(); diff --git a/src/sio/sio_fdc37c66x.c b/src/sio/sio_fdc37c66x.c index 3cda6c206..812bbf91b 100644 --- a/src/sio/sio_fdc37c66x.c +++ b/src/sio/sio_fdc37c66x.c @@ -73,7 +73,7 @@ set_com34_addr(fdc37c66x_t *dev) static void set_serial_addr(fdc37c66x_t *dev, int port) { - uint8_t shift = (port << 4); + uint8_t shift = (port << 2); double clock_src = 24000000.0 / 13.0; if (dev->regs[4] & (1 << (4 + port))) @@ -81,7 +81,7 @@ set_serial_addr(fdc37c66x_t *dev, int port) serial_remove(dev->uart[port]); if (dev->regs[2] & (4 << shift)) { - switch (dev->regs[2] & (3 << shift)) { + switch ((dev->regs[2] >> shift) & 3) { case 0: serial_setup(dev->uart[port], SERIAL1_ADDR, SERIAL1_IRQ); break; @@ -112,11 +112,11 @@ lpt1_handler(fdc37c66x_t *dev) break; case 2: lpt1_init(0x378); - lpt1_irq(5); + lpt1_irq(7 /*5*/); break; case 3: lpt1_init(0x278); - lpt1_irq(5); + lpt1_irq(7 /*5*/); break; } } @@ -264,6 +264,13 @@ fdc37c66x_reset(fdc37c66x_t *dev) dev->regs[0xd] = dev->chip_id; dev->regs[0xe] = 0x01; + set_serial_addr(dev, 0); + set_serial_addr(dev, 1); + + lpt1_handler(dev); + + fdc_handler(dev); + if (dev->has_ide) ide_handler(dev); } From 4e8600e3b1e370687dd6dba5cc560e5552a1db82 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 20 Aug 2021 16:56:17 +0200 Subject: [PATCH 47/96] PS/2 mouse command F6. --- src/device/mouse_ps2.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/device/mouse_ps2.c b/src/device/mouse_ps2.c index f8ba676e0..649182ca5 100644 --- a/src/device/mouse_ps2.c +++ b/src/device/mouse_ps2.c @@ -194,6 +194,7 @@ ps2_write(uint8_t val, void *priv) keyboard_at_adddata_mouse_cmd(0xfa); break; + case 0xf6: /* set defaults */ case 0xff: /* reset */ mouse_reset: dev->mode = MODE_STREAM; @@ -201,8 +202,10 @@ mouse_reset: mouse_scan = 1; keyboard_at_mouse_reset(); keyboard_at_adddata_mouse_cmd(0xfa); - keyboard_at_adddata_mouse_cmd(0xaa); - keyboard_at_adddata_mouse_cmd(0x00); + if (dev->command == 0xff) { + keyboard_at_adddata_mouse_cmd(0xaa); + keyboard_at_adddata_mouse_cmd(0x00); + } break; default: From 19c374c0463231466d283310ba385cb960a28a25 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 20 Aug 2021 16:58:27 +0200 Subject: [PATCH 48/96] Temporary changes to make merger possible. --- src/device/mouse_ps2.c | 61 ++++++++++------------ src/disk/hdc_ide_sff8038i.c | 101 +++++++++--------------------------- 2 files changed, 51 insertions(+), 111 deletions(-) diff --git a/src/device/mouse_ps2.c b/src/device/mouse_ps2.c index 649182ca5..3fe743748 100644 --- a/src/device/mouse_ps2.c +++ b/src/device/mouse_ps2.c @@ -93,27 +93,22 @@ ps2_write(uint8_t val, void *priv) mouse_t *dev = (mouse_t *)priv; uint8_t temp; - pclog("ps2_write(%02X)\n", val); - if (dev->flags & FLAG_CTRLDAT) { dev->flags &= ~FLAG_CTRLDAT; - if (val == 0xff) - goto mouse_reset; - switch (dev->command) { case 0xe8: /* set mouse resolution */ dev->resolution = val; - keyboard_at_adddata_mouse_cmd(0xfa); + keyboard_at_adddata_mouse(0xfa); break; case 0xf3: /* set sample rate */ dev->sample_rate = val; - keyboard_at_adddata_mouse_cmd(0xfa); /* Command response */ + keyboard_at_adddata_mouse(0xfa); /* Command response */ break; default: - keyboard_at_adddata_mouse_cmd(0xfc); + keyboard_at_adddata_mouse(0xfc); } } else { dev->command = val; @@ -121,21 +116,21 @@ ps2_write(uint8_t val, void *priv) switch (dev->command) { case 0xe6: /* set scaling to 1:1 */ dev->flags &= ~FLAG_SCALED; - keyboard_at_adddata_mouse_cmd(0xfa); + keyboard_at_adddata_mouse(0xfa); break; case 0xe7: /* set scaling to 2:1 */ dev->flags |= FLAG_SCALED; - keyboard_at_adddata_mouse_cmd(0xfa); + keyboard_at_adddata_mouse(0xfa); break; case 0xe8: /* set mouse resolution */ dev->flags |= FLAG_CTRLDAT; - keyboard_at_adddata_mouse_cmd(0xfa); + keyboard_at_adddata_mouse(0xfa); break; case 0xe9: /* status request */ - keyboard_at_adddata_mouse_cmd(0xfa); + keyboard_at_adddata_mouse(0xfa); temp = (dev->flags & 0x30); if (mouse_buttons & 0x01) temp |= 0x01; @@ -143,13 +138,13 @@ ps2_write(uint8_t val, void *priv) temp |= 0x02; if (mouse_buttons & 0x04) temp |= 0x03; - keyboard_at_adddata_mouse_cmd(temp); - keyboard_at_adddata_mouse_cmd(dev->resolution); - keyboard_at_adddata_mouse_cmd(dev->sample_rate); + keyboard_at_adddata_mouse(temp); + keyboard_at_adddata_mouse(dev->resolution); + keyboard_at_adddata_mouse(dev->sample_rate); break; case 0xeb: /* Get mouse data */ - keyboard_at_adddata_mouse_cmd(0xfa); + keyboard_at_adddata_mouse(0xfa); temp = 0; if (dev->x < 0) @@ -162,54 +157,53 @@ ps2_write(uint8_t val, void *priv) temp |= 2; if ((mouse_buttons & 4) && (dev->flags & FLAG_INTELLI)) temp |= 4; - keyboard_at_adddata_mouse_cmd(temp); - keyboard_at_adddata_mouse_cmd(dev->x & 0xff); - keyboard_at_adddata_mouse_cmd(dev->y & 0xff); + keyboard_at_adddata_mouse(temp); + keyboard_at_adddata_mouse(dev->x & 0xff); + keyboard_at_adddata_mouse(dev->y & 0xff); if (dev->flags & FLAG_INTMODE) - keyboard_at_adddata_mouse_cmd(dev->z); + keyboard_at_adddata_mouse(dev->z); break; case 0xf2: /* read ID */ - keyboard_at_adddata_mouse_cmd(0xfa); + keyboard_at_adddata_mouse(0xfa); if (dev->flags & FLAG_INTMODE) - keyboard_at_adddata_mouse_cmd(0x03); + keyboard_at_adddata_mouse(0x03); else - keyboard_at_adddata_mouse_cmd(0x00); + keyboard_at_adddata_mouse(0x00); break; case 0xf3: /* set command mode */ dev->flags |= FLAG_CTRLDAT; - keyboard_at_adddata_mouse_cmd(0xfa); /* ACK for command byte */ + keyboard_at_adddata_mouse(0xfa); /* ACK for command byte */ break; case 0xf4: /* enable */ dev->flags |= FLAG_ENABLED; mouse_scan = 1; - keyboard_at_adddata_mouse_cmd(0xfa); + keyboard_at_adddata_mouse(0xfa); break; case 0xf5: /* disable */ dev->flags &= ~FLAG_ENABLED; mouse_scan = 0; - keyboard_at_adddata_mouse_cmd(0xfa); + keyboard_at_adddata_mouse(0xfa); break; case 0xf6: /* set defaults */ case 0xff: /* reset */ -mouse_reset: dev->mode = MODE_STREAM; dev->flags &= 0x88; - mouse_scan = 1; + mouse_scan = 0; keyboard_at_mouse_reset(); - keyboard_at_adddata_mouse_cmd(0xfa); + keyboard_at_adddata_mouse(0xfa); if (dev->command == 0xff) { - keyboard_at_adddata_mouse_cmd(0xaa); - keyboard_at_adddata_mouse_cmd(0x00); + keyboard_at_adddata_mouse(0xaa); + keyboard_at_adddata_mouse(0x00); } break; default: - keyboard_at_adddata_mouse_cmd(0xfe); + keyboard_at_adddata_mouse(0xfe); } } @@ -241,9 +235,6 @@ ps2_poll(int x, int y, int z, int b, void *priv) return(0xff); #endif - if ((keyboard_at_fixed_channel() & 0xf00) == 0x200) - return(0xff); - if (!mouse_scan) return(0xff); diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index 023883720..733868cc3 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -370,49 +370,32 @@ void sff_bus_master_set_irq(int channel, void *priv) { sff8038i_t *dev = (sff8038i_t *) priv; - dev->status &= ~0x04; - dev->status |= (channel >> 4); + if (!(dev->status & 0x04) || (channel & 0x40)) { + dev->status &= ~4; + dev->status |= (channel >> 4); + } channel &= 0x01; - - switch (dev->irq_mode[channel]) { - case 0: - default: - /* Legacy IRQ mode. */ - if (dev->status & 0x04) - picint(1 << (14 + channel)); - else - picintc(1 << (14 + channel)); - break; - case 1: - /* Native PCI IRQ mode with interrupt pin. */ - if (dev->status & 0x04) - pci_set_irq(dev->slot, dev->irq_pin); - else - pci_clear_irq(dev->slot, dev->irq_pin); - break; - case 2: - case 5: - /* MIRQ 0 or 1. */ - if (dev->status & 0x04) - pci_set_mirq(dev->irq_mode[channel] & 1, 0); - else - pci_clear_mirq(dev->irq_mode[channel] & 1, 0); - break; - case 3: - /* Native PCI IRQ mode with specified interrupt line. */ - if (dev->status & 0x04) - picintlevel(1 << dev->irq_line); - else - picintc(1 << dev->irq_line); - break; - case 4: - /* ALi Aladdin Native PCI INTAJ mode. */ - if (dev->status & 0x04) - pci_set_mirq(channel + 2, dev->irq_level[channel]); - else - pci_clear_mirq(channel + 2, dev->irq_level[channel]); - break; + if (dev->status & 0x04) { + sff_log("SFF8038i: Channel %i IRQ raise\n", channel); + if (dev->irq_mode[channel] == 3) + picintlevel(1 << dev->irq_line); + else if ((dev->irq_mode[channel] == 2) && channel && pci_use_mirq(0)) + pci_set_mirq(0, 0); + else if (dev->irq_mode[channel] == 1) + pci_set_irq(dev->slot, dev->irq_pin); + else + picint(1 << (14 + channel)); + } else { + sff_log("SFF8038i: Channel %i IRQ lower\n", channel); + if (dev->irq_mode[channel] == 3) + picintc(1 << dev->irq_line); + else if ((dev->irq_mode[channel] == 2) && channel && pci_use_mirq(0)) + pci_clear_mirq(0, 0); + else if (dev->irq_mode[channel] == 1) + pci_clear_irq(dev->slot, dev->irq_pin); + else + picintc(1 << (14 + channel)); } } @@ -485,42 +468,10 @@ sff_set_irq_line(sff8038i_t *dev, int irq_line) } -void -sff_set_irq_level(sff8038i_t *dev, int channel, int irq_level) -{ - dev->irq_level[channel] = 0; -} - - void sff_set_irq_mode(sff8038i_t *dev, int channel, int irq_mode) { dev->irq_mode[channel] = irq_mode; - - switch (dev->irq_mode[channel]) { - case 0: - default: - /* Legacy IRQ mode. */ - sff_log("[%08X] Setting channel %i to legacy IRQ %i\n", dev, channel, 14 + channel); - break; - case 1: - /* Native PCI IRQ mode with interrupt pin. */ - sff_log("[%08X] Setting channel %i to native PCI INT%c\n", dev, channel, '@' + dev->irq_pin); - break; - case 2: - case 5: - /* MIRQ 0 or 1. */ - sff_log("[%08X] Setting channel %i to PCI MIRQ%i\n", dev, channel, irq_mode & 1); - break; - case 3: - /* Native PCI IRQ mode with specified interrupt line. */ - sff_log("[%08X] Setting channel %i to native PCI IRQ %i\n", dev, channel, dev->irq_line); - break; - case 4: - /* ALi Aladdin Native PCI INTAJ mode. */ - sff_log("[%08X] Setting channel %i to INT%cJ\n", dev, channel, 'A' + channel); - break; - } } @@ -557,11 +508,9 @@ static void ide_set_bus_master(next_id, sff_bus_master_dma, sff_bus_master_set_irq, dev); dev->slot = 7; - dev->irq_mode[0] = 0; /* Channel 0 goes to IRQ 14. */ - dev->irq_mode[1] = 2; /* Channel 1 goes to MIRQ0. */ + dev->irq_mode[0] = dev->irq_mode[1] = 2; dev->irq_pin = PCI_INTA; dev->irq_line = 14; - dev->irq_level[0] = dev->irq_level[1] = 0; next_id++; From 583f84a8b42dbf707df64617291adf61af55745f Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 20 Aug 2021 17:00:30 +0200 Subject: [PATCH 49/96] And back. --- src/device/mouse_ps2.c | 61 +++++++++++++---------- src/disk/hdc_ide_sff8038i.c | 97 ++++++++++++++++++++++++++++--------- 2 files changed, 110 insertions(+), 48 deletions(-) diff --git a/src/device/mouse_ps2.c b/src/device/mouse_ps2.c index 3fe743748..649182ca5 100644 --- a/src/device/mouse_ps2.c +++ b/src/device/mouse_ps2.c @@ -93,22 +93,27 @@ ps2_write(uint8_t val, void *priv) mouse_t *dev = (mouse_t *)priv; uint8_t temp; + pclog("ps2_write(%02X)\n", val); + if (dev->flags & FLAG_CTRLDAT) { dev->flags &= ~FLAG_CTRLDAT; + if (val == 0xff) + goto mouse_reset; + switch (dev->command) { case 0xe8: /* set mouse resolution */ dev->resolution = val; - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse_cmd(0xfa); break; case 0xf3: /* set sample rate */ dev->sample_rate = val; - keyboard_at_adddata_mouse(0xfa); /* Command response */ + keyboard_at_adddata_mouse_cmd(0xfa); /* Command response */ break; default: - keyboard_at_adddata_mouse(0xfc); + keyboard_at_adddata_mouse_cmd(0xfc); } } else { dev->command = val; @@ -116,21 +121,21 @@ ps2_write(uint8_t val, void *priv) switch (dev->command) { case 0xe6: /* set scaling to 1:1 */ dev->flags &= ~FLAG_SCALED; - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse_cmd(0xfa); break; case 0xe7: /* set scaling to 2:1 */ dev->flags |= FLAG_SCALED; - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse_cmd(0xfa); break; case 0xe8: /* set mouse resolution */ dev->flags |= FLAG_CTRLDAT; - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse_cmd(0xfa); break; case 0xe9: /* status request */ - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse_cmd(0xfa); temp = (dev->flags & 0x30); if (mouse_buttons & 0x01) temp |= 0x01; @@ -138,13 +143,13 @@ ps2_write(uint8_t val, void *priv) temp |= 0x02; if (mouse_buttons & 0x04) temp |= 0x03; - keyboard_at_adddata_mouse(temp); - keyboard_at_adddata_mouse(dev->resolution); - keyboard_at_adddata_mouse(dev->sample_rate); + keyboard_at_adddata_mouse_cmd(temp); + keyboard_at_adddata_mouse_cmd(dev->resolution); + keyboard_at_adddata_mouse_cmd(dev->sample_rate); break; case 0xeb: /* Get mouse data */ - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse_cmd(0xfa); temp = 0; if (dev->x < 0) @@ -157,53 +162,54 @@ ps2_write(uint8_t val, void *priv) temp |= 2; if ((mouse_buttons & 4) && (dev->flags & FLAG_INTELLI)) temp |= 4; - keyboard_at_adddata_mouse(temp); - keyboard_at_adddata_mouse(dev->x & 0xff); - keyboard_at_adddata_mouse(dev->y & 0xff); + keyboard_at_adddata_mouse_cmd(temp); + keyboard_at_adddata_mouse_cmd(dev->x & 0xff); + keyboard_at_adddata_mouse_cmd(dev->y & 0xff); if (dev->flags & FLAG_INTMODE) - keyboard_at_adddata_mouse(dev->z); + keyboard_at_adddata_mouse_cmd(dev->z); break; case 0xf2: /* read ID */ - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse_cmd(0xfa); if (dev->flags & FLAG_INTMODE) - keyboard_at_adddata_mouse(0x03); + keyboard_at_adddata_mouse_cmd(0x03); else - keyboard_at_adddata_mouse(0x00); + keyboard_at_adddata_mouse_cmd(0x00); break; case 0xf3: /* set command mode */ dev->flags |= FLAG_CTRLDAT; - keyboard_at_adddata_mouse(0xfa); /* ACK for command byte */ + keyboard_at_adddata_mouse_cmd(0xfa); /* ACK for command byte */ break; case 0xf4: /* enable */ dev->flags |= FLAG_ENABLED; mouse_scan = 1; - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse_cmd(0xfa); break; case 0xf5: /* disable */ dev->flags &= ~FLAG_ENABLED; mouse_scan = 0; - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse_cmd(0xfa); break; case 0xf6: /* set defaults */ case 0xff: /* reset */ +mouse_reset: dev->mode = MODE_STREAM; dev->flags &= 0x88; - mouse_scan = 0; + mouse_scan = 1; keyboard_at_mouse_reset(); - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse_cmd(0xfa); if (dev->command == 0xff) { - keyboard_at_adddata_mouse(0xaa); - keyboard_at_adddata_mouse(0x00); + keyboard_at_adddata_mouse_cmd(0xaa); + keyboard_at_adddata_mouse_cmd(0x00); } break; default: - keyboard_at_adddata_mouse(0xfe); + keyboard_at_adddata_mouse_cmd(0xfe); } } @@ -235,6 +241,9 @@ ps2_poll(int x, int y, int z, int b, void *priv) return(0xff); #endif + if ((keyboard_at_fixed_channel() & 0xf00) == 0x200) + return(0xff); + if (!mouse_scan) return(0xff); diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index 733868cc3..b5362e6f9 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -371,31 +371,50 @@ sff_bus_master_set_irq(int channel, void *priv) { sff8038i_t *dev = (sff8038i_t *) priv; if (!(dev->status & 0x04) || (channel & 0x40)) { - dev->status &= ~4; + dev->status &= ~0x04; dev->status |= (channel >> 4); } channel &= 0x01; - if (dev->status & 0x04) { - sff_log("SFF8038i: Channel %i IRQ raise\n", channel); - if (dev->irq_mode[channel] == 3) - picintlevel(1 << dev->irq_line); - else if ((dev->irq_mode[channel] == 2) && channel && pci_use_mirq(0)) - pci_set_mirq(0, 0); - else if (dev->irq_mode[channel] == 1) - pci_set_irq(dev->slot, dev->irq_pin); - else - picint(1 << (14 + channel)); - } else { - sff_log("SFF8038i: Channel %i IRQ lower\n", channel); - if (dev->irq_mode[channel] == 3) - picintc(1 << dev->irq_line); - else if ((dev->irq_mode[channel] == 2) && channel && pci_use_mirq(0)) - pci_clear_mirq(0, 0); - else if (dev->irq_mode[channel] == 1) - pci_clear_irq(dev->slot, dev->irq_pin); - else - picintc(1 << (14 + channel)); + + switch (dev->irq_mode[channel]) { + case 0: + default: + /* Legacy IRQ mode. */ + if (dev->status & 0x04) + picint(1 << (14 + channel)); + else + picintc(1 << (14 + channel)); + break; + case 1: + /* Native PCI IRQ mode with interrupt pin. */ + if (dev->status & 0x04) + pci_set_irq(dev->slot, dev->irq_pin); + else + pci_clear_irq(dev->slot, dev->irq_pin); + break; + case 2: + case 5: + /* MIRQ 0 or 1. */ + if (dev->status & 0x04) + pci_set_mirq(dev->irq_mode[channel] & 1, 0); + else + pci_clear_mirq(dev->irq_mode[channel] & 1, 0); + break; + case 3: + /* Native PCI IRQ mode with specified interrupt line. */ + if (dev->status & 0x04) + picintlevel(1 << dev->irq_line); + else + picintc(1 << dev->irq_line); + break; + case 4: + /* ALi Aladdin Native PCI INTAJ mode. */ + if (dev->status & 0x04) + pci_set_mirq(channel + 2, dev->irq_level[channel]); + else + pci_clear_mirq(channel + 2, dev->irq_level[channel]); + break; } } @@ -468,10 +487,42 @@ sff_set_irq_line(sff8038i_t *dev, int irq_line) } +void +sff_set_irq_level(sff8038i_t *dev, int channel, int irq_level) +{ + dev->irq_level[channel] = 0; +} + + void sff_set_irq_mode(sff8038i_t *dev, int channel, int irq_mode) { dev->irq_mode[channel] = irq_mode; + + switch (dev->irq_mode[channel]) { + case 0: + default: + /* Legacy IRQ mode. */ + sff_log("[%08X] Setting channel %i to legacy IRQ %i\n", dev, channel, 14 + channel); + break; + case 1: + /* Native PCI IRQ mode with interrupt pin. */ + sff_log("[%08X] Setting channel %i to native PCI INT%c\n", dev, channel, '@' + dev->irq_pin); + break; + case 2: + case 5: + /* MIRQ 0 or 1. */ + sff_log("[%08X] Setting channel %i to PCI MIRQ%i\n", dev, channel, irq_mode & 1); + break; + case 3: + /* Native PCI IRQ mode with specified interrupt line. */ + sff_log("[%08X] Setting channel %i to native PCI IRQ %i\n", dev, channel, dev->irq_line); + break; + case 4: + /* ALi Aladdin Native PCI INTAJ mode. */ + sff_log("[%08X] Setting channel %i to INT%cJ\n", dev, channel, 'A' + channel); + break; + } } @@ -508,9 +559,11 @@ static void ide_set_bus_master(next_id, sff_bus_master_dma, sff_bus_master_set_irq, dev); dev->slot = 7; - dev->irq_mode[0] = dev->irq_mode[1] = 2; + dev->irq_mode[0] = 0; /* Channel 0 goes to IRQ 14. */ + dev->irq_mode[1] = 2; /* Channel 1 goes to MIRQ0. */ dev->irq_pin = PCI_INTA; dev->irq_line = 14; + dev->irq_level[0] = dev->irq_level[1] = 0; next_id++; From d9eb945fafa69b851cc3b4895ae5be2db46009fc Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 20 Aug 2021 17:18:08 +0200 Subject: [PATCH 50/96] Let's do this again. --- src/disk/hdc_ide_sff8038i.c | 99 +++++++++---------------------------- 1 file changed, 24 insertions(+), 75 deletions(-) diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index b5362e6f9..b00b2a66d 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -370,51 +370,34 @@ void sff_bus_master_set_irq(int channel, void *priv) { sff8038i_t *dev = (sff8038i_t *) priv; + uint8_t irq = !!(channel & 0x40); + if (!(dev->status & 0x04) || (channel & 0x40)) { - dev->status &= ~0x04; + dev->status &= ~4; dev->status |= (channel >> 4); } channel &= 0x01; - - switch (dev->irq_mode[channel]) { - case 0: - default: - /* Legacy IRQ mode. */ - if (dev->status & 0x04) - picint(1 << (14 + channel)); - else - picintc(1 << (14 + channel)); - break; - case 1: - /* Native PCI IRQ mode with interrupt pin. */ - if (dev->status & 0x04) - pci_set_irq(dev->slot, dev->irq_pin); - else - pci_clear_irq(dev->slot, dev->irq_pin); - break; - case 2: - case 5: - /* MIRQ 0 or 1. */ - if (dev->status & 0x04) - pci_set_mirq(dev->irq_mode[channel] & 1, 0); - else - pci_clear_mirq(dev->irq_mode[channel] & 1, 0); - break; - case 3: - /* Native PCI IRQ mode with specified interrupt line. */ - if (dev->status & 0x04) - picintlevel(1 << dev->irq_line); - else - picintc(1 << dev->irq_line); - break; - case 4: - /* ALi Aladdin Native PCI INTAJ mode. */ - if (dev->status & 0x04) - pci_set_mirq(channel + 2, dev->irq_level[channel]); - else - pci_clear_mirq(channel + 2, dev->irq_level[channel]); - break; + if (irq) { + sff_log("SFF8038i: Channel %i IRQ raise\n", channel); + if (dev->irq_mode[channel] == 3) + picintlevel(1 << dev->irq_line); + else if ((dev->irq_mode[channel] == 2) && channel && pci_use_mirq(0)) + pci_set_mirq(0, 0); + else if (dev->irq_mode[channel] == 1) + pci_set_irq(dev->slot, dev->irq_pin); + else + picint(1 << (14 + channel)); + } else { + sff_log("SFF8038i: Channel %i IRQ lower\n", channel); + if (dev->irq_mode[channel] == 3) + picintc(1 << dev->irq_line); + else if ((dev->irq_mode[channel] == 2) && channel && pci_use_mirq(0)) + pci_clear_mirq(0, 0); + else if (dev->irq_mode[channel] == 1) + pci_clear_irq(dev->slot, dev->irq_pin); + else + picintc(1 << (14 + channel)); } } @@ -487,42 +470,10 @@ sff_set_irq_line(sff8038i_t *dev, int irq_line) } -void -sff_set_irq_level(sff8038i_t *dev, int channel, int irq_level) -{ - dev->irq_level[channel] = 0; -} - - void sff_set_irq_mode(sff8038i_t *dev, int channel, int irq_mode) { dev->irq_mode[channel] = irq_mode; - - switch (dev->irq_mode[channel]) { - case 0: - default: - /* Legacy IRQ mode. */ - sff_log("[%08X] Setting channel %i to legacy IRQ %i\n", dev, channel, 14 + channel); - break; - case 1: - /* Native PCI IRQ mode with interrupt pin. */ - sff_log("[%08X] Setting channel %i to native PCI INT%c\n", dev, channel, '@' + dev->irq_pin); - break; - case 2: - case 5: - /* MIRQ 0 or 1. */ - sff_log("[%08X] Setting channel %i to PCI MIRQ%i\n", dev, channel, irq_mode & 1); - break; - case 3: - /* Native PCI IRQ mode with specified interrupt line. */ - sff_log("[%08X] Setting channel %i to native PCI IRQ %i\n", dev, channel, dev->irq_line); - break; - case 4: - /* ALi Aladdin Native PCI INTAJ mode. */ - sff_log("[%08X] Setting channel %i to INT%cJ\n", dev, channel, 'A' + channel); - break; - } } @@ -559,11 +510,9 @@ static void ide_set_bus_master(next_id, sff_bus_master_dma, sff_bus_master_set_irq, dev); dev->slot = 7; - dev->irq_mode[0] = 0; /* Channel 0 goes to IRQ 14. */ - dev->irq_mode[1] = 2; /* Channel 1 goes to MIRQ0. */ + dev->irq_mode[0] = dev->irq_mode[1] = 2; dev->irq_pin = PCI_INTA; dev->irq_line = 14; - dev->irq_level[0] = dev->irq_level[1] = 0; next_id++; From 0cebc8669ae081b093c685775b365ac7a26e8648 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 20 Aug 2021 17:20:25 +0200 Subject: [PATCH 51/96] And back. --- src/disk/hdc_ide_sff8038i.c | 97 ++++++++++++++++++++++++++++--------- 1 file changed, 75 insertions(+), 22 deletions(-) diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index b00b2a66d..44d9ad545 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -373,31 +373,50 @@ sff_bus_master_set_irq(int channel, void *priv) uint8_t irq = !!(channel & 0x40); if (!(dev->status & 0x04) || (channel & 0x40)) { - dev->status &= ~4; + dev->status &= ~0x04; dev->status |= (channel >> 4); } channel &= 0x01; - if (irq) { - sff_log("SFF8038i: Channel %i IRQ raise\n", channel); - if (dev->irq_mode[channel] == 3) - picintlevel(1 << dev->irq_line); - else if ((dev->irq_mode[channel] == 2) && channel && pci_use_mirq(0)) - pci_set_mirq(0, 0); - else if (dev->irq_mode[channel] == 1) - pci_set_irq(dev->slot, dev->irq_pin); - else - picint(1 << (14 + channel)); - } else { - sff_log("SFF8038i: Channel %i IRQ lower\n", channel); - if (dev->irq_mode[channel] == 3) - picintc(1 << dev->irq_line); - else if ((dev->irq_mode[channel] == 2) && channel && pci_use_mirq(0)) - pci_clear_mirq(0, 0); - else if (dev->irq_mode[channel] == 1) - pci_clear_irq(dev->slot, dev->irq_pin); - else - picintc(1 << (14 + channel)); + + switch (dev->irq_mode[channel]) { + case 0: + default: + /* Legacy IRQ mode. */ + if (irq) + picint(1 << (14 + channel)); + else + picintc(1 << (14 + channel)); + break; + case 1: + /* Native PCI IRQ mode with interrupt pin. */ + if (irq) + pci_set_irq(dev->slot, dev->irq_pin); + else + pci_clear_irq(dev->slot, dev->irq_pin); + break; + case 2: + case 5: + /* MIRQ 0 or 1. */ + if (irq) + pci_set_mirq(dev->irq_mode[channel] & 1, 0); + else + pci_clear_mirq(dev->irq_mode[channel] & 1, 0); + break; + case 3: + /* Native PCI IRQ mode with specified interrupt line. */ + if (irq) + picintlevel(1 << dev->irq_line); + else + picintc(1 << dev->irq_line); + break; + case 4: + /* ALi Aladdin Native PCI INTAJ mode. */ + if (irq) + pci_set_mirq(channel + 2, dev->irq_level[channel]); + else + pci_clear_mirq(channel + 2, dev->irq_level[channel]); + break; } } @@ -470,10 +489,42 @@ sff_set_irq_line(sff8038i_t *dev, int irq_line) } +void +sff_set_irq_level(sff8038i_t *dev, int channel, int irq_level) +{ + dev->irq_level[channel] = 0; +} + + void sff_set_irq_mode(sff8038i_t *dev, int channel, int irq_mode) { dev->irq_mode[channel] = irq_mode; + + switch (dev->irq_mode[channel]) { + case 0: + default: + /* Legacy IRQ mode. */ + sff_log("[%08X] Setting channel %i to legacy IRQ %i\n", dev, channel, 14 + channel); + break; + case 1: + /* Native PCI IRQ mode with interrupt pin. */ + sff_log("[%08X] Setting channel %i to native PCI INT%c\n", dev, channel, '@' + dev->irq_pin); + break; + case 2: + case 5: + /* MIRQ 0 or 1. */ + sff_log("[%08X] Setting channel %i to PCI MIRQ%i\n", dev, channel, irq_mode & 1); + break; + case 3: + /* Native PCI IRQ mode with specified interrupt line. */ + sff_log("[%08X] Setting channel %i to native PCI IRQ %i\n", dev, channel, dev->irq_line); + break; + case 4: + /* ALi Aladdin Native PCI INTAJ mode. */ + sff_log("[%08X] Setting channel %i to INT%cJ\n", dev, channel, 'A' + channel); + break; + } } @@ -510,9 +561,11 @@ static void ide_set_bus_master(next_id, sff_bus_master_dma, sff_bus_master_set_irq, dev); dev->slot = 7; - dev->irq_mode[0] = dev->irq_mode[1] = 2; + dev->irq_mode[0] = 0; /* Channel 0 goes to IRQ 14. */ + dev->irq_mode[1] = 2; /* Channel 1 goes to MIRQ0. */ dev->irq_pin = PCI_INTA; dev->irq_line = 14; + dev->irq_level[0] = dev->irq_level[1] = 0; next_id++; From 70870be9e25b7f1b27a1d4e0f2ec409aae088c6a Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 20 Aug 2021 17:25:58 +0200 Subject: [PATCH 52/96] CPL is now forced to 0 when switching from real to protected mode. --- src/cpu/x86_ops_mov_ctrl.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/cpu/x86_ops_mov_ctrl.h b/src/cpu/x86_ops_mov_ctrl.h index 16e7aa7fa..17f51b971 100644 --- a/src/cpu/x86_ops_mov_ctrl.h +++ b/src/cpu/x86_ops_mov_ctrl.h @@ -125,6 +125,9 @@ static int opMOV_CRx_r_a16(uint32_t fetchdat) 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; @@ -181,6 +184,9 @@ static int opMOV_CRx_r_a32(uint32_t fetchdat) 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; From f99f6bcf1808a9ef75e320c18378e9ce55e0993c Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 20 Aug 2021 17:28:17 +0200 Subject: [PATCH 53/96] The relocated SMBASE read from the SMM saved state now has bits 24-31 cleared. --- src/cpu/386_common.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index fbb67df1c..77b5ed373 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -592,7 +592,7 @@ smram_restore_state_p5(uint32_t *saved_state) smm_seg_load(&cpu_state.seg_gs); if (SMM_REVISION_ID & SMM_SMBASE_RELOCATION) - smbase = saved_state[SMRAM_FIELD_P5_SMBASE_OFFSET]; + smbase = saved_state[SMRAM_FIELD_P5_SMBASE_OFFSET] & 0x00ffffff; /* Am486/5x86 stuff */ if (!is_pentium) { @@ -1306,6 +1306,11 @@ leave_smm(void) x386_common_log("EAX = %08X, EBX = %08X, ECX = %08X, EDX = %08X, ESI = %08X, EDI = %08X, ESP = %08X, EBP = %08X\n", EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP); x386_common_log("leave_smm()\n"); + + if (cr0 & 1) + pclog("%s mode\n", (cpu_state.eflags & VM_FLAG) ? "V86" : "Protected"); + else + pclog("Real mode\n"); } From 660956a15dfe05bfa89407fae3b62cdc1367b093 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 20 Aug 2021 17:29:41 +0200 Subject: [PATCH 54/96] AMD K6 CPU's are no longer treated as K6 for SMM purposes. --- src/cpu/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 5da0778ab..e29bca7d5 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -381,7 +381,7 @@ cpu_set(void) and the WinChip datasheet claims those are Pentium-compatible as well. AMD Am486DXL/DXL2 also has compatible SMM, or would if not for it's different SMBase*/ is_pentium = (cpu_isintel && (cpu_s->cpu_type >= CPU_i486SX_SLENH) && (cpu_s->cpu_type < CPU_PENTIUMPRO)) || !strcmp(cpu_f->manufacturer, "IDT") || (cpu_s->cpu_type == CPU_Am486DXL); - is_k5 = !strcmp(cpu_f->manufacturer, "AMD") && (cpu_s->cpu_type > CPU_ENH_Am486DX); + is_k5 = !strcmp(cpu_f->manufacturer, "AMD") && (cpu_s->cpu_type > CPU_ENH_Am486DX) && (cpu_s->cpu_type < CPU_K6); is_k6 = (cpu_s->cpu_type >= CPU_K6) && !strcmp(cpu_f->manufacturer, "AMD"); /* The Samuel 2 datasheet claims it's Celeron-compatible. */ is_p6 = (cpu_isintel && (cpu_s->cpu_type >= CPU_PENTIUMPRO)) || !strcmp(cpu_f->manufacturer, "VIA"); From 66cef5b762c5cea738de59226451fee01eac63d9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 20 Aug 2021 17:30:52 +0200 Subject: [PATCH 55/96] Removed excess logging from 386_common.c. --- src/cpu/386_common.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index 77b5ed373..1c5fa8b3e 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -1306,11 +1306,6 @@ leave_smm(void) x386_common_log("EAX = %08X, EBX = %08X, ECX = %08X, EDX = %08X, ESI = %08X, EDI = %08X, ESP = %08X, EBP = %08X\n", EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP); x386_common_log("leave_smm()\n"); - - if (cr0 & 1) - pclog("%s mode\n", (cpu_state.eflags & VM_FLAG) ? "V86" : "Protected"); - else - pclog("Real mode\n"); } From a76fda99d8038a03c78ab9679fc16fcd7c564d37 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 20 Aug 2021 17:50:42 +0200 Subject: [PATCH 56/96] Various Super I/O chip rewrites and fixes (and implemented dual-chip mode for the SMC FDC73C669). --- src/include/86box/sio.h | 1 + src/sio/sio_fdc37c651.c | 344 +++++++++++++++++++++++++++------------- src/sio/sio_fdc37c661.c | 120 ++++++++------ src/sio/sio_fdc37c669.c | 95 +++++++---- src/sio/sio_fdc37c66x.c | 2 +- src/sio/sio_w83977f.c | 28 ++-- 6 files changed, 387 insertions(+), 203 deletions(-) diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index 1786a9569..3b90f72c8 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -21,6 +21,7 @@ extern void vt82c686_sio_write(uint8_t addr, uint8_t val, void *priv); extern const device_t acc3221_device; extern const device_t f82c710_device; extern const device_t fdc37c651_device; +extern const device_t fdc37c651_ide_device; extern const device_t fdc37c661_device; extern const device_t fdc37c663_device; extern const device_t fdc37c663_ide_device; diff --git a/src/sio/sio_fdc37c651.c b/src/sio/sio_fdc37c651.c index 2bfd3fd93..a19460d4c 100644 --- a/src/sio/sio_fdc37c651.c +++ b/src/sio/sio_fdc37c651.c @@ -6,10 +6,11 @@ * * This file is part of the 86Box distribution. * - * Emulation of the SMC FDC37C651 Super I/O + * Implementation of the SMC FDC37C651 Super I/O Chip. * - * Authors: Tiseno100 - * Copyright 2020 Tiseno100 + * Authors: Miran Grca, + * + * Copyright 2021 Miran Grca. */ #include #include @@ -30,15 +31,17 @@ #include <86box/fdc.h> #include <86box/sio.h> + #ifdef ENABLE_FDC37C651_LOG int fdc37c651_do_log = ENABLE_FDC37C651_LOG; + + static void fdc37c651_log(const char *fmt, ...) { va_list ap; - if (fdc37c651_do_log) - { + if (fdc37c651_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); @@ -48,143 +51,264 @@ fdc37c651_log(const char *fmt, ...) #define fdc37c651_log(fmt, ...) #endif -typedef struct -{ - uint8_t configuration_select, regs[3]; - uint16_t com3, com4; - fdc_t *fdc_controller; +typedef struct { + uint8_t tries, has_ide, + regs[16]; + int cur_reg, + com3_addr, com4_addr; + fdc_t *fdc; serial_t *uart[2]; - } fdc37c651_t; + static void -fdc37c651_write(uint16_t addr, uint8_t val, void *priv) +set_com34_addr(fdc37c651_t *dev) { - fdc37c651_t *dev = (fdc37c651_t *)priv; - - switch (addr) - { - case 0x3f0: - dev->configuration_select = val; - break; - case 0x3f1: - switch (dev->configuration_select) - { - case 0: /* CR0 */ - dev->regs[dev->configuration_select] = val; - ide_pri_disable(); - fdc_remove(dev->fdc_controller); - - if (val & 1) /* Enable IDE */ - ide_pri_enable(); - - if (val & 0x10) /* Enable FDC */ - fdc_set_base(dev->fdc_controller, 0x3f0); - - break; - - case 1: /* CR1 */ - dev->regs[dev->configuration_select] = val; - lpt1_remove(); - - if ((val & 3) != 0) /* Program LPT if not Disabled */ - lpt1_init((val & 2) ? ((val & 1) ? 0x278 : 0x378) : 0x3f8); - - switch ((val >> 4) & 3) /* COM3 & 4 Select*/ - { - case 0: - dev->com3 = 0x338; - dev->com4 = 0x238; - break; - case 1: - dev->com3 = 0x3e8; - dev->com4 = 0x2e8; - break; - case 2: - dev->com3 = 0x2e8; - dev->com4 = 0x2e0; - break; - case 3: - dev->com3 = 0x220; - dev->com4 = 0x228; - break; - } - - break; - - case 2: /* CR2 */ - dev->regs[dev->configuration_select] = val; - serial_remove(dev->uart[0]); - serial_remove(dev->uart[1]); - - if (val & 4) - serial_setup(dev->uart[0], (val & 2) ? ((val & 1) ? dev->com4 : dev->com3) : ((val & 1) ? 0x2f8 : 0x3f8), 4); - - if (val & 0x40) - serial_setup(dev->uart[1], (val & 0x20) ? ((val & 0x10) ? dev->com4 : dev->com3) : ((val & 0x10) ? 0x2f8 : 0x3f8), 3); - - break; - } - break; + switch (dev->regs[1] & 0x60) { + case 0x00: + dev->com3_addr = 0x338; + dev->com4_addr = 0x238; + break; + case 0x20: + dev->com3_addr = 0x3e8; + dev->com4_addr = 0x2e8; + break; + case 0x40: + dev->com3_addr = 0x3e8; + dev->com4_addr = 0x2e0; + break; + case 0x60: + dev->com3_addr = 0x220; + dev->com4_addr = 0x228; + break; } } -static uint8_t -fdc37c651_read(uint16_t addr, void *priv) -{ - fdc37c651_t *dev = (fdc37c651_t *)priv; - return dev->regs[dev->configuration_select]; +static void +set_serial_addr(fdc37c651_t *dev, int port) +{ + uint8_t shift = (port << 2); + + serial_remove(dev->uart[port]); + if (dev->regs[2] & (4 << shift)) { + switch ((dev->regs[2] >> shift) & 3) { + case 0: + serial_setup(dev->uart[port], SERIAL1_ADDR, SERIAL1_IRQ); + break; + case 1: + serial_setup(dev->uart[port], SERIAL2_ADDR, SERIAL2_IRQ); + break; + case 2: + serial_setup(dev->uart[port], dev->com3_addr, 4); + break; + case 3: + serial_setup(dev->uart[port], dev->com4_addr, 3); + break; + } + } } + +static void +lpt1_handler(fdc37c651_t *dev) +{ + lpt1_remove(); + switch (dev->regs[1] & 3) { + case 1: + lpt1_init(0x3bc); + lpt1_irq(7); + break; + case 2: + lpt1_init(0x378); + lpt1_irq(7 /*5*/); + break; + case 3: + lpt1_init(0x278); + lpt1_irq(7 /*5*/); + break; + } +} + + +static void +fdc_handler(fdc37c651_t *dev) +{ + fdc_remove(dev->fdc); + if (dev->regs[0] & 0x10) + fdc_set_base(dev->fdc, 0x03f0); +} + + + +static void +ide_handler(fdc37c651_t *dev) +{ + /* TODO: Make an ide_disable(channel) and ide_enable(channel) so we can simplify this. */ + if (dev->has_ide == 2) { + ide_sec_disable(); + ide_set_base(1, 0x1f0); + ide_set_side(1, 0x3f6); + if (dev->regs[0x00] & 0x01) + ide_sec_enable(); + } else if (dev->has_ide == 1) { + ide_pri_disable(); + ide_set_base(0, 0x1f0); + ide_set_side(0, 0x3f6); + if (dev->regs[0x00] & 0x01) + ide_pri_enable(); + } +} + + +static void +fdc37c651_write(uint16_t port, uint8_t val, void *priv) +{ + fdc37c651_t *dev = (fdc37c651_t *) priv; + uint8_t valxor = 0; + + if (dev->tries == 2) { + if (port == 0x3f0) { + if (val == 0xaa) + dev->tries = 0; + else + dev->cur_reg = val; + } else { + if (dev->cur_reg > 15) + return; + + valxor = val ^ dev->regs[dev->cur_reg]; + dev->regs[dev->cur_reg] = val; + + switch(dev->cur_reg) { + case 0: + if (dev->has_ide && (valxor & 0x01)) + ide_handler(dev); + if (valxor & 0x10) + fdc_handler(dev); + break; + case 1: + if (valxor & 3) + lpt1_handler(dev); + if (valxor & 0x60) { + set_com34_addr(dev); + set_serial_addr(dev, 0); + set_serial_addr(dev, 1); + } + break; + case 2: + if (valxor & 7) + set_serial_addr(dev, 0); + if (valxor & 0x70) + set_serial_addr(dev, 1); + break; + } + } + } else if ((port == 0x3f0) && (val == 0x55)) + dev->tries++; +} + + +static uint8_t +fdc37c651_read(uint16_t port, void *priv) +{ + fdc37c651_t *dev = (fdc37c651_t *) priv; + uint8_t ret = 0x00; + + if (dev->tries == 2) { + if (port == 0x3f1) + ret = dev->regs[dev->cur_reg]; + } + + return ret; +} + + +static void +fdc37c651_reset(fdc37c651_t *dev) +{ + dev->com3_addr = 0x338; + dev->com4_addr = 0x238; + + serial_remove(dev->uart[0]); + serial_setup(dev->uart[0], SERIAL1_ADDR, SERIAL1_IRQ); + + serial_remove(dev->uart[1]); + serial_setup(dev->uart[1], SERIAL2_ADDR, SERIAL2_IRQ); + + lpt1_remove(); + lpt1_init(0x378); + + fdc_reset(dev->fdc); + fdc_remove(dev->fdc); + + dev->tries = 0; + memset(dev->regs, 0, 16); + + dev->regs[0x0] = 0x3f; + dev->regs[0x1] = 0x9f; + dev->regs[0x2] = 0xdc; + + set_serial_addr(dev, 0); + set_serial_addr(dev, 1); + + lpt1_handler(dev); + + fdc_handler(dev); + + if (dev->has_ide) + ide_handler(dev); +} + + static void fdc37c651_close(void *priv) { - fdc37c651_t *dev = (fdc37c651_t *)priv; + fdc37c651_t *dev = (fdc37c651_t *) priv; + free(dev); } + static void * fdc37c651_init(const device_t *info) { - fdc37c651_t *dev = (fdc37c651_t *)malloc(sizeof(fdc37c651_t)); + fdc37c651_t *dev = (fdc37c651_t *) malloc(sizeof(fdc37c651_t)); memset(dev, 0, sizeof(fdc37c651_t)); - dev->fdc_controller = device_add(&fdc_at_smc_device); + dev->fdc = device_add(&fdc_at_smc_device); + dev->uart[0] = device_add_inst(&ns16450_device, 1); dev->uart[1] = device_add_inst(&ns16450_device, 2); - device_add(&ide_isa_device); - /* Program Defaults */ - dev->regs[0] = 0x3f; - dev->regs[1] = 0x9f; - dev->regs[2] = 0xdc; - ide_pri_disable(); - fdc_remove(dev->fdc_controller); - lpt1_remove(); - serial_remove(dev->uart[0]); - serial_remove(dev->uart[1]); + dev->has_ide = (info->local >> 8) & 0xff; - ide_pri_enable(); - fdc_set_base(dev->fdc_controller, 0x3f0); - lpt1_init(0x278); - serial_setup(dev->uart[0], 0x2f8, 4); - serial_setup(dev->uart[1], 0x3f8, 3); + io_sethandler(0x03f0, 0x0002, + fdc37c651_read, NULL, NULL, fdc37c651_write, NULL, NULL, dev); - io_sethandler(0x03f0, 2, fdc37c651_read, NULL, NULL, fdc37c651_write, NULL, NULL, dev); + fdc37c651_reset(dev); return dev; } + +/* The three appear to differ only in the chip ID, if I + understood their datasheets correctly. */ const device_t fdc37c651_device = { - "SMC FDC37C651", + "SMC FDC37C651 Super I/O", 0, 0, - fdc37c651_init, - fdc37c651_close, - NULL, - {NULL}, - NULL, - NULL, - NULL}; + fdc37c651_init, fdc37c651_close, NULL, + { NULL }, NULL, NULL, + NULL +}; + +const device_t fdc37c651_ide_device = { + "SMC FDC37C651 Super I/O (With IDE)", + 0, + 0x100, + fdc37c651_init, fdc37c651_close, NULL, + { NULL }, NULL, NULL, + NULL +}; diff --git a/src/sio/sio_fdc37c661.c b/src/sio/sio_fdc37c661.c index 159a68d47..8a17053a6 100644 --- a/src/sio/sio_fdc37c661.c +++ b/src/sio/sio_fdc37c661.c @@ -6,8 +6,7 @@ * * This file is part of the 86Box distribution. * - * Implementation of the SMC FDC37C661 Super - * I/O Chip. + * Implementation of the SMC FDC37C661 Super I/O Chip. * * * @@ -16,7 +15,6 @@ * * Copyright 2008-2020 Sarah Walker. * Copyright 2016-2020 Miran Grca. - * Copyright 2020 plant/nerd73. */ #include #include @@ -38,8 +36,8 @@ typedef struct { - uint8_t lock[2], - regs[4]; + uint8_t chip_id, tries, + has_ide, regs[16]; int cur_reg, com3_addr, com4_addr; fdc_t *fdc; @@ -47,19 +45,6 @@ typedef struct { } fdc37c661_t; -static void -write_lock(fdc37c661_t *dev, uint8_t val) -{ - if (val == 0x55 && dev->lock[1] == 0x55) - fdc_3f1_enable(dev->fdc, 0); - if ((dev->lock[0] == 0x55) && (dev->lock[1] == 0x55) && (val != 0x55)) - fdc_3f1_enable(dev->fdc, 1); - - dev->lock[0] = dev->lock[1]; - dev->lock[1] = val; -} - - static void set_com34_addr(fdc37c661_t *dev) { @@ -87,10 +72,11 @@ set_com34_addr(fdc37c661_t *dev) static void set_serial_addr(fdc37c661_t *dev, int port) { - uint8_t shift = (port << 4); + uint8_t shift = (port << 2); + serial_remove(dev->uart[port]); if (dev->regs[2] & (4 << shift)) { - switch (dev->regs[2] & (3 << shift)) { + switch ((dev->regs[2] >> shift) & 3) { case 0: serial_setup(dev->uart[port], SERIAL1_ADDR, SERIAL1_IRQ); break; @@ -119,11 +105,11 @@ lpt1_handler(fdc37c661_t *dev) break; case 2: lpt1_init(0x378); - lpt1_irq(5); + lpt1_irq(7 /*5*/); break; case 3: lpt1_init(0x278); - lpt1_irq(5); + lpt1_irq(7 /*5*/); break; } } @@ -134,7 +120,28 @@ fdc_handler(fdc37c661_t *dev) { fdc_remove(dev->fdc); if (dev->regs[0] & 0x10) - fdc_set_base(dev->fdc, 0x03f0); + fdc_set_base(dev->fdc, 0x03f0); +} + + + +static void +ide_handler(fdc37c661_t *dev) +{ + /* TODO: Make an ide_disable(channel) and ide_enable(channel) so we can simplify this. */ + if (dev->has_ide == 2) { + ide_sec_disable(); + ide_set_base(1, 0x1f0); + ide_set_side(1, 0x3f6); + if (dev->regs[0x00] & 0x01) + ide_sec_enable(); + } else if (dev->has_ide == 1) { + ide_pri_disable(); + ide_set_base(0, 0x1f0); + ide_set_side(0, 0x3f6); + if (dev->regs[0x00] & 0x01) + ide_pri_enable(); + } } @@ -144,14 +151,14 @@ fdc37c661_write(uint16_t port, uint8_t val, void *priv) fdc37c661_t *dev = (fdc37c661_t *) priv; uint8_t valxor = 0; - if ((dev->lock[0] == 0x55) && (dev->lock[1] == 0x55)) { + if (dev->tries == 2) { if (port == 0x3f0) { if (val == 0xaa) - write_lock(dev, val); + dev->tries = 0; else dev->cur_reg = val; } else { - if (dev->cur_reg > 4) + if (dev->cur_reg > 15) return; valxor = val ^ dev->regs[dev->cur_reg]; @@ -159,6 +166,8 @@ fdc37c661_write(uint16_t port, uint8_t val, void *priv) switch(dev->cur_reg) { case 0: + if (dev->has_ide && (valxor & 0x01)) + ide_handler(dev); if (valxor & 0x10) fdc_handler(dev); break; @@ -166,33 +175,21 @@ fdc37c661_write(uint16_t port, uint8_t val, void *priv) if (valxor & 3) lpt1_handler(dev); if (valxor & 0x60) { - serial_remove(dev->uart[0]); - serial_remove(dev->uart[1]); set_com34_addr(dev); set_serial_addr(dev, 0); set_serial_addr(dev, 1); } break; case 2: - if (valxor & 7) { - serial_remove(dev->uart[0]); + if (valxor & 7) set_serial_addr(dev, 0); - } - if (valxor & 0x70) { - serial_remove(dev->uart[1]); + if (valxor & 0x70) set_serial_addr(dev, 1); - } - break; - case 3: - if (valxor & 4) - fdc_update_enh_mode(dev->fdc, (dev->regs[3] & 4) ? 1 : 0); break; } } - } else { - if (port == 0x3f0) - write_lock(dev, val); - } + } else if ((port == 0x3f0) && (val == 0x55)) + dev->tries++; } @@ -200,9 +197,9 @@ static uint8_t fdc37c661_read(uint16_t port, void *priv) { fdc37c661_t *dev = (fdc37c661_t *) priv; - uint8_t ret = 0xff; + uint8_t ret = 0x00; - if ((dev->lock[0] == 0x55) && (dev->lock[1] == 0x55)) { + if (dev->tries == 2) { if (port == 0x3f1) ret = dev->regs[dev->cur_reg]; } @@ -227,14 +224,25 @@ fdc37c661_reset(fdc37c661_t *dev) lpt1_init(0x378); fdc_reset(dev->fdc); + fdc_remove(dev->fdc); - memset(dev->lock, 0, 2); + dev->tries = 0; memset(dev->regs, 0, 16); dev->regs[0x0] = 0x3f; dev->regs[0x1] = 0x9f; dev->regs[0x2] = 0xdc; dev->regs[0x3] = 0x78; + + set_serial_addr(dev, 0); + set_serial_addr(dev, 1); + + lpt1_handler(dev); + + fdc_handler(dev); + + if (dev->has_ide) + ide_handler(dev); } @@ -255,23 +263,37 @@ fdc37c661_init(const device_t *info) 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->uart[0] = device_add_inst(&ns16450_device, 1); + dev->uart[1] = device_add_inst(&ns16450_device, 2); + + dev->chip_id = info->local & 0xff; + dev->has_ide = (info->local >> 8) & 0xff; io_sethandler(0x03f0, 0x0002, fdc37c661_read, NULL, NULL, fdc37c661_write, NULL, NULL, dev); fdc37c661_reset(dev); - + return dev; } + +/* The three appear to differ only in the chip ID, if I + understood their datasheets correctly. */ const device_t fdc37c661_device = { "SMC FDC37C661 Super I/O", 0, - 0, + 0x00, fdc37c661_init, fdc37c661_close, NULL, { NULL }, NULL, NULL, NULL }; +const device_t fdc37c661_ide_device = { + "SMC FDC37C661 Super I/O (With IDE)", + 0, + 0x100, + fdc37c661_init, fdc37c661_close, NULL, + { NULL }, NULL, NULL, + NULL +}; diff --git a/src/sio/sio_fdc37c669.c b/src/sio/sio_fdc37c669.c index b2d76814e..d223cf0df 100644 --- a/src/sio/sio_fdc37c669.c +++ b/src/sio/sio_fdc37c669.c @@ -33,7 +33,7 @@ typedef struct { - uint8_t tries, + uint8_t id, tries, regs[42]; int locked, rw_locked, cur_reg; @@ -42,6 +42,9 @@ typedef struct { } fdc37c669_t; +static int next_id = 0; + + static uint16_t make_port(fdc37c669_t *dev, uint8_t reg) { @@ -114,7 +117,7 @@ fdc37c669_write(uint16_t port, uint8_t val, void *priv) switch(dev->cur_reg) { case 0: - if (valxor & 8) { + if (!dev->id && (valxor & 8)) { fdc_remove(dev->fdc); if ((dev->regs[0] & 8) && (dev->regs[0x20] & 0xc0)) fdc_set_base(dev->fdc, make_port(dev, 0x20)); @@ -122,9 +125,15 @@ fdc37c669_write(uint16_t port, uint8_t val, void *priv) break; case 1: if (valxor & 4) { - lpt1_remove(); - if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40)) - lpt1_init(make_port(dev, 0x23)); + if (dev->id) { + lpt2_remove(); + if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40)) + lpt2_init(make_port(dev, 0x23)); + } else { + lpt1_remove(); + if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40)) + lpt1_init(make_port(dev, 0x23)); + } } if (valxor & 7) dev->rw_locked = (val & 8) ? 0 : 1; @@ -142,23 +151,23 @@ fdc37c669_write(uint16_t port, uint8_t val, void *priv) } break; case 3: - if (valxor & 2) + if (!dev->id && (valxor & 2)) fdc_update_enh_mode(dev->fdc, (val & 2) ? 1 : 0); break; case 5: - if (valxor & 0x18) + if (!dev->id && (valxor & 0x18)) fdc_update_densel_force(dev->fdc, (val & 0x18) >> 3); - if (valxor & 0x20) + if (!dev->id && (valxor & 0x20)) fdc_set_swap(dev->fdc, (val & 0x20) >> 5); break; case 0xB: - if (valxor & 3) + if (!dev->id && (valxor & 3)) fdc_update_rwc(dev->fdc, 0, val & 3); - if (valxor & 0xC) + if (!dev->id && (valxor & 0xC)) fdc_update_rwc(dev->fdc, 1, (val & 0xC) >> 2); break; case 0x20: - if (valxor & 0xfc) { + if (!dev->id && (valxor & 0xfc)) { fdc_remove(dev->fdc); if ((dev->regs[0] & 8) && (dev->regs[0x20] & 0xc0)) fdc_set_base(dev->fdc, make_port(dev, 0x20)); @@ -166,9 +175,15 @@ fdc37c669_write(uint16_t port, uint8_t val, void *priv) break; case 0x23: if (valxor) { - lpt1_remove(); - if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40)) - lpt1_init(make_port(dev, 0x23)); + if (dev->id) { + lpt2_remove(); + if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40)) + lpt2_init(make_port(dev, 0x23)); + } else { + lpt1_remove(); + if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40)) + lpt1_init(make_port(dev, 0x23)); + } } break; case 0x24: @@ -186,8 +201,12 @@ fdc37c669_write(uint16_t port, uint8_t val, void *priv) } break; case 0x27: - if (valxor & 0xf) - lpt1_irq(val & 0xf); + if (valxor & 0xf) { + if (dev->id) + lpt2_irq(val & 0xf); + else + lpt1_irq(val & 0xf); + } break; case 0x28: if (valxor & 0xf) { @@ -226,17 +245,12 @@ fdc37c669_read(uint16_t port, void *priv) static void fdc37c669_reset(fdc37c669_t *dev) { - fdc_reset(dev->fdc); - serial_remove(dev->uart[0]); serial_setup(dev->uart[0], SERIAL1_ADDR, SERIAL1_IRQ); serial_remove(dev->uart[1]); serial_setup(dev->uart[1], SERIAL2_ADDR, SERIAL2_IRQ); - lpt1_remove(); - lpt1_init(0x378); - memset(dev->regs, 0, 42); dev->regs[0x00] = 0x28; dev->regs[0x01] = 0x9c; @@ -249,11 +263,27 @@ fdc37c669_reset(fdc37c669_t *dev) dev->regs[0x20] = (0x3f0 >> 2) & 0xfc; dev->regs[0x21] = (0x1f0 >> 2) & 0xfc; dev->regs[0x22] = ((0x3f6 >> 2) & 0xfc) | 1; - dev->regs[0x23] = (0x378 >> 2); - dev->regs[0x24] = (0x3f8 >> 2) & 0xfe; - dev->regs[0x25] = (0x2f8 >> 2) & 0xfe; + if (dev->id == 1) { + dev->regs[0x23] = (0x278 >> 2); + + lpt2_remove(); + lpt2_init(0x278); + + dev->regs[0x24] = (SERIAL3_ADDR >> 2) & 0xfe; + dev->regs[0x25] = (SERIAL4_ADDR >> 2) & 0xfe; + } else { + fdc_reset(dev->fdc); + + lpt1_remove(); + lpt1_init(0x378); + + dev->regs[0x23] = (0x378 >> 2); + + dev->regs[0x24] = (SERIAL1_ADDR >> 2) & 0xfe; + dev->regs[0x25] = (SERIAL2_ADDR >> 2) & 0xfe; + } dev->regs[0x26] = (2 << 4) | 3; - dev->regs[0x27] = (6 << 4) | 7; + dev->regs[0x27] = (6 << 4) | (dev->id ? 5 : 7); dev->regs[0x28] = (4 << 4) | 3; dev->locked = 0; @@ -266,6 +296,8 @@ fdc37c669_close(void *priv) { fdc37c669_t *dev = (fdc37c669_t *) priv; + next_id = 0; + free(dev); } @@ -276,16 +308,21 @@ fdc37c669_init(const device_t *info) fdc37c669_t *dev = (fdc37c669_t *) malloc(sizeof(fdc37c669_t)); memset(dev, 0, sizeof(fdc37c669_t)); - dev->fdc = device_add(&fdc_at_smc_device); + dev->id = next_id; - dev->uart[0] = device_add_inst(&ns16550_device, 1); - dev->uart[1] = device_add_inst(&ns16550_device, 2); + if (next_id != 1) + dev->fdc = device_add(&fdc_at_smc_device); - io_sethandler(info->local ? 0x370 : 0x3f0, 0x0002, + dev->uart[0] = device_add_inst(&ns16550_device, (next_id << 1) + 1); + dev->uart[1] = device_add_inst(&ns16550_device, (next_id << 1) + 2); + + io_sethandler(info->local ? 0x370 : (next_id ? 0x370 : 0x3f0), 0x0002, fdc37c669_read, NULL, NULL, fdc37c669_write, NULL, NULL, dev); fdc37c669_reset(dev); + next_id++; + return dev; } diff --git a/src/sio/sio_fdc37c66x.c b/src/sio/sio_fdc37c66x.c index 812bbf91b..ce8776944 100644 --- a/src/sio/sio_fdc37c66x.c +++ b/src/sio/sio_fdc37c66x.c @@ -256,7 +256,7 @@ fdc37c66x_reset(fdc37c66x_t *dev) dev->tries = 0; memset(dev->regs, 0, 16); - dev->regs[0x0] = 0x2a; + dev->regs[0x0] = 0x3a; dev->regs[0x1] = 0x9f; dev->regs[0x2] = 0xdc; dev->regs[0x3] = 0x78; diff --git a/src/sio/sio_w83977f.c b/src/sio/sio_w83977f.c index dc3f1c012..46a75ac9e 100644 --- a/src/sio/sio_w83977f.c +++ b/src/sio/sio_w83977f.c @@ -268,11 +268,11 @@ w83977f_write(uint16_t port, uint8_t val, void *priv) if (dev->id == 1) break; - if (valxor & 0x20) + if (!dev->id && (valxor & 0x20)) fdc_update_drv2en(dev->fdc, (val & 0x20) ? 0 : 1); - if (valxor & 0x10) + if (!dev->id && (valxor & 0x10)) fdc_set_swap(dev->fdc, (val & 0x10) ? 1 : 0); - if (valxor & 0x01) + if (!dev->id && (valxor & 0x01)) fdc_update_enh_mode(dev->fdc, (val & 0x01) ? 1 : 0); break; case 0x01: @@ -291,13 +291,13 @@ w83977f_write(uint16_t port, uint8_t val, void *priv) if (dev->id == 1) break; - if (valxor & 0xc0) + if (!dev->id && (valxor & 0xc0)) fdc_update_boot_drive(dev->fdc, (val & 0xc0) >> 6); - if (valxor & 0x0c) + if (!dev->id && (valxor & 0x0c)) fdc_update_densel_force(dev->fdc, (val & 0x0c) >> 2); - if (valxor & 0x02) + if (!dev->id && (valxor & 0x02)) fdc_set_diswr(dev->fdc, (val & 0x02) ? 1 : 0); - if (valxor & 0x01) + if (!dev->id && (valxor & 0x01)) fdc_set_swwp(dev->fdc, (val & 0x01) ? 1 : 0); break; } @@ -308,13 +308,13 @@ w83977f_write(uint16_t port, uint8_t val, void *priv) if (dev->id == 1) break; - if (valxor & 0xc0) + if (!dev->id && (valxor & 0xc0)) fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6); - if (valxor & 0x30) + if (!dev->id && (valxor & 0x30)) fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4); - if (valxor & 0x0c) + if (!dev->id && (valxor & 0x0c)) fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2); - if (valxor & 0x03) + if (!dev->id && (valxor & 0x03)) fdc_update_rwc(dev->fdc, 0, val & 0x03); break; } @@ -325,7 +325,7 @@ w83977f_write(uint16_t port, uint8_t val, void *priv) if (dev->id == 1) break; - if (valxor & 0x18) + if (!dev->id && (valxor & 0x18)) fdc_update_drvrate(dev->fdc, dev->cur_reg & 0x03, (val & 0x18) >> 3); break; } @@ -347,7 +347,7 @@ w83977f_read(uint16_t port, void *priv) ret = dev->cur_reg; else { if (!dev->rw_locked) { - if ((dev->cur_reg == 0xf2) && (ld == 0x00)) + if (!dev->id && ((dev->cur_reg == 0xf2) && (ld == 0x00))) ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6)); else if (dev->cur_reg >= 0x30) ret = dev->dev_regs[ld][dev->cur_reg - 0x30]; @@ -506,7 +506,7 @@ w83977f_reset(w83977f_t *dev) dev->dev_regs[10][0xc0] = 0x8f; } - if (next_id == 1) { + if (dev->id == 1) { serial_setup(dev->uart[0], SERIAL3_ADDR, SERIAL3_IRQ); serial_setup(dev->uart[1], SERIAL4_ADDR, SERIAL4_IRQ); } else { From 3e7057d458cd818dad6af24c98ebd1e09a489282 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 20 Aug 2021 19:18:40 +0200 Subject: [PATCH 57/96] Changes to lpt.h. --- src/include/86box/lpt.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/include/86box/lpt.h b/src/include/86box/lpt.h index 7fecd4ce7..109de58ba 100644 --- a/src/include/86box/lpt.h +++ b/src/include/86box/lpt.h @@ -21,15 +21,15 @@ extern void lpt_port_irq(int i, uint8_t irq); extern void lpt_port_remove(int i); extern void lpt1_remove_ams(void); -#define lpt1_init(a) lpt_port_init(0, a); -#define lpt1_irq(a) lpt_port_irq(0, a); -#define lpt1_remove() lpt_port_remove(0); -#define lpt2_init(a) lpt_port_init(1, a); -#define lpt2_irq(a) lpt_port_irq(1, a); -#define lpt2_remove() lpt_port_remove(1); -#define lpt3_init(a) lpt_port_init(2, a); -#define lpt3_irq(a) lpt_port_irq(2, a); -#define lpt3_remove() lpt_port_remove(2); +#define lpt1_init(a) lpt_port_init(0, a) +#define lpt1_irq(a) lpt_port_irq(0, a) +#define lpt1_remove() lpt_port_remove(0) +#define lpt2_init(a) lpt_port_init(1, a) +#define lpt2_irq(a) lpt_port_irq(1, a) +#define lpt2_remove() lpt_port_remove(1) +#define lpt3_init(a) lpt_port_init(2, a) +#define lpt3_irq(a) lpt_port_irq(2, a) +#define lpt3_remove() lpt_port_remove(2) void lpt_devices_init(void); From 67367798a7ccc06647994eb26230a7d3f58f17b8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 21 Aug 2021 18:19:10 +0200 Subject: [PATCH 58/96] Merged various SMC FDC67C6xx Super I/O chips into one file, re-added the UMC88xx 486 chipsets (and four machines for it) based on work by tiseno100 and my own work, various other fixes, and added quite a few machines (including the AOpen AP5VM which now works), also added the remaining ALi M6117 machine (Protech SBC with Award BIOS), and made the Intel Advanced/ATX's on-board S3 Trio64V+ work, as well as the on-board S3 Trio64/V2 of the two Compaq Presarios. --- src/chipset/CMakeLists.txt | 4 +- src/chipset/intel_piix.c | 22 ++ src/chipset/sis_85c50x.c | 3 +- src/chipset/umc_8886.c | 219 ++++++++----- src/chipset/umc_8890.c | 180 ----------- src/chipset/umc_hb4.c | 272 +++++++++------- src/device/keyboard_at.c | 9 +- src/include/86box/chipset.h | 5 + src/include/86box/machine.h | 17 + src/include/86box/pci.h | 2 + src/include/86box/video.h | 3 + src/io.c | 6 +- src/machine/m_at_286_386sx.c | 54 +++- src/machine/m_at_386dx_486.c | 164 +++++++++- src/machine/m_at_compaq.c | 4 +- src/machine/m_at_slot1.c | 7 +- src/machine/m_at_socket4.c | 65 ++++ src/machine/m_at_socket7.c | 64 +++- src/machine/m_at_socket7_3v.c | 10 + src/machine/m_at_sockets7.c | 41 +++ src/machine/machine.c | 4 + src/machine/machine_table.c | 37 ++- src/pci.c | 15 +- src/port_92.c | 17 +- src/sio/CMakeLists.txt | 4 +- src/sio/sio_fdc37c651.c | 314 ------------------- src/sio/sio_fdc37c661.c | 299 ------------------ src/sio/{sio_fdc37c66x.c => sio_fdc37c6xx.c} | 130 ++++++-- src/video/vid_s3.c | 31 +- src/video/vid_table.c | 44 ++- src/video/vid_tgui9440.c | 118 ++++--- src/win/Makefile.mingw | 7 +- 32 files changed, 1030 insertions(+), 1141 deletions(-) delete mode 100644 src/chipset/umc_8890.c delete mode 100644 src/sio/sio_fdc37c651.c delete mode 100644 src/sio/sio_fdc37c661.c rename src/sio/{sio_fdc37c66x.c => sio_fdc37c6xx.c} (71%) diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index c015e900d..4e46e0db4 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -18,8 +18,8 @@ add_library(chipset OBJECT acc2168.c cs8230.c ali1429.c ali1489.c ali1531.c ali1 intel_4x0.c intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c opti495.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 sis_85c310.c - sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c stpc.c via_apollo.c via_pipc.c vl82c480.c - wd76c10.c) + sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c stpc.c umc_8886.c umc_hb4.c via_apollo.c + via_pipc.c vl82c480.c wd76c10.c) if(I450KX) target_sources(chipset PRIVATE intel_i450kx.c) diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index f4c9bcb68..a694da235 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -1234,6 +1234,17 @@ piix_reset(void *p) piix_write(3, 0x91, 0x00, p); piix_write(3, 0xd2, 0x00, p); } + + sff_set_irq_mode(dev->bm[0], 0, 0); + sff_set_irq_mode(dev->bm[1], 0, 0); + + if (dev->type >= 4) { + sff_set_irq_mode(dev->bm[0], 1, 0); + sff_set_irq_mode(dev->bm[1], 1, 0); + } else { + sff_set_irq_mode(dev->bm[0], 1, 2); + sff_set_irq_mode(dev->bm[1], 1, 2); + } } @@ -1286,6 +1297,17 @@ static void ide_board_set_force_ata3(1, 1); } + sff_set_irq_mode(dev->bm[0], 0, 0); + sff_set_irq_mode(dev->bm[1], 0, 0); + + if (dev->type >= 4) { + sff_set_irq_mode(dev->bm[0], 1, 0); + sff_set_irq_mode(dev->bm[1], 1, 0); + } else { + sff_set_irq_mode(dev->bm[0], 1, 2); + sff_set_irq_mode(dev->bm[1], 1, 2); + } + if (dev->type >= 3) dev->usb = device_add(&usb_device); diff --git a/src/chipset/sis_85c50x.c b/src/chipset/sis_85c50x.c index bbc8a8ec5..c01690064 100644 --- a/src/chipset/sis_85c50x.c +++ b/src/chipset/sis_85c50x.c @@ -107,8 +107,7 @@ sis_85c50x_smm_recalc(sis_85c50x_t *dev) switch ((dev->pci_conf[0x65] & 0xe0) >> 5) { case 0x00: - if (!(dev->pci_conf[0x54] & 0xc0)) - smram_enable(dev->smram, 0xe0000, 0xe0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1); + smram_enable(dev->smram, 0xe0000, 0xe0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1); break; case 0x01: smram_enable(dev->smram, 0xb0000, ram_base, 0x10000, (dev->pci_conf[0x65] & 0x10), 1); diff --git a/src/chipset/umc_8886.c b/src/chipset/umc_8886.c index ca492a0b8..b3e721e9f 100644 --- a/src/chipset/umc_8886.c +++ b/src/chipset/umc_8886.c @@ -16,10 +16,11 @@ * Copyright 2021 Tiseno100. */ -/* UMC 8886 Configuration Registers +/* + UMC 8886xx Configuration Registers - TODO: - - More Appropriate Bitmasking(If it's even possible) + Note: PMU functionality is quite basic. There may be Enable/Disable bits, IRQ/SMI picks and it also + required for 386_common.c to get patched in order to function properly. Warning: Register documentation may be inaccurate! @@ -35,10 +36,8 @@ Bits 3-0 PCI IRQ for INTC Function 0 Register 46: - Bit 7: Replace SMI request for non-SMM CPU's (1: IRQ15/0: IRQ10) - - Function 0 Register 51: - Bit 2: VGA Power Down (0: Standard/1: VESA DPMS) + Bit 7: PMU Trigger(1: By IRQ/0: By SMI) + Bit 6: IRQ SMI Request (1: IRQ 10) (Supposedly 0 according to Phoenix is IRQ 15 but doesn't seem to make sense) Function 0 Register 56: Bit 1-0 ISA Bus Speed @@ -46,10 +45,14 @@ 0 1 PCICLK/4 1 0 PCICLK/2 + Function 0 Register A3: + Bit 7: Unlock SMM + Bit 6: Software SMI trigger + Function 0 Register A4: Bit 0: Host to PCI Clock (1: 1 by 1/0: 1 by half) - Function 1 Register 4: + Function 1 Register 4: (UMC 8886AF/8886BF Only!) Bit 0: Enable Internal IDE */ @@ -69,6 +72,7 @@ #include <86box/hdd.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> +#include <86box/pic.h> #include <86box/pci.h> #include <86box/chipset.h> @@ -76,16 +80,17 @@ #ifdef ENABLE_UMC_8886_LOG int umc_8886_do_log = ENABLE_UMC_8886_LOG; + + static void umc_8886_log(const char *fmt, ...) { va_list ap; - if (umc_8886_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + if (umc_8886_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else @@ -94,23 +99,24 @@ umc_8886_log(const char *fmt, ...) /* 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) +#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 BF Southbridge variant */ -#define HAS_IDE dev->has_ide +/* 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 +#define SB_ID dev->sb_id 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 */ + 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 */ + } umc_8886_t; @@ -121,39 +127,69 @@ umc_8886_ide_handler(int status) ide_sec_disable(); if (status) { - ide_pri_enable(); - ide_sec_enable(); + ide_pri_enable(); + ide_sec_enable(); } } static void -um8886_write(int func, int addr, uint8_t val, void *priv) +umc_8886_write(int func, int addr, uint8_t val, void *priv) { umc_8886_t *dev = (umc_8886_t *)priv; - umc_8886_log("UM8886: dev->regs[%02x] = %02x (%02x)\n", addr, val, func); - /* We don't know the RW status of registers but Phoenix writes on some RO registers too*/ - if (addr > 3) switch (func) { - case 0: /* Southbridge */ + switch (func) { + case 0: /* PCI to ISA Bridge */ + umc_8886_log("UM8886: dev->regs[%02x] = %02x POST %02x\n", addr, val, inb(0x80)); + switch (addr) { - case 0x43: - case 0x44: + case 0x04: case 0x05: + dev->pci_conf_sb[func][addr] = val; + break; + + case 0x07: + 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: case 0x44: dev->pci_conf_sb[func][addr] = val; pci_set_irq_routing(INTA, IRQRECALCA); pci_set_irq_routing(INTB, IRQRECALCB); break; + case 0x45: + dev->pci_conf_sb[func][addr] = val; + break; + case 0x46: - dev->pci_conf_sb[func][addr] = val & 0xaf; + dev->pci_conf_sb[func][addr] = val; + + if (val & 0x40) + picint(1 << ((val & 0x80) ? 15 : 10)); + break; case 0x47: - dev->pci_conf_sb[func][addr] = val & 0x4f; + 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; + switch (val & 2) { case 0: cpu_set_isa_pci_div(3); @@ -165,51 +201,65 @@ um8886_write(int func, int addr, uint8_t val, void *priv) cpu_set_isa_pci_div(2); break; } + break; case 0x57: - dev->pci_conf_sb[func][addr] = val & 0x38; + case 0x70 ... 0x76: + case 0x80: case 0x81: + case 0x90 ... 0x92: + case 0xa0 ... 0xa2: + dev->pci_conf_sb[func][addr] = val; break; - case 0x71: - dev->pci_conf_sb[func][addr] = val & 1; - break; + case 0xa3: + dev->pci_conf_sb[func][addr] = val; - case 0x90: - dev->pci_conf_sb[func][addr] = val & 2; - break; + /* SMI Provocation (Bit 7 Enable SMM + Bit 6 Software SMI */ + if (((dev->pci_conf_sb[0][0xa3] >> 6) == 3) && !in_smm) + smi_line = 1; - case 0x92: - dev->pci_conf_sb[func][addr] = val & 0x1f; - break; - - case 0xa0: - dev->pci_conf_sb[func][addr] = val & 0xfc; break; case 0xa4: - dev->pci_conf_sb[func][addr] = val & 0x89; + dev->pci_conf_sb[func][addr] = val; cpu_set_pci_speed(cpu_busspeed / ((val & 1) ? 1 : 2)); break; - default: + case 0xa5 ... 0xa8: dev->pci_conf_sb[func][addr] = val; break; } break; - case 1: /* IDE Controller */ - dev->pci_conf_sb[func][addr] = val; - if ((addr == 4) && HAS_IDE) - umc_8886_ide_handler(val & 1); + + case 1: /* IDE Controller */ + umc_8886_log("UM8886-IDE: dev->regs[%02x] = %02x POST: %02x\n", addr, val, inb(0x80)); + + switch (addr) { + case 0x04: + dev->pci_conf_sb[func][addr] = val; + umc_8886_ide_handler(val & 1); + break; + + case 0x07: + dev->pci_conf_sb[func][addr] &= ~(val & 0xf9); + break; + + case 0x3c: + case 0x40: case 0x41: + dev->pci_conf_sb[func][addr] = val; + break; + } break; } } static uint8_t -um8886_read(int func, int addr, void *priv) +umc_8886_read(int func, int addr, void *priv) { umc_8886_t *dev = (umc_8886_t *)priv; + return dev->pci_conf_sb[func][addr]; } @@ -219,26 +269,51 @@ umc_8886_reset(void *priv) { umc_8886_t *dev = (umc_8886_t *)priv; - /* Defaults */ - dev->pci_conf_sb[0][0] = 0x60; /* UMC */ + 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][2] = (SB_ID & 0xff); /* 8886xx */ dev->pci_conf_sb[0][3] = ((SB_ID >> 8) & 0xff); - dev->pci_conf_sb[0][8] = 1; + 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][0x09] = 0x00; dev->pci_conf_sb[0][0x0a] = 0x01; dev->pci_conf_sb[0][0x0b] = 0x06; - for (int i = 1; i < 5; i++) /* Disable all IRQ interrupts */ - pci_set_irq_routing(i, PCI_IRQ_DISABLED); + 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][0x47] = 0x40; + dev->pci_conf_sb[0][0x50] = 1; + dev->pci_conf_sb[0][0x51] = 3; + 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; + + dev->pci_conf_sb[1][2] = 0x3a; /* 8886BF IDE */ + dev->pci_conf_sb[1][3] = 0x67; + dev->pci_conf_sb[1][4] = 1; /* Start with Internal IDE Enabled */ + + 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); } + + for (int i = 1; i < 5; i++) /* Disable all IRQ interrupts */ + pci_set_irq_routing(i, PCI_IRQ_DISABLED); } @@ -257,12 +332,12 @@ 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, um8886_read, um8886_write, dev); /* Device 12: UMC 8886xx */ + dev->has_ide = !!(info->local == 0x886a); + pci_add_card(PCI_ADD_SOUTHBRIDGE, umc_8886_read, umc_8886_write, dev); /* Device 12: UMC 8886xx */ /* Add IDE if UM8886AF variant */ if (HAS_IDE) - device_add(&ide_pci_2ch_device); + device_add(&ide_pci_2ch_device); /* Get the Southbridge Revision */ SB_ID = info->local; @@ -277,24 +352,16 @@ const device_t umc_8886f_device = { "UMC 8886F", DEVICE_PCI, 0x8886, - umc_8886_init, - umc_8886_close, - umc_8886_reset, - { NULL }, - NULL, - NULL, + umc_8886_init, umc_8886_close, umc_8886_reset, + { NULL }, NULL, NULL, NULL }; const device_t umc_8886af_device = { - "UMC 8886AF", + "UMC 8886AF/8886BF", DEVICE_PCI, 0x886a, - umc_8886_init, - umc_8886_close, - umc_8886_reset, - { NULL }, - NULL, - NULL, + umc_8886_init, umc_8886_close, umc_8886_reset, + { NULL }, NULL, NULL, NULL }; diff --git a/src/chipset/umc_8890.c b/src/chipset/umc_8890.c deleted file mode 100644 index da49037d1..000000000 --- a/src/chipset/umc_8890.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Implementation of the UMC 8890 Chipset. - * - * Note: This chipset has no datasheet, everything were done via - * reverse engineering the BIOS of various machines using it. - * - * - * Authors: Tiseno100, - * - * Copyright 2021 Tiseno100. - */ - -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include "cpu.h" -#include <86box/timer.h> -#include <86box/io.h> -#include <86box/device.h> - -#include <86box/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 - -/* Shadow RAM Flags */ -#define ENABLE_SHADOW (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) -#define DISABLE_SHADOW (MEM_READ_EXTANY | MEM_WRITE_EXTANY) - -typedef struct umc_8890_t -{ - apm_t *apm; - smram_t *smram; - - uint8_t pci_conf[256]; -} umc_8890_t; - -uint16_t umc_8890_shadow_flag(uint8_t flag) -{ -return (flag & 1) ? (MEM_READ_INTERNAL | ((flag & 2) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY); -} - -void umc_8890_shadow(umc_8890_t *dev) -{ - - mem_set_mem_state_both(0xe0000, 0x10000, umc_8890_shadow_flag((dev->pci_conf[0x5f] & 0x0c) >> 2)); - mem_set_mem_state_both(0xf0000, 0x10000, umc_8890_shadow_flag((dev->pci_conf[0x5f] & 0xc0) >> 6)); - - for(int i = 0; i < 8; i++) - mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, umc_8890_shadow_flag(!!(dev->pci_conf[0x5d] & (1 << i)))); - - flushmmucache_nopc(); -} - -static void -um8890_write(int func, int addr, uint8_t val, void *priv) -{ - umc_8890_t *dev = (umc_8890_t *)priv; - - dev->pci_conf[addr] = val; - - switch (addr) - { - case 0x5c: - case 0x5d: - case 0x5e: - case 0x5f: - umc_8890_shadow(dev); - break; - - case 0x65: /* We don't know the default SMRAM values */ - smram_disable_all(); - smram_enable(dev->smram, 0xe0000, 0xe0000, 0x10000, dev->pci_conf[0x65] & 0x10, 1); - flushmmucache_nopc(); - 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; - return dev->pci_conf[addr]; -} - -static void -umc_8890_reset(void *priv) -{ - umc_8890_t *dev = (umc_8890_t *)priv; - - /* Defaults */ - dev->pci_conf[0] = 0x60; /* UMC */ - dev->pci_conf[1] = 0x10; - - dev->pci_conf[2] = 0x91; /* 8891F */ - dev->pci_conf[3] = 0x88; - - dev->pci_conf[8] = 1; - - dev->pci_conf[0x09] = 0x00; - dev->pci_conf[0x0a] = 0x00; - dev->pci_conf[0x0b] = 0x06; -} - -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 *)malloc(sizeof(umc_8890_t)); - memset(dev, 0, sizeof(umc_8890_t)); - pci_add_card(PCI_ADD_NORTHBRIDGE, um8890_read, um8890_write, dev); /* Device 0: UMC 8890 */ - - /* APM */ - dev->apm = device_add(&apm_pci_device); - - /* SMRAM(Needs excessive documentation before we begin SMM implementation) */ - dev->smram = smram_add(); - - /* Port 92 */ - device_add(&port_92_pci_device); - - umc_8890_reset(dev); - - return dev; -} - -const device_t umc_8890_device = { - "UMC 8890(8891BF/8892BF)", - DEVICE_PCI, - 0x886a, - umc_8890_init, - umc_8890_close, - umc_8890_reset, - {NULL}, - NULL, - NULL, - NULL}; diff --git a/src/chipset/umc_hb4.c b/src/chipset/umc_hb4.c index f9371ae5f..136fc03a0 100644 --- a/src/chipset/umc_hb4.c +++ b/src/chipset/umc_hb4.c @@ -20,66 +20,72 @@ */ /* -UMC HB4 Configuration Registers + UMC HB4 Configuration Registers -Sources & Notes: -Cache registers were found at Vogons: https://www.vogons.org/viewtopic.php?f=46&t=68829&start=20 -Basic Reverse engineering effort was done personally by me + Sources & Notes: + Cache registers were found at Vogons: https://www.vogons.org/viewtopic.php?f=46&t=68829&start=20 + Basic Reverse engineering effort was done personally by me -TODO: -- APM, SMM, SMRAM registers(Did some early work. Still quite incomplete) -- More Appropriate Bitmasking(If it's even possible) + Warning: Register documentation may be inaccurate! -Warning: Register documentation may be inaccurate! + UMC 8881x: -UMC 8881x: + Register 50: + Bit 7: Enable L2 Cache + Bit 6: Cache Policy (0: Write Thru / 1: Write Back) -Register 50: -Bit 7: Enable L2 Cache -Bit 6: Cache Policy (0: Write Thru / 1: Write Back) + Bit 5-4 Cache Speed + 0 0 Read 3-2-2-2 Write 3T + 0 1 Read 3-1-1-1 Write 3T + 1 0 Read 2-2-2-2 Write 2T + 1 1 Read 2-1-1-1 Write 2T -Bit 5-4 Cache Speed - 0 0 Read 3-2-2-2 Write 3T - 0 1 Read 3-1-1-1 Write 3T - 1 0 Read 2-2-2-2 Write 2T - 1 1 Read 2-1-1-1 Write 2T + Bit 3 Cache Banks (0: 1 Bank / 1: 2 Banks) -Bit 3 Cache Banks (0: 1 Bank / 1: 2 Banks) + Bit 2-1-0 Cache Size + 0 0 0 0KB + 0 0 1 64KB + x-x-x Multiplications of 2(64*2 for 0 1 0) till 2MB -Bit 2-1-0 Cache Size - 0 0 0 0KB - 0 0 1 64KB - x-x-x Multiplications of 2(64*2 for 0 1 0) till 2MB + Register 51: + Bit 7-6 DRAM Read Speed + 5-4 DRAM Write Speed + 0 0 1 Waits + 0 1 1 Waits + 1 0 1 Wait + 1 1 0 Waits -Register 51: -Bit 7-6 DRAM Read Speed - 5-4 DRAM Write Speed - 0 0 1 Waits - 0 1 1 Waits - 1 0 1 Wait - 1 1 0 Waits + Bit 3 Resource Lock Enable + Bit 2 Graphics Adapter (0: VL Bus / 1: PCI Bus) + Bit 1 L1 WB Policy (0: WT / 1: WB) + Bit 0 L2 Cache Tag Lenght (0: 7 Bits / 1: 8 Bits) -Bit 3 Resource Lock Enable -Bit 2 Graphics Adapter (0: VL Bus / 1: PCI Bus) -Bit 1 L1 WB Policy (0: WT / 1: WB) -Bit 0 L2 Cache Tag Lenght (0: 7 Bits / 1: 8 Bits) + Register 52: + Bit 7: Host-to-PCI Post Write (0: 1 Wait State / 1: 0 Wait States) -Register 52: -Bit 7: Host-to-PCI Post Write (0: 1 Wait State / 1: 0 Wait States) + Register 54: + Bit 7: DC000-DFFFF Read Enable + Bit 6: D8000-DBFFF Read Enable + Bit 5: D4000-D7FFF Read Enable + Bit 4: D0000-D3FFF Read Enable + 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 -Register 54: -Bit 7: DC000-DFFFF -Bit 6: D8000-DBFFF -Bit 5: D4000-D7FFF -Bit 4: D0000-D3FFF -Bit 3: CC000-CFFFF -Bit 2: C8000-CBFFF -Bit 1: C0000-C7FFF -Bit 0: Reserved + Register 55: + Bit 7: E0000-FFFF Read Enable + Bit 6: Shadow Write Status (1: Write Protect/0: Write) -Register 55: -Bit 7: Enable Shadow Reads For System & Selected Segments -Bit 6: Write Protect Enable + Register 56h & 57h: DRAM Bank 0 Configuration + Register 58h & 59h: DRAM Bank 1 Configuration + + Register 60: + Bit 5-4: SMRAM Position(Lot's of uncertainty to those bits) + 0 0 A0000 to E0000 + 1 0 A0000 to ????? (Phoenix uses it to no avail) + + Bit 0: SMRAM Local Access Enable */ #include @@ -95,7 +101,6 @@ Bit 6: Write Protect Enable #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> @@ -103,149 +108,192 @@ Bit 6: Write Protect Enable #include <86box/chipset.h> + #ifdef ENABLE_HB4_LOG int hb4_do_log = ENABLE_HB4_LOG; + + static void hb4_log(const char *fmt, ...) { va_list ap; - if (hb4_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + if (hb4_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else #define hb4_log(fmt, ...) #endif -/* Shadow RAM Flags */ -#define CAN_READ ((dev->pci_conf[0x55] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) -#define CAN_WRITE ((dev->pci_conf[0x55] & 0x40) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL) -#define DISABLE (MEM_READ_EXTANY | MEM_WRITE_EXTANY) typedef struct hb4_t { - apm_t *apm; - smram_t *smram; - - uint8_t pci_conf[256]; /* PCI Registers */ + uint8_t pci_conf[128]; /* PCI Registers */ + smram_t *smram; /* SMRAM Handler */ } hb4_t; -void hb4_shadow(int cur_addr, hb4_t *dev) -{ - mem_set_mem_state_both(0xc0000, 0x8000, (dev->pci_conf[0x54] & 2) ? (CAN_READ | CAN_WRITE) : DISABLE); - for (int i = 2; i < 8; i++) - mem_set_mem_state_both(0xc8000 + ((i - 2) << 14), 0x4000, (dev->pci_conf[0x54] & (1 << i)) ? (CAN_READ | CAN_WRITE) : DISABLE); - mem_set_mem_state_both(0xe0000, 0x20000, CAN_READ | CAN_WRITE); - - flushmmucache_nopc(); +void +hb4_shadow(hb4_t *dev) +{ + mem_set_mem_state_both(0xe0000, 0x20000, ((dev->pci_conf[0x55] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | + ((dev->pci_conf[0x55] & 0x40) ? MEM_WRITE_EXTANY : MEM_WRITE_INTERNAL)); + + if (dev->pci_conf[0x54] & 1) { + if (dev->pci_conf[0x54] & 2) + mem_set_mem_state_both(0xc0000, 0x8000, MEM_READ_INTERNAL | ((dev->pci_conf[0x55] & 0x40) ? MEM_WRITE_EXTANY :MEM_WRITE_INTERNAL)); + else + mem_set_mem_state_both(0xc0000, 0x8000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + + for (int i = 0; i < 5; i++) { + if ((dev->pci_conf[0x54] >> i) & 4) + mem_set_mem_state_both(0xc8000 + (i << 14), 0x8000, MEM_READ_INTERNAL | ((dev->pci_conf[0x55] & 0x40) ? MEM_WRITE_EXTANY :MEM_WRITE_INTERNAL)); + else + mem_set_mem_state_both(0xc8000 + (i << 14), 0x8000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + } + } + + flushmmucache_nopc(); } + static void -um8881_write(int func, int addr, uint8_t val, void *priv) +hb4_smram(hb4_t *dev) +{ + smram_disable_all(); + + smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x20000, dev->pci_conf[0x60] & 0x01, 1); +} + + +static void +hb4_write(int func, int addr, uint8_t val, void *priv) { hb4_t *dev = (hb4_t *)priv; - hb4_log("UM8881: dev->regs[%02x] = %02x\n", addr, val); + hb4_log("UM8881: dev->regs[%02x] = %02x POST: %02x \n", addr, val, inb(0x80)); - if (addr > 3) /* We don't know the RW status of registers but Phoenix writes on some RO registers too*/ + switch (addr) { + case 0x04: case 0x05: + dev->pci_conf[addr] = val; + break; - switch (addr) - { - case 0x50: - dev->pci_conf[addr] = ((val & 0xf8) | 4); /* Hardcode Cache Size to 512KB */ - cpu_cache_ext_enabled = !!(val & 0x80); /* Fixes freezing issues on the HOT-433A*/ - cpu_update_waitstates(); - break; + case 0x07: + dev->pci_conf[addr] &= ~(val & 0xf9); + break; - case 0x54: - case 0x55: - dev->pci_conf[addr] = val & (!(addr & 1) ? 0xfe : 0xff); - hb4_shadow(addr, dev); - break; + case 0x0c: case 0x0d: + dev->pci_conf[addr] = val; + break; - case 0x60: - dev->pci_conf[addr] = val & 0x3f; - break; + case 0x50: + dev->pci_conf[addr] = ((val & 0xf8) | 4); /* Hardcode Cache Size to 512KB */ + cpu_cache_ext_enabled = !!(val & 0x80); /* Fixes freezing issues on the HOT-433A*/ + cpu_update_waitstates(); + break; - case 0x61: - dev->pci_conf[addr] = val & 0x0f; - break; + case 0x51: case 0x52: + case 0x53: + dev->pci_conf[addr] = val; + break; - default: - dev->pci_conf[addr] = val; - break; - } + case 0x54: case 0x55: + dev->pci_conf[addr] = val; + hb4_shadow(dev); + break; + + case 0x56 ... 0x5f: + dev->pci_conf[addr] = val; + break; + + case 0x60: + dev->pci_conf[addr] = val; + hb4_smram(dev); + break; + + case 0x61: + dev->pci_conf[addr] = val; + break; + } } + static uint8_t -um8881_read(int func, int addr, void *priv) +hb4_read(int func, int addr, void *priv) { hb4_t *dev = (hb4_t *)priv; + return dev->pci_conf[addr]; } + static void hb4_reset(void *priv) { hb4_t *dev = (hb4_t *)priv; - /* Defaults */ 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[8] = 1; + dev->pci_conf[7] = 2; + + dev->pci_conf[8] = 4; 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[0x5d] = 0x20; + dev->pci_conf[0x5f] = 0xff; + + hb4_shadow(dev); + hb4_write(0, 0x60, 0x20, dev); } + static void hb4_close(void *priv) { hb4_t *dev = (hb4_t *)priv; - //smram_del(dev->smram); free(dev); } + static void * hb4_init(const device_t *info) { hb4_t *dev = (hb4_t *)malloc(sizeof(hb4_t)); memset(dev, 0, sizeof(hb4_t)); - pci_add_card(PCI_ADD_NORTHBRIDGE, um8881_read, um8881_write, dev); /* Device 10: UMC 8881x */ - - /* APM */ - dev->apm = device_add(&apm_pci_device); - - /* SMRAM(Needs excessive documentation before we begin SMM implementation) */ - //dev->smram = smram_add(); + pci_add_card(PCI_ADD_NORTHBRIDGE, hb4_read, hb4_write, dev); /* Device 10: UMC 8881x */ /* Port 92 */ device_add(&port_92_pci_device); + /* SMRAM */ + dev->smram = smram_add(); + hb4_reset(dev); return dev; } + const device_t umc_hb4_device = { "UMC HB4(8881F)", DEVICE_PCI, 0x886a, - hb4_init, - hb4_close, - hb4_reset, - {NULL}, - NULL, - NULL, - NULL}; + hb4_init, hb4_close, hb4_reset, + { NULL }, NULL, NULL, + NULL +}; diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 7f5ee51db..5431b9236 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -1184,7 +1184,7 @@ write_output(atkbd_t *dev, uint8_t val) kbd_log("ATkbc: write output port: %02X (old: %02X)\n", val, dev->p2); if (!(dev->flags & KBC_FLAG_PS2)) - val |= ((dev->mem[0x20] << 4) & 0x30); + val |= ((dev->mem[0x20] << 4) & 0x10); dev->kbd_inhibit = (val & 0x40); dev->mouse_inhibit = (val & 0x08); @@ -1211,6 +1211,7 @@ write_output(atkbd_t *dev, uint8_t val) if ((dev->p2 ^ val) & 0x01) { /*Reset*/ if (! (val & 0x01)) { /* Pin 0 selected. */ + pclog("write_output(): Pulse reset!\n"); softresetx86(); /*Pulse reset!*/ cpu_set_edx(); smbase = is_am486dxl ? 0x00060000 : 0x00030000; @@ -1503,10 +1504,8 @@ kbc_command(atkbd_t *dev) case 0xd0: /* read output port */ kbd_log("ATkbc: read output port\n"); mask = 0xff; - if (dev->mem[0x20] & 0x10) + if (!(dev->flags & KBC_FLAG_PS2) && (dev->mem[0x20] & 0x10)) mask &= 0xbf; - if ((dev->flags & KBC_FLAG_PS2) && (dev->mem[0x20] & 0x20)) - mask &= 0xf7; kbc_transmit(dev, dev->p2 & mask); break; @@ -2885,7 +2884,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) dev->status &= ~STAT_IFULL; kbc_send_to_ob(dev, 'H', 0, 0x00); } */ - kbc_process(dev); + // kbc_process(dev); #endif break; } diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index 4ecff681e..83642fe62 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -124,6 +124,11 @@ extern const device_t stpc_atlas_device; extern const device_t stpc_serial_device; 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_hb4_device; + /* VIA */ extern const device_t via_vt82c49x_device; extern const device_t via_vt82c49x_pci_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index a04b423ef..a805dc4ba 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -284,6 +284,7 @@ extern int machine_at_sbc_350a_init(const machine_t *); extern int machine_at_flytech386_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 *); extern int machine_at_awardsx_init(const machine_t *); @@ -369,12 +370,18 @@ extern int machine_at_arb1479_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_atc1415_init(const machine_t *); +extern int machine_at_actionpc2600_init(const machine_t *); + #ifdef EMU_DEVICE_H extern const device_t *at_acera1g_get_device(void); extern const device_t *at_vect486vl_get_device(void); extern const device_t *at_d824_get_device(void); extern const device_t *at_pcs46c_get_device(void); extern const device_t *at_valuepoint433_get_device(void); +extern const device_t *at_sbc_490_get_device(void); #endif /* m_at_commodore.c */ @@ -394,6 +401,7 @@ extern void machine_at_award_common_init(const machine_t *); extern void machine_at_sp4_common_init(const machine_t *model); +extern int machine_at_excalibur_pci_init(const machine_t *); extern int machine_at_p5mp3_init(const machine_t *); extern int machine_at_dellxp60_init(const machine_t *); extern int machine_at_opti560l_init(const machine_t *); @@ -407,6 +415,7 @@ extern int machine_at_excalibur_init(const machine_t *); extern int machine_at_p5vl_init(const machine_t *); +extern int machine_at_excalibur_pci_2_init(const machine_t *); extern int machine_at_p5sp4_init(const machine_t *); #ifdef EMU_DEVICE_H @@ -462,6 +471,7 @@ extern int machine_at_ap5s_init(const machine_t *); #ifdef EMU_DEVICE_H extern const device_t *at_endeavor_get_device(void); extern const device_t *at_thor_get_device(void); +#define at_mrthor_get_device at_thor_get_device extern const device_t *at_pb640_get_device(void); #endif @@ -474,6 +484,7 @@ extern int machine_at_equium5200_init(const machine_t *); extern int machine_at_pcv240_init(const machine_t *); extern int machine_at_p65up5_cp55t2d_init(const machine_t *); +extern int machine_at_ap5vm_init(const machine_t *); extern int machine_at_p55tvp4_init(const machine_t *); extern int machine_at_5ivg_init(const machine_t *); extern int machine_at_8500tvxa_init(const machine_t *); @@ -504,6 +515,11 @@ extern int machine_at_ms5146_init(const machine_t *); extern int machine_at_m560_init(const machine_t *); extern int machine_at_ms5164_init(const machine_t *); +#ifdef EMU_DEVICE_H +extern const device_t *at_presario2240_get_device(void); +#define at_presario4500_get_device at_presario2240_get_device +#endif + /* m_at_sockets7.c */ extern int machine_at_p5a_init(const machine_t *); extern int machine_at_m579_init(const machine_t *); @@ -513,6 +529,7 @@ extern int machine_at_ga_5ax_init(const machine_t *); extern int machine_at_ax59pro_init(const machine_t *); extern int machine_at_mvp3_init(const machine_t *); extern int machine_at_ficva503a_init(const machine_t *); +extern int machine_at_sy_5ema_pro_init(const machine_t *); /* m_at_socket8.c */ #if defined(DEV_BRANCH) && defined(USE_I450KX) diff --git a/src/include/86box/pci.h b/src/include/86box/pci.h index 4ca5d94c4..b9fa700bf 100644 --- a/src/include/86box/pci.h +++ b/src/include/86box/pci.h @@ -52,6 +52,8 @@ #define PCI_IRQ_DISABLED -1 +#define PCI_ADD_STRICT 0x80 + enum { PCI_CARD_NORTHBRIDGE = 0, PCI_CARD_AGPBRIDGE, diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 5bd424f9e..0c839ff9b 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -167,6 +167,7 @@ extern void updatewindowsize(int x, int y); extern void video_init(void); extern void video_close(void); extern void video_reset_close(void); +extern void video_pre_reset(int card); extern void video_reset(int card); extern uint8_t video_force_resize_get(void); extern void video_force_resize_set(uint8_t res); @@ -357,6 +358,7 @@ extern const device_t s3_elsa_winner2000_pro_x_964_vlb_device; extern const device_t s3_elsa_winner2000_pro_x_pci_device; extern const device_t s3_elsa_winner2000_pro_x_vlb_device; extern const device_t s3_trio64v2_dx_pci_device; +extern const device_t s3_trio64v2_dx_onboard_pci_device; /* S3 ViRGE */ extern const device_t s3_virge_325_vlb_device; @@ -380,6 +382,7 @@ extern const device_t sigma_device; extern const device_t tgui9400cxi_device; 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 tgui9680_pci_device; diff --git a/src/io.c b/src/io.c index 2751cc639..742e601c4 100644 --- a/src/io.c +++ b/src/io.c @@ -315,6 +315,10 @@ inb(uint16_t port) if (!found) cycles -= io_delay; + /* TriGem 486-BIOS MHz output. */ + if (port == 0x1ed) + ret = 0xfe; + io_log("[%04X:%08X] (%i, %i, %04i) in b(%04X) = %02X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); return(ret); @@ -338,7 +342,7 @@ outb(uint16_t port, uint8_t val) } p = q; } - + if (!found) { cycles -= io_delay; #ifdef USE_DYNAREC diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 091723b3c..b4d5b4ed6 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -120,11 +120,11 @@ machine_at_ama932j_init(const machine_t *model) machine_at_common_ide_init(model); - machine_at_headland_common_init(1); - if (gfxcard == VID_INTERNAL) device_add(&oti067_ama932j_device); + machine_at_headland_common_init(1); + return ret; } @@ -439,14 +439,14 @@ machine_at_spc4620p_init(const machine_t *model) if (bios_only || !ret) return ret; + if (gfxcard == VID_INTERNAL) + device_add(&ati28800k_spc4620p_device); + machine_at_scat_init(model, 1); if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); - if (gfxcard == VID_INTERNAL) - device_add(&ati28800k_spc4620p_device); - return ret; } @@ -550,13 +550,13 @@ machine_at_wd76c10_init(const machine_t *model) machine_at_common_init(model); + if (gfxcard == VID_INTERNAL) + device_add(¶dise_wd90c11_megapc_device); + device_add(&keyboard_ps2_quadtel_device); device_add(&wd76c10_device); - if (gfxcard == VID_INTERNAL) - device_add(¶dise_wd90c11_megapc_device); - return ret; } @@ -621,11 +621,11 @@ machine_at_cmdsl386sx25_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_scamp_common_init(model); - if (gfxcard == VID_INTERNAL) device_add(&gd5402_onboard_device); + machine_at_scamp_common_init(model); + return ret; } @@ -648,11 +648,11 @@ machine_at_spc6033p_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_scamp_common_init(model); - if (gfxcard == VID_INTERNAL) device_add(&ati28800k_spc6033p_device); + machine_at_scamp_common_init(model); + return ret; } @@ -736,11 +736,12 @@ machine_at_flytech386_init(const machine_t *model) device_add(&ali1217_device); device_add(&w83787f_ide_en_device); - device_add(&keyboard_ps2_device); if (gfxcard == VID_INTERNAL) device_add(&tvga8900d_device); + device_add(&keyboard_ps2_device); + return ret; } @@ -788,7 +789,29 @@ machine_at_pja511m_init(const machine_t *model) machine_at_common_init(model); device_add_inst(&fdc37c669_device, 1); - //device_add_inst(&fdc37c669_device, 2); /* enable when dual FDC37C669 is implemented */ + device_add_inst(&fdc37c669_device, 2); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&ali6117d_device); + device_add(&sst_flash_29ee010_device); + + return ret; +} + + +int +machine_at_prox1332_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/prox1332/D30B3AC1.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&fdc37c669_device); device_add(&keyboard_ps2_ami_pci_device); device_add(&ali6117d_device); device_add(&sst_flash_29ee010_device); @@ -845,13 +868,14 @@ machine_at_3302_init(const machine_t *model) machine_at_common_ide_init(model); device_add(&neat_device); - device_add(&keyboard_at_ncr_device); if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); if (gfxcard == VID_INTERNAL) device_add(¶dise_pvga1a_ncr3302_device); + + device_add(&keyboard_at_ncr_device); return ret; } diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 0cc901538..cf27a999d 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -175,23 +175,25 @@ machine_at_valuepoint433_init(const machine_t *model) // hangs without the PS/2 machine_at_common_ide_init(model); device_add(&sis_85c461_device); - device_add(&keyboard_ps2_device); - - if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); - if (gfxcard == VID_INTERNAL) device_add(&et4000w32_onboard_device); + device_add(&keyboard_ps2_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + return ret; } + const device_t * at_valuepoint433_get_device(void) { return &et4000w32_onboard_device; } + int machine_at_ecs386_init(const machine_t *model) { @@ -346,15 +348,16 @@ machine_at_vect486vl_init(const machine_t *model) // has HDC problems if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_ide_init(model); device_add(&vl82c480_device); - device_add(&keyboard_ps2_ami_device); - device_add(&fdc37c651_device); if (gfxcard == VID_INTERNAL) device_add(&gd5428_onboard_device); + device_add(&keyboard_ps2_ami_device); + device_add(&fdc37c651_ide_device); + return ret; } @@ -379,12 +382,13 @@ machine_at_d824_init(const machine_t *model) machine_at_common_init(model); device_add(&vl82c480_device); - device_add(&keyboard_ps2_device); - device_add(&fdc37c651_device); if (gfxcard == VID_INTERNAL) device_add(&gd5428_onboard_device); + device_add(&keyboard_ps2_device); + device_add(&fdc37c651_device); + return ret; } @@ -408,11 +412,11 @@ machine_at_acera1g_init(const machine_t *model) return ret; machine_at_common_init(model); + device_add(&ali1429_device); if (gfxcard == VID_INTERNAL) device_add(&gd5428_onboard_device); - device_add(&ali1429_device); device_add(&keyboard_ps2_acer_pci_device); device_add(&ide_isa_2ch_device); @@ -1364,14 +1368,18 @@ machine_at_sbc_490_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(0x01, PCI_CARD_VIDEO, 4, 1, 2, 3); 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, 2, 3, 4); + pci_register_slot(0x01, PCI_CARD_VIDEO, 4, 1, 2, 3); device_add(&ali1489_device); device_add(&fdc37c665_device); + + if (gfxcard == VID_INTERNAL) + device_add(&tgui9440_onboard_pci_device); + device_add(&keyboard_ps2_ami_device); device_add(&sst_flash_29ee010_device); @@ -1379,6 +1387,13 @@ machine_at_sbc_490_init(const machine_t *model) } +const device_t * +at_sbc_490_get_device(void) +{ + return &tgui9440_onboard_pci_device; +} + + int machine_at_tf_486_init(const machine_t *model) { @@ -1519,3 +1534,128 @@ machine_at_pcm5330_init(const machine_t *model) return ret; } + + +int +machine_at_ecs486_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ecs486/8810AIO.32J", + 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(0x0f, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x0c, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0d, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0e, PCI_CARD_NORMAL, 3, 4, 1, 2); + + device_add(&umc_hb4_device); + device_add(&umc_8886f_device); + device_add(&ide_cmd640_pci_legacy_only_device); + device_add(&fdc37c665_device); + device_add(&intel_flash_bxt_device); + device_add(&keyboard_at_ami_device); + + return ret; +} + + +int +machine_at_hot433_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/hot433/433AUS33.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(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(&intel_flash_bxt_device); + device_add(&keyboard_at_ami_device); + + return ret; +} + + +int +machine_at_atc1415_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/atc1415/1415V330.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(0x0c, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); + + device_add(&umc_hb4_device); + device_add(&umc_8886af_device); + device_add(&keyboard_at_ami_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + + +int +machine_at_actionpc2600_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/actionpc2600/action2600.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(0x12, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + 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(&intel_flash_bxt_device); + device_add(&keyboard_at_ami_device); + + return ret; +} diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index e0aef82ef..a2e8ce2a1 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -810,8 +810,6 @@ at_cpqiii_get_device(void) static void machine_at_compaq_init(const machine_t *model, int type) { - machine_at_init(model); - if (type != COMPAQ_DESKPRO386) mem_remap_top(384); @@ -846,6 +844,8 @@ machine_at_compaq_init(const machine_t *model, int type) device_add(&ide_isa_device); break; } + + machine_at_init(model); } diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index cf6a276aa..3c9baaa05 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -645,13 +645,14 @@ machine_at_ms6168_common_init(const machine_t *model) device_add(&i440zx_device); device_add(&piix4e_device); device_add(&w83977ef_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&intel_flash_bxt_device); - spd_register(SPD_TYPE_SDRAM, 0x3, 256); if (gfxcard == VID_INTERNAL) device_add(&voodoo_3_2000_agp_onboard_8m_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&intel_flash_bxt_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 256); + if (sound_card_current == SOUND_INTERNAL) { device_add(&es1371_onboard_device); device_add(&cs4297_device); diff --git a/src/machine/m_at_socket4.c b/src/machine/m_at_socket4.c index 16673b22f..7e8dd9232 100644 --- a/src/machine/m_at_socket4.c +++ b/src/machine/m_at_socket4.c @@ -111,6 +111,38 @@ machine_at_sp4_common_init(const machine_t *model) } +int +machine_at_excalibur_pci_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_inverted("roms/machines/excalibur_pci/S701P.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_2); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x03, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&fdc37c665_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&ide_cmd640_pci_legacy_only_device); + + device_add(&i430lx_device); + device_add(&sio_zb_device); + device_add(&intel_flash_bxt_ami_device); + + return ret; +} + + int machine_at_p5mp3_init(const machine_t *model) { @@ -331,6 +363,7 @@ machine_at_pb520r_init(const machine_t *model) return ret; } + const device_t * at_pb520r_get_device(void) { @@ -389,6 +422,38 @@ machine_at_p5vl_init(const machine_t *model) } +int +machine_at_excalibur_pci_2_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_inverted("roms/machines/excalibur_pci-2/S722P.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(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_IDE, 0, 0, 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(&fdc37c665_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&ide_cmd640_pci_legacy_only_device); + + device_add(&sis_85c50x_device); + device_add(&intel_flash_bxt_ami_device); + + return ret; +} + + int machine_at_p5sp4_init(const machine_t *model) { diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index 112be1c60..d9e9b7cd1 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -44,6 +44,7 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/nvr.h> +#include <86box/scsi_ncr53c8xx.h> int @@ -78,6 +79,41 @@ machine_at_acerv35n_init(const machine_t *model) } +int +machine_at_ap5vm_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ap5vm/AP5V270.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); + /* It seems there were plans for an on-board NCR 53C810 according to some clues + left in the manual, but were latter scrapped. The BIOS still support that + PCI device, though, so why not. */ + pci_register_slot(0x06, PCI_CARD_SCSI, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&i430vx_device); + device_add(&piix3_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&fdc37c665_device); + device_add(&ncr53c810_onboard_pci_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + + int machine_at_p55t2p4_init(const machine_t *model) { @@ -366,9 +402,12 @@ machine_at_presario2240_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, 1, 2, 3, 4); - pci_register_slot(0x14, PCI_CARD_SOUND, 3, 0, 0, 0); + pci_register_slot(0x14, PCI_CARD_VIDEO, 3, 0, 0, 0); pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4); + if (gfxcard == VID_INTERNAL) + device_add(&s3_trio64v2_dx_onboard_pci_device); + device_add(&i430vx_device); device_add(&piix3_device); device_add(&keyboard_ps2_ami_pci_device); @@ -379,6 +418,13 @@ machine_at_presario2240_init(const machine_t *model) } +const device_t * +at_presario2240_get_device(void) +{ + return &s3_trio64v2_dx_onboard_pci_device; +} + + int machine_at_presario4500_init(const machine_t *model) { @@ -395,8 +441,11 @@ machine_at_presario4500_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, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x14, PCI_CARD_VIDEO, 3, 0, 0, 0); + pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4); + + if (gfxcard == VID_INTERNAL) + device_add(&s3_trio64v2_dx_onboard_pci_device); device_add(&i430vx_device); device_add(&piix3_device); @@ -646,12 +695,21 @@ machine_at_an430tx_init(const machine_t *model) { int ret; +#if 1 ret = bios_load_linear_combined2("roms/machines/an430tx/P10-0095.BIO", "roms/machines/an430tx/P10-0095.BI1", "roms/machines/an430tx/P10-0095.BI2", "roms/machines/an430tx/P10-0095.BI3", "roms/machines/an430tx/P10-0095.RCV", 0x3a000, 160); +#else + ret = bios_load_linear_combined2("roms/machines/an430tx/P06-0062.BIO", + "roms/machines/an430tx/P06-0062.BI1", + "roms/machines/an430tx/P06-0062.BI2", + "roms/machines/an430tx/P06-0062.BI3", + "roms/machines/an430tx/P10-0095.RCV", + 0x3a000, 160); +#endif if (bios_only || !ret) return ret; @@ -661,7 +719,7 @@ machine_at_an430tx_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, 1, 2, 3, 4); /* PIIX4 */ - pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); + // pci_register_slot(0x08, PCI_CARD_VIDEO, 4, 0, 0, 0); pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 1b1f7c7be..5ee87fc44 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -60,6 +60,9 @@ machine_at_thor_common_init(const machine_t *model, int mr) pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 3, 2, 1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + if (gfxcard == VID_INTERNAL) + device_add(&s3_phoenix_trio64vplus_onboard_pci_device); + // device_add(&keyboard_ps2_ami_pci_device); device_add(&keyboard_ps2_intel_ami_pci_device); device_add(&i430fx_device); @@ -165,6 +168,13 @@ machine_at_thor_init(const machine_t *model) } +const device_t * +at_thor_get_device(void) +{ + return &s3_phoenix_trio64vplus_onboard_pci_device; +} + + int machine_at_mrthor_init(const machine_t *model) { diff --git a/src/machine/m_at_sockets7.c b/src/machine/m_at_sockets7.c index e9487ecfe..66eca228f 100644 --- a/src/machine/m_at_sockets7.c +++ b/src/machine/m_at_sockets7.c @@ -284,3 +284,44 @@ machine_at_ficva503a_init(const machine_t *model) return ret; } + + +int +machine_at_sy_5ema_pro_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/sy-5ema_pro/5emo1aa2.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(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 3, 4); + 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(0x0C, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + + device_add(&via_mvp3_device); + device_add(&via_vt82c686a_device); + device_add(&keyboard_ps2_ami_pci_device); + // device_add(&via_vt82c686_sio_device); + device_add(&fdc37c669_device); + device_add(&sst_flash_39sf010_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 256); + device_add(&via_vt82c686_hwm_device); /* fans: CPU1, Chassis; temperatures: CPU, System, unused */ + hwm_values.temperatures[0] += 2; /* CPU offset */ + hwm_values.temperatures[1] += 2; /* System offset */ + hwm_values.temperatures[2] = 0; /* unused */ + + device_add(&wm9701a_device); /* on daughtercard */ + + return ret; +} diff --git a/src/machine/machine.c b/src/machine/machine.c index afa79b02c..91cdbef33 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -97,6 +97,10 @@ machine_init_ex(int m) device_add(&cassette_device); cart_reset(); + + /* Prepare some video-related things if we're using internal + or no video. */ + video_pre_reset(gfxcard); } /* All good, boot the machine! */ diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 5a5ae8b21..b458b5a5f 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -252,6 +252,8 @@ const machine_t machines[] = { { "[ALi M1217] MR 386SX clone", "mr1217", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 16384, 1024, 127, machine_at_mr1217_init, NULL }, /* Has IBM PS/2 Type 1 KBC firmware. */ { "[ALi M6117] Acrosser PJ-A511M", "pja511m", MACHINE_TYPE_386SX, CPU_PKG_M6117, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768,1024, 127, machine_at_pja511m_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. */ + { "[ALi M6117C] Protech ProX-1332", "prox1332", MACHINE_TYPE_386SX, CPU_PKG_M6117, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 32768,1024, 127, machine_at_prox1332_init, 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. */ @@ -398,7 +400,7 @@ const machine_t machines[] = { /* 486 machines which utilize the PCI bus */ /* This has an AMIKey-2, which is an updated version of type 'H'. */ - { "[ALi M1489] AAEON SBC-490", "sbc-490", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_sbc_490_init, NULL }, + { "[ALi M1489] AAEON SBC-490", "sbc-490", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 1024, 65536, 1024, 255, machine_at_sbc_490_init, at_sbc_490_get_device }, /* Has the ALi M1487/9's on-chip keyboard controller which clones a standard AT KBC. */ { "[ALi M1489] ABIT AB-PB4", "abpb4", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_abpb4_init, NULL }, @@ -443,6 +445,14 @@ const machine_t machines[] = { /* According to MrKsoft, his real 4DPS has an AMIKey-2, which is an updated version of type 'H'. */ { "[SiS 496] Zida Tomato 4DP", "4dps", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 261120, 1024, 255, machine_at_4dps_init, NULL }, + /* This has the UMC 88xx on-chip KBC. */ + { "[UMC 8881] A-Trend ATC-1415", "atc1415", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_atc1415_init, NULL }, + /* This has an AMIKey-2, which is an updated version of type 'H'. */ + { "[UMC 8881] ECS Elite UM8810PAIO", "ecs486", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_ecs486_init, NULL }, + /* Has AMIKey Z(!) KBC firmware. */ + { "[UMC 8881] Epson Action PC 2600", "actionpc2600", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 262144, 1024, 255, machine_at_actionpc2600_init, NULL }, + /* This has a Holtek KBC. */ + { "[UMC 8881] Shuttle HOT-433A", "hot433", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 262144, 1024, 255, machine_at_hot433_init, NULL }, /* Has a VIA VT82C406 KBC+RTC that likely has identical commands to the VT82C42N. */ { "[VIA VT82C496G] DFI G486VPA", "g486vpa", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_g486vpa_init, NULL }, /* Has a VIA VT82C42N KBC. */ @@ -465,6 +475,12 @@ const machine_t machines[] = { /* Socket 4 machines */ /* 430LX */ + /* Has AMIKey H KBC firmware (AMIKey-2), per POST screen with BIOS string + shown in the manual. Has PS/2 mouse support with serial-style (DB9) + connector. + The boot block for BIOS recovery requires an unknown bit on port 805h + to be clear. */ + { "[i430LX] AMI Excalibur PCI Pentium", "excalibur_pci", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_excalibur_pci_init, NULL }, /* Has AMIKey F KBC firmware (AMIKey). */ { "[i430LX] ASUS P/I-P5MP3", "p5mp3", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE, 2048, 196608, 2048, 127, machine_at_p5mp3_init, NULL }, /* Has IBM PS/2 Type 1 KBC firmware. */ @@ -494,9 +510,11 @@ const machine_t machines[] = { /* This has AMIKey 'F' KBC firmware. */ { "[OPTi 597] Supermicro P5VL-PCI", "p5vl", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_VLB, 8192, 131072, 8192, 127, machine_at_p5vl_init, NULL }, - /* SiS 85C50x */ + /* SiS 50x */ + /* This has an unknown AMI KBC firmware, most likely AMIKey / type 'F'. */ + { "[SiS 50x] AMI Excalibur PCI-II Pentium ISA","excalibur_pci-2", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_excalibur_pci_2_init, NULL }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ - { "[SiS 85C50x] ASUS PCI/I-P5SP4", "p5sp4", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p5sp4_init, NULL }, + { "[SiS 50x] ASUS PCI/I-P5SP4", "p5sp4", MACHINE_TYPE_SOCKET4, CPU_PKG_SOCKET4, 0, 60000000, 66666667, 5000, 5000, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p5sp4_init, NULL }, /* Socket 5 machines */ /* 430NX */ @@ -557,11 +575,11 @@ const machine_t machines[] = { /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . */ - { "[i430FX] Intel Advanced/ATX", "thor", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_thor_init, NULL }, + { "[i430FX] Intel Advanced/ATX", "thor", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_thor_init, at_thor_get_device }, /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . */ - { "[i430FX] Intel Advanced/ATX (MR BIOS)", "mrthor", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_mrthor_init, NULL }, + { "[i430FX] Intel Advanced/ATX (MR BIOS)", "mrthor", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_mrthor_init, at_mrthor_get_device }, /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . */ @@ -624,6 +642,8 @@ const machine_t machines[] = { { "[i430HX] ASUS P/I-P65UP5 (C-P55T2D)", "p65up5_cp55t2d", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_p65up5_cp55t2d_init, NULL }, /* 430VX */ + /* This has the VIA VT82C42N KBC. */ + { "[i430VX] AOpen AP5VM", "ap5vm", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2600, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_SCSI, 8192, 131072, 8192, 127, machine_at_ap5vm_init, NULL }, /* Has AMIKey H KBC firmware (AMIKey-2). */ { "[i430VX] ASUS P/I-P55TVP4", "p55tvp4", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p55tvp4_init, NULL }, /* The BIOS does not send a single non-standard KBC command, so it must have a standard IBM @@ -633,9 +653,9 @@ const machine_t machines[] = { { "[i430VX] Biostar MB-8500TVX-A", "8500tvxa", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2600, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_8500tvxa_init, NULL }, /* The BIOS does not send a single non-standard KBC command, but the board has a SMC Super I/O chip with on-chip KBC and AMI MegaKey KBC firmware. */ - { "[i430VX] Compaq Presario 2240", "presario2240", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_presario2240_init, NULL }, + { "[i430VX] Compaq Presario 2240", "presario2240", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_presario2240_init, at_presario2240_get_device }, /* This most likely has AMI MegaKey as above. */ - { "[i430VX] Compaq Presario 4500", "presario4500", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_presario4500_init, NULL }, + { "[i430VX] Compaq Presario 4500", "presario4500", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_presario4500_init, at_presario4500_get_device }, /* The BIOS sends KBC command CB which is an AMI KBC command, so it has an AMI KBC firmware. */ { "[i430VX] Epox P55-VA", "p55va", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p55va_init, NULL }, /* The BIOS does not send a single non-standard KBC command. */ @@ -711,6 +731,9 @@ const machine_t machines[] = { /* Has the VIA VT82C686A southbridge with on-chip KBC identical to the VIA VT82C42N. */ { "[VIA MVP3] FIC VA-503A", "ficva503a", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 1800, 3100, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_ficva503a_init, NULL }, + /* Has the VIA VT82C686A southbridge with on-chip KBC identical to the VIA + VT82C42N. */ + { "[VIA MVP3] Soyo SY-5EMA Pro", "sy-5ema_pro", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 1800, 3100, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_sy_5ema_pro_init, NULL }, /* Socket 8 machines */ /* 450KX */ diff --git a/src/pci.c b/src/pci.c index a23f44768..37c9976a5 100644 --- a/src/pci.c +++ b/src/pci.c @@ -888,10 +888,17 @@ pci_find_slot(uint8_t add_type, uint8_t ignore_slot) dev = &pci_cards[i]; if (!dev->read && !dev->write && ((ignore_slot == 0xff) || (i != ignore_slot))) { - if (((dev->type == PCI_CARD_NORMAL) && (add_type >= PCI_ADD_NORMAL)) || - (dev->type == add_type)) { - ret = i; - break; + if (add_type & PCI_ADD_STRICT) { + if (dev->type == (add_type & 0x7f)) { + ret = i; + break; + } + } else { + if (((dev->type == PCI_CARD_NORMAL) && ((add_type & 0x7f) >= PCI_ADD_NORMAL)) || + (dev->type == (add_type & 0x7f))) { + ret = i; + break; + } } } } diff --git a/src/port_92.c b/src/port_92.c index d46d2327b..5e19bee34 100644 --- a/src/port_92.c +++ b/src/port_92.c @@ -64,7 +64,13 @@ port_92_readb(uint16_t port, void *priv) static uint16_t port_92_readw(uint16_t port, void *priv) { - return port_92_readb(port, priv); + uint16_t ret = 0xffff; + port_92_t *dev = (port_92_t *) priv; + + if (!(dev->flags & PORT_92_PCI)) + ret = port_92_readb(port, priv); + + return ret; } @@ -106,7 +112,10 @@ port_92_writeb(uint16_t port, uint8_t val, void *priv) static void port_92_writew(uint16_t port, uint16_t val, void *priv) { - port_92_writeb(port, val & 0xff, priv); + port_92_t *dev = (port_92_t *) priv; + + if (!(dev->flags & PORT_92_PCI)) + port_92_writeb(port, val & 0xff, priv); } @@ -146,7 +155,7 @@ port_92_add(void *priv) { port_92_t *dev = (port_92_t *) priv; - if (dev->flags & PORT_92_WORD) + if (dev->flags & (PORT_92_WORD | PORT_92_PCI)) io_sethandler(0x0092, 2, port_92_readb, port_92_readw, NULL, port_92_writeb, port_92_writew, NULL, dev); else @@ -160,7 +169,7 @@ port_92_remove(void *priv) { port_92_t *dev = (port_92_t *) priv; - if (dev->flags & PORT_92_WORD) + if (dev->flags & (PORT_92_WORD | PORT_92_PCI)) io_removehandler(0x0092, 2, port_92_readb, port_92_readw, NULL, port_92_writeb, port_92_writew, NULL, dev); else diff --git a/src/sio/CMakeLists.txt b/src/sio/CMakeLists.txt index 902f8b231..856f6aaa6 100644 --- a/src/sio/CMakeLists.txt +++ b/src/sio/CMakeLists.txt @@ -13,8 +13,8 @@ # Copyright 2020,2021 David Hrdlička. # -add_library(sio OBJECT sio_acc3221.c sio_f82c710.c sio_82091aa.c sio_fdc37c651.c sio_fdc37c661.c - sio_fdc37c66x.c sio_fdc37c67x.c sio_fdc37c669.c sio_fdc37c93x.c sio_fdc37m60x.c +add_library(sio OBJECT sio_acc3221.c sio_f82c710.c sio_82091aa.c sio_fdc37c6xx.c + sio_fdc37c67x.c sio_fdc37c669.c sio_fdc37c93x.c sio_fdc37m60x.c sio_it8661f.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 diff --git a/src/sio/sio_fdc37c651.c b/src/sio/sio_fdc37c651.c deleted file mode 100644 index a19460d4c..000000000 --- a/src/sio/sio_fdc37c651.c +++ /dev/null @@ -1,314 +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 SMC FDC37C651 Super I/O Chip. - * - * Authors: Miran Grca, - * - * Copyright 2021 Miran Grca. - */ -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/io.h> -#include <86box/timer.h> -#include <86box/device.h> -#include <86box/lpt.h> -#include <86box/serial.h> -#include <86box/hdc.h> -#include <86box/hdc_ide.h> -#include <86box/fdd.h> -#include <86box/fdc.h> -#include <86box/sio.h> - - -#ifdef ENABLE_FDC37C651_LOG -int fdc37c651_do_log = ENABLE_FDC37C651_LOG; - - -static void -fdc37c651_log(const char *fmt, ...) -{ - va_list ap; - - if (fdc37c651_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -#define fdc37c651_log(fmt, ...) -#endif - - -typedef struct { - uint8_t tries, has_ide, - regs[16]; - int cur_reg, - com3_addr, com4_addr; - fdc_t *fdc; - serial_t *uart[2]; -} fdc37c651_t; - - -static void -set_com34_addr(fdc37c651_t *dev) -{ - switch (dev->regs[1] & 0x60) { - case 0x00: - dev->com3_addr = 0x338; - dev->com4_addr = 0x238; - break; - case 0x20: - dev->com3_addr = 0x3e8; - dev->com4_addr = 0x2e8; - break; - case 0x40: - dev->com3_addr = 0x3e8; - dev->com4_addr = 0x2e0; - break; - case 0x60: - dev->com3_addr = 0x220; - dev->com4_addr = 0x228; - break; - } -} - - -static void -set_serial_addr(fdc37c651_t *dev, int port) -{ - uint8_t shift = (port << 2); - - serial_remove(dev->uart[port]); - if (dev->regs[2] & (4 << shift)) { - switch ((dev->regs[2] >> shift) & 3) { - case 0: - serial_setup(dev->uart[port], SERIAL1_ADDR, SERIAL1_IRQ); - break; - case 1: - serial_setup(dev->uart[port], SERIAL2_ADDR, SERIAL2_IRQ); - break; - case 2: - serial_setup(dev->uart[port], dev->com3_addr, 4); - break; - case 3: - serial_setup(dev->uart[port], dev->com4_addr, 3); - break; - } - } -} - - -static void -lpt1_handler(fdc37c651_t *dev) -{ - lpt1_remove(); - switch (dev->regs[1] & 3) { - case 1: - lpt1_init(0x3bc); - lpt1_irq(7); - break; - case 2: - lpt1_init(0x378); - lpt1_irq(7 /*5*/); - break; - case 3: - lpt1_init(0x278); - lpt1_irq(7 /*5*/); - break; - } -} - - -static void -fdc_handler(fdc37c651_t *dev) -{ - fdc_remove(dev->fdc); - if (dev->regs[0] & 0x10) - fdc_set_base(dev->fdc, 0x03f0); -} - - - -static void -ide_handler(fdc37c651_t *dev) -{ - /* TODO: Make an ide_disable(channel) and ide_enable(channel) so we can simplify this. */ - if (dev->has_ide == 2) { - ide_sec_disable(); - ide_set_base(1, 0x1f0); - ide_set_side(1, 0x3f6); - if (dev->regs[0x00] & 0x01) - ide_sec_enable(); - } else if (dev->has_ide == 1) { - ide_pri_disable(); - ide_set_base(0, 0x1f0); - ide_set_side(0, 0x3f6); - if (dev->regs[0x00] & 0x01) - ide_pri_enable(); - } -} - - -static void -fdc37c651_write(uint16_t port, uint8_t val, void *priv) -{ - fdc37c651_t *dev = (fdc37c651_t *) priv; - uint8_t valxor = 0; - - if (dev->tries == 2) { - if (port == 0x3f0) { - if (val == 0xaa) - dev->tries = 0; - else - dev->cur_reg = val; - } else { - if (dev->cur_reg > 15) - return; - - valxor = val ^ dev->regs[dev->cur_reg]; - dev->regs[dev->cur_reg] = val; - - switch(dev->cur_reg) { - case 0: - if (dev->has_ide && (valxor & 0x01)) - ide_handler(dev); - if (valxor & 0x10) - fdc_handler(dev); - break; - case 1: - if (valxor & 3) - lpt1_handler(dev); - if (valxor & 0x60) { - set_com34_addr(dev); - set_serial_addr(dev, 0); - set_serial_addr(dev, 1); - } - break; - case 2: - if (valxor & 7) - set_serial_addr(dev, 0); - if (valxor & 0x70) - set_serial_addr(dev, 1); - break; - } - } - } else if ((port == 0x3f0) && (val == 0x55)) - dev->tries++; -} - - -static uint8_t -fdc37c651_read(uint16_t port, void *priv) -{ - fdc37c651_t *dev = (fdc37c651_t *) priv; - uint8_t ret = 0x00; - - if (dev->tries == 2) { - if (port == 0x3f1) - ret = dev->regs[dev->cur_reg]; - } - - return ret; -} - - -static void -fdc37c651_reset(fdc37c651_t *dev) -{ - dev->com3_addr = 0x338; - dev->com4_addr = 0x238; - - serial_remove(dev->uart[0]); - serial_setup(dev->uart[0], SERIAL1_ADDR, SERIAL1_IRQ); - - serial_remove(dev->uart[1]); - serial_setup(dev->uart[1], SERIAL2_ADDR, SERIAL2_IRQ); - - lpt1_remove(); - lpt1_init(0x378); - - fdc_reset(dev->fdc); - fdc_remove(dev->fdc); - - dev->tries = 0; - memset(dev->regs, 0, 16); - - dev->regs[0x0] = 0x3f; - dev->regs[0x1] = 0x9f; - dev->regs[0x2] = 0xdc; - - set_serial_addr(dev, 0); - set_serial_addr(dev, 1); - - lpt1_handler(dev); - - fdc_handler(dev); - - if (dev->has_ide) - ide_handler(dev); -} - - -static void -fdc37c651_close(void *priv) -{ - fdc37c651_t *dev = (fdc37c651_t *) priv; - - free(dev); -} - - -static void * -fdc37c651_init(const device_t *info) -{ - fdc37c651_t *dev = (fdc37c651_t *) malloc(sizeof(fdc37c651_t)); - memset(dev, 0, sizeof(fdc37c651_t)); - - dev->fdc = device_add(&fdc_at_smc_device); - - dev->uart[0] = device_add_inst(&ns16450_device, 1); - dev->uart[1] = device_add_inst(&ns16450_device, 2); - - dev->has_ide = (info->local >> 8) & 0xff; - - io_sethandler(0x03f0, 0x0002, - fdc37c651_read, NULL, NULL, fdc37c651_write, NULL, NULL, dev); - - fdc37c651_reset(dev); - - return dev; -} - - -/* The three appear to differ only in the chip ID, if I - understood their datasheets correctly. */ -const device_t fdc37c651_device = { - "SMC FDC37C651 Super I/O", - 0, - 0, - fdc37c651_init, fdc37c651_close, NULL, - { NULL }, NULL, NULL, - NULL -}; - -const device_t fdc37c651_ide_device = { - "SMC FDC37C651 Super I/O (With IDE)", - 0, - 0x100, - fdc37c651_init, fdc37c651_close, NULL, - { NULL }, NULL, NULL, - NULL -}; diff --git a/src/sio/sio_fdc37c661.c b/src/sio/sio_fdc37c661.c deleted file mode 100644 index 8a17053a6..000000000 --- a/src/sio/sio_fdc37c661.c +++ /dev/null @@ -1,299 +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 SMC FDC37C661 Super I/O Chip. - * - * - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - */ -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/io.h> -#include <86box/timer.h> -#include <86box/device.h> -#include <86box/pci.h> -#include <86box/lpt.h> -#include <86box/serial.h> -#include <86box/hdc.h> -#include <86box/hdc_ide.h> -#include <86box/fdd.h> -#include <86box/fdc.h> -#include <86box/sio.h> - - -typedef struct { - uint8_t chip_id, tries, - has_ide, regs[16]; - int cur_reg, - com3_addr, com4_addr; - fdc_t *fdc; - serial_t *uart[2]; -} fdc37c661_t; - - -static void -set_com34_addr(fdc37c661_t *dev) -{ - switch (dev->regs[1] & 0x60) { - case 0x00: - dev->com3_addr = 0x338; - dev->com4_addr = 0x238; - break; - case 0x20: - dev->com3_addr = 0x3e8; - dev->com4_addr = 0x2e8; - break; - case 0x40: - dev->com3_addr = 0x3e8; - dev->com4_addr = 0x2e0; - break; - case 0x60: - dev->com3_addr = 0x220; - dev->com4_addr = 0x228; - break; - } -} - - -static void -set_serial_addr(fdc37c661_t *dev, int port) -{ - uint8_t shift = (port << 2); - - serial_remove(dev->uart[port]); - if (dev->regs[2] & (4 << shift)) { - switch ((dev->regs[2] >> shift) & 3) { - case 0: - serial_setup(dev->uart[port], SERIAL1_ADDR, SERIAL1_IRQ); - break; - case 1: - serial_setup(dev->uart[port], SERIAL2_ADDR, SERIAL2_IRQ); - break; - case 2: - serial_setup(dev->uart[port], dev->com3_addr, 4); - break; - case 3: - serial_setup(dev->uart[port], dev->com4_addr, 3); - break; - } - } -} - - -static void -lpt1_handler(fdc37c661_t *dev) -{ - lpt1_remove(); - switch (dev->regs[1] & 3) { - case 1: - lpt1_init(0x3bc); - lpt1_irq(7); - break; - case 2: - lpt1_init(0x378); - lpt1_irq(7 /*5*/); - break; - case 3: - lpt1_init(0x278); - lpt1_irq(7 /*5*/); - break; - } -} - - -static void -fdc_handler(fdc37c661_t *dev) -{ - fdc_remove(dev->fdc); - if (dev->regs[0] & 0x10) - fdc_set_base(dev->fdc, 0x03f0); -} - - - -static void -ide_handler(fdc37c661_t *dev) -{ - /* TODO: Make an ide_disable(channel) and ide_enable(channel) so we can simplify this. */ - if (dev->has_ide == 2) { - ide_sec_disable(); - ide_set_base(1, 0x1f0); - ide_set_side(1, 0x3f6); - if (dev->regs[0x00] & 0x01) - ide_sec_enable(); - } else if (dev->has_ide == 1) { - ide_pri_disable(); - ide_set_base(0, 0x1f0); - ide_set_side(0, 0x3f6); - if (dev->regs[0x00] & 0x01) - ide_pri_enable(); - } -} - - -static void -fdc37c661_write(uint16_t port, uint8_t val, void *priv) -{ - fdc37c661_t *dev = (fdc37c661_t *) priv; - uint8_t valxor = 0; - - if (dev->tries == 2) { - if (port == 0x3f0) { - if (val == 0xaa) - dev->tries = 0; - else - dev->cur_reg = val; - } else { - if (dev->cur_reg > 15) - return; - - valxor = val ^ dev->regs[dev->cur_reg]; - dev->regs[dev->cur_reg] = val; - - switch(dev->cur_reg) { - case 0: - if (dev->has_ide && (valxor & 0x01)) - ide_handler(dev); - if (valxor & 0x10) - fdc_handler(dev); - break; - case 1: - if (valxor & 3) - lpt1_handler(dev); - if (valxor & 0x60) { - set_com34_addr(dev); - set_serial_addr(dev, 0); - set_serial_addr(dev, 1); - } - break; - case 2: - if (valxor & 7) - set_serial_addr(dev, 0); - if (valxor & 0x70) - set_serial_addr(dev, 1); - break; - } - } - } else if ((port == 0x3f0) && (val == 0x55)) - dev->tries++; -} - - -static uint8_t -fdc37c661_read(uint16_t port, void *priv) -{ - fdc37c661_t *dev = (fdc37c661_t *) priv; - uint8_t ret = 0x00; - - if (dev->tries == 2) { - if (port == 0x3f1) - ret = dev->regs[dev->cur_reg]; - } - - return ret; -} - - -static void -fdc37c661_reset(fdc37c661_t *dev) -{ - dev->com3_addr = 0x338; - dev->com4_addr = 0x238; - - serial_remove(dev->uart[0]); - serial_setup(dev->uart[0], SERIAL1_ADDR, SERIAL1_IRQ); - - serial_remove(dev->uart[1]); - serial_setup(dev->uart[1], SERIAL2_ADDR, SERIAL2_IRQ); - - lpt1_remove(); - lpt1_init(0x378); - - fdc_reset(dev->fdc); - fdc_remove(dev->fdc); - - dev->tries = 0; - memset(dev->regs, 0, 16); - - dev->regs[0x0] = 0x3f; - dev->regs[0x1] = 0x9f; - dev->regs[0x2] = 0xdc; - dev->regs[0x3] = 0x78; - - set_serial_addr(dev, 0); - set_serial_addr(dev, 1); - - lpt1_handler(dev); - - fdc_handler(dev); - - if (dev->has_ide) - ide_handler(dev); -} - - -static void -fdc37c661_close(void *priv) -{ - fdc37c661_t *dev = (fdc37c661_t *) priv; - - free(dev); -} - - -static void * -fdc37c661_init(const device_t *info) -{ - fdc37c661_t *dev = (fdc37c661_t *) malloc(sizeof(fdc37c661_t)); - memset(dev, 0, sizeof(fdc37c661_t)); - - dev->fdc = device_add(&fdc_at_smc_device); - - dev->uart[0] = device_add_inst(&ns16450_device, 1); - dev->uart[1] = device_add_inst(&ns16450_device, 2); - - dev->chip_id = info->local & 0xff; - dev->has_ide = (info->local >> 8) & 0xff; - - io_sethandler(0x03f0, 0x0002, - fdc37c661_read, NULL, NULL, fdc37c661_write, NULL, NULL, dev); - - fdc37c661_reset(dev); - - return dev; -} - - -/* The three appear to differ only in the chip ID, if I - understood their datasheets correctly. */ -const device_t fdc37c661_device = { - "SMC FDC37C661 Super I/O", - 0, - 0x00, - fdc37c661_init, fdc37c661_close, NULL, - { NULL }, NULL, NULL, - NULL -}; - -const device_t fdc37c661_ide_device = { - "SMC FDC37C661 Super I/O (With IDE)", - 0, - 0x100, - fdc37c661_init, fdc37c661_close, NULL, - { NULL }, NULL, NULL, - NULL -}; diff --git a/src/sio/sio_fdc37c66x.c b/src/sio/sio_fdc37c6xx.c similarity index 71% rename from src/sio/sio_fdc37c66x.c rename to src/sio/sio_fdc37c6xx.c index ce8776944..59f93c1fa 100644 --- a/src/sio/sio_fdc37c66x.c +++ b/src/sio/sio_fdc37c6xx.c @@ -37,17 +37,18 @@ typedef struct { - uint8_t chip_id, tries, - has_ide, regs[16]; + uint8_t max_reg, chip_id, + tries, has_ide, + regs[16]; int cur_reg, com3_addr, com4_addr; fdc_t *fdc; serial_t *uart[2]; -} fdc37c66x_t; +} fdc37c6xx_t; static void -set_com34_addr(fdc37c66x_t *dev) +set_com34_addr(fdc37c6xx_t *dev) { switch (dev->regs[1] & 0x60) { case 0x00: @@ -71,7 +72,7 @@ set_com34_addr(fdc37c66x_t *dev) static void -set_serial_addr(fdc37c66x_t *dev, int port) +set_serial_addr(fdc37c6xx_t *dev, int port) { uint8_t shift = (port << 2); double clock_src = 24000000.0 / 13.0; @@ -102,7 +103,7 @@ set_serial_addr(fdc37c66x_t *dev, int port) static void -lpt1_handler(fdc37c66x_t *dev) +lpt1_handler(fdc37c6xx_t *dev) { lpt1_remove(); switch (dev->regs[1] & 3) { @@ -123,7 +124,7 @@ lpt1_handler(fdc37c66x_t *dev) static void -fdc_handler(fdc37c66x_t *dev) +fdc_handler(fdc37c6xx_t *dev) { fdc_remove(dev->fdc); if (dev->regs[0] & 0x10) @@ -133,7 +134,7 @@ fdc_handler(fdc37c66x_t *dev) static void -ide_handler(fdc37c66x_t *dev) +ide_handler(fdc37c6xx_t *dev) { /* TODO: Make an ide_disable(channel) and ide_enable(channel) so we can simplify this. */ if (dev->has_ide == 2) { @@ -153,9 +154,9 @@ ide_handler(fdc37c66x_t *dev) static void -fdc37c66x_write(uint16_t port, uint8_t val, void *priv) +fdc37c6xx_write(uint16_t port, uint8_t val, void *priv) { - fdc37c66x_t *dev = (fdc37c66x_t *) priv; + fdc37c6xx_t *dev = (fdc37c6xx_t *) priv; uint8_t valxor = 0; if (dev->tries == 2) { @@ -165,7 +166,7 @@ fdc37c66x_write(uint16_t port, uint8_t val, void *priv) else dev->cur_reg = val; } else { - if (dev->cur_reg > 15) + if (dev->cur_reg > dev->max_reg) return; valxor = val ^ dev->regs[dev->cur_reg]; @@ -221,9 +222,9 @@ fdc37c66x_write(uint16_t port, uint8_t val, void *priv) static uint8_t -fdc37c66x_read(uint16_t port, void *priv) +fdc37c6xx_read(uint16_t port, void *priv) { - fdc37c66x_t *dev = (fdc37c66x_t *) priv; + fdc37c6xx_t *dev = (fdc37c6xx_t *) priv; uint8_t ret = 0x00; if (dev->tries == 2) { @@ -236,7 +237,7 @@ fdc37c66x_read(uint16_t port, void *priv) static void -fdc37c66x_reset(fdc37c66x_t *dev) +fdc37c6xx_reset(fdc37c6xx_t *dev) { dev->com3_addr = 0x338; dev->com4_addr = 0x238; @@ -256,13 +257,33 @@ fdc37c66x_reset(fdc37c66x_t *dev) dev->tries = 0; memset(dev->regs, 0, 16); - dev->regs[0x0] = 0x3a; + switch (dev->chip_id) { + case 0x63: case 0x65: + dev->max_reg = 0x0f; + dev->regs[0x0] = 0x3b; + break; + case 0x64: case 0x66: + dev->max_reg = 0x0f; + dev->regs[0x0] = 0x2b; + break; + default: + dev->max_reg = (dev->chip_id >= 0x61) ? 0x03 : 0x02; + dev->regs[0x0] = 0x3f; + break; + } + dev->regs[0x1] = 0x9f; dev->regs[0x2] = 0xdc; dev->regs[0x3] = 0x78; - dev->regs[0x6] = 0xff; - dev->regs[0xd] = dev->chip_id; - dev->regs[0xe] = 0x01; + + if (dev->chip_id >= 0x63) { + dev->regs[0x6] = 0xff; + dev->regs[0xd] = dev->chip_id; + if (dev->chip_id >= 0x65) + dev->regs[0xe] = 0x02; + else + dev->regs[0xe] = 0x01; + } set_serial_addr(dev, 0); set_serial_addr(dev, 1); @@ -277,32 +298,37 @@ fdc37c66x_reset(fdc37c66x_t *dev) static void -fdc37c66x_close(void *priv) +fdc37c6xx_close(void *priv) { - fdc37c66x_t *dev = (fdc37c66x_t *) priv; + fdc37c6xx_t *dev = (fdc37c6xx_t *) priv; free(dev); } static void * -fdc37c66x_init(const device_t *info) +fdc37c6xx_init(const device_t *info) { - fdc37c66x_t *dev = (fdc37c66x_t *) malloc(sizeof(fdc37c66x_t)); - memset(dev, 0, sizeof(fdc37c66x_t)); + fdc37c6xx_t *dev = (fdc37c6xx_t *) malloc(sizeof(fdc37c6xx_t)); + memset(dev, 0, sizeof(fdc37c6xx_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->chip_id = info->local & 0xff; dev->has_ide = (info->local >> 8) & 0xff; - io_sethandler(0x03f0, 0x0002, - fdc37c66x_read, NULL, NULL, fdc37c66x_write, NULL, NULL, dev); + if (dev->chip_id >= 0x63) { + dev->uart[0] = device_add_inst(&ns16550_device, 1); + dev->uart[1] = device_add_inst(&ns16550_device, 2); + } else { + dev->uart[0] = device_add_inst(&ns16450_device, 1); + dev->uart[1] = device_add_inst(&ns16450_device, 2); + } - fdc37c66x_reset(dev); + io_sethandler(0x03f0, 0x0002, + fdc37c6xx_read, NULL, NULL, fdc37c6xx_write, NULL, NULL, dev); + + fdc37c6xx_reset(dev); return dev; } @@ -310,11 +336,47 @@ fdc37c66x_init(const device_t *info) /* The three appear to differ only in the chip ID, if I understood their datasheets correctly. */ +const device_t fdc37c651_device = { + "SMC FDC37C651 Super I/O", + 0, + 0x51, + fdc37c6xx_init, fdc37c6xx_close, NULL, + { NULL }, NULL, NULL, + NULL +}; + +const device_t fdc37c651_ide_device = { + "SMC FDC37C651 Super I/O (With IDE)", + 0, + 0x151, + fdc37c6xx_init, fdc37c6xx_close, NULL, + { NULL }, NULL, NULL, + NULL +}; + +const device_t fdc37c661_device = { + "SMC FDC37C661 Super I/O", + 0, + 0x61, + fdc37c6xx_init, fdc37c6xx_close, NULL, + { NULL }, NULL, NULL, + NULL +}; + +const device_t fdc37c661_ide_device = { + "SMC FDC37C661 Super I/O (With IDE)", + 0, + 0x161, + fdc37c6xx_init, fdc37c6xx_close, NULL, + { NULL }, NULL, NULL, + NULL +}; + const device_t fdc37c663_device = { "SMC FDC37C663 Super I/O", 0, 0x63, - fdc37c66x_init, fdc37c66x_close, NULL, + fdc37c6xx_init, fdc37c6xx_close, NULL, { NULL }, NULL, NULL, NULL }; @@ -323,7 +385,7 @@ const device_t fdc37c663_ide_device = { "SMC FDC37C663 Super I/O (With IDE)", 0, 0x163, - fdc37c66x_init, fdc37c66x_close, NULL, + fdc37c6xx_init, fdc37c6xx_close, NULL, { NULL }, NULL, NULL, NULL }; @@ -332,7 +394,7 @@ const device_t fdc37c665_device = { "SMC FDC37C665 Super I/O", 0, 0x65, - fdc37c66x_init, fdc37c66x_close, NULL, + fdc37c6xx_init, fdc37c6xx_close, NULL, { NULL }, NULL, NULL, NULL }; @@ -341,7 +403,7 @@ const device_t fdc37c665_ide_device = { "SMC FDC37C665 Super I/O (With IDE)", 0, 0x265, - fdc37c66x_init, fdc37c66x_close, NULL, + fdc37c6xx_init, fdc37c6xx_close, NULL, { NULL }, NULL, NULL, NULL }; @@ -350,7 +412,7 @@ const device_t fdc37c666_device = { "SMC FDC37C666 Super I/O", 0, 0x66, - fdc37c66x_init, fdc37c66x_close, NULL, + fdc37c6xx_init, fdc37c6xx_close, NULL, { NULL }, NULL, NULL, NULL }; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 74ead9b62..2b30146b5 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -73,6 +73,7 @@ enum S3_METHEUS_86C928, S3_AMI_86C924, S3_TRIO64V2_DX, + S3_TRIO64V2_DX_ONBOARD, S3_PHOENIX_TRIO64VPLUS, S3_PHOENIX_TRIO64VPLUS_ONBOARD, S3_DIAMOND_STEALTH_SE, @@ -2460,8 +2461,14 @@ s3_in(uint16_t addr, void *p) break; case 0x3c5: - if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) - return svga->seqregs[svga->seqaddr]; + if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) { + 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) && (svga->seqaddr == 0x17)) + svga->seqregs[svga->seqaddr] ^= 0x01; + return temp; + } break; case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: @@ -5884,6 +5891,11 @@ static void *s3_init(const device_t *info) chip = S3_TRIO64V2; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_pci); break; + case S3_TRIO64V2_DX_ONBOARD: + bios_fn = NULL; + chip = S3_TRIO64V2; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64_pci); + break; default: free(s3); return NULL; @@ -6205,6 +6217,7 @@ static void *s3_init(const device_t *info) break; case S3_TRIO64V2_DX: + case S3_TRIO64V2_DX_ONBOARD: svga->decode_mask = (4 << 20) - 1; s3->id = 0xe1; /*Trio64V2/DX*/ s3->id_ext = s3->id_ext_pci = 0x01; @@ -6981,3 +6994,17 @@ const device_t s3_trio64v2_dx_pci_device = s3_standard_config }; + +const device_t s3_trio64v2_dx_onboard_pci_device = +{ + "S3 Trio64V2/DX On-Board PCI", + DEVICE_PCI, + S3_TRIO64V2_DX_ONBOARD, + s3_init, + s3_close, + NULL, + { NULL }, + s3_speed_changed, + s3_force_redraw, + s3_standard_config +}; diff --git a/src/video/vid_table.c b/src/video/vid_table.c index 20b2b11bc..46ea13292 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -235,18 +235,9 @@ video_reset_close(void) } -void -video_reset(int card) +static void +video_prepare(void) { - /* This is needed to avoid duplicate resets. */ - if ((video_get_type() != VIDEO_FLAG_TYPE_NONE) && was_reset) - return; - - vid_table_log("VIDEO: reset (gfxcard=%d, internal=%d)\n", - card, (machines[machine].flags & MACHINE_VIDEO)?1:0); - - loadfont("roms/video/mda/mda.rom", 0); - /* Reset (deallocate) the video font arrays. */ if (fontdatksc5601) { free(fontdatksc5601); @@ -260,14 +251,39 @@ video_reset(int card) /* Reset the blend. */ herc_blend = 0; + /* Do an inform on the default values, so that that there's some sane values initialized + even if the device init function does not do an inform of its own. */ + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_default); +} + + +void +video_pre_reset(int card) +{ + if ((card == VID_NONE) || \ + (card == VID_INTERNAL) || (machines[machine].flags & MACHINE_VIDEO_ONLY)) + video_prepare(); +} + + +void +video_reset(int card) +{ + /* This is needed to avoid duplicate resets. */ + if ((video_get_type() != VIDEO_FLAG_TYPE_NONE) && was_reset) + return; + + vid_table_log("VIDEO: reset (gfxcard=%d, internal=%d)\n", + card, (machines[machine].flags & MACHINE_VIDEO)?1:0); + + loadfont("roms/video/mda/mda.rom", 0); + /* Do not initialize internal cards here. */ if (!(card == VID_NONE) && \ !(card == VID_INTERNAL) && !(machines[machine].flags & MACHINE_VIDEO_ONLY)) { vid_table_log("VIDEO: initializing '%s'\n", video_cards[card].name); - /* Do an inform on the default values, so that that there's some sane values initialized - even if the device init function does not do an inform of its own. */ - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_default); + video_prepare(); /* Initialize the video card. */ device_add(video_cards[card].device); diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index 90872027f..fa522fd43 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -88,10 +88,12 @@ enum { TGUI_9400CXI = 0, TGUI_9440, - TGUI_9660, - TGUI_9680 + TGUI_9660, + TGUI_9680 }; +#define ONBOARD 0x0100 + typedef struct tgui_t { mem_mapping_t linear_mapping; @@ -160,6 +162,8 @@ typedef struct tgui_t volatile int write_blitter; void *i2c, *ddc; + + int has_bios; } tgui_t; video_timings_t timing_tgui_vlb = {VIDEO_BUS, 4, 8, 16, 4, 8, 16}; @@ -908,13 +912,13 @@ uint8_t tgui_pci_read(int func, int addr, void *p) case 0x16: return tgui->mmio_base >> 16; case 0x17: return tgui->mmio_base >> 24; - case 0x30: return (tgui->pci_regs[0x30] & 0x01); /*BIOS ROM address*/ - case 0x31: return 0x00; - case 0x32: return tgui->pci_regs[0x32]; - case 0x33: return tgui->pci_regs[0x33]; - - case 0x3c: return tgui->int_line; - case 0x3d: return PCI_INTA; + case 0x30: return tgui->has_bios ? (tgui->pci_regs[0x30] & 0x01) : 0x00; /*BIOS ROM address*/ + case 0x31: return 0x00; + case 0x32: return tgui->has_bios ? tgui->pci_regs[0x32] : 0x00; + case 0x33: return tgui->has_bios ? tgui->pci_regs[0x33] : 0x00; + + case 0x3c: return tgui->int_line; + case 0x3d: return PCI_INTA; } return 0; } @@ -970,23 +974,25 @@ void tgui_pci_write(int func, int addr, uint8_t val, void *p) tgui->mmio_base = (tgui->mmio_base & 0x00e00000) | (val << 24); tgui_recalcmapping(tgui); break; - - case 0x30: case 0x32: case 0x33: - tgui->pci_regs[addr] = val; - if (tgui->pci_regs[0x30] & 0x01) - { - uint32_t biosaddr = (tgui->pci_regs[0x32] << 16) | (tgui->pci_regs[0x33] << 24); - mem_mapping_set_addr(&tgui->bios_rom.mapping, biosaddr, 0x8000); - } - else - { - mem_mapping_disable(&tgui->bios_rom.mapping); - } - return; - - case 0x3c: - tgui->int_line = val; - return; + + case 0x30: case 0x32: case 0x33: + if (tgui->has_bios) { + tgui->pci_regs[addr] = val; + if (tgui->pci_regs[0x30] & 0x01) + { + uint32_t biosaddr = (tgui->pci_regs[0x32] << 16) | (tgui->pci_regs[0x33] << 24); + mem_mapping_set_addr(&tgui->bios_rom.mapping, biosaddr, 0x8000); + } + else + { + mem_mapping_disable(&tgui->bios_rom.mapping); + } + } + return; + + case 0x3c: + tgui->int_line = val; + return; } } @@ -2801,16 +2807,15 @@ tgui_mmio_read_l(uint32_t addr, void *p) static void *tgui_init(const device_t *info) { const char *bios_fn; - int type = info->local; tgui_t *tgui = malloc(sizeof(tgui_t)); - svga_t *svga = &tgui->svga; + svga_t *svga = &tgui->svga; memset(tgui, 0, sizeof(tgui_t)); tgui->vram_size = device_get_config_int("memory") << 20; tgui->vram_mask = tgui->vram_size - 1; - tgui->type = type; + tgui->type = info->local & 0xff; tgui->pci = !!(info->flags & DEVICE_PCI); @@ -2819,7 +2824,7 @@ static void *tgui_init(const device_t *info) bios_fn = ROM_TGUI_9400CXI; break; case TGUI_9440: - bios_fn = ROM_TGUI_9440; + bios_fn = (info->local & ONBOARD) ? NULL : ROM_TGUI_9440; break; case TGUI_9660: case TGUI_9680: @@ -2830,7 +2835,10 @@ static void *tgui_init(const device_t *info) return NULL; } - rom_init(&tgui->bios_rom, (char *) bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + tgui->has_bios = (bios_fn != NULL); + + if (tgui->has_bios) + rom_init(&tgui->bios_rom, (char *) bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); if (tgui->pci) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_tgui_pci); @@ -2844,33 +2852,39 @@ static void *tgui_init(const device_t *info) NULL); if (tgui->type == TGUI_9400CXI) - svga->ramdac = device_add(&tkd8001_ramdac_device); + svga->ramdac = device_add(&tkd8001_ramdac_device); mem_mapping_add(&tgui->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, tgui_accel_write_fb_b, tgui_accel_write_fb_w, tgui_accel_write_fb_l, NULL, MEM_MAPPING_EXTERNAL, svga); mem_mapping_add(&tgui->accel_mapping, 0, 0, tgui_accel_read, tgui_accel_read_w, tgui_accel_read_l, tgui_accel_write, tgui_accel_write_w, tgui_accel_write_l, NULL, MEM_MAPPING_EXTERNAL, tgui); - if (tgui->type >= TGUI_9440) - mem_mapping_add(&tgui->mmio_mapping, 0, 0, tgui_mmio_read, tgui_mmio_read_w, tgui_mmio_read_l, tgui_mmio_write, tgui_mmio_write_w, tgui_mmio_write_l, NULL, MEM_MAPPING_EXTERNAL, tgui); + if (tgui->type >= TGUI_9440) + mem_mapping_add(&tgui->mmio_mapping, 0, 0, tgui_mmio_read, tgui_mmio_read_w, tgui_mmio_read_l, tgui_mmio_write, tgui_mmio_write_w, tgui_mmio_write_l, NULL, MEM_MAPPING_EXTERNAL, tgui); mem_mapping_disable(&tgui->accel_mapping); - mem_mapping_disable(&tgui->mmio_mapping); + mem_mapping_disable(&tgui->mmio_mapping); - tgui_set_io(tgui); + tgui_set_io(tgui); - if (tgui->pci && (tgui->type >= TGUI_9440)) + if (tgui->pci && (tgui->type >= TGUI_9440)) { + if (tgui->has_bios) tgui->card = pci_add_card(PCI_ADD_VIDEO, tgui_pci_read, tgui_pci_write, tgui); + else + tgui->card = pci_add_card(PCI_ADD_VIDEO | PCI_ADD_STRICT, tgui_pci_read, tgui_pci_write, tgui); + } - tgui->pci_regs[PCI_REG_COMMAND] = 3; + tgui->pci_regs[PCI_REG_COMMAND] = 3; + if (tgui->has_bios) { tgui->pci_regs[0x30] = 0x00; tgui->pci_regs[0x32] = 0x0c; tgui->pci_regs[0x33] = 0x00; + } - if (tgui->type >= TGUI_9440) - svga->packed_chain4 = 1; - - if (tgui->type >= TGUI_9660) { - tgui->i2c = i2c_gpio_init("ddc_tgui"); - tgui->ddc = ddc_init(i2c_gpio_get_bus(tgui->i2c)); - } + if (tgui->type >= TGUI_9440) + svga->packed_chain4 = 1; + + if (tgui->type >= TGUI_9660) { + tgui->i2c = i2c_gpio_init("ddc_tgui"); + tgui->ddc = ddc_init(i2c_gpio_get_bus(tgui->i2c)); + } return tgui; } @@ -3019,6 +3033,20 @@ const device_t tgui9440_pci_device = tgui9440_config }; +const device_t tgui9440_onboard_pci_device = +{ + "Trident TGUI 9440AGi On-Board PCI", + DEVICE_PCI, + TGUI_9440 | ONBOARD, + tgui_init, + tgui_close, + NULL, + { NULL }, + tgui_speed_changed, + tgui_force_redraw, + tgui9440_config +}; + const device_t tgui9660_pci_device = { "Trident TGUI 9660XGi PCI", diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 9b01db329..bcea4ab6e 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -328,7 +328,7 @@ else endif endif ifeq ($(DEBUG), y) - DFLAGS += -ggdb -DDEBUG + DFLAGS += -ggdb -DDEBUG -DUSE_ACYCS AOPTIM := ifndef COPTIM COPTIM := -Og @@ -599,6 +599,7 @@ CHIPSETOBJ := acc2168.o \ scamp.o scat.o \ stpc.o \ wd76c10.o vl82c480.o \ + umc_8886.o umc_hb4.o \ via_vt82c49x.o via_vt82c505.o via_apollo.o via_pipc.o \ sis_85c310.o sis_85c4xx.o sis_85c496.o sis_85c50x.o sis_5511.o sis_5571.o @@ -645,8 +646,8 @@ DEVOBJ := bugger.o cartridge.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hw endif SIOOBJ := sio_acc3221.o \ - sio_f82c710.o sio_82091aa.o sio_fdc37c651.o \ - sio_fdc37c661.o sio_fdc37c66x.o sio_fdc37c67x.o sio_fdc37c669.o sio_fdc37c93x.o sio_fdc37m60x.o \ + sio_f82c710.o sio_82091aa.o sio_fdc37c6xx.o \ + sio_fdc37c67x.o sio_fdc37c669.o sio_fdc37c93x.o sio_fdc37m60x.o \ sio_it8661f.o \ sio_pc87306.o sio_pc87307.o sio_pc87309.o sio_pc87310.o sio_pc87311.o sio_pc87332.o \ sio_prime3b.o sio_prime3c.o \ From 2f3bb38dde83af94a4c31805d533d136569cc710 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 23 Aug 2021 17:26:40 +0200 Subject: [PATCH 59/96] Implemented the UMOV instruction on a number of CPU's, needed by some Phoenix BIOS'es. --- src/cpu/386_ops.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index 5b472298b..8d2b9edf9 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -148,9 +148,9 @@ static int fopcode; static int ILLEGAL(uint32_t fetchdat) { + pclog("[%04X:%08X] Illegal instruction %08X (%02X)\n", CS, cpu_state.pc, fetchdat, fopcode); cpu_state.pc = cpu_state.oldpc; - pclog("Illegal instruction %08X (%02X)\n", fetchdat, fopcode); x86illegal(); return 0; } @@ -457,7 +457,7 @@ const OpFn OP_TABLE(386_0f)[1024] = /*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, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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, @@ -479,7 +479,7 @@ const OpFn OP_TABLE(386_0f)[1024] = /*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, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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, @@ -501,7 +501,7 @@ const OpFn OP_TABLE(386_0f)[1024] = /*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, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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, @@ -523,7 +523,7 @@ const OpFn OP_TABLE(386_0f)[1024] = /*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, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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, @@ -548,7 +548,7 @@ const OpFn OP_TABLE(486_0f)[1024] = /*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, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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, @@ -570,7 +570,7 @@ const OpFn OP_TABLE(486_0f)[1024] = /*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, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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, @@ -592,7 +592,7 @@ const OpFn OP_TABLE(486_0f)[1024] = /*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, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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, @@ -614,7 +614,7 @@ const OpFn OP_TABLE(486_0f)[1024] = /*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, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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, @@ -821,7 +821,7 @@ const OpFn OP_TABLE(ibm486_0f)[1024] = /*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, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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*/ opWRMSR, ILLEGAL, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -843,7 +843,7 @@ const OpFn OP_TABLE(ibm486_0f)[1024] = /*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, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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*/ opWRMSR, ILLEGAL, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -865,7 +865,7 @@ const OpFn OP_TABLE(ibm486_0f)[1024] = /*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, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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*/ opWRMSR, ILLEGAL, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -887,7 +887,7 @@ const OpFn OP_TABLE(ibm486_0f)[1024] = /*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, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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*/ opWRMSR, ILLEGAL, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1094,7 +1094,7 @@ const OpFn OP_TABLE(pentium_0f)[1024] = /*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, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1116,7 +1116,7 @@ const OpFn OP_TABLE(pentium_0f)[1024] = /*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, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1138,7 +1138,7 @@ const OpFn OP_TABLE(pentium_0f)[1024] = /*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, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1160,7 +1160,7 @@ const OpFn OP_TABLE(pentium_0f)[1024] = /*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, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, 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*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, From b798b59a698963e3ace6605a92fd09db4d676fd5 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 23 Aug 2021 21:48:42 +0200 Subject: [PATCH 60/96] Some ALi M1429G changes, including returning registers in the Cyrix range as FF. --- src/chipset/ali1429.c | 100 +++++++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 45 deletions(-) diff --git a/src/chipset/ali1429.c b/src/chipset/ali1429.c index 08cc6ff14..da8ded3ab 100644 --- a/src/chipset/ali1429.c +++ b/src/chipset/ali1429.c @@ -38,17 +38,19 @@ #include <86box/smram.h> #include <86box/chipset.h> -#define disabled_shadow (MEM_READ_EXTANY | MEM_WRITE_EXTANY) +#define disabled_shadow (MEM_READ_EXTANY | MEM_WRITE_EXTANY) + #ifdef ENABLE_ALI1429_LOG int ali1429_do_log = ENABLE_ALI1429_LOG; + + static void ali1429_log(const char *fmt, ...) { va_list ap; - if (ali1429_do_log) - { + if (ali1429_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); @@ -58,17 +60,19 @@ ali1429_log(const char *fmt, ...) #define ali1429_log(fmt, ...) #endif + typedef struct { - uint8_t index, cfg_locked, - regs[256]; + uint8_t index, cfg_locked, + regs[256]; - smram_t *smram; + smram_t * smram; } ali1429_t; -static void ali1429_shadow_recalc(ali1429_t *dev) -{ +static void +ali1429_shadow_recalc(ali1429_t *dev) +{ uint32_t base, i, can_write, can_read; shadowbios = (dev->regs[0x13] & 0x40) && (dev->regs[0x14] & 0x01); @@ -77,8 +81,7 @@ static void ali1429_shadow_recalc(ali1429_t *dev) can_write = (dev->regs[0x14] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; can_read = (dev->regs[0x14] & 0x01) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - for (i = 0; i < 8; i++) - { + for (i = 0; i < 8; i++) { base = 0xc0000 + (i << 15); if (dev->regs[0x13] & (1 << i)) @@ -87,56 +90,61 @@ static void ali1429_shadow_recalc(ali1429_t *dev) mem_set_mem_state_both(base, 0x8000, disabled_shadow); } - flushmmucache(); + flushmmucache_nopc(); } + static void ali1429_write(uint16_t addr, uint8_t val, void *priv) { ali1429_t *dev = (ali1429_t *)priv; - switch (addr) - { - case 0x22: - dev->index = val; - break; + switch (addr) { + case 0x22: + dev->index = val; + break; - case 0x23: - if (dev->index != 0x03) - ali1429_log("M1429: dev->regs[%02x] = %02x\n", dev->index, val); + case 0x23: +#ifdef ENABLE_ALI1429_LOG + if (dev->index != 0x03) + ali1429_log("M1429: dev->regs[%02x] = %02x\n", dev->index, val); +#endif - if (dev->index == 0x03) - dev->cfg_locked = !(val == 0xc5); + if (dev->index == 0x03) + dev->cfg_locked = !(val == 0xc5); - if (!dev->cfg_locked) - { - dev->regs[dev->index] = val; + if (!dev->cfg_locked) { + dev->regs[dev->index] = val; - switch (dev->index) - { - case 0x13: - case 0x14: - ali1429_shadow_recalc(dev); - break; + switch (dev->index) { + case 0x13: case 0x14: + ali1429_shadow_recalc(dev); + break; - case 0x18: - cpu_cache_ext_enabled = !!(val & 2); - cpu_update_waitstates(); - break; - } - } - - break; + case 0x18: + cpu_cache_ext_enabled = !!(val & 2); + cpu_update_waitstates(); + break; + } + } + break; } } + static uint8_t ali1429_read(uint16_t addr, void *priv) { ali1429_t *dev = (ali1429_t *)priv; - return (addr == 0x23) ? dev->regs[dev->index] : 0xff; + uint8_t ret = 0xff; + + if ((addr == 0x23) && (dev->index < 0xc0)) + ret = dev->regs[dev->index]; + + return ret; } + static void ali1429_close(void *priv) { @@ -145,16 +153,16 @@ ali1429_close(void *priv) free(dev); } + static void * ali1429_init(const device_t *info) { ali1429_t *dev = (ali1429_t *)malloc(sizeof(ali1429_t)); memset(dev, 0, sizeof(ali1429_t)); - /* - M1429 Ports: - 22h Index Port - 23h Data Port + /* M1429 Ports: + 22h Index Port + 23h Data Port */ io_sethandler(0x0022, 0x0002, ali1429_read, NULL, NULL, ali1429_write, NULL, NULL, dev); @@ -167,6 +175,7 @@ ali1429_init(const device_t *info) return dev; } + const device_t ali1429_device = { "ALi M1429", 0, @@ -174,7 +183,8 @@ const device_t ali1429_device = { ali1429_init, ali1429_close, NULL, - {NULL}, + { NULL }, NULL, NULL, - NULL}; + NULL +}; From 3ddbca6fca0b9c306b9c28071def6ff085b7e9bb Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 23 Aug 2021 22:01:25 +0200 Subject: [PATCH 61/96] Merged tiseno100's ALi M1429(G) changes. --- src/chipset/ali1429.c | 151 +++++++++++++++++++++++++++++++----- src/include/86box/chipset.h | 1 + 2 files changed, 132 insertions(+), 20 deletions(-) diff --git a/src/chipset/ali1429.c b/src/chipset/ali1429.c index da8ded3ab..2ccddc1be 100644 --- a/src/chipset/ali1429.c +++ b/src/chipset/ali1429.c @@ -38,7 +38,7 @@ #include <86box/smram.h> #include <86box/chipset.h> -#define disabled_shadow (MEM_READ_EXTANY | MEM_WRITE_EXTANY) +#define GREEN dev->is_g /* Is G Variant */ #ifdef ENABLE_ALI1429_LOG @@ -63,10 +63,8 @@ ali1429_log(const char *fmt, ...) typedef struct { - uint8_t index, cfg_locked, - regs[256]; - - smram_t * smram; + uint8_t is_g, index, cfg_locked, reg_57h, + regs[90]; } ali1429_t; @@ -87,7 +85,7 @@ ali1429_shadow_recalc(ali1429_t *dev) if (dev->regs[0x13] & (1 << i)) mem_set_mem_state_both(base, 0x8000, can_read | can_write); else - mem_set_mem_state_both(base, 0x8000, disabled_shadow); + mem_set_mem_state_both(base, 0x8000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); } flushmmucache_nopc(); @@ -114,17 +112,93 @@ ali1429_write(uint16_t addr, uint8_t val, void *priv) dev->cfg_locked = !(val == 0xc5); if (!dev->cfg_locked) { - dev->regs[dev->index] = val; - + /* Common M1429 Registers */ switch (dev->index) { + case 0x10: case 0x11: + dev->regs[dev->index] = val; + break; + + case 0x12: + dev->regs[dev->index] = val; + if(val & 4) + mem_remap_top(128); + else + mem_remap_top(0); + break; + case 0x13: case 0x14: + dev->regs[dev->index] = val; ali1429_shadow_recalc(dev); break; + case 0x15: case 0x16: + case 0x17: + dev->regs[dev->index] = val; + break; + case 0x18: + dev->regs[dev->index] = (val & 0x8f) | 0x20; cpu_cache_ext_enabled = !!(val & 2); cpu_update_waitstates(); break; + + case 0x19: case 0x1a: + case 0x1e: + dev->regs[dev->index] = val; + break; + + case 0x20: + dev->regs[dev->index] = val; + + switch(val & 7) { + case 0: case 7: /* Illegal */ + cpu_set_isa_speed(7159091); + break; + + case 1: + cpu_set_isa_speed(cpu_busspeed / 4); + break; + + case 2: + cpu_set_isa_speed(cpu_busspeed / 5); + break; + + case 3: + cpu_set_isa_speed(cpu_busspeed / 6); + break; + + case 4: + cpu_set_isa_speed(cpu_busspeed / 8); + break; + + case 5: + cpu_set_isa_speed(cpu_busspeed / 10); + break; + + case 6: + cpu_set_isa_speed(cpu_busspeed / 12); + break; + } + break; + + case 0x21 ... 0x27: + dev->regs[dev->index] = val; + break; + } + + /* M1429G Only Registers */ + if (GREEN) { + switch (dev->index) { + case 0x30 ... 0x41: + case 0x43: case 0x45: + case 0x4a: + dev->regs[dev->index] = val; + break; + + case 0x57: + dev->reg_57h = val; + break; + } } } break; @@ -138,8 +212,12 @@ ali1429_read(uint16_t addr, void *priv) ali1429_t *dev = (ali1429_t *)priv; uint8_t ret = 0xff; - if ((addr == 0x23) && (dev->index < 0xc0)) + if ((addr == 0x23) && (dev->index >= 0x10) && (dev->index <= 0x4a)) ret = dev->regs[dev->index]; + else if ((addr == 0x23) && (dev->index == 0x57)) + ret = dev->reg_57h; + else if (addr == 0x22) + ret = dev->index; return ret; } @@ -154,37 +232,70 @@ ali1429_close(void *priv) } +static void +ali1429_defaults(ali1429_t *dev) +{ + /* M1429 Defaults */ + dev->regs[0x10] = 0xf0; + dev->regs[0x11] = 0xff; + dev->regs[0x12] = 0x10; + dev->regs[0x14] = 0x48; + dev->regs[0x15] = 0x40; + dev->regs[0x17] = 0x7a; + dev->regs[0x1a] = 0x80; + dev->regs[0x22] = 0x80; + dev->regs[0x23] = 0x57; + dev->regs[0x25] = 0xc0; + dev->regs[0x27] = 0x30; + + /* M1429G Default Registers */ + if (GREEN) { + dev->regs[0x31] = 0x88; + dev->regs[0x32] = 0xc0; + dev->regs[0x38] = 0xe5; + dev->regs[0x40] = 0xe3; + dev->regs[0x41] = 2; + dev->regs[0x45] = 0x80; + } +} + + static void * ali1429_init(const device_t *info) { ali1429_t *dev = (ali1429_t *)malloc(sizeof(ali1429_t)); memset(dev, 0, sizeof(ali1429_t)); + dev->cfg_locked = 1; + GREEN = info->local; + /* M1429 Ports: 22h Index Port 23h Data Port */ io_sethandler(0x0022, 0x0002, ali1429_read, NULL, NULL, ali1429_write, NULL, NULL, dev); - dev->cfg_locked = 1; - - device_add(&apm_device); device_add(&port_92_device); - /* dev->smram = smram_add(); */ + + ali1429_defaults(dev); return dev; } - const device_t ali1429_device = { "ALi M1429", 0, 0, - ali1429_init, - ali1429_close, - NULL, - { NULL }, - NULL, - NULL, + ali1429_init, ali1429_close, NULL, + { NULL }, NULL, NULL, + NULL +}; + +const device_t ali1429g_device = { + "ALi M1429G", + 0, + 1, + ali1429_init, ali1429_close, NULL, + { NULL }, NULL, NULL, NULL }; diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index 83642fe62..9a7db6c64 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -24,6 +24,7 @@ extern const device_t acc2168_device; /* ALi */ extern const device_t ali1217_device; extern const device_t ali1429_device; +extern const device_t ali1429g_device; extern const device_t ali1489_device; extern const device_t ali1531_device; extern const device_t ali1541_device; From d30ad04a88b897597fe036579c7aff109858bec9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 24 Aug 2021 21:11:00 +0200 Subject: [PATCH 62/96] UMC UM88xx fixes, ALi M1429 documentation, and added the DataExpert 386SX, PC Chips M919, Samsung SPC7700P-LW, and Acrosser AR-B1423C. Also renamed the ALi M1429G AMI WinBIOS 486 to Kaimei 486. --- src/chipset/ali1429.c | 66 ++++++++++++++++-- src/chipset/umc_8886.c | 62 +++++++++++------ src/chipset/umc_hb4.c | 20 ++++-- src/include/86box/machine.h | 6 +- src/machine/m_at_286_386sx.c | 30 +++++++-- src/machine/m_at_386dx_486.c | 127 ++++++++++++++++++++++++++++++----- src/machine/machine_table.c | 29 +++++--- 7 files changed, 277 insertions(+), 63 deletions(-) diff --git a/src/chipset/ali1429.c b/src/chipset/ali1429.c index 2ccddc1be..b96ec7896 100644 --- a/src/chipset/ali1429.c +++ b/src/chipset/ali1429.c @@ -8,15 +8,71 @@ * * Implementation of the ALi M1429 chipset. * - * Note: This chipset has no datasheet, everything were done via - * reverse engineering the BIOS of various machines using it. + * Note: This chipset has no datasheet, everything were done via + * reverse engineering the BIOS of various machines using it. * - * Authors: Tiseno100 - * - * Copyright 2020 Tiseno100 + * Authors: Tiseno100, + * Miran Grca, * + * Copyright 2020,2021 Tiseno100. + * Copyright 2021,2021 Miran Grca. */ +/* + ALi M1429/M1429G Configuration Registers + + Notes: Incorporated sometimes with a M1435 PCI-to-VLB Bridge + M1429G is just a 1429 with Green Functionality + SMM in it's entirety needs more research + + Warning: Register documentation may be inaccurate! + + Register 03h: Write C5h to unlock the configuration registers + + Register 10h & 11h: DRAM Bank Configuration + + Register 12h: + Bit 2: Memory Remapping Enable (128KB) + + Register 13h: + Bit 7: Shadow RAM Enable for F8000-FFFFF + Bit 6: Shadow RAM Enable for F0000-F7FFF + Bit 5: Shadow RAM Enable for E8000-FFFFF + Bit 4: Shadow RAM Enable for E0000-F7FFF + Bit 3: Shadow RAM Enable for D8000-FFFFF + Bit 2: Shadow RAM Enable for D0000-F7FFF + Bit 1: Shadow RAM Enable for C8000-FFFFF + Bit 0: Shadow RAM Enable for C0000-F7FFF + + Register 14h: + Bit 1: Shadow RAM Write for Enabled Segments + Bit 0: Shadow RAM Read for Enabled Segments + + Register 18h: + Bit 6-5-4 (Cache Size) + 0 0 0 32KB + 0 0 1 128KB + 0 1 0 256KB + 0 1 1 512KB + 1 0 0 64KB + 1 0 1 256KB + 1 1 0 512KB + 1 1 1 1MB + + Bit 1: L2 Cache Enable + + Register 20h: + Bits 2-1-0: Bus Clock Speed + 0 0 0: 7.1519Mhz (ATCLK2) + 0 0 1: CLK2IN/4 + 0 1 0: CLK2IN/5 + 0 1 1: CLK2IN/6 + 1 0 0: CLK2IN/8 + 1 0 1: CLK2IN/10 + 1 1 0: CLK2IN/12 + +*/ + #include #include #include diff --git a/src/chipset/umc_8886.c b/src/chipset/umc_8886.c index b3e721e9f..a8962030b 100644 --- a/src/chipset/umc_8886.c +++ b/src/chipset/umc_8886.c @@ -12,8 +12,10 @@ * reverse engineering the BIOS of various machines using it. * * Authors: Tiseno100, + * Miran Grca, * * Copyright 2021 Tiseno100. + * Copyright 2021 Miran Grca. */ /* @@ -35,9 +37,9 @@ Bits 7-4 PCI IRQ for INTD Bits 3-0 PCI IRQ for INTC - Function 0 Register 46: - Bit 7: PMU Trigger(1: By IRQ/0: By SMI) - Bit 6: IRQ SMI Request (1: IRQ 10) (Supposedly 0 according to Phoenix is IRQ 15 but doesn't seem to make sense) + Function 0 Register 46 (corrected by Miran Grca): + Bit 7: IRQ SMI Request (1: IRQ 15, 0: IRQ 10) + Bit 6: PMU Trigger(1: By IRQ/0: By SMI) Function 0 Register 56: Bit 1-0 ISA Bus Speed @@ -45,9 +47,17 @@ 0 1 PCICLK/4 1 0 PCICLK/2 - Function 0 Register A3: + Function 0 Register A2 - non-software SMI# status register + (documented by Miran Grca): + Bit 4: I set, graphics card goes into sleep mode + This register is most likely R/WC + + Function 0 Register A3 (added more details by Miran Grca): Bit 7: Unlock SMM - Bit 6: Software SMI trigger + Bit 6: Software SMI trigger (also doubles as software SMI# status register, + cleared by writing a 0 to it - see the handler used by Phoenix BIOS'es): + If Function 0 Register 46 Bit 6 is set, it raises the specified IRQ (15 + or 10) instead. Function 0 Register A4: Bit 0: Host to PCI Clock (1: 1 by 1/0: 1 by half) @@ -78,6 +88,9 @@ #include <86box/chipset.h> +#define IDE_BIT 0x01 + + #ifdef ENABLE_UMC_8886_LOG int umc_8886_do_log = ENABLE_UMC_8886_LOG; @@ -113,10 +126,10 @@ umc_8886_log(const char *fmt, ...) typedef struct umc_8886_t { - uint8_t pci_conf_sb[2][256]; /* PCI Registers */ + uint8_t max_func, /* Last function number */ + pci_conf_sb[2][256]; /* PCI Registers */ uint16_t sb_id; /* Southbridge Revision */ int has_ide; /* Check if Southbridge Revision is AF or F */ - } umc_8886_t; @@ -138,7 +151,7 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) { umc_8886_t *dev = (umc_8886_t *)priv; - switch (func) { + if (func <= dev->max_func) switch (func) { case 0: /* PCI to ISA Bridge */ umc_8886_log("UM8886: dev->regs[%02x] = %02x POST %02x\n", addr, val, inb(0x80)); @@ -171,11 +184,8 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) break; case 0x46: + /* Bit 6 seems to be the IRQ/SMI# toggle, 1 = IRQ, 0 = SMI#. */ dev->pci_conf_sb[func][addr] = val; - - if (val & 0x40) - picint(1 << ((val & 0x80) ? 15 : 10)); - break; case 0x47: @@ -208,17 +218,25 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) case 0x70 ... 0x76: case 0x80: case 0x81: case 0x90 ... 0x92: - case 0xa0 ... 0xa2: + case 0xa0 ... 0xa1: dev->pci_conf_sb[func][addr] = val; break; + case 0xa2: + dev->pci_conf_sb[func][addr] &= ~val; + break; + case 0xa3: + /* SMI Provocation (Bit 7 Enable SMM + Bit 6 Software SMI) */ + if (((val & 0xc0) == 0xc0) && !(dev->pci_conf_sb[0][0xa3] & 0x40)) { + if (dev->pci_conf_sb[0][0x46] & 0x40) + picint(1 << ((dev->pci_conf_sb[0][0x46] & 0x80) ? 15 : 10)); + else + smi_line = 1; + dev->pci_conf_sb[0][0xa3] |= 0x04; + } + dev->pci_conf_sb[func][addr] = val; - - /* SMI Provocation (Bit 7 Enable SMM + Bit 6 Software SMI */ - if (((dev->pci_conf_sb[0][0xa3] >> 6) == 3) && !in_smm) - smi_line = 1; - break; case 0xa4: @@ -259,8 +277,12 @@ static uint8_t umc_8886_read(int func, int addr, void *priv) { umc_8886_t *dev = (umc_8886_t *)priv; + uint8_t ret = 0xff; - return dev->pci_conf_sb[func][addr]; + if (func <= dev->max_func) + ret = dev->pci_conf_sb[func][addr]; + + return ret; } @@ -339,6 +361,8 @@ umc_8886_init(const device_t *info) if (HAS_IDE) device_add(&ide_pci_2ch_device); + dev->max_func = (HAS_IDE) ? 1 : 0; + /* Get the Southbridge Revision */ SB_ID = info->local; diff --git a/src/chipset/umc_hb4.c b/src/chipset/umc_hb4.c index 136fc03a0..ca544f7ac 100644 --- a/src/chipset/umc_hb4.c +++ b/src/chipset/umc_hb4.c @@ -15,8 +15,10 @@ * around the web. * * Authors: Tiseno100, + * Miran Grca, * * Copyright 2021 Tiseno100. + * Copyright 2021 Miran Grca. */ /* @@ -81,11 +83,9 @@ Register 58h & 59h: DRAM Bank 1 Configuration Register 60: - Bit 5-4: SMRAM Position(Lot's of uncertainty to those bits) - 0 0 A0000 to E0000 - 1 0 A0000 to ????? (Phoenix uses it to no avail) - - Bit 0: SMRAM Local Access Enable + 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 + SMRAM appears to always be enabled in SMM, and always set to A0000-BFFFF. */ #include @@ -165,7 +165,17 @@ hb4_smram(hb4_t *dev) { smram_disable_all(); + /* 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, 0x000a0000, 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); + } } diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index a805dc4ba..cd3cce9b8 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -277,6 +277,7 @@ extern int machine_at_shuttle386sx_init(const machine_t *); extern int machine_at_adi386sx_init(const machine_t *); extern int machine_at_cmdsl386sx16_init(const machine_t *); extern int machine_at_cmdsl386sx25_init(const machine_t *); +extern int machine_at_dataexpert386sx_init(const machine_t *); extern int machine_at_spc6033p_init(const machine_t *); extern int machine_at_wd76c10_init(const machine_t *); extern int machine_at_arb1374_init(const machine_t *); @@ -288,7 +289,7 @@ extern int machine_at_prox1332_init(const machine_t *); extern int machine_at_awardsx_init(const machine_t *); -extern int machine_at_pc916sx_init(const machine_t *); +extern int machine_at_pc916sx_init(const machine_t *); #ifdef EMU_DEVICE_H extern const device_t *at_ama932j_get_device(void); @@ -366,6 +367,7 @@ extern int machine_at_sbc_490_init(const machine_t *); extern int machine_at_tf_486_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_pcm9340_init(const machine_t *); extern int machine_at_pcm5330_init(const machine_t *); @@ -374,6 +376,8 @@ extern int machine_at_ecs486_init(const machine_t *); extern int machine_at_hot433_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_m919_init(const machine_t *); +extern int machine_at_spc7700p_lw_init(const machine_t *); #ifdef EMU_DEVICE_H extern const device_t *at_acera1g_get_device(void); diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index b4d5b4ed6..c2f9a433d 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -590,14 +590,17 @@ machine_at_cmdsl386sx16_init(const machine_t *model) static void -machine_at_scamp_common_init(const machine_t *model) +machine_at_scamp_common_init(const machine_t *model, int is_ps2) { machine_at_common_ide_init(model); - device_add(&keyboard_ps2_ami_device); + if (is_ps2) + device_add(&keyboard_ps2_ami_device); + else + device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); device_add(&vlsi_scamp_device); } @@ -624,7 +627,24 @@ machine_at_cmdsl386sx25_init(const machine_t *model) if (gfxcard == VID_INTERNAL) device_add(&gd5402_onboard_device); - machine_at_scamp_common_init(model); + machine_at_scamp_common_init(model, 1); + + return ret; +} + + +int +machine_at_dataexpert386sx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/dataexpert386sx/5e9f20e5ef967717086346.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_scamp_common_init(model, 0); return ret; } @@ -651,7 +671,7 @@ machine_at_spc6033p_init(const machine_t *model) if (gfxcard == VID_INTERNAL) device_add(&ati28800k_spc6033p_device); - machine_at_scamp_common_init(model); + machine_at_scamp_common_init(model, 1); return ret; } diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index cf27a999d..2068b3c88 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -412,7 +412,7 @@ machine_at_acera1g_init(const machine_t *model) return ret; machine_at_common_init(model); - device_add(&ali1429_device); + device_add(&ali1429g_device); if (gfxcard == VID_INTERNAL) device_add(&gd5428_onboard_device); @@ -482,11 +482,14 @@ machine_at_decpc_lpv_init(const machine_t *model) } static void -machine_at_ali1429_common_init(const machine_t *model) +machine_at_ali1429_common_init(const machine_t *model, int is_green) { machine_at_common_ide_init(model); - device_add(&ali1429_device); + if (is_green) + device_add(&ali1429g_device); + else + device_add(&ali1429_device); device_add(&keyboard_at_ami_device); @@ -506,7 +509,7 @@ machine_at_ali1429_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_ali1429_common_init(model); + machine_at_ali1429_common_init(model, 0); return ret; } @@ -523,7 +526,7 @@ machine_at_winbios1429_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_ali1429_common_init(model); + machine_at_ali1429_common_init(model, 1); return ret; } @@ -1450,6 +1453,34 @@ machine_at_itoxstar_init(const machine_t *model) } +int +machine_at_arb1423c_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/arb1423c/A1423C.v12", + 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); + pci_register_slot(0x1F, PCI_CARD_NORMAL, 1, 0, 0, 0); + pci_register_slot(0x1E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x1D, PCI_CARD_NORMAL, 3, 4, 1, 2); + device_add(&w83977f_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&stpc_consumer2_device); + device_add(&winbond_flash_w29c020_device); + + return ret; +} + + int machine_at_arb1479_init(const machine_t *model) { @@ -1552,10 +1583,10 @@ machine_at_ecs486_init(const machine_t *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(0x0f, PCI_CARD_IDE, 0, 0, 0, 0); - pci_register_slot(0x0c, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0d, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0e, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0F, PCI_CARD_IDE, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); device_add(&umc_hb4_device); device_add(&umc_8886f_device); @@ -1584,10 +1615,10 @@ machine_at_hot433_init(const machine_t *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(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); + 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); @@ -1615,7 +1646,7 @@ machine_at_atc1415_init(const machine_t *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(0x0c, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); @@ -1646,10 +1677,10 @@ machine_at_actionpc2600_init(const machine_t *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(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); + 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); @@ -1659,3 +1690,63 @@ machine_at_actionpc2600_init(const machine_t *model) return ret; } + + +int +machine_at_m919_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/m919/9190914s.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(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); + + device_add(&umc_hb4_device); + device_add(&umc_8886af_device); + device_add(&um8669f_device); + device_add(&sst_flash_29ee010_device); + device_add(&keyboard_at_ami_device); + + return ret; +} + + +int +machine_at_spc7700p_lw_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/spc7700p-lw/77LW13FH.P24", + 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(0x0C, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); + + device_add(&umc_hb4_device); + device_add(&umc_8886af_device); + device_add(&fdc37c665_device); + device_add(&intel_flash_bxt_device); + device_add(&keyboard_at_ami_device); + + return ret; +} diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index b458b5a5f..77c5fbea4 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -99,11 +99,7 @@ const machine_type_t machine_types[] = { Write Input Port, same as on AMIKey-3. Machines to remove: - - Hedaka HED-919; - - A-Trend ATC-1415; - - ECS Elite UM8810PAIO; - - Shuttle HOT-433A; - - Azza 5IVG (if a more interesting machine with Prime3C is found). + - Hedaka HED-919. */ @@ -276,6 +272,10 @@ const machine_t machines[] = { the IBM PS/2 Type 1 KBC firmware unless evidence emerges of any proprietary commands. */ { "[SCAMP] Commodore SL386SX-25", "cmdsl386sx25", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 8192, 512, 127, machine_at_cmdsl386sx25_init, at_cmdsl386sx25_get_device }, + /* The closest BIOS string I find to this one's, differs only in one part, + and ends in -8, so I'm going to assume that this, too, has an AMI '8' + (AMI Keyboard BIOS Plus) KBC firmware. */ + { "[SCAMP] DataExpert 386SX", "dataexpert386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 10000000, 25000000, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_dataexpert386sx_init, NULL }, /* Has IBM PS/2 Type 1 KBC firmware. */ { "[SCAMP] Samsung SPC-6033P", "spc6033p", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 12288, 2048, 127, machine_at_spc6033p_init, at_spc6033p_get_device }, /* Has an unknown AMI KBC firmware, I'm going to assume 'F' until a @@ -297,6 +297,7 @@ const machine_t machines[] = { { "[ACC 2168] AMI 386DX clone", "acc386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_acc386_init, NULL }, /* Has an AMI Keyboard BIOS PLUS KBC firmware ('8'). */ { "[C&T 386] ECS 386/32", "ecs386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_ecs386_init, NULL }, + /* Has IBM AT KBC firmware. */ { "[C&T 386] Samsung SPC-6000A", "spc6000a", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_spc6000a_init, NULL }, /* Uses Compaq KBC firmware. */ { "[ISA] Compaq Portable III (386)", "portableiii386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_VIDEO, 1024, 14336, 1024, 127, machine_at_portableiii386_init, at_cpqiii_get_device }, @@ -366,7 +367,7 @@ const machine_t machines[] = { { "[ALi M1429G] Acer A1G", "acera1g", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 4096, 36864, 1024, 127, machine_at_acera1g_init, at_acera1g_get_device }, /* There are two similar BIOS strings with -H, and one with -U, so I'm going to give it an AMIKey H KBC firmware. */ - { "[ALi M1429G] AMI WinBIOS 486", "win486", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_winbios1429_init, NULL }, + { "[ALi M1429G] Kaimei 486", "win486", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_winbios1429_init, NULL }, /* Uses an Intel KBC with Phoenix MultiKey KBC firmware. */ { "[SiS 461] DEC DECpc LPV", "decpc_lpv", MACHINE_TYPE_486_S2, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 1024, 32768, 1024, 127, machine_at_decpc_lpv_init, NULL }, /* Uses an NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware. */ @@ -446,13 +447,18 @@ const machine_t machines[] = { of type 'H'. */ { "[SiS 496] Zida Tomato 4DP", "4dps", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 261120, 1024, 255, machine_at_4dps_init, NULL }, /* This has the UMC 88xx on-chip KBC. */ - { "[UMC 8881] A-Trend ATC-1415", "atc1415", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_atc1415_init, NULL }, + { "[UMC 888x] A-Trend ATC-1415", "atc1415", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 65536, 1024, 255, machine_at_atc1415_init, NULL }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ - { "[UMC 8881] ECS Elite UM8810PAIO", "ecs486", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_ecs486_init, NULL }, + { "[UMC 888x] ECS Elite UM8810PAIO", "ecs486", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_ecs486_init, NULL }, /* Has AMIKey Z(!) KBC firmware. */ - { "[UMC 8881] Epson Action PC 2600", "actionpc2600", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 262144, 1024, 255, machine_at_actionpc2600_init, NULL }, + { "[UMC 888x] Epson Action PC 2600", "actionpc2600", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 262144, 1024, 255, machine_at_actionpc2600_init, 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. */ + { "[UMC 888x] PC Chips M919", "m919", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_VLB | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_m919_init, NULL }, + /* Has IBM PS/2 Type 1 KBC firmware. Uses a mysterious I/O port C05. */ + { "[UMC 888x] Samsung SPC7700P-LW", "spc7700p-lw", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_spc7700p_lw_init, NULL }, /* This has a Holtek KBC. */ - { "[UMC 8881] Shuttle HOT-433A", "hot433", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 262144, 1024, 255, machine_at_hot433_init, NULL }, + { "[UMC 888x] Shuttle HOT-433A", "hot433", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 262144, 1024, 255, machine_at_hot433_init, NULL }, /* Has a VIA VT82C406 KBC+RTC that likely has identical commands to the VT82C42N. */ { "[VIA VT82C496G] DFI G486VPA", "g486vpa", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_IDE_DUAL, 1024, 131072, 1024, 255, machine_at_g486vpa_init, NULL }, /* Has a VIA VT82C42N KBC. */ @@ -463,6 +469,9 @@ const machine_t machines[] = { /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ { "[STPC Client] ITOX STAR", "itoxstar", MACHINE_TYPE_486_MISC, CPU_PKG_STPC, 0, 66666667, 75000000, 0, 0, 1.0, 1.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 255, machine_at_itoxstar_init, NULL }, + /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ + { "[STPC Consumer-II] Acrosser AR-B1423C", "arb1423c", MACHINE_TYPE_486_MISC, CPU_PKG_STPC, 0, 66666667, 66666667, 0, 0, 2.0, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 32768, 163840, 8192, 255, machine_at_arb1423c_init, NULL }, /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ { "[STPC Consumer-II] Acrosser AR-B1479", "arb1479", MACHINE_TYPE_486_MISC, CPU_PKG_STPC, 0, 66666667, 66666667, 0, 0, 2.0, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 32768, 163840, 8192, 255, machine_at_arb1479_init, NULL }, From ccdf583b26f82c8b6a865283a4265b9534097641 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 24 Aug 2021 21:11:47 +0200 Subject: [PATCH 63/96] A slight AT NVR code clean-up. --- src/nvr_at.c | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/nvr_at.c b/src/nvr_at.c index ff1c6fcb0..8be4aa7f8 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -559,6 +559,26 @@ timer_tick(nvr_t *nvr) } +static void +nvr_reg_common_write(uint16_t reg, uint8_t val, nvr_t *nvr, local_t *local) +{ + if ((reg == 0x2c) && (local->flags & FLAG_LS_HACK)) + nvr->new = 0; + if ((reg == 0x52) && (local->flags & FLAG_APOLLO_HACK)) + nvr->new = 0; + if ((reg >= 0x38) && (reg <= 0x3f) && local->wp[0]) + return; + if ((reg >= 0xb8) && (reg <= 0xbf) && local->wp[1]) + return; + if (local->lock[reg]) + return; + if (nvr->regs[reg] != val) { + nvr->regs[reg] = val; + nvr_dosave = 1; + } +} + + /* This must be exposed because ACPI uses it. */ void nvr_reg_write(uint16_t reg, uint8_t val, void *priv) @@ -604,28 +624,17 @@ nvr_reg_write(uint16_t reg, uint8_t val, void *priv) nvr->regs[0x2f] = checksum & 0xff; break; } - /*FALLTHROUGH*/ + nvr_reg_common_write(reg, val, nvr, local); + break; case 0x32: if ((reg == 0x32) && (local->cent == RTC_CENTURY_VIA) && local->wp_32) break; - /* FALLTHROUGH */ + nvr_reg_common_write(reg, val, nvr, local); + break; default: /* non-RTC registers are just NVRAM */ - if ((reg == 0x2c) && (local->flags & FLAG_LS_HACK)) - nvr->new = 0; - if ((reg == 0x52) && (local->flags & FLAG_APOLLO_HACK)) - nvr->new = 0; - if ((reg >= 0x38) && (reg <= 0x3f) && local->wp[0]) - break; - if ((reg >= 0xb8) && (reg <= 0xbf) && local->wp[1]) - break; - if (local->lock[reg]) - break; - if (nvr->regs[reg] != val) { - nvr->regs[reg] = val; - nvr_dosave = 1; - } + nvr_reg_common_write(reg, val, nvr, local); break; } From 03253ec93c594960871483815b2baa3372dd58b7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 3 Sep 2021 16:40:07 +0200 Subject: [PATCH 64/96] Trident changes to make merging easier. --- src/video/vid_tgui9440.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index fa522fd43..ddceff618 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -2870,7 +2870,7 @@ static void *tgui_init(const device_t *info) tgui->card = pci_add_card(PCI_ADD_VIDEO | PCI_ADD_STRICT, tgui_pci_read, tgui_pci_write, tgui); } - tgui->pci_regs[PCI_REG_COMMAND] = 3; + tgui->pci_regs[PCI_REG_COMMAND] = 7; if (tgui->has_bios) { tgui->pci_regs[0x30] = 0x00; @@ -2878,8 +2878,8 @@ static void *tgui_init(const device_t *info) tgui->pci_regs[0x33] = 0x00; } - if (tgui->type >= TGUI_9440) - svga->packed_chain4 = 1; + if (tgui->type >= TGUI_9440) + svga->packed_chain4 = 1; if (tgui->type >= TGUI_9660) { tgui->i2c = i2c_gpio_init("ddc_tgui"); From 81db8ea205a72f0b3d110ba99b5fcf89851315b9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 3 Sep 2021 16:41:11 +0200 Subject: [PATCH 65/96] I have to do this, apparently. --- src/video/vid_tgui9440.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index ddceff618..642991b58 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -2881,11 +2881,6 @@ static void *tgui_init(const device_t *info) if (tgui->type >= TGUI_9440) svga->packed_chain4 = 1; - if (tgui->type >= TGUI_9660) { - tgui->i2c = i2c_gpio_init("ddc_tgui"); - tgui->ddc = ddc_init(i2c_gpio_get_bus(tgui->i2c)); - } - return tgui; } From b75d9a20012cb6ce24c101eb876aba1d78cc7a98 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 3 Sep 2021 16:42:39 +0200 Subject: [PATCH 66/96] And back. --- src/video/vid_tgui9440.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index dfce72e06..e067d7a4b 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -3005,7 +3005,7 @@ static void *tgui_init(const device_t *info) tgui->card = pci_add_card(PCI_ADD_VIDEO | PCI_ADD_STRICT, tgui_pci_read, tgui_pci_write, tgui); } - tgui->pci_regs[PCI_REG_COMMAND] = 7; + tgui->pci_regs[PCI_REG_COMMAND] = 7; if (tgui->has_bios) { tgui->pci_regs[0x30] = 0x00; @@ -3013,8 +3013,13 @@ static void *tgui_init(const device_t *info) tgui->pci_regs[0x33] = 0x00; } - if (tgui->type >= TGUI_9440) - svga->packed_chain4 = 1; + if (tgui->type >= TGUI_9440) + svga->packed_chain4 = 1; + + if (tgui->type >= TGUI_9660) { + tgui->i2c = i2c_gpio_init("ddc_tgui"); + tgui->ddc = ddc_init(i2c_gpio_get_bus(tgui->i2c)); + } return tgui; } From 901c2741192e2dc2d0e437d50a740e40bd4c1c73 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 8 Sep 2021 00:08:10 +0200 Subject: [PATCH 67/96] Committed three files to make the merger possible. --- src/chipset/CMakeLists.txt | 16 +++++++++------- src/video/CMakeLists.txt | 6 +++--- src/win/Makefile.mingw | 21 +++++++-------------- 3 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 4e46e0db4..3ed588afd 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -13,13 +13,15 @@ # Copyright 2020,2021 David Hrdlička. # -add_library(chipset OBJECT acc2168.c cs8230.c ali1429.c ali1489.c ali1531.c ali1541.c ali1543.c - ali1621.c ali6117.c headland.c intel_82335.c contaq_82c59x.c cs4031.c intel_420ex.c - intel_4x0.c intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c - opti495.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 sis_85c310.c - sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c stpc.c umc_8886.c umc_hb4.c via_apollo.c - via_pipc.c vl82c480.c wd76c10.c) +add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1217.c ali1429.c ali1489.c et6000.c headland.c + intel_82335.c cs4031.c intel_420ex.c intel_4x0.c intel_sio.c intel_piix.c ../ioapic.c + neat.c opti283.c opti291.c opti495.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 sis_5598.c + umc_8886.c umc_8890.c umc_hb4.c + via_vt82c49x.c via_vt82c505.c sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c + gc100.c stpc.c + via_apollo.c via_pipc.c wd76c10.c + vl82c480.c) if(I450KX) target_sources(chipset PRIVATE intel_i450kx.c) diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index 4b5f029b9..50572dbd8 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -20,9 +20,9 @@ add_library(vid OBJECT video.c vid_table.c vid_cga.c vid_cga_comp.c vid_svga_render.c vid_ddc.c vid_vga.c vid_ati_eeprom.c vid_ati18800.c vid_ati28800.c vid_ati_mach64.c vid_ati68860_ramdac.c vid_bt48x_ramdac.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 vid_rtg310x.c - vid_ti_cf62011.c vid_tvga.c vid_tgui9440.c vid_tkd8001_ramdac.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 vid_rtg310x.c + vid_f82c425.c vid_ti_cf62011.c vid_tvga.c vid_tgui9440.c vid_tkd8001_ramdac.c vid_att20c49x_ramdac.c vid_s3.c vid_s3_virge.c vid_ibm_rgb528_ramdac.c vid_sdac_ramdac.c vid_ogc.c vid_nga.c vid_tvp3026_ramdac.c) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 913549911..e96f00a06 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -598,20 +598,13 @@ CPUOBJ := $(DYNARECOBJ) \ 808x.o 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o \ x86seg.o x87.o x87_timings.o -CHIPSETOBJ := acc2168.o \ - contaq_82c59x.o \ - cs4031.o cs8230.o \ - ali1429.o ali1489.o ali1531.o ali1541.o ali1543.o ali1621.o ali6117.o \ - gc100.o headland.o \ - intel_82335.o intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \ - neat.o \ - opti283.o opti291.o opti391.o opti495.o opti822.o opti895.o opti5x7.o \ - scamp.o scat.o \ - stpc.o \ - wd76c10.o vl82c480.o \ - umc_8886.o umc_hb4.o \ - via_vt82c49x.o via_vt82c505.o via_apollo.o via_pipc.o \ - sis_85c310.o sis_85c4xx.o sis_85c496.o sis_85c50x.o sis_5511.o sis_5571.o +CHIPSETOBJ := 82c100.o acc2168.o cs8230.o ali1217.o ali1429.o ali1489.o et6000.o headland.o intel_82335.o cs4031.o \ + intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \ + neat.o opti495.o opti822.o opti895.o opti5x7.o scamp.o scat.o via_vt82c49x.o via_vt82c505.o \ + gc100.o \ + sis_85c310.o sis_85c4xx.o sis_85c496.o sis_85c50x.o sis_5511.o sis_5571.o sis_5598.o stpc.o opti283.o opti291.o \ + umc_8886.o umc_8890.o umc_hb4.o \ + via_apollo.o via_pipc.o wd76c10.o vl82c480.o MCHOBJ := machine.o machine_table.o \ m_xt.o m_xt_compaq.o \ From d5f656e86627823cfee68c0370e8b0799884ca23 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 8 Sep 2021 00:10:13 +0200 Subject: [PATCH 68/96] And back. --- src/chipset/CMakeLists.txt | 16 +++++++--------- src/video/CMakeLists.txt | 4 ++-- src/win/Makefile.mingw | 24 +++++++++++++++--------- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 3ed588afd..770b54006 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -13,15 +13,13 @@ # Copyright 2020,2021 David Hrdlička. # -add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1217.c ali1429.c ali1489.c et6000.c headland.c - intel_82335.c cs4031.c intel_420ex.c intel_4x0.c intel_sio.c intel_piix.c ../ioapic.c - neat.c opti283.c opti291.c opti495.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 sis_5598.c - umc_8886.c umc_8890.c umc_hb4.c - via_vt82c49x.c via_vt82c505.c sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c - gc100.c stpc.c - via_apollo.c via_pipc.c wd76c10.c - vl82c480.c) +add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1429.c ali1489.c ali1531.c ali1541.c ali1543.c + ali1621.c ali6117.c headland.c intel_82335.c contaq_82c59x.c cs4031.c intel_420ex.c + intel_4x0.c intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c + opti495.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 sis_85c310.c + sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c stpc.c umc_8886.c umc_hb4.c via_apollo.c + via_pipc.c vl82c480.c wd76c10.c) if(I450KX) target_sources(chipset PRIVATE intel_i450kx.c) diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index 50572dbd8..c23e42917 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -20,8 +20,8 @@ add_library(vid OBJECT video.c vid_table.c vid_cga.c vid_cga_comp.c vid_svga_render.c vid_ddc.c vid_vga.c vid_ati_eeprom.c vid_ati18800.c vid_ati28800.c vid_ati_mach64.c vid_ati68860_ramdac.c vid_bt48x_ramdac.c vid_av9194.c vid_icd2061.c vid_ics2494.c vid_ics2595.c vid_cl54xx.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 vid_rtg310x.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 vid_rtg310x.c vid_f82c425.c vid_ti_cf62011.c vid_tvga.c vid_tgui9440.c vid_tkd8001_ramdac.c vid_att20c49x_ramdac.c vid_s3.c vid_s3_virge.c vid_ibm_rgb528_ramdac.c vid_sdac_ramdac.c vid_ogc.c vid_nga.c vid_tvp3026_ramdac.c) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index a6e2da67f..175f2a6d7 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -598,13 +598,20 @@ CPUOBJ := $(DYNARECOBJ) \ 808x.o 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o \ x86seg.o x87.o x87_timings.o -CHIPSETOBJ := 82c100.o acc2168.o cs8230.o ali1217.o ali1429.o ali1489.o et6000.o headland.o intel_82335.o cs4031.o \ - intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \ - neat.o opti495.o opti822.o opti895.o opti5x7.o scamp.o scat.o via_vt82c49x.o via_vt82c505.o \ - gc100.o \ - sis_85c310.o sis_85c4xx.o sis_85c496.o sis_85c50x.o sis_5511.o sis_5571.o sis_5598.o stpc.o opti283.o opti291.o \ - umc_8886.o umc_8890.o umc_hb4.o \ - via_apollo.o via_pipc.o wd76c10.o vl82c480.o +CHIPSETOBJ := 82c100.o acc2168.o \ + contaq_82c59x.o \ + cs4031.o cs8230.o \ + ali1429.o ali1489.o ali1531.o ali1541.o ali1543.o ali1621.o ali6117.o \ + gc100.o headland.o \ + intel_82335.o intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \ + neat.o \ + opti283.o opti291.o opti391.o opti495.o opti822.o opti895.o opti5x7.o \ + scamp.o scat.o \ + stpc.o \ + wd76c10.o vl82c480.o \ + umc_8886.o umc_hb4.o \ + via_vt82c49x.o via_vt82c505.o via_apollo.o via_pipc.o \ + sis_85c310.o sis_85c4xx.o sis_85c496.o sis_85c50x.o sis_5511.o sis_5571.o MCHOBJ := machine.o machine_table.o \ m_xt.o m_xt_compaq.o \ @@ -613,7 +620,7 @@ MCHOBJ := machine.o machine_table.o \ m_xt_xi8088.o m_xt_zenith.o \ m_pcjr.o \ m_amstrad.o m_europc.o \ - m_xt_olivetti.o m_tandy.o m_v86p.o \ + m_xt_olivetti.o m_tandy.o \ m_at.o m_at_commodore.o \ m_at_t3100e.o m_at_t3100e_vid.o \ m_ps1.o m_ps1_hdc.o \ @@ -765,7 +772,6 @@ VIDOBJ := video.o \ vid_paradise.o \ vid_rtg310x.o \ vid_ti_cf62011.o \ - vid_f82c425.o \ vid_tvga.o \ vid_tgui9440.o vid_tkd8001_ramdac.o \ vid_att20c49x_ramdac.o \ From 372b59524be903ba5cd48bd3f7a86e96cc1941a9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 8 Sep 2021 00:51:57 +0200 Subject: [PATCH 69/96] Added m_v86p.o to the makefile. --- src/win/Makefile.mingw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 175f2a6d7..793be3b17 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -620,7 +620,7 @@ MCHOBJ := machine.o machine_table.o \ m_xt_xi8088.o m_xt_zenith.o \ m_pcjr.o \ m_amstrad.o m_europc.o \ - m_xt_olivetti.o m_tandy.o \ + m_xt_olivetti.o m_tandy.o m_v86p.o \ m_at.o m_at_commodore.o \ m_at_t3100e.o m_at_t3100e_vid.o \ m_ps1.o m_ps1_hdc.o \ From 22481af97af49d2edacd583579594dd0f8d30963 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 8 Sep 2021 01:51:47 +0200 Subject: [PATCH 70/96] Makefile fix. --- src/win/Makefile.mingw | 1 + 1 file changed, 1 insertion(+) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 793be3b17..ba4ecef21 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -772,6 +772,7 @@ VIDOBJ := video.o \ vid_paradise.o \ vid_rtg310x.o \ vid_ti_cf62011.o \ + vid_f82c425.o \ vid_tvga.o \ vid_tgui9440.o vid_tkd8001_ramdac.o \ vid_att20c49x_ramdac.o \ From 827fc28deca375aa21fe8f6a02e4f3597edc6701 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Sep 2021 22:26:17 +0200 Subject: [PATCH 71/96] Minor fixes in machine_table.c. --- src/machine/machine_table.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 610eb137c..d58e60296 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -581,7 +581,7 @@ const machine_t machines[] = { /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . */ - { "[i430FX] Gateway 2000 Thor", "gw2katx", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_gw2katx_init, NULL }, + { "[i430FX] Gateway 2000 Thor", "gw2katx", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_gw2katx_init, NULL }, /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . */ @@ -589,7 +589,7 @@ const machine_t machines[] = { /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . */ - { "[i430FX] Intel Advanced/ATX (MR BIOS)", "mrthor", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_mrthor_init, at_mrthor_get_device }, + { "[i430FX] Intel Advanced/ATX (MR BIOS)", "mrthor", MACHINE_TYPE_SOCKET7_3V, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_mrthor_init, at_mrthor_get_device }, /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the PC87306 Super I/O chip, command 0xA1 returns '5'. Command 0xA0 copyright string: (C)1994 AMI . */ @@ -748,7 +748,7 @@ const machine_t machines[] = { /* Socket 8 machines */ /* 450KX */ #if defined(DEV_BRANCH) && defined(USE_I450KX) - /* This has an AMIKey, which is an updated version of type 'F'. */ + /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[i450KX] ASUS P/I-P6RP4", "p6rp4", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_p6rp4_init, NULL }, #endif From d2f3720a23789cd2491f8659fad501bb59596c71 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Sep 2021 22:29:17 +0200 Subject: [PATCH 72/96] Manually merged a change to machine_table.c. --- src/machine/machine_table.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index d58e60296..81b994d7c 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -118,6 +118,7 @@ const machine_t machines[] = { { "[8088] Eagle PC Spirit", "pcspirit", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_pcspirit_init, NULL }, { "[8088] Generic XT clone", "genxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_genxt_init, NULL }, { "[8088] Juko ST", "jukopc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_jukopc_init, NULL }, + { "[8088] Multitech PC-500", "multitech_pc500", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_multitechpc500_init, NULL }, { "[8088] Multitech PC-700", "pc700", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_pc700_init, NULL }, { "[8088] NCR PC4i", "pc4i", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_pc4i_init, NULL }, { "[8088] Olivetti M19", "m19", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 4772728, 7159092, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 256, 640, 256, 0, machine_xt_m19_init, m19_get_device }, From dbdf07aa96830ac0eb76aa7273bf1c05d2db4fb0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Sep 2021 22:33:39 +0200 Subject: [PATCH 73/96] Two files to resolve conflicts. --- src/CMakeLists.txt | 6 +++--- src/win/Makefile.mingw | 10 ++++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4bb131bd2..a3cbc2e76 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,9 +14,9 @@ # # WIN32 marks us as a GUI app on Windows -add_executable(86Box WIN32 86box.c config.c log.c random.c timer.c io.c acpi.c apm.c - dma.c ddma.c nmi.c pic.c pit.c port_6x.c port_92.c ppi.c pci.c mca.c usb.c - device.c nvr.c nvr_at.c nvr_ps2.c) +add_executable(86Box WIN32 86box.c config.c random.c timer.c io.c acpi.c apm.c + dma.c ddma.c nmi.c pic.c pit.c port_92.c ppi.c pci.c mca.c usb.c + device.c nvr.c nvr_at.c nvr_ps2.c thread.c) if(NEW_DYNAREC) add_compile_definitions(USE_NEW_DYNAREC) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index ba4ecef21..29d0c3456 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -585,8 +585,14 @@ CXXFLAGS := $(CFLAGS) ######################################################################### # Create the (final) list of objects to build. # ######################################################################### -MAINOBJ := 86box.o config.o log.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \ - nmi.o pic.o pit.o port_6x.o port_92.o ppi.o pci.o mca.o \ +ifeq ($(PTHREAD), y) +MAINOBJ := 86box.o config.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \ + nmi.o pic.o pit.o port_92.o ppi.o pci.o mca.o \ + usb.o device.o nvr.o nvr_at.o nvr_ps2.o thread.o \ + $(VNCOBJ) +else +MAINOBJ := 86box.o config.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \ + nmi.o pic.o pit.o port_92.o ppi.o pci.o mca.o \ usb.o device.o nvr.o nvr_at.o nvr_ps2.o \ $(VNCOBJ) From b0367133d6c987286c2fcf4b50fa24d7f91389ca Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 14 Sep 2021 22:36:21 +0200 Subject: [PATCH 74/96] And back. --- src/CMakeLists.txt | 4 ++-- src/win/Makefile.mingw | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a3cbc2e76..2bfca1c94 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,8 +14,8 @@ # # WIN32 marks us as a GUI app on Windows -add_executable(86Box WIN32 86box.c config.c random.c timer.c io.c acpi.c apm.c - dma.c ddma.c nmi.c pic.c pit.c port_92.c ppi.c pci.c mca.c usb.c +add_executable(86Box WIN32 86box.c config.c log.c random.c timer.c io.c acpi.c apm.c + dma.c ddma.c nmi.c pic.c pit.c port_6x.c port_92.c ppi.c pci.c mca.c usb.c device.c nvr.c nvr_at.c nvr_ps2.c thread.c) if(NEW_DYNAREC) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index d168796ec..90f7ab19e 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -590,13 +590,13 @@ CXXFLAGS := $(CFLAGS) # Create the (final) list of objects to build. # ######################################################################### ifeq ($(PTHREAD), y) -MAINOBJ := 86box.o config.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \ - nmi.o pic.o pit.o port_92.o ppi.o pci.o mca.o \ +MAINOBJ := 86box.o config.o log.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \ + nmi.o pic.o pit.o port_6x.o port_92.o ppi.o pci.o mca.o \ usb.o device.o nvr.o nvr_at.o nvr_ps2.o thread.o \ $(VNCOBJ) else -MAINOBJ := 86box.o config.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \ - nmi.o pic.o pit.o port_92.o ppi.o pci.o mca.o \ +MAINOBJ := 86box.o config.o log.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \ + nmi.o pic.o pit.o port_6x.o port_92.o ppi.o pci.o mca.o \ usb.o device.o nvr.o nvr_at.o nvr_ps2.o \ $(VNCOBJ) endif From 89f1583a348a767e5dfe5ed71d12c846cdd1d163 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 17 Sep 2021 02:52:44 +0200 Subject: [PATCH 75/96] Fixed UMC 888x shadow RAM. --- src/chipset/umc_hb4.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/chipset/umc_hb4.c b/src/chipset/umc_hb4.c index ca544f7ac..b3d5cb0dc 100644 --- a/src/chipset/umc_hb4.c +++ b/src/chipset/umc_hb4.c @@ -139,20 +139,22 @@ typedef struct hb4_t void hb4_shadow(hb4_t *dev) { + int state, i; + mem_set_mem_state_both(0xe0000, 0x20000, ((dev->pci_conf[0x55] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->pci_conf[0x55] & 0x40) ? MEM_WRITE_EXTANY : MEM_WRITE_INTERNAL)); if (dev->pci_conf[0x54] & 1) { - if (dev->pci_conf[0x54] & 2) - mem_set_mem_state_both(0xc0000, 0x8000, MEM_READ_INTERNAL | ((dev->pci_conf[0x55] & 0x40) ? MEM_WRITE_EXTANY :MEM_WRITE_INTERNAL)); - else - mem_set_mem_state_both(0xc0000, 0x8000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + state = (dev->pci_conf[0x54] & 0x02) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[0x55] & 0x40) ? MEM_WRITE_EXTANY : MEM_WRITE_INTERNAL; - for (int i = 0; i < 5; i++) { - if ((dev->pci_conf[0x54] >> i) & 4) - mem_set_mem_state_both(0xc8000 + (i << 14), 0x8000, MEM_READ_INTERNAL | ((dev->pci_conf[0x55] & 0x40) ? MEM_WRITE_EXTANY :MEM_WRITE_INTERNAL)); - else - mem_set_mem_state_both(0xc8000 + (i << 14), 0x8000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + mem_set_mem_state_both(0xc0000, 0x8000, state); + + for (i = 0; i < 6; i++) { + state = (dev->pci_conf[0x54] & (1 << (i + 2))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[0x55] & 0x40) ? MEM_WRITE_EXTANY : MEM_WRITE_INTERNAL; + + mem_set_mem_state_both(0xc8000 + (i << 4), 0x4000, state); } } @@ -265,7 +267,8 @@ hb4_reset(void *priv) dev->pci_conf[0x5d] = 0x20; dev->pci_conf[0x5f] = 0xff; - hb4_shadow(dev); + hb4_write(0, 0x54, 0x00, dev); + hb4_write(0, 0x55, 0x00, dev); hb4_write(0, 0x60, 0x20, dev); } From 626e8e58bb6ffd24279d0e5e2689f54405d2ae42 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 17 Sep 2021 02:54:19 +0200 Subject: [PATCH 76/96] Implemented a PIIX register written to by the ZAPPA that is officially reserved on PIIX (but otherwise exists on PIIX3). --- src/chipset/intel_piix.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index a694da235..aa91c2fd5 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -528,6 +528,8 @@ piix_write(int func, int addr, uint8_t val, void *priv) case 0xab: if (dev->type == 3) fregs[addr] &= (val & 0x01); + else if (dev->type < 3) + fregs[addr] = val; break; case 0xb0: if (dev->type == 4) From b8a2fdfd0acd844941559782814bff5e9a81187c Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 17 Sep 2021 02:55:43 +0200 Subject: [PATCH 77/96] KBC reset is now hard reset. --- src/cpu/cpu.h | 1 + src/cpu/x86.c | 40 ++++++++++++++++++++++---- src/device/keyboard_at.c | 62 ++++++++++++++++++++++++++++------------ 3 files changed, 79 insertions(+), 24 deletions(-) diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index b28934951..68a053b6f 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -656,6 +656,7 @@ extern void resetx86(void); extern void refreshread(void); extern void resetreadlookup(void); extern void softresetx86(void); +extern void hardresetx86(void); extern void x86_int(int num); extern void x86_int_sw(int num); extern int x86_int_sw_rm(int num); diff --git a/src/cpu/x86.c b/src/cpu/x86.c index e652c5d27..c16939559 100644 --- a/src/cpu/x86.c +++ b/src/cpu/x86.c @@ -26,6 +26,8 @@ #include "cpu.h" #include "x86.h" #include <86box/machine.h> +#include <86box/device.h> +#include <86box/dma.h> #include <86box/io.h> #include <86box/mem.h> #include <86box/rom.h> @@ -239,7 +241,7 @@ reset_common(int hard) leave_smm(); /* Needed for the ALi M1533. */ - if (soft_reset_pci && !hard) + if (is486 && (hard || soft_reset_pci)) pci_reset(); use32 = 0; @@ -275,13 +277,13 @@ reset_common(int hard) if (is386 || hard) EAX = EBX = ECX = EDX = ESI = EDI = EBP = ESP = 0; - if (hard) { + /* if (hard) { makeznptable(); resetreadlookup(); makemod1table(); cpu_set_edx(); mmu_perm = 4; - } + } */ x86seg_reset(); #ifdef USE_DYNAREC if (hard) @@ -299,8 +301,9 @@ reset_common(int hard) smi_block = 0; if (hard) { - smbase = is_am486dxl ? 0x00060000 : 0x00030000; - ppi_reset(); + if (is486) + smbase = is_am486dxl ? 0x00060000 : 0x00030000; + // ppi_reset(); } in_sys = 0; @@ -320,6 +323,15 @@ void resetx86(void) { reset_common(1); +/* ---- */ + makeznptable(); + resetreadlookup(); + makemod1table(); + cpu_set_edx(); + mmu_perm = 4; + + ppi_reset(); +/* ---- */ soft_reset_mask = 0; } @@ -334,3 +346,21 @@ softresetx86(void) reset_common(0); } + + +/* Actual hard reset. */ +void +hardresetx86(void) +{ + dma_reset(); + device_reset_all(); + + cpu_alt_reset = 0; + + mem_a20_alt = 0; + mem_a20_recalc(); + + flushmmucache(); + + resetx86(); +} diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 5431b9236..c64f8b87f 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -1181,6 +1181,8 @@ static void write_output(atkbd_t *dev, uint8_t val) { uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + uint8_t old = dev->p2; + kbd_log("ATkbc: write output port: %02X (old: %02X)\n", val, dev->p2); if (!(dev->flags & KBC_FLAG_PS2)) @@ -1189,36 +1191,43 @@ write_output(atkbd_t *dev, uint8_t val) dev->kbd_inhibit = (val & 0x40); dev->mouse_inhibit = (val & 0x08); - if ((dev->p2 ^ val) & 0x20) { /*IRQ 12*/ + /* IRQ 12 */ + if ((old ^ val) & 0x20) { if (val & 0x20) { kbd_log("ATkbc: write_output(): IRQ 12\n"); picint(1 << 12); } else picintc(1 << 12); } - if ((dev->p2 ^ val) & 0x10) { /*IRQ 1*/ + + /* IRQ 1 */ + if ((old ^ val) & 0x10) { if (val & 0x10) { kbd_log("ATkbc: write_output(): IRQ 1\n"); picint(1 << 1); } else picintc(1 << 1); } - if ((dev->p2 ^ val) & 0x02) { /*A20 enable change*/ + + /* A20 enable change */ + if ((old ^ val) & 0x02) { mem_a20_key = val & 0x02; mem_a20_recalc(); flushmmucache(); } - if ((dev->p2 ^ val) & 0x01) { /*Reset*/ - if (! (val & 0x01)) { + + /* Do this here to avoid an infinite reset loop. */ + dev->p2 = val; + + /* 0 holds the CPU in the RESET state, 1 releases it. To simply this, + we just do everything on release. */ + if ((val & 0x01) && !(old & 0x01)) { + if (val & 0x01) { /* Pin 0 selected. */ pclog("write_output(): Pulse reset!\n"); - softresetx86(); /*Pulse reset!*/ - cpu_set_edx(); - smbase = is_am486dxl ? 0x00060000 : 0x00030000; + hardresetx86(); /*Pulse reset!*/ } } - /* Mask off the A20 stuff because we use mem_a20_key directly for that. */ - dev->p2 = val; } @@ -2315,8 +2324,8 @@ write64_ami(void *priv, uint8_t val) case 0xa1: /* get controller version */ kbd_log("ATkbc: AMI - get controller version\n"); - // kbc_transmit(dev, 'H'); - kbc_transmit(dev, 'Z'); + kbc_transmit(dev, 'H'); + // kbc_transmit(dev, 'Z'); return 0; case 0xa2: /* clear keyboard controller lines P22/P23 */ @@ -2928,13 +2937,14 @@ kbd_reset(void *priv) { atkbd_t *dev = (atkbd_t *)priv; int i; - uint8_t kbc_ven = 0x0; - kbc_ven = dev->flags & KBC_VEN_MASK; + uint8_t kbc_ven; - dev->status = STAT_UNLOCKED; - dev->mem[0x20] = 0x01; - dev->mem[0x20] |= CCB_TRANSLATE; - write_output(dev, 0xcf); + if (dev == NULL) + return; + + kbc_ven = dev->flags & KBC_VEN_MASK; + + dev->status &= ~(STAT_IFULL | STAT_OFULL | STAT_CD); dev->last_irq = 0; dev->secr_phase = 0; dev->kbd_in = 0; @@ -2973,6 +2983,20 @@ kbd_reset(void *priv) } +static void +kbd_power_on(atkbd_t *dev) +{ + kbd_reset(dev); + + dev->status = STAT_UNLOCKED; + /* Write the value here first, so that we don't hit a pulse reset. */ + dev->p2 = 0xcf; + write_output(dev, 0xcf); + dev->mem[0x20] = 0x01; + dev->mem[0x20] |= CCB_TRANSLATE; +} + + /* Reset the AT keyboard - this is needed for the PCI TRC and is done until a better solution is found. */ void @@ -3064,7 +3088,7 @@ kbd_init(const device_t *info) break; } - kbd_reset(dev); + kbd_power_on(dev); /* We need this, sadly. */ SavedKbd = dev; From 2e3c2602f74f5ae2938af8c1c98f4997f01baef8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 21 Sep 2021 13:02:22 +0200 Subject: [PATCH 78/96] Removed the M6117 flag from the CPU and Machine CMakeLists.txt files. --- src/cpu/CMakeLists.txt | 4 ---- src/machine/CMakeLists.txt | 4 ---- 2 files changed, 8 deletions(-) diff --git a/src/cpu/CMakeLists.txt b/src/cpu/CMakeLists.txt index dd91a5ec1..ab27b77c0 100644 --- a/src/cpu/CMakeLists.txt +++ b/src/cpu/CMakeLists.txt @@ -24,10 +24,6 @@ if(CYRIX_6X86) target_compile_definitions(cpu PRIVATE USE_CYRIX_6X86) endif() -if(M6117) - target_compile_definitions(cpu PRIVATE USE_M6117) -endif() - if(DYNAREC) add_library(cgt OBJECT codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_k6.c diff --git a/src/machine/CMakeLists.txt b/src/machine/CMakeLists.txt index 54c3c3646..6643566ee 100644 --- a/src/machine/CMakeLists.txt +++ b/src/machine/CMakeLists.txt @@ -47,8 +47,4 @@ endif() if(M154X) target_compile_definitions(mch PRIVATE USE_M154X) -endif() - -if(M6117) - target_compile_definitions(mch PRIVATE USE_M6117) endif() \ No newline at end of file From 5ad606a8f27b6af8cd99f9eafb1363c40f245fd1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 25 Sep 2021 15:30:06 +0200 Subject: [PATCH 79/96] UMC HB4 shadow RAM overhaul and SMRAM fixes, slight changes to SiS 85c4xx, a fix for SiS 85c50x, fixed SMBASE on 486 (it should *NOT* zero the most significant 8 bits!), various improvements to mem.c (eg. mem_invalidate_range() is now faster), fixed resetting PCI on soft reset, and made the KBC soft reset again. --- src/chipset/sis_85c4xx.c | 244 +++++++++++++++------------------------ src/chipset/sis_85c50x.c | 2 +- src/chipset/umc_8886.c | 6 + src/chipset/umc_hb4.c | 166 +++++++++++++++++++++----- src/cpu/386_common.c | 2 +- src/cpu/x86.c | 7 +- src/device/keyboard_at.c | 54 ++++----- src/mem/mem.c | 75 +++++------- 8 files changed, 304 insertions(+), 252 deletions(-) diff --git a/src/chipset/sis_85c4xx.c b/src/chipset/sis_85c4xx.c index 0a2bf34af..4ca0c76d7 100644 --- a/src/chipset/sis_85c4xx.c +++ b/src/chipset/sis_85c4xx.c @@ -22,6 +22,7 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" +#include "x86.h" #include <86box/timer.h> #include <86box/io.h> #include <86box/device.h> @@ -39,6 +40,7 @@ typedef struct reg_base, reg_last, reg_00, is_471, regs[39], scratch[2]; + uint32_t mem_state[8]; smram_t *smram; port_92_t *port_92; } sis_85c4xx_t; @@ -47,7 +49,7 @@ typedef struct static void sis_85c4xx_recalcmapping(sis_85c4xx_t *dev) { - uint32_t base; + uint32_t base, n = 0; uint32_t i, shflags = 0; uint32_t readext, writeext; uint8_t romcs = 0xc0, cur_romcs; @@ -73,12 +75,25 @@ sis_85c4xx_recalcmapping(sis_85c4xx_t *dev) shadowbios_write |= (base >= 0xe0000) && !(dev->regs[0x02] & 0x40); shflags = (dev->regs[0x02] & 0x80) ? MEM_READ_INTERNAL : readext; shflags |= (dev->regs[0x02] & 0x40) ? writeext : MEM_WRITE_INTERNAL; - mem_set_mem_state(base, 0x8000, shflags); - } else - mem_set_mem_state(base, 0x8000, readext | writeext); + if (dev->mem_state[i] != shflags) { + n++; + mem_set_mem_state(base, 0x8000, shflags); + if ((base >= 0xf0000) && (dev->mem_state[i] & MEM_READ_INTERNAL) && !(shflags & MEM_READ_INTERNAL)) + mem_invalidate_range(base, base + 0x7fff); + dev->mem_state[i] = shflags; + } + } else { + shflags = readext | writeext; + if (dev->mem_state[i] != shflags) { + n++; + mem_set_mem_state(base, 0x8000, shflags); + dev->mem_state[i] = shflags; + } + } } - flushmmucache_nopc(); + if (n > 0) + flushmmucache_nopc(); } @@ -141,7 +156,8 @@ sis_85c4xx_out(uint16_t port, uint8_t val, void *priv) case 0x02: case 0x03: case 0x08: - sis_85c4xx_recalcmapping(dev); + if (valxor) + sis_85c4xx_recalcmapping(dev); break; case 0x0b: @@ -237,6 +253,69 @@ sis_85c4xx_in(uint16_t port, void *priv) } +static void +sis_85c4xx_reset(void *priv) +{ + sis_85c4xx_t *dev = (sis_85c4xx_t *) priv; + int mem_size_mb = mem_size >> 10; + static uint8_t ram_4xx[64] = { 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + static uint8_t ram_471[64] = { 0x00, 0x00, 0x01, 0x01, 0x02, 0x20, 0x09, 0x09, 0x04, 0x04, 0x05, 0x05, 0x0b, 0x0b, 0x0b, 0x0b, + 0x13, 0x21, 0x06, 0x06, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x1b, 0x1b, 0x1b, 0x1b, 0x0f, 0x0f, 0x0f, 0x0f, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e }; + + memset(dev->regs, 0x00, sizeof(dev->regs)); + + if (cpu_s->rspeed < 25000000) + dev->regs[0x08] = 0x80; + + if (dev->is_471) { + dev->regs[0x09] = 0x40; + if (mem_size_mb >= 64) { + if ((mem_size_mb >= 65) && (mem_size_mb < 68)) + dev->regs[0x09] |= 0x22; + else + dev->regs[0x09] |= 0x24; + } else + dev->regs[0x09] |= ram_471[mem_size_mb]; + + dev->regs[0x11] = 0x09; + dev->regs[0x12] = 0xff; + dev->regs[0x1f] = 0x20; /* Video access enabled. */ + dev->regs[0x23] = 0xf0; + dev->regs[0x26] = 0x01; + + smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x00010000, 0, 1); + + port_92_remove(dev->port_92); + + mem_remap_top(256); + soft_reset_mask = 0; + } else { + /* Bits 6 and 7 must be clear on the SiS 40x. */ + if (dev->reg_base == 0x60) + dev->reg_00 = 0x24; + + if (mem_size_mb == 64) + dev->regs[0x00] = 0x1f; + else if (mem_size_mb < 64) + dev->regs[0x00] = ram_4xx[mem_size_mb]; + + dev->regs[0x11] = 0x01; + } + + dev->scratch[0] = dev->scratch[1] = 0xff; + + cpu_cache_ext_enabled = 0; + cpu_update_waitstates(); + + sis_85c4xx_recalcmapping(dev); +} + + static void sis_85c4xx_close(void *priv) { @@ -252,8 +331,6 @@ sis_85c4xx_close(void *priv) static void * sis_85c4xx_init(const device_t *info) { - int mem_size_mb; - sis_85c4xx_t *dev = (sis_85c4xx_t *) malloc(sizeof(sis_85c4xx_t)); memset(dev, 0, sizeof(sis_85c4xx_t)); @@ -261,161 +338,22 @@ sis_85c4xx_init(const device_t *info) dev->reg_base = info->local & 0xff; - mem_size_mb = mem_size >> 10; - - if (cpu_s->rspeed < 25000000) - dev->regs[0x08] = 0x80; - if (dev->is_471) { dev->reg_last = dev->reg_base + 0x76; - dev->regs[0x09] = 0x40; - switch (mem_size_mb) { - case 0: case 1: - dev->regs[0x09] |= 0x00; - break; - case 2: case 3: - dev->regs[0x09] |= 0x01; - break; - case 4: - dev->regs[0x09] |= 0x02; - break; - case 5: - dev->regs[0x09] |= 0x20; - break; - case 6: case 7: - dev->regs[0x09] |= 0x09; - break; - case 8: case 9: - dev->regs[0x09] |= 0x04; - break; - case 10: case 11: - dev->regs[0x09] |= 0x05; - break; - case 12: case 13: case 14: case 15: - dev->regs[0x09] |= 0x0b; - break; - case 16: - dev->regs[0x09] |= 0x13; - break; - case 17: - dev->regs[0x09] |= 0x21; - break; - case 18: case 19: - dev->regs[0x09] |= 0x06; - break; - case 20: case 21: case 22: case 23: - dev->regs[0x09] |= 0x0d; - break; - case 24: case 25: case 26: case 27: - case 28: case 29: case 30: case 31: - dev->regs[0x09] |= 0x0e; - break; - case 32: case 33: case 34: case 35: - dev->regs[0x09] |= 0x1b; - break; - case 36: case 37: case 38: case 39: - dev->regs[0x09] |= 0x0f; - break; - case 40: case 41: case 42: case 43: - case 44: case 45: case 46: case 47: - dev->regs[0x09] |= 0x17; - break; - case 48: - dev->regs[0x09] |= 0x1e; - break; - default: - if (mem_size_mb < 64) - dev->regs[0x09] |= 0x1e; - else if ((mem_size_mb >= 65) && (mem_size_mb < 68)) - dev->regs[0x09] |= 0x22; - else - dev->regs[0x09] |= 0x24; - break; - } - - dev->regs[0x11] = 0x09; - dev->regs[0x12] = 0xff; - dev->regs[0x1f] = 0x20; /* Video access enabled. */ - dev->regs[0x23] = 0xf0; - dev->regs[0x26] = 0x01; - dev->smram = smram_add(); - smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x00010000, 0, 1); dev->port_92 = device_add(&port_92_device); - port_92_remove(dev->port_92); - } else { + } else dev->reg_last = dev->reg_base + 0x11; - /* Bits 6 and 7 must be clear on the SiS 40x. */ - if (dev->reg_base == 0x60) - dev->reg_00 = 0x24; - - switch (mem_size_mb) { - case 1: - default: - dev->regs[0x00] = 0x00; - break; - case 2: - dev->regs[0x00] = 0x01; - break; - case 4: - dev->regs[0x00] = 0x02; - break; - case 6: - dev->regs[0x00] = 0x03; - break; - case 8: - dev->regs[0x00] = 0x04; - break; - case 10: - dev->regs[0x00] = 0x05; - break; - case 12: - dev->regs[0x00] = 0x0b; - break; - case 16: - dev->regs[0x00] = 0x19; - break; - case 18: - dev->regs[0x00] = 0x06; - break; - case 20: - dev->regs[0x00] = 0x14; - break; - case 24: - dev->regs[0x00] = 0x15; - break; - case 32: - dev->regs[0x00] = 0x1b; - break; - case 36: - dev->regs[0x00] = 0x16; - break; - case 40: - dev->regs[0x00] = 0x17; - break; - case 48: - dev->regs[0x00] = 0x1e; - break; - case 64: - dev->regs[0x00] = 0x1f; - break; - } - - dev->regs[0x11] = 0x01; - } - io_sethandler(0x0022, 0x0002, sis_85c4xx_in, NULL, NULL, sis_85c4xx_out, NULL, NULL, dev); - dev->scratch[0] = dev->scratch[1] = 0xff; - io_sethandler(0x00e1, 0x0002, sis_85c4xx_in, NULL, NULL, sis_85c4xx_out, NULL, NULL, dev); - sis_85c4xx_recalcmapping(dev); + sis_85c4xx_reset(dev); return dev; } @@ -425,7 +363,7 @@ const device_t sis_85c401_device = { "SiS 85c401/85c402", 0, 0x060, - sis_85c4xx_init, sis_85c4xx_close, NULL, + sis_85c4xx_init, sis_85c4xx_close, sis_85c4xx_reset, { NULL }, NULL, NULL, NULL }; @@ -434,7 +372,7 @@ const device_t sis_85c460_device = { "SiS 85c460", 0, 0x050, - sis_85c4xx_init, sis_85c4xx_close, NULL, + sis_85c4xx_init, sis_85c4xx_close, sis_85c4xx_reset, { NULL }, NULL, NULL, NULL }; @@ -444,7 +382,7 @@ const device_t sis_85c461_device = { "SiS 85c461", 0, 0x050, - sis_85c4xx_init, sis_85c4xx_close, NULL, + sis_85c4xx_init, sis_85c4xx_close, sis_85c4xx_reset, { NULL }, NULL, NULL, NULL }; @@ -453,7 +391,7 @@ const device_t sis_85c471_device = { "SiS 85c407/85c471", 0, 0x150, - sis_85c4xx_init, sis_85c4xx_close, NULL, + sis_85c4xx_init, sis_85c4xx_close, sis_85c4xx_reset, { NULL }, NULL, NULL, NULL }; diff --git a/src/chipset/sis_85c50x.c b/src/chipset/sis_85c50x.c index c01690064..84ad90c91 100644 --- a/src/chipset/sis_85c50x.c +++ b/src/chipset/sis_85c50x.c @@ -89,7 +89,7 @@ sis_85c50x_shadow_recalc(sis_85c50x_t *dev) mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x56] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY)); } - flushmmucache(); + flushmmucache_nopc(); } diff --git a/src/chipset/umc_8886.c b/src/chipset/umc_8886.c index a8962030b..591805329 100644 --- a/src/chipset/umc_8886.c +++ b/src/chipset/umc_8886.c @@ -291,6 +291,9 @@ umc_8886_reset(void *priv) { umc_8886_t *dev = (umc_8886_t *)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; @@ -336,6 +339,9 @@ umc_8886_reset(void *priv) for (int i = 1; i < 5; i++) /* Disable all IRQ interrupts */ pci_set_irq_routing(i, PCI_IRQ_DISABLED); + + cpu_set_isa_pci_div(3); + cpu_set_pci_speed(cpu_busspeed / 2); } diff --git a/src/chipset/umc_hb4.c b/src/chipset/umc_hb4.c index b3d5cb0dc..d147bf5f7 100644 --- a/src/chipset/umc_hb4.c +++ b/src/chipset/umc_hb4.c @@ -97,6 +97,7 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" +#include "x86.h" #include <86box/timer.h> #include <86box/io.h> #include <86box/device.h> @@ -106,6 +107,18 @@ #include <86box/port_92.h> #include <86box/smram.h> +#ifdef USE_DYNAREC +# include "codegen_public.h" +#else +#ifdef USE_NEW_DYNAREC +# define PAGE_MASK_SHIFT 6 +#else +# define PAGE_MASK_INDEX_MASK 3 +# define PAGE_MASK_INDEX_SHIFT 10 +# define PAGE_MASK_SHIFT 4 +#endif +# define PAGE_MASK_MASK 63 +#endif #include <86box/chipset.h> @@ -131,34 +144,108 @@ hb4_log(const char *fmt, ...) typedef struct hb4_t { - uint8_t pci_conf[128]; /* PCI Registers */ - smram_t *smram; /* SMRAM Handler */ + uint8_t shadow, + shadow_read, shadow_write, + pci_conf[256]; /* PCI Registers */ + int mem_state[9]; + smram_t *smram[2]; /* SMRAM Handlers */ } hb4_t; +static int shadow_bios[4] = { (MEM_READ_EXTANY | MEM_WRITE_INTERNAL), (MEM_READ_EXTANY | MEM_WRITE_EXTANY), + (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL), (MEM_READ_INTERNAL | MEM_WRITE_EXTANY) }; +static int shadow_read[2] = { MEM_READ_EXTANY, MEM_READ_INTERNAL }; +static int shadow_write[2] = { MEM_WRITE_INTERNAL, MEM_WRITE_EXTANY }; + + +int +hb4_shadow_bios_high(hb4_t *dev) +{ + int state; + + state = shadow_bios[dev->pci_conf[0x55] >> 6]; + + if (state != dev->mem_state[8]) { + mem_set_mem_state_both(0xf0000, 0x10000, state); + if ((dev->mem_state[8] & MEM_READ_INTERNAL) && !(state & MEM_READ_INTERNAL)) + mem_invalidate_range(0xf0000, 0xfffff); + dev->mem_state[8] = state; + return 1; + } + + return 0; +} + + +int +hb4_shadow_bios_low(hb4_t *dev) +{ + int state; + + state = shadow_bios[(dev->pci_conf[0x55] >> 6) & (dev->shadow | 0x01)]; + + if (state != dev->mem_state[7]) { + mem_set_mem_state_both(0xe0000, 0x10000, state); + dev->mem_state[7] = state; + return 1; + } + + return 0; +} + + +int +hb4_shadow_main(hb4_t *dev) +{ + int i, state; + int n = 0; + + for (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]; + + if (state != dev->mem_state[i + 1]) { + n++; + mem_set_mem_state_both(0xc8000 + (i << 14), 0x4000, state); + dev->mem_state[i + 1] = state; + } + } + + return n; +} + + +int +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]; + + if (state != dev->mem_state[0]) { + mem_set_mem_state_both(0xc0000, 0x8000, state); + dev->mem_state[0] = state; + return 1; + } + + return 0; +} + + void hb4_shadow(hb4_t *dev) { - int state, i; + int n = 0; + pclog("SHADOW: %02X%02X\n", dev->pci_conf[0x55], dev->pci_conf[0x54]); - mem_set_mem_state_both(0xe0000, 0x20000, ((dev->pci_conf[0x55] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | - ((dev->pci_conf[0x55] & 0x40) ? MEM_WRITE_EXTANY : MEM_WRITE_INTERNAL)); + n = hb4_shadow_bios_high(dev); + n += hb4_shadow_bios_low(dev); + n += hb4_shadow_main(dev); + n += hb4_shadow_video(dev); - if (dev->pci_conf[0x54] & 1) { - state = (dev->pci_conf[0x54] & 0x02) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - state |= (dev->pci_conf[0x55] & 0x40) ? MEM_WRITE_EXTANY : MEM_WRITE_INTERNAL; - - mem_set_mem_state_both(0xc0000, 0x8000, state); - - for (i = 0; i < 6; i++) { - state = (dev->pci_conf[0x54] & (1 << (i + 2))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; - state |= (dev->pci_conf[0x55] & 0x40) ? MEM_WRITE_EXTANY : MEM_WRITE_INTERNAL; - - mem_set_mem_state_both(0xc8000 + (i << 4), 0x4000, state); - } - } - - flushmmucache_nopc(); + if (n > 0) + flushmmucache_nopc(); } @@ -169,7 +256,9 @@ hb4_smram(hb4_t *dev) /* 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, 0x000a0000, 0x000a0000, 0x20000, dev->pci_conf[0x60] & 0x01, 1); + 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); /* Bit 5 seems to set data to go to PCI and code to DRAM. The Samsung SPC7700P-LW uses this. */ @@ -185,6 +274,8 @@ static void hb4_write(int func, int addr, uint8_t val, void *priv) { hb4_t *dev = (hb4_t *)priv; + uint8_t old; + hb4_log("UM8881: dev->regs[%02x] = %02x POST: %02x \n", addr, val, inb(0x80)); switch (addr) { @@ -207,11 +298,23 @@ hb4_write(int func, int addr, uint8_t val, void *priv) break; case 0x51: case 0x52: - case 0x53: dev->pci_conf[addr] = val; break; - case 0x54: case 0x55: + case 0x53: + old = dev->pci_conf[addr]; + dev->pci_conf[addr] = val; + pclog("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; dev->pci_conf[addr] = val; hb4_shadow(dev); break; @@ -236,8 +339,12 @@ static uint8_t hb4_read(int func, int addr, void *priv) { hb4_t *dev = (hb4_t *)priv; + uint8_t ret = 0xff; - return dev->pci_conf[addr]; + if (func == 0) + ret = dev->pci_conf[addr]; + + return ret; } @@ -245,6 +352,7 @@ static void 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; @@ -269,7 +377,12 @@ hb4_reset(void *priv) hb4_write(0, 0x54, 0x00, dev); hb4_write(0, 0x55, 0x00, dev); - hb4_write(0, 0x60, 0x20, dev); + hb4_write(0, 0x60, 0x80, dev); + + cpu_cache_ext_enabled = 0; + cpu_update_waitstates(); + + memset(dev->mem_state, 0x00, sizeof(dev->mem_state)); } @@ -294,7 +407,8 @@ hb4_init(const device_t *info) device_add(&port_92_pci_device); /* SMRAM */ - dev->smram = smram_add(); + dev->smram[0] = smram_add(); + dev->smram[1] = smram_add(); hb4_reset(dev); diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index 467ea01eb..4eb9530ba 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -591,7 +591,7 @@ smram_restore_state_p5(uint32_t *saved_state) smm_seg_load(&cpu_state.seg_gs); if (SMM_REVISION_ID & SMM_SMBASE_RELOCATION) - smbase = saved_state[SMRAM_FIELD_P5_SMBASE_OFFSET] & 0x00ffffff; + smbase = saved_state[SMRAM_FIELD_P5_SMBASE_OFFSET]; /* Am486/5x86 stuff */ if (!is_pentium) { diff --git a/src/cpu/x86.c b/src/cpu/x86.c index c16939559..725d674e8 100644 --- a/src/cpu/x86.c +++ b/src/cpu/x86.c @@ -241,8 +241,13 @@ reset_common(int hard) leave_smm(); /* Needed for the ALi M1533. */ - if (is486 && (hard || soft_reset_pci)) + if (is486 && (hard || soft_reset_pci)) { pci_reset(); + if (!hard && soft_reset_pci) { + dma_reset(); + device_reset_all(); + } + } use32 = 0; cpu_cur_status = 0; diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index c64f8b87f..5dc67ad55 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -673,6 +673,7 @@ kbd_status(const char *fmt, ...) } +// #define ENABLE_KEYBOARD_AT_LOG 1 #ifdef ENABLE_KEYBOARD_AT_LOG int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG; @@ -1219,13 +1220,14 @@ write_output(atkbd_t *dev, uint8_t val) /* Do this here to avoid an infinite reset loop. */ dev->p2 = val; - /* 0 holds the CPU in the RESET state, 1 releases it. To simply this, + /* 0 holds the CPU in the RESET state, 1 releases it. To simplify this, we just do everything on release. */ if ((val & 0x01) && !(old & 0x01)) { if (val & 0x01) { /* Pin 0 selected. */ pclog("write_output(): Pulse reset!\n"); - hardresetx86(); /*Pulse reset!*/ + softresetx86(); /*Pulse reset!*/ + cpu_set_edx(); } } } @@ -2936,18 +2938,36 @@ static void kbd_reset(void *priv) { atkbd_t *dev = (atkbd_t *)priv; - int i; - uint8_t kbc_ven; if (dev == NULL) return; - kbc_ven = dev->flags & KBC_VEN_MASK; - dev->status &= ~(STAT_IFULL | STAT_OFULL | STAT_CD); dev->last_irq = 0; + picintc(1 << 1); + picintc(1 << 12); dev->secr_phase = 0; dev->kbd_in = 0; + dev->ob = 0xff; + + sc_or = 0; +} + + +static void +kbd_power_on(atkbd_t *dev) +{ + int i; + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + + kbd_reset(dev); + + dev->status = STAT_UNLOCKED; + /* Write the value here first, so that we don't hit a pulse reset. */ + dev->p2 = 0xcf; + write_output(dev, 0xcf); + dev->mem[0x20] = 0x01; + dev->mem[0x20] |= CCB_TRANSLATE; dev->ami_mode = !!(dev->flags & KBC_FLAG_PS2); /* Set up the correct Video Type bits. */ @@ -2960,17 +2980,15 @@ kbd_reset(void *priv) dev->inhibit = 0x10; kbd_log("ATkbc: input port = %02x\n", dev->p1); - keyboard_mode = 0x02 | (dev->mem[0x20] & CCB_TRANSLATE); - /* Enable keyboard, disable mouse. */ set_enable_kbd(dev, 1); keyboard_scan = 1; set_enable_mouse(dev, 0); mouse_scan = 0; - dev->ob = 0xff; + dev->mem[0x31] = 0xfe; - sc_or = 0; + keyboard_mode = 0x02 | (dev->mem[0x20] & CCB_TRANSLATE); for (i = 1; i <= 2; i++) kbc_queue_reset(i); @@ -2978,22 +2996,6 @@ kbd_reset(void *priv) memset(keyboard_set3_flags, 0, 512); set_scancode_map(dev); - - dev->mem[0x31] = 0xfe; -} - - -static void -kbd_power_on(atkbd_t *dev) -{ - kbd_reset(dev); - - dev->status = STAT_UNLOCKED; - /* Write the value here first, so that we don't hit a pulse reset. */ - dev->p2 = 0xcf; - write_output(dev, 0xcf); - dev->mem[0x20] = 0x01; - dev->mem[0x20] |= CCB_TRANSLATE; } diff --git a/src/mem/mem.c b/src/mem/mem.c index 693f9db2a..855cdd93a 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -1913,13 +1913,13 @@ page_remove_from_evict_list(page_t *p) void mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) { - if ((p != NULL) && (p->mem == page_ff)) + if (p == NULL) return; #ifdef USE_DYNAREC - if (val != p->mem[addr & 0xfff] || codegen_in_recompile) { + if ((p->mem == NULL) || (p->mem == page_ff) || (val != p->mem[addr & 0xfff]) || codegen_in_recompile) { #else - if (val != p->mem[addr & 0xfff]) { + if ((p->mem == NULL) || (p->mem == page_ff) || (val != p->mem[addr & 0xfff])) { #endif uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; @@ -1939,13 +1939,13 @@ mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) void mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) { - if ((p != NULL) && (p->mem == page_ff)) + if (p == NULL) return; #ifdef USE_DYNAREC - if (val != *(uint16_t *)&p->mem[addr & 0xfff] || codegen_in_recompile) { + if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint16_t *)&p->mem[addr & 0xfff]) || codegen_in_recompile) { #else - if (val != *(uint16_t *)&p->mem[addr & 0xfff]) { + if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint16_t *)&p->mem[addr & 0xfff])) { #endif uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; @@ -1975,13 +1975,13 @@ mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) void mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) { - if ((p != NULL) && (p->mem == page_ff)) + if (p == NULL) return; #ifdef USE_DYNAREC - if (val != *(uint32_t *)&p->mem[addr & 0xfff] || codegen_in_recompile) { + if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint32_t *)&p->mem[addr & 0xfff]) || codegen_in_recompile) { #else - if (val != *(uint32_t *)&p->mem[addr & 0xfff]) { + if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint32_t *)&p->mem[addr & 0xfff])) { #endif uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; @@ -2007,13 +2007,13 @@ mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) void mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) { - if ((p != NULL) && (p->mem == page_ff)) + if (p == NULL) return; #ifdef USE_DYNAREC - if ((p == NULL) || (p->mem == NULL) || (val != p->mem[addr & 0xfff]) || codegen_in_recompile) { + if ((p->mem == NULL) || (p->mem == page_ff) || (val != p->mem[addr & 0xfff]) || codegen_in_recompile) { #else - if ((p == NULL) || (p->mem == NULL) || (val != p->mem[addr & 0xfff])) { + if ((p->mem == NULL) || (p->mem == page_ff) || (val != p->mem[addr & 0xfff])) { #endif uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; @@ -2025,13 +2025,13 @@ mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) void mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) { - if ((p != NULL) && (p->mem == page_ff)) + if (p == NULL) return; #ifdef USE_DYNAREC - if ((p == NULL) || (p->mem == NULL) || (val != *(uint16_t *)&p->mem[addr & 0xfff]) || codegen_in_recompile) { + if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint16_t *)&p->mem[addr & 0xfff]) || codegen_in_recompile) { #else - if ((p == NULL) || (p->mem == NULL) || (val != *(uint16_t *)&p->mem[addr & 0xfff])) { + if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint16_t *)&p->mem[addr & 0xfff])) { #endif uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); if ((addr & 0xf) == 0xf) @@ -2045,13 +2045,13 @@ mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) void mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) { - if ((p != NULL) && (p->mem == page_ff)) + if (p == NULL) return; #ifdef USE_DYNAREC - if ((p == NULL) || (p->mem == NULL) || (val != *(uint32_t *)&p->mem[addr & 0xfff]) || codegen_in_recompile) { + if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint32_t *)&p->mem[addr & 0xfff]) || codegen_in_recompile) { #else - if ((p == NULL) || (p->mem == NULL) || (val != *(uint32_t *)&p->mem[addr & 0xfff])) { + if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint32_t *)&p->mem[addr & 0xfff])) { #endif uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); if ((addr & 0xf) >= 0xd) @@ -2180,42 +2180,27 @@ mem_write_remappedl(uint32_t addr, uint32_t val, void *priv) void mem_invalidate_range(uint32_t start_addr, uint32_t end_addr) { - uint64_t mask; #ifdef USE_NEW_DYNAREC int byte_offset; uint64_t byte_mask; - uint32_t i; page_t *p; start_addr &= ~PAGE_MASK_MASK; end_addr = (end_addr + PAGE_MASK_MASK) & ~PAGE_MASK_MASK; - for (; start_addr <= end_addr; start_addr += (1 << PAGE_MASK_SHIFT)) { + for (; start_addr <= end_addr; start_addr += 0x1000) { if ((start_addr >> 12) >= pages_sz) continue; - mask = (uint64_t)1 << ((start_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - p = &pages[start_addr >> 12]; - p->dirty_mask |= mask; - if ((p->code_present_mask & mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); + if (p) { + p->dirty_mask = 0xffffffffffffffffULL; - for (i = start_addr; (i <= end_addr) && (i < (start_addr + (1 << PAGE_MASK_SHIFT))); i++) { - /* Do not look at the byte stuff if start_addr >= (mem_size * 1024), as we do not allocate the - byte dirty and code present mask arrays beyond the end of RAM. */ - if (i < (mem_size << 10)) { - byte_offset = (i >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; - byte_mask = (uint64_t)1 << (i & PAGE_BYTE_MASK_MASK); + if (p->byte_dirty_mask) + memset(p->byte_dirty_mask, 0xff, 64 * sizeof(uint64_t)); - if (p) { - if (p->byte_dirty_mask) - p->byte_dirty_mask[byte_offset] |= byte_mask; - if (p->byte_code_present_mask && (p->byte_code_present_mask[byte_offset] & byte_mask) && - !page_in_evict_list(p)) - page_add_to_evict_list(p); - } - } + if (!page_in_evict_list(p)) + page_add_to_evict_list(p); } } #else @@ -2223,14 +2208,12 @@ mem_invalidate_range(uint32_t start_addr, uint32_t end_addr) start_addr &= ~PAGE_MASK_MASK; end_addr = (end_addr + PAGE_MASK_MASK) & ~PAGE_MASK_MASK; - for (; start_addr <= end_addr; start_addr += (1 << PAGE_MASK_SHIFT)) { - mask = (uint64_t)1 << ((start_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - + for (; start_addr <= end_addr; start_addr += 0x1000) { /* Do nothing if the pages array is empty or DMA reads/writes to/from PCI device memory addresses may crash the emulator. */ cur_addr = (start_addr >> 12); if (cur_addr < pages_sz) - pages[cur_addr].dirty_mask[(start_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; + memset(pages[cur_addr].dirty_mask, 0xff, sizeof(pages[cur_addr].dirty_mask)); } #endif } @@ -2712,6 +2695,7 @@ mem_reset(void) if ((c << 12) >= (mem_size << 10)) pages[c].mem = page_ff; else { +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) if (mem_size > 1048576) { if ((c << 12) < (1 << 30)) pages[c].mem = &ram[c << 12]; @@ -2719,6 +2703,9 @@ mem_reset(void) pages[c].mem = &ram2[(c << 12) - (1 << 30)]; } else pages[c].mem = &ram[c << 12]; +#else + pages[c].mem = &ram[c << 12]; +#endif } if (c < m) { pages[c].write_b = mem_write_ramb_page; From 114539b2b26eb7c670436e23c295ded86e546a89 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 2 Oct 2021 23:07:12 +0200 Subject: [PATCH 80/96] Added a pic_set_pci() function that adds the PIC I/O aliases. --- src/include/86box/pic.h | 1 + src/pic.c | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/include/86box/pic.h b/src/include/86box/pic.h index 139aa5195..33be66135 100644 --- a/src/include/86box/pic.h +++ b/src/include/86box/pic.h @@ -45,6 +45,7 @@ extern void pic_elcr_write(uint16_t port, uint8_t val, void *priv); extern uint8_t pic_elcr_read(uint16_t port, void *priv); extern void pic_set_shadow(int sh); +extern void pic_set_pci(void); extern void pic_init(void); extern void pic_init_pcjr(void); extern void pic2_init(void); diff --git a/src/pic.c b/src/pic.c index 36bd4b0e2..86db5389c 100644 --- a/src/pic.c +++ b/src/pic.c @@ -515,6 +515,18 @@ pic_write(uint16_t addr, uint8_t val, void *priv) } +void +pic_set_pci(void) +{ + int i; + + for (i = 0x0024; i < 0x0040; i++) { + io_sethandler(i, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic); + io_sethandler(i + 0x0080, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic2); + } +} + + void pic_init(void) { From 63d208182aea3dadbc0675b36407c9cface83bd4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 4 Oct 2021 15:38:43 +0200 Subject: [PATCH 81/96] Fixed pic_set_pci(). --- src/pic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pic.c b/src/pic.c index 86db5389c..38cee8951 100644 --- a/src/pic.c +++ b/src/pic.c @@ -520,7 +520,7 @@ pic_set_pci(void) { int i; - for (i = 0x0024; i < 0x0040; i++) { + for (i = 0x0024; i < 0x0040; i += 4) { io_sethandler(i, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic); io_sethandler(i + 0x0080, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic2); } From 9765090991557a5ea9697c9819c4c5744ad84bbc Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 4 Oct 2021 19:52:04 +0200 Subject: [PATCH 82/96] Made pic_set_pci() also add aliases on 1120-113F and 11A0-11BF. --- src/pic.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/pic.c b/src/pic.c index 38cee8951..c77f08023 100644 --- a/src/pic.c +++ b/src/pic.c @@ -524,6 +524,11 @@ pic_set_pci(void) io_sethandler(i, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic); io_sethandler(i + 0x0080, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic2); } + + for (i = 0x1120; i < 0x1140; i += 4) { + io_sethandler(i, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic); + io_sethandler(i + 0x0080, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic2); + } } From d858033ae8329473a1dfdf0c8b1765566d1592fd Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 6 Oct 2021 18:17:32 +0200 Subject: [PATCH 83/96] Removed the two IMS8848 machines. --- src/machine/machine_table.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 3a57cf0c6..6910a5274 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -432,10 +432,6 @@ const machine_t machines[] = { { "[i420TX] ASUS PCI/I-486SP3", "486sp3", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL | MACHINE_SCSI, 1024, 131072, 1024, 127, machine_at_486sp3_init, NULL }, /* This has the Phoenix MultiKey KBC firmware. */ { "[i420TX] Intel Classic/PCI", "alfredo", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_alfredo_init, NULL }, - /* This most likely has a standalone AMI Megakey 1993, which is type 'P', like the below Tekram board. */ - { "[IMS 8848] J-Bond PCI400C-B", "pci400c_b", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_pci400c_b_init, NULL }, - /* This has a standalone AMI Megakey 1993, which is type 'P'. */ - { "[IMS 8848] Tekram G486IP", "g486ip", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_g486ip_init, NULL }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[SiS 496] ASUS PVI-486SP3C", "486sp3c", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_IDE_DUAL, 1024, 261120, 1024, 255, machine_at_486sp3c_init, NULL }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ From 126688fc5e93c95da9c1f42b2e6ce250ba40726b Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 9 Oct 2021 16:40:47 +0200 Subject: [PATCH 84/96] Added a comment related to the PB450. --- src/device/keyboard_at.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 5dc67ad55..6a3d9c370 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -2067,6 +2067,8 @@ write64_generic(void *priv, uint8_t val) Bit 2 must be 0 (and Acer V10 disables CMOS setup if it's 1), Bit 4 must be 0, Bit 6 ignored. + Packard Bell PB450: + Bit 2 must be 1. P6RP4: Bit 2 must be 1 or CMOS setup is disabled. */ kbd_log("ATkbc: read input port\n"); From 79999818f5b97e2f15903e8b43b011ee88a0e6c4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 9 Oct 2021 17:27:07 +0200 Subject: [PATCH 85/96] A slight fix to the OPTi 611 IDE controller. --- src/disk/hdc_ide_opti611.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/disk/hdc_ide_opti611.c b/src/disk/hdc_ide_opti611.c index 73a52a723..4cdf06b78 100644 --- a/src/disk/hdc_ide_opti611.c +++ b/src/disk/hdc_ide_opti611.c @@ -56,11 +56,11 @@ opti611_cfg_write(uint16_t addr, uint8_t val, void *priv) case 0x0002: dev->regs[0x12] = (val & 0xc1) | 0x02; if (val & 0xc0) { + if (val & 0x40) + dev->cfg_locked = 1; dev->in_cfg = 0; opti611_ide_handler(dev); } - if (val & 0x40) - dev->cfg_locked = 1; break; case 0x0003: dev->regs[0x03] = (val & 0xdf); From 1c2d1e702bafae6a71c1c32d23659642453964cb Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 9 Oct 2021 17:37:09 +0200 Subject: [PATCH 86/96] Assorted changes and bugfixes and added the two IMS 8848 machines. --- src/86box.c | 20 ++ src/chipset/ims8848.c | 411 ++++++++++++++++++++++++++++++++ src/chipset/intel_4x0.c | 54 ++--- src/chipset/opti499.c | 264 ++++++++++++++++++++ src/chipset/sis_5511.c | 177 ++++++++------ src/cpu/cpu.c | 6 + src/cpu/cpu.h | 3 + src/cpu/x86.c | 21 +- src/cpu/x86_ops_misc.h | 2 + src/cpu/x86_ops_mov_ctrl.h | 81 ++++++- src/device/phoenix_486_jumper.c | 47 +++- src/include/86box/chipset.h | 5 +- src/include/86box/machine.h | 3 + src/include/86box/mem.h | 2 + src/include/86box/smram.h | 2 + src/io.c | 3 + src/machine/m_at_386dx_486.c | 71 +++++- src/machine/machine_table.c | 4 + src/mem/smram.c | 58 ++++- src/win/Makefile.mingw | 2 +- 20 files changed, 1086 insertions(+), 150 deletions(-) create mode 100644 src/chipset/ims8848.c create mode 100644 src/chipset/opti499.c diff --git a/src/86box.c b/src/86box.c index eca8544a5..e965f84c5 100644 --- a/src/86box.c +++ b/src/86box.c @@ -724,6 +724,26 @@ pc_init_modules(void) wchar_t temp[512]; char tempc[512]; + c = m = 0; + while (machine_get_internal_name_ex(c) != NULL) { + m = machine_available(c); + if (!m) + pclog("Missing machine: %s\n", machine_getname_ex(c)); + c++; + } + + c = m = 0; + while (video_get_internal_name(c) != NULL) { + memset(tempc, 0, sizeof(tempc)); + device_get_name(video_card_getdevice(c), 0, tempc); + if ((c > 1) && !(tempc[0])) + break; + m = video_card_available(c); + if (!m) + pclog("Missing video card: %s\n", tempc); + c++; + } + pc_log("Scanning for ROM images:\n"); c = m = 0; while (machine_get_internal_name_ex(m) != NULL) { diff --git a/src/chipset/ims8848.c b/src/chipset/ims8848.c new file mode 100644 index 000000000..da758ad5e --- /dev/null +++ b/src/chipset/ims8848.c @@ -0,0 +1,411 @@ +/* + * 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 IMS 8848/8849 chipset. + * + * + * + * Authors: Miran Grca, + * Tiseno100, + * + * Copyright 2021 Miran Grca. + * Copyright 2021 Tiseno100. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/io.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/smram.h> +#include <86box/pci.h> +#include <86box/port_92.h> +#include <86box/chipset.h> + + +/* + IMS 884x Configuration Registers + + Note: IMS 884x are rebadged ATMEL AT 40411/40412 chipsets + + By: Tiseno100, Miran Grca(OBattler) + + Register 00h: + Bit 3: F0000-FFFFF Shadow Enable + Bit 2: E0000-EFFFF Shadow Enable + Bit 0: ???? + + Register 04h: + Bit 3: Cache Write Hit Wait State + Bit 2: Cache Read Hit Wait State + + Register 06h: + Bit 3: System BIOS Cacheable (1: Yes / 0: No) + Bit 1: Power Management Mode (1: IRQ / 0: SMI#) + + Register 08h: + Bit 2: System BIOS Shadow Write (1: Enable / 0: Disable) + Bit 1: System BIOS Shadow Read? + + Register 0Dh: + Bit 0: IO 100H-3FFH Idle Detect (1: Enable / 0: Disable) + + Register 0Eh: + Bit 7: DMA & Local Bus Idle Detect (1: Enable / 0: Disable) + Bit 6: Floppy Disk Idle Detect (1: Enable / 0: Disable) + Bit 5: IDE Idle Detect (1: Enable / 0: Disable) + Bit 4: Serial Port Idle Detect (1: Enable / 0: Disable) + Bit 3: Parallel Port Idle Detect (1: Enable / 0: Disable) + Bit 2: Keyboard Idle Detect (1: Enable / 0: Disable) + Bit 1: Video Idle Detect (1: Enable / 0: Disable) + + Register 12h: + Bits 3-2: Power Saving Timer (00 = 1 MIN, 01 = 3 MIN, 10 = 5 MIN, 11 = 8 MIN) + Bit 1: Base Memory (1: 512KB / 0: 640KB) + + Register 1Ah: + Bit 3: Cache Write Hit W/S For PCI (1: Enabled / 0: Disable) + Bit 2: Cache Read Hit W/S For PCI (1: Enabled / 0: Disable) + Bit 1: VESA Clock Skew (1: 4ns/6ns, 0: No Delay/2ns) + + Register 1Bh: + Bit 6: Enable SMRAM (always at 30000-4FFFF) in SMM + Bit 5: ???? + Bit 4: Software SMI# + Bit 3: DC000-DFFFF Shadow Enable + Bit 2: D8000-DBFFF Shadow Enable + Bit 1: D4000-D7FFF Shadow Enable + Bit 0: D0000-D3FFF Shadow Enable + + Register 1Ch: + Bits 7-4: INTA IRQ routing (0 = disabled, 1 to F = IRQ) + Bit 3: CC000-CFFFF Shadow Enable + Bit 2: C8000-CBFFF Shadow Enable + Bit 1: C4000-C7FFF Shadow Enable + Bit 0: C0000-C3FFF Shadow Enable + + Register 1Dh: + Bits 7-4: INTB IRQ routing (0 = disabled, 1 to F = IRQ) + + Register 1Eh: + Bits 7-4: INTC IRQ routing (0 = disabled, 1 to F = IRQ) + Bit 1: C4000-C7FFF Cacheable + Bit 0: C0000-C3FFF Cacheable + + Register 21h: + Bits 7-4: INTD IRQ routing (0 = disabled, 1 to F = IRQ) + + Register 22h: + Bit 5: Local Bus Master #2 select (0 = VESA, 1 = PCI) + Bit 4: Local Bus Master #1 select (0 = VESA, 1 = PCI) + Bits 1-0: Internal HADS# Delay Always (00 = No Delay, 01 = 1 Clk, 10 = 2 Clks) + + Register 23h: + Bit 7: Seven Bits Tag (1: Enabled / 0: Disable) + Bit 3: Extend LBRDY#(VL Master) (1: Enabled / 0: Disable) + Bit 2: Sync LRDY#(VL Slave) (1: Enabled / 0: Disable) + Bit 0: HADS# Delay After LB. Cycle (1: Enabled / 0: Disable) +*/ + +typedef struct +{ + uint8_t idx, access_data, + regs[256], pci_conf[256]; + + smram_t *smram; +} ims8848_t; + + +#ifdef ENABLE_IMS8848_LOG +int ims8848_do_log = ENABLE_IMS8848_LOG; + + +static void +ims8848_log(const char *fmt, ...) +{ + va_list ap; + + if (ims8848_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define ims8848_log(fmt, ...) +#endif + + +/* Shadow write always enabled, 1B and 1C control C000-DFFF read. */ +static void +ims8848_recalc(ims8848_t *dev) +{ + int i, state_on; + uint32_t base; + ims8848_log("SHADOW: 00 = %02X, 08 = %02X, 1B = %02X, 1C = %02X\n", + dev->regs[0x00], dev->regs[0x08], dev->regs[0x1b], dev->regs[0x1c]); + + state_on = MEM_READ_INTERNAL; + state_on |= (dev->regs[0x08] & 0x04) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + + for (i = 0; i < 2; i++) { + base = 0xe0000 + (i << 16); + if (dev->regs[0x00] & (1 << (i + 2))) + mem_set_mem_state_both(base, 0x10000, state_on); + else + mem_set_mem_state_both(base, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + } + + for (i = 0; i < 4; i++) { + base = 0xc0000 + (i << 14); + if (dev->regs[0x1c] & (1 << i)) + mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + else + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + + base = 0xd0000 + (i << 14); + if (dev->regs[0x1b] & (1 << i)) + mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + else + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + } + + flushmmucache_nopc(); +} + + +static void +ims8848_base_memory(ims8848_t *dev) +{ + /* We can use the proper mem_set_access to handle that. */ + mem_set_mem_state_both(0x80000, 0x20000, (dev->regs[0x12] & 2) ? + (MEM_READ_DISABLED | MEM_WRITE_DISABLED) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); +} + + +static void +ims8848_smram(ims8848_t *dev) +{ + smram_disable_all(); + + smram_enable(dev->smram, 0x00030000, 0x00030000, 0x20000, dev->regs[0x1b] & 0x40, 1); +} + + +static void +ims8848_write(uint16_t addr, uint8_t val, void *priv) +{ + ims8848_t *dev = (ims8848_t *) priv; + uint8_t old = dev->regs[dev->idx]; + + switch (addr) { + case 0x22: + ims8848_log("[W] IDX = %02X\n", val); + dev->idx = val; + break; + case 0x23: + ims8848_log("[W] IDX IN = %02X\n", val); + if (((val & 0x0f) == ((dev->idx >> 4) & 0x0f)) && ((val & 0xf0) == ((dev->idx << 4) & 0xf0))) + dev->access_data = 1; + break; + case 0x24: + ims8848_log("[W] [%i] REG %02X = %02X\n", dev->access_data, dev->idx, val); + if (dev->access_data) { + dev->regs[dev->idx] = val; + switch (dev->idx) { + case 0x00: case 0x08: case 0x1b: case 0x1c: + /* Shadow RAM */ + ims8848_recalc(dev); + if (dev->idx == 0x1b) { + ims8848_smram(dev); + if (!(old & 0x10) && (val & 0x10)) + smi_line = 1; + } else if (dev->idx == 0x1c) + pci_set_irq_routing(PCI_INTA, (val >> 4) ? (val >> 4) : PCI_IRQ_DISABLED); + break; + + case 0x1d: case 0x1e: + pci_set_irq_routing(PCI_INTB + (dev->idx - 0x1d), (val >> 4) ? (val >> 4) : PCI_IRQ_DISABLED); + break; + case 0x21: + pci_set_irq_routing(PCI_INTD, (val >> 4) ? (val >> 4) : PCI_IRQ_DISABLED); + break; + + case 0x12: + /* Base Memory */ + ims8848_base_memory(dev); + break; + } + dev->access_data = 0; + } + break; + } +} + + +static uint8_t +ims8848_read(uint16_t addr, void *priv) +{ + uint8_t ret = 0xff; + ims8848_t *dev = (ims8848_t *) priv; +#ifdef ENABLE_IMS8848_LOG + uint8_t old_ad = dev->access_data; +#endif + + switch (addr) { + case 0x22: + ims8848_log("[R] IDX = %02X\n", ret); + ret = dev->idx; + break; + case 0x23: + ims8848_log("[R] IDX IN = %02X\n", ret); + ret = (dev->idx >> 4) | (dev->idx << 4); + break; + case 0x24: + if (dev->access_data) { + ret = dev->regs[dev->idx]; + dev->access_data = 0; + } + ims8848_log("[R] [%i] REG %02X = %02X\n", old_ad, dev->idx, ret); + break; + } + + return ret; +} + + +static void +ims8849_pci_write(int func, int addr, uint8_t val, void *priv) +{ + ims8848_t *dev = (ims8848_t *)priv; + + ims8848_log("IMS 884x-PCI: dev->regs[%02x] = %02x POST: %02x\n", addr, val, inb(0x80)); + + if (func == 0) switch (addr) { + case 0x04: + dev->pci_conf[addr] = val; + break; + + case 0x05: + dev->pci_conf[addr] = val & 3; + break; + + case 0x07: + dev->pci_conf[addr] &= val & 0xf7; + break; + + case 0x0c ... 0x0d: + dev->pci_conf[addr] = val; + break; + + case 0x52 ... 0x55: + dev->pci_conf[addr] = val; + break; + } +} + + +static uint8_t +ims8849_pci_read(int func, int addr, void *priv) +{ + ims8848_t *dev = (ims8848_t *)priv; + uint8_t ret = 0xff; + + if (func == 0) + ret = dev->pci_conf[addr]; + + return ret; +} + + +static void +ims8848_reset(void *priv) +{ + ims8848_t *dev = (ims8848_t *)priv; + + memset(dev->regs, 0x00, sizeof(dev->regs)); + memset(dev->pci_conf, 0x00, sizeof(dev->pci_conf)); + + dev->pci_conf[0x00] = 0xe0; /* Integrated Micro Solutions (IMS) */ + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x49; /* 8849 */ + dev->pci_conf[0x03] = 0x88; + + dev->pci_conf[0x04] = 0x07; + dev->pci_conf[0x07] = 0x02; + + dev->pci_conf[0x0b] = 0x06; + + ims8848_recalc(dev); /* Shadow RAM Setup */ + ims8848_base_memory(dev); /* Base Memory Setup */ + + 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); + + ims8848_smram(dev); +} + + +static void +ims8848_close(void *priv) +{ + ims8848_t *dev = (ims8848_t *) priv; + + smram_del(dev->smram); + + free(dev); +} + + +static void * +ims8848_init(const device_t *info) +{ + ims8848_t *dev = (ims8848_t *) malloc(sizeof(ims8848_t)); + memset(dev, 0, sizeof(ims8848_t)); + + device_add(&port_92_device); + + /* IMS 8848: + 22h Index + 23h Data Unlock + 24h Data + + IMS 8849: + PCI Device 0: IMS 8849 Dummy for compatibility reasons + */ + io_sethandler(0x0022, 0x0003, ims8848_read, NULL, NULL, ims8848_write, NULL, NULL, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, ims8849_pci_read, ims8849_pci_write, dev); + + dev->smram = smram_add(); + smram_set_separate_smram(1); + + cpu_cache_ext_enabled = 1; + cpu_update_waitstates(); + + ims8848_reset(dev); + + return dev; +} + + +const device_t ims8848_device = { + "IMS 8848/8849", + 0, + 0, + ims8848_init, ims8848_close, ims8848_reset, + { NULL }, NULL, NULL, + NULL +}; diff --git a/src/chipset/intel_4x0.c b/src/chipset/intel_4x0.c index 6da41c24f..bf64bd00f 100644 --- a/src/chipset/intel_4x0.c +++ b/src/chipset/intel_4x0.c @@ -55,6 +55,7 @@ typedef struct smram_locked, max_drb, drb_unit, drb_default; uint8_t regs[256], regs_locked[256]; + uint8_t mem_state[256]; int type; smram_t *smram_low, *smram_high; } i4x0_t; @@ -81,23 +82,18 @@ i4x0_log(const char *fmt, ...) static void -i4x0_map(uint32_t addr, uint32_t size, int state) +i4x0_map(i4x0_t *dev, uint32_t addr, uint32_t size, int state) { - switch (state & 3) { - case 0: - mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - break; - case 1: - mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); - break; - case 2: - mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); - break; - case 3: - mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; + uint32_t base = addr >> 12; + int states[4] = { MEM_READ_EXTANY | MEM_WRITE_EXTANY, MEM_READ_INTERNAL | MEM_WRITE_EXTANY, + MEM_READ_EXTANY | MEM_WRITE_INTERNAL, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL }; + + state &= 3; + if (dev->mem_state[base] != state) { + mem_set_mem_state_both(addr, size, states[state]); + dev->mem_state[base] = state; + flushmmucache_nopc(); } - flushmmucache_nopc(); } @@ -584,10 +580,10 @@ i4x0_write(int func, int addr, uint8_t val, void *priv) case 0x59: /* PAM0 */ if (dev->type <= INTEL_430NX) { if ((regs[0x59] ^ val) & 0x0f) - i4x0_map(0x80000, 0x20000, val & 0x0f); + i4x0_map(dev, 0x80000, 0x20000, val & 0x0f); } if ((regs[0x59] ^ val) & 0xf0) { - i4x0_map(0xf0000, 0x10000, val >> 4); + i4x0_map(dev, 0xf0000, 0x10000, val >> 4); shadowbios = (val & 0x10); } if (dev->type > INTEL_430NX) @@ -597,44 +593,44 @@ i4x0_write(int func, int addr, uint8_t val, void *priv) break; case 0x5a: /* PAM1 */ if ((regs[0x5a] ^ val) & 0x0f) - i4x0_map(0xc0000, 0x04000, val & 0xf); + i4x0_map(dev, 0xc0000, 0x04000, val & 0xf); if ((regs[0x5a] ^ val) & 0xf0) - i4x0_map(0xc4000, 0x04000, val >> 4); + i4x0_map(dev, 0xc4000, 0x04000, val >> 4); regs[0x5a] = val & 0x77; break; case 0x5b: /*PAM2 */ if ((regs[0x5b] ^ val) & 0x0f) - i4x0_map(0xc8000, 0x04000, val & 0xf); + i4x0_map(dev, 0xc8000, 0x04000, val & 0xf); if ((regs[0x5b] ^ val) & 0xf0) - i4x0_map(0xcc000, 0x04000, val >> 4); + i4x0_map(dev, 0xcc000, 0x04000, val >> 4); regs[0x5b] = val & 0x77; break; case 0x5c: /*PAM3 */ if ((regs[0x5c] ^ val) & 0x0f) - i4x0_map(0xd0000, 0x04000, val & 0xf); + i4x0_map(dev, 0xd0000, 0x04000, val & 0xf); if ((regs[0x5c] ^ val) & 0xf0) - i4x0_map(0xd4000, 0x04000, val >> 4); + i4x0_map(dev, 0xd4000, 0x04000, val >> 4); regs[0x5c] = val & 0x77; break; case 0x5d: /* PAM4 */ if ((regs[0x5d] ^ val) & 0x0f) - i4x0_map(0xd8000, 0x04000, val & 0xf); + i4x0_map(dev, 0xd8000, 0x04000, val & 0xf); if ((regs[0x5d] ^ val) & 0xf0) - i4x0_map(0xdc000, 0x04000, val >> 4); + i4x0_map(dev, 0xdc000, 0x04000, val >> 4); regs[0x5d] = val & 0x77; break; case 0x5e: /* PAM5 */ if ((regs[0x5e] ^ val) & 0x0f) - i4x0_map(0xe0000, 0x04000, val & 0xf); + i4x0_map(dev, 0xe0000, 0x04000, val & 0xf); if ((regs[0x5e] ^ val) & 0xf0) - i4x0_map(0xe4000, 0x04000, val >> 4); + i4x0_map(dev, 0xe4000, 0x04000, val >> 4); regs[0x5e] = val & 0x77; break; case 0x5f: /* PAM6 */ if ((regs[0x5f] ^ val) & 0x0f) - i4x0_map(0xe8000, 0x04000, val & 0xf); + i4x0_map(dev, 0xe8000, 0x04000, val & 0xf); if ((regs[0x5f] ^ val) & 0xf0) - i4x0_map(0xec000, 0x04000, val >> 4); + i4x0_map(dev, 0xec000, 0x04000, val >> 4); regs[0x5f] = val & 0x77; break; case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: diff --git a/src/chipset/opti499.c b/src/chipset/opti499.c new file mode 100644 index 000000000..87bc39c8d --- /dev/null +++ b/src/chipset/opti499.c @@ -0,0 +1,264 @@ +/* + * 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 OPTi 82C493/82C499 chipset. + * + * + * + * Authors: Tiseno100, + * Miran Grca, + * + * Copyright 2008-2020 Tiseno100. + * Copyright 2016-2020 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/io.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/port_92.h> +#include <86box/chipset.h> + + +typedef struct +{ + uint8_t idx, + regs[256], scratch[2]; +} opti499_t; + + +#ifdef ENABLE_OPTI499_LOG +int opti499_do_log = ENABLE_OPTI499_LOG; + + +static void +opti499_log(const char *fmt, ...) +{ + va_list ap; + + if (opti499_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define opti499_log(fmt, ...) +#endif + + +static void +opti499_recalc(opti499_t *dev) +{ + uint32_t base; + uint32_t i, shflags = 0; + + shadowbios = 0; + shadowbios_write = 0; + + if (dev->regs[0x22] & 0x80) { + shadowbios = 1; + shadowbios_write = 0; + shflags = MEM_READ_EXTANY | MEM_WRITE_INTERNAL; + } else { + shadowbios = 0; + shadowbios_write = 1; + shflags = MEM_READ_INTERNAL | MEM_WRITE_DISABLED; + } + + mem_set_mem_state_both(0xf0000, 0x10000, shflags); + + for (i = 0; i < 8; i++) { + base = 0xd0000 + (i << 14); + + if ((dev->regs[0x22] & ((base >= 0xe0000) ? 0x20 : 0x40)) && + (dev->regs[0x23] & (1 << i))) { + shflags = MEM_READ_INTERNAL; + shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; + } else { + if (dev->regs[0x2d] && (1 << ((i >> 1) + 2))) + shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY; + else + shflags = MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL; + } + + mem_set_mem_state_both(base, 0x4000, shflags); + } + + for (i = 0; i < 4; i++) { + base = 0xc0000 + (i << 14); + + if ((dev->regs[0x26] & 0x10) && (dev->regs[0x26] & (1 << i))) { + shflags = MEM_READ_INTERNAL; + shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; + } else { + if (dev->regs[0x26] & 0x40) { + if (dev->regs[0x2d] && (1 << (i >> 1))) + shflags = MEM_READ_EXTANY; + else + shflags = MEM_READ_EXTERNAL; + shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; + } else { + if (dev->regs[0x2d] && (1 << (i >> 1))) + shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY; + else + shflags = MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL; + } + } + + mem_set_mem_state_both(base, 0x4000, shflags); + } + + flushmmucache_nopc(); +} + + +static void +opti499_write(uint16_t addr, uint8_t val, void *priv) +{ + opti499_t *dev = (opti499_t *) priv; + + switch (addr) { + case 0x22: + opti499_log("[%04X:%08X] [W] dev->idx = %02X\n", CS, cpu_state.pc, val); + dev->idx = val; + break; + case 0x24: + if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) { + if (dev->idx == 0x20) + dev->regs[dev->idx] = (dev->regs[dev->idx] & 0xc0) | (val & 0x3f); + else + dev->regs[dev->idx] = val; + opti499_log("[%04X:%08X] [W] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, val); + + switch(dev->idx) { + case 0x20: + reset_on_hlt = !(val & 0x02); + break; + + case 0x21: + cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10); + cpu_update_waitstates(); + break; + + case 0x22: case 0x23: + case 0x26: case 0x2d: + opti499_recalc(dev); + break; + } + } + break; + + case 0xe1: case 0xe2: + dev->scratch[addr] = val; + break; + } +} + + +static uint8_t +opti499_read(uint16_t addr, void *priv) +{ + uint8_t ret = 0xff; + opti499_t *dev = (opti499_t *) priv; + + switch (addr) { + case 0x22: + opti499_log("[%04X:%08X] [R] dev->idx = %02X\n", CS, cpu_state.pc, ret); + break; + case 0x24: + if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) { + if (dev->idx == 0x2d) + ret = dev->regs[dev->idx] & 0xbf; + else + ret = dev->regs[dev->idx]; + opti499_log("[%04X:%08X] [R] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, ret); + } + break; + case 0xe1: + case 0xe2: + ret = dev->scratch[addr]; + break; + } + + return ret; +} + + +static void +opti499_reset(void *priv) +{ + opti499_t *dev = (opti499_t *) priv; + + memset(dev->regs, 0xff, sizeof(dev->regs)); + memset(&(dev->regs[0x20]), 0x00, 14 * sizeof(uint8_t)); + + dev->scratch[0] = dev->scratch[1] = 0xff; + + dev->regs[0x22] = 0x84; + dev->regs[0x24] = 0x87; + dev->regs[0x25] = 0xf0; + dev->regs[0x27] = 0xd1; + dev->regs[0x28] = dev->regs[0x2a] = 0x80; + dev->regs[0x29] = dev->regs[0x2b] = 0x10; + dev->regs[0x2d] = 0x40; + + reset_on_hlt = 1; + + cpu_cache_ext_enabled = 0; + cpu_update_waitstates(); + + opti499_recalc(dev); + + free(dev); +} + + +static void +opti499_close(void *priv) +{ + opti499_t *dev = (opti499_t *) priv; + + free(dev); +} + + +static void * +opti499_init(const device_t *info) +{ + opti499_t *dev = (opti499_t *) malloc(sizeof(opti499_t)); + memset(dev, 0, sizeof(opti499_t)); + + device_add(&port_92_device); + + io_sethandler(0x0022, 0x0001, opti499_read, NULL, NULL, opti499_write, NULL, NULL, dev); + io_sethandler(0x0024, 0x0001, opti499_read, NULL, NULL, opti499_write, NULL, NULL, dev); + + opti499_reset(dev); + + io_sethandler(0x00e1, 0x0002, opti499_read, NULL, NULL, opti499_write, NULL, NULL, dev); + + return dev; +} + + +const device_t opti499_device = { + "OPTi 82C499", + 0, + 1, + opti499_init, opti499_close, opti499_reset, + { NULL }, NULL, NULL, + NULL +}; diff --git a/src/chipset/sis_5511.c b/src/chipset/sis_5511.c index 673d37ebe..f85b021b5 100644 --- a/src/chipset/sis_5511.c +++ b/src/chipset/sis_5511.c @@ -79,40 +79,56 @@ typedef struct sis_5511_t } sis_5511_t; static void -sis_5511_shadow_recalc(int cur_reg, sis_5511_t *dev) +sis_5511_shadow_recalc(sis_5511_t *dev) { - if (cur_reg == 0x86) - mem_set_mem_state_both(0xf0000, 0x10000, ((dev->pci_conf[cur_reg] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->pci_conf[cur_reg] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); - else - { - mem_set_mem_state_both(0xc0000 + ((cur_reg & 7) << 15), 0x4000, ((dev->pci_conf[cur_reg] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->pci_conf[cur_reg] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); - mem_set_mem_state_both(0xc4000 + ((cur_reg & 7) << 15), 0x4000, ((dev->pci_conf[cur_reg] & 8) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->pci_conf[cur_reg] & 2) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); - } + int i, state; + uint32_t base; - flushmmucache_nopc(); + for (i = 0x80; i <= 0x86; i++) { + if (i == 0x86) { + 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); + pclog("000F0000-000FFFFF\n"); + } else { + base = ((i & 0x07) << 15) + 0xc0000; + + 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); + pclog("%08X-%08X\n", base, base + 0x3fff); + + 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); + pclog("%08X-%08X\n", base + 0x4000, base + 0x7fff); + } + } + + flushmmucache_nopc(); } static void sis_5511_smram_recalc(sis_5511_t *dev) { - smram_disable_all(); + 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; - } + 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; + } flushmmucache(); } + void sis_5513_ide_handler(sis_5511_t *dev) { ide_pri_disable(); @@ -140,31 +156,19 @@ void sis_5513_bm_handler(sis_5511_t *dev) sff_bus_master_handler(dev->ide_drive[1], dev->pci_conf_sb[1][4] & 4, BUS_MASTER_BASE + 8); } + static void sis_5511_write(int func, int addr, uint8_t val, void *priv) { - sis_5511_t *dev = (sis_5511_t *)priv; + sis_5511_t *dev = (sis_5511_t *)priv; - switch (addr) - { - case 0x04: /* Command - low byte */ - dev->pci_conf[addr] = val; - break; - - 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] &= 0x16; + switch (addr) { + case 0x07: /* Status - High Byte */ + dev->pci_conf[addr] &= 0xb0; break; case 0x50: - dev->pci_conf[addr] = (val & 0xf9) | 4; + dev->pci_conf[addr] = val; cpu_cache_ext_enabled = !!(val & 0x40); cpu_update_waitstates(); break; @@ -177,8 +181,7 @@ sis_5511_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf[addr] = val & 0x3f; break; - case 0x53: - case 0x54: + case 0x53: case 0x54: dev->pci_conf[addr] = val; break; @@ -186,15 +189,17 @@ sis_5511_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf[addr] = val & 0xf8; break; - case 0x57: - case 0x58: - case 0x59: + 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; - port_92_set_features(dev->port_92, !!(val & 0x40), !!(val & 0x80)); break; case 0x5b: @@ -214,22 +219,18 @@ sis_5511_write(int func, int addr, uint8_t val, void *priv) break; case 0x5f: - dev->pci_conf[addr] = val; + dev->pci_conf[addr] = val & 0xfe; break; case 0x60: dev->pci_conf[addr] = val & 0x3e; - if (!!(val & 2) && (dev->pci_conf[0x68] & 1)) - { + if ((dev->pci_conf[0x68] & 1) && (val & 2)) { smi_line = 1; dev->pci_conf[0x69] |= 1; } break; - case 0x61: /* STPCLK# Assertion Timer */ - case 0x62: /* STPCLK# De-assertion Timer */ - case 0x63: /* System Standby Timer */ - case 0x64: + case 0x61 ... 0x64: dev->pci_conf[addr] = val; break; @@ -242,8 +243,7 @@ sis_5511_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf[addr] = val & 0x7f; break; - case 0x67: - case 0x68: + case 0x67: case 0x68: dev->pci_conf[addr] = val; break; @@ -251,11 +251,7 @@ sis_5511_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf[addr] &= val; break; - case 0x6a: - case 0x6b: - case 0x6c: - case 0x6d: - case 0x6e: + case 0x6a ... 0x6e: dev->pci_conf[addr] = val; break; @@ -329,8 +325,7 @@ sis_5511_write(int func, int addr, uint8_t val, void *priv) case 0x85: case 0x86: dev->pci_conf[addr] = val & ((addr == 0x86) ? 0xe8 : 0xee); - sis_5511_shadow_recalc(addr, dev); - sis_5511_smram_recalc(dev); + sis_5511_shadow_recalc(dev); break; case 0x90: /* 5512 General Purpose Register Index */ @@ -620,24 +615,45 @@ sis_5513_isa_read(uint16_t addr, void *priv) return 0xff; } + static void sis_5511_reset(void *priv) { - sis_5511_t *dev = (sis_5511_t *)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] = dev->pci_conf[0x6b] = 0x00; + dev->pci_conf[0x6c] = dev->pci_conf[0x6d] = 0x00; + dev->pci_conf[0x6e] = dev->pci_conf[0x6f] = 0x00; + + cpu_cache_ext_enabled = 0; + cpu_update_waitstates(); - /* 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] = 7; - dev->pci_conf[0x07] = 2; - dev->pci_conf[0x0b] = 6; - dev->pci_conf[0x52] = 0x20; - dev->pci_conf[0x61] = 0xff; - dev->pci_conf[0x62] = 0xff; - dev->pci_conf[0x63] = 0xff; - dev->pci_conf[0x67] = 0xff; dev->pci_conf[0x6b] = 0xff; dev->pci_conf[0x6c] = 0xff; dev->pci_conf[0x70] = 4; @@ -652,6 +668,15 @@ sis_5511_reset(void *priv) dev->pci_conf[0x7c] = 4; dev->pci_conf[0x7e] = 4; dev->pci_conf[0x7f] = 0x80; + 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; + sis_5511_smram_recalc(dev); + sis_5511_shadow_recalc(dev); /* SiS 5513 */ dev->pci_conf_sb[0][0x00] = 0x39; diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 1664576fb..14d7a9b63 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -124,6 +124,10 @@ int isa_cycles, cpu_inited, timing_jmp_rm, timing_jmp_pm, timing_jmp_pm_gate, timing_misaligned; uint32_t cpu_features, cpu_fast_off_flags; +uint32_t _tr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +uint32_t cache_index = 0; +uint8_t _cache[2048]; + uint64_t cpu_CR4_mask, tsc = 0; uint64_t pmc[2] = {0, 0}; @@ -2290,6 +2294,7 @@ amd_k_invalid_rdmsr: EDX = tsc >> 32; break; } + pclog("RDMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX); break; case CPU_PENTIUMPRO: @@ -2695,6 +2700,7 @@ amd_k_invalid_wrmsr: case CPU_CxGX1: case CPU_Cx6x86MX: #endif + pclog("WRMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX); switch (ECX) { case 0x10: tsc = EAX | ((uint64_t)EDX << 32); diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 68a053b6f..9beac3fab 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -542,6 +542,9 @@ extern uint64_t amd_efer, star; #define msw cpu_state.CR0.w extern uint32_t cr2, cr3, cr4; extern uint32_t dr[8]; +extern uint32_t _tr[8]; +extern uint32_t cache_index; +extern uint8_t _cache[2048]; /*Segments - diff --git a/src/cpu/x86.c b/src/cpu/x86.c index 725d674e8..55ef45000 100644 --- a/src/cpu/x86.c +++ b/src/cpu/x86.c @@ -282,13 +282,13 @@ reset_common(int hard) if (is386 || hard) EAX = EBX = ECX = EDX = ESI = EDI = EBP = ESP = 0; - /* if (hard) { + if (hard) { makeznptable(); resetreadlookup(); makemod1table(); cpu_set_edx(); mmu_perm = 4; - } */ + } x86seg_reset(); #ifdef USE_DYNAREC if (hard) @@ -308,15 +308,19 @@ reset_common(int hard) if (hard) { if (is486) smbase = is_am486dxl ? 0x00060000 : 0x00030000; - // ppi_reset(); + ppi_reset(); } in_sys = 0; shadowbios = shadowbios_write = 0; alt_access = cpu_end_block_after_ins = 0; - if (hard) + if (hard) { reset_on_hlt = hlt_reset_pending = 0; + cache_index = 0; + memset(_tr, 0x00, sizeof(_tr)); + memset(_cache, 0x00, sizeof(_cache)); + } if (!is286) reset_808x(hard); @@ -328,15 +332,6 @@ void resetx86(void) { reset_common(1); -/* ---- */ - makeznptable(); - resetreadlookup(); - makemod1table(); - cpu_set_edx(); - mmu_perm = 4; - - ppi_reset(); -/* ---- */ soft_reset_mask = 0; } diff --git a/src/cpu/x86_ops_misc.h b/src/cpu/x86_ops_misc.h index a6e7e9193..e630c685b 100644 --- a/src/cpu/x86_ops_misc.h +++ b/src/cpu/x86_ops_misc.h @@ -607,6 +607,8 @@ static int opF7_l_a32(uint32_t fetchdat) static int opHLT(uint32_t fetchdat) { + pclog("HLT: CS = %04X, DS = %04X, ES = %04X, SS = %04X, IP = %04X\n", CS, DS, ES, SS, cpu_state.pc); + if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) { x86gpf(NULL,0); diff --git a/src/cpu/x86_ops_mov_ctrl.h b/src/cpu/x86_ops_mov_ctrl.h index 17f51b971..28504890c 100644 --- a/src/cpu/x86_ops_mov_ctrl.h +++ b/src/cpu/x86_ops_mov_ctrl.h @@ -256,54 +256,113 @@ static int opMOV_DRx_r_a32(uint32_t fetchdat) return 0; } +static void opMOV_r_TRx(void) +{ + uint32_t base; + + base = _tr[4] & 0xfffff800; + switch (cpu_reg) { + case 3: + pclog("[R] %08X cache = %08X\n", base + cache_index, _tr[3]); + _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 ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) + if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))) { x86gpf(NULL, 0); return 1; } fetch_ea_16(fetchdat); - cpu_state.regs[cpu_rm].l = 0; - CLOCK_CYCLES(6); + 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 ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) + if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))) { x86gpf(NULL, 0); return 1; } fetch_ea_32(fetchdat); - cpu_state.regs[cpu_rm].l = 0; - CLOCK_CYCLES(6); + 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, ctl; + + _tr[cpu_reg] = cpu_state.regs[cpu_rm].l; + base = _tr[4] & 0xfffff800; + ctl = _tr[5] & 3; + switch (cpu_reg) { + case 3: + pclog("[W] %08X cache = %08X\n", base + cache_index, _tr[3]); + *(uint32_t *) &(_cache[cache_index]) = _tr[3]; + cache_index = (cache_index + 4) & 0xf; + break; + case 4: + if (!(cr0 & 1) && !(_tr[5] & (1 << 19))) + pclog("TAG = %08X, DEST = %08X\n", base, base + cache_index - 16); + break; + case 5: + pclog("[16] EXT = %i (%i), SET = %04X\n", !!(_tr[5] & (1 << 19)), _tr[5] & 0x03, _tr[5] & 0x7f0); + if (!(_tr[5] & (1 << 19))) { + switch(ctl) { + case 0: + pclog(" Cache fill or read...\n", base); + break; + case 1: + base += (_tr[5] & 0x7f0); + pclog(" Writing 16 bytes to %08X...\n", base); + for (i = 0; i < 16; i += 4) + mem_writel_phys(base + i, *(uint32_t *) &(_cache[i])); + break; + case 2: + base += (_tr[5] & 0x7f0); + pclog(" Reading 16 bytes from %08X...\n", base); + for (i = 0; i < 16; i += 4) + *(uint32_t *) &(_cache[i]) = mem_readl_phys(base + i); + break; + case 3: + pclog(" Cache invalidate/flush...\n", base); + break; + } + } + break; + } + CLOCK_CYCLES(6); +} static int opMOV_TRx_r_a16(uint32_t fetchdat) { - if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) + if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))) { x86gpf(NULL, 0); return 1; } fetch_ea_16(fetchdat); - CLOCK_CYCLES(6); + 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 ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) + if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))) { x86gpf(NULL, 0); return 1; } - fetch_ea_16(fetchdat); - CLOCK_CYCLES(6); + fetch_ea_32(fetchdat); + opMOV_TRx_r(); PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1); return 0; } diff --git a/src/device/phoenix_486_jumper.c b/src/device/phoenix_486_jumper.c index 5a07362d2..53fea5d92 100644 --- a/src/device/phoenix_486_jumper.c +++ b/src/device/phoenix_486_jumper.c @@ -39,11 +39,14 @@ typedef struct { - uint8_t jumper; + uint8_t type, jumper; } phoenix_486_jumper_t; + #ifdef ENABLE_PHOENIX_486_JUMPER_LOG int phoenix_486_jumper_do_log = ENABLE_PHOENIX_486_JUMPER_LOG; + + static void phoenix_486_jumper_log(const char *fmt, ...) { @@ -59,14 +62,19 @@ phoenix_486_jumper_log(const char *fmt, ...) #define phoenix_486_jumper_log(fmt, ...) #endif + static void phoenix_486_jumper_write(uint16_t addr, uint8_t val, void *priv) { phoenix_486_jumper_t *dev = (phoenix_486_jumper_t *) priv; phoenix_486_jumper_log("Phoenix 486 Jumper: Write %02x\n", val); - dev->jumper = val; + if (dev->type == 1) + dev->jumper = val & 0xbf; + else + dev->jumper = val; } + static uint8_t phoenix_486_jumper_read(uint16_t addr, void *priv) { @@ -76,6 +84,21 @@ phoenix_486_jumper_read(uint16_t addr, void *priv) } +static void +phoenix_486_jumper_reset(void *priv) +{ + phoenix_486_jumper_t *dev = (phoenix_486_jumper_t *) priv; + + if (dev->type == 1) + dev->jumper = 0x00; + else { + dev->jumper = 0x9f; + if (gfxcard != 0x01) + dev->jumper |= 0x40; + } +} + + static void phoenix_486_jumper_close(void *priv) { @@ -84,26 +107,38 @@ phoenix_486_jumper_close(void *priv) free(dev); } + static void * phoenix_486_jumper_init(const device_t *info) { phoenix_486_jumper_t *dev = (phoenix_486_jumper_t *) malloc(sizeof(phoenix_486_jumper_t)); memset(dev, 0, sizeof(phoenix_486_jumper_t)); - dev->jumper = 0x9f; - if (gfxcard != 0x01) - dev->jumper |= 0x40; + dev->type = info->local; + + phoenix_486_jumper_reset(dev); io_sethandler(0x0078, 0x0001, phoenix_486_jumper_read, NULL, NULL, phoenix_486_jumper_write, NULL, NULL, dev); return dev; } + const device_t phoenix_486_jumper_device = { "Phoenix 486 Jumper Readout", 0, 0, - phoenix_486_jumper_init, phoenix_486_jumper_close, NULL, + phoenix_486_jumper_init, phoenix_486_jumper_close, phoenix_486_jumper_reset, + { NULL }, NULL, NULL, + NULL +}; + + +const device_t phoenix_486_jumper_pci_device = { + "Phoenix 486 Jumper Readout (PCI machines)", + 0, + 1, + phoenix_486_jumper_init, phoenix_486_jumper_close, phoenix_486_jumper_reset, { NULL }, NULL, NULL, NULL }; diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index c12aec7e8..988717406 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -59,6 +59,9 @@ extern const device_t headland_ht18a_device; extern const device_t headland_ht18b_device; extern const device_t headland_ht18c_device; +/* IMS */ +extern const device_t ims8848_device; + /* Intel */ extern const device_t intel_82335_device; extern const device_t i420ex_device; @@ -162,7 +165,7 @@ extern const device_t wd76c10_device; /* Miscellaneous Hardware */ extern const device_t phoenix_486_jumper_device; -extern const device_t vpc2007_device; +extern const device_t phoenix_486_jumper_pci_device; #if defined(DEV_BRANCH) && defined(USE_OLIVETTI) extern const device_t olivetti_eva_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index b3c875925..8fa2b2f12 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -366,6 +366,9 @@ extern int machine_at_ms4145_init(const machine_t *); extern int machine_at_sbc_490_init(const machine_t *); extern int machine_at_tf_486_init(const machine_t *); +extern int machine_at_pci400c_b_init(const machine_t *); +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 *); diff --git a/src/include/86box/mem.h b/src/include/86box/mem.h index 2bd76eb30..dfcbef242 100644 --- a/src/include/86box/mem.h +++ b/src/include/86box/mem.h @@ -89,6 +89,7 @@ /* Internal execute access, external read access. */ #define MEM_READ_EXTERNAL_EX 0 #define MEM_READ_SMRAM (ACCESS_X_SMRAM | ACCESS_R_SMRAM) +#define MEM_READ_CACHE (ACCESS_X_CACHE | ACCESS_R_CACHE) #define MEM_READ_SMRAM_EX (ACCESS_X_SMRAM) #define MEM_EXEC_SMRAM MEM_READ_SMRAM_EX #define MEM_READ_SMRAM_2 (ACCESS_R_SMRAM) @@ -104,6 +105,7 @@ #define MEM_WRITE_ROMCS (ACCESS_W_ROMCS) #define MEM_WRITE_EXTANY (ACCESS_W_ROMCS) #define MEM_WRITE_SMRAM (ACCESS_W_SMRAM) +#define MEM_WRITE_CACHE (ACCESS_W_CACHE) /* Theese two are going to be identical. */ #define MEM_WRITE_DISABLED_EX MEM_READ_DISABLED #define MEM_WRITE_MASK 0x03e0 diff --git a/src/include/86box/smram.h b/src/include/86box/smram.h index 3d91c1e96..6fc89971e 100644 --- a/src/include/86box/smram.h +++ b/src/include/86box/smram.h @@ -52,6 +52,8 @@ extern void smram_enable(smram_t *smr, uint32_t host_base, uint32_t ram_base, ui extern int smram_enabled(smram_t *smr); /* Changes the SMRAM state. */ extern void smram_state_change(smram_t *smr, int smm, int flags); +/* Enables or disables the use of a separate SMRAM for addresses below A0000. */ +extern void smram_set_separate_smram(uint8_t set); #endif /*EMU_SMRAM_H*/ diff --git a/src/io.c b/src/io.c index 742e601c4..21ea02f1b 100644 --- a/src/io.c +++ b/src/io.c @@ -319,6 +319,9 @@ inb(uint16_t port) if (port == 0x1ed) ret = 0xfe; + if (port == 0x2b60) + ret = 0x00; + io_log("[%04X:%08X] (%i, %i, %04i) in b(%04X) = %02X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); return(ret); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 2068b3c88..50718475b 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -66,7 +66,7 @@ machine_at_acc386_init(const machine_t *model) device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } @@ -1147,6 +1147,68 @@ machine_at_486sp3_init(const machine_t *model) } +int +machine_at_pci400c_b_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/pci400c-b/032295.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&ide_isa_device); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 4, 3, 2, 1); /* 0F = Slot 1 */ + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 0E = Slot 2 */ + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 0D = Slot 3 */ + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 0C = Slot 4 */ + device_add(&keyboard_ps2_ami_pci_device); /* Assume AMI Megakey 1993 stanalone ('P') + because of the Tekram machine below. */ + + device_add(&ims8848_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + + +int +machine_at_g486ip_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/g486ip/G486IP.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&ide_isa_device); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 03 = Slot 1 */ + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 04 = Slot 2 */ + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 05 = Slot 3 */ + device_add(&keyboard_ps2_ami_pci_device); /* AMI Megakey 1993 stanalone ('P') */ + + device_add(&ims8848_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + + int machine_at_486sp3g_init(const machine_t *model) { @@ -1623,8 +1685,10 @@ machine_at_hot433_init(const machine_t *model) device_add(&umc_hb4_device); device_add(&umc_8886af_device); device_add(&um8669f_device); - device_add(&intel_flash_bxt_device); - device_add(&keyboard_at_ami_device); + // device_add(&intel_flash_bxt_device); + device_add(&sst_flash_29ee010_device); + // device_add(&keyboard_at_ami_device); + device_add(&keyboard_ps2_ami_device); return ret; } @@ -1652,6 +1716,7 @@ machine_at_atc1415_init(const machine_t *model) device_add(&umc_hb4_device); device_add(&umc_8886af_device); + device_add(&intel_flash_bxt_device); device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 6910a5274..3a57cf0c6 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -432,6 +432,10 @@ const machine_t machines[] = { { "[i420TX] ASUS PCI/I-486SP3", "486sp3", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL | MACHINE_SCSI, 1024, 131072, 1024, 127, machine_at_486sp3_init, NULL }, /* This has the Phoenix MultiKey KBC firmware. */ { "[i420TX] Intel Classic/PCI", "alfredo", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_alfredo_init, NULL }, + /* This most likely has a standalone AMI Megakey 1993, which is type 'P', like the below Tekram board. */ + { "[IMS 8848] J-Bond PCI400C-B", "pci400c_b", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_pci400c_b_init, NULL }, + /* This has a standalone AMI Megakey 1993, which is type 'P'. */ + { "[IMS 8848] Tekram G486IP", "g486ip", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_g486ip_init, NULL }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[SiS 496] ASUS PVI-486SP3C", "486sp3c", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_IDE_DUAL, 1024, 261120, 1024, 255, machine_at_486sp3c_init, NULL }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ diff --git a/src/mem/smram.c b/src/mem/smram.c index 1173d716a..8e405af8a 100644 --- a/src/mem/smram.c +++ b/src/mem/smram.c @@ -32,6 +32,9 @@ static smram_t *base_smram, *last_smram; +static uint8_t use_separate_smram = 0; +static uint8_t smram[0x40000]; + #ifdef ENABLE_SMRAM_LOG int smram_do_log = ENABLE_SMRAM_LOG; @@ -61,8 +64,10 @@ smram_read(uint32_t addr, void *priv) if (new_addr >= (1 << 30)) return mem_read_ram_2gb(new_addr, priv); - else + else if (!use_separate_smram || (new_addr >= 0xa0000)) return mem_read_ram(new_addr, priv); + else + return dev->mapping.exec[addr - dev->host_base]; } @@ -74,8 +79,10 @@ smram_readw(uint32_t addr, void *priv) if (new_addr >= (1 << 30)) return mem_read_ram_2gbw(new_addr, priv); - else + else if (!use_separate_smram || (new_addr >= 0xa0000)) return mem_read_ramw(new_addr, priv); + else + return *(uint16_t *) &(dev->mapping.exec[addr - dev->host_base]); } @@ -87,8 +94,10 @@ smram_readl(uint32_t addr, void *priv) if (new_addr >= (1 << 30)) return mem_read_ram_2gbl(new_addr, priv); - else + else if (!use_separate_smram || (new_addr >= 0xa0000)) return mem_read_raml(new_addr, priv); + else + return *(uint32_t *) &(dev->mapping.exec[addr - dev->host_base]); } @@ -98,7 +107,10 @@ smram_write(uint32_t addr, uint8_t val, void *priv) smram_t *dev = (smram_t *) priv; uint32_t new_addr = addr - dev->host_base + dev->ram_base; - mem_write_ram(new_addr, val, priv); + if (!use_separate_smram || (new_addr >= 0xa0000)) + mem_write_ram(new_addr, val, priv); + else + dev->mapping.exec[addr - dev->host_base] = val; } @@ -108,7 +120,10 @@ smram_writew(uint32_t addr, uint16_t val, void *priv) smram_t *dev = (smram_t *) priv; uint32_t new_addr = addr - dev->host_base + dev->ram_base; - mem_write_ramw(new_addr, val, priv); + if (!use_separate_smram || (new_addr >= 0xa0000)) + mem_write_ramw(new_addr, val, priv); + else + *(uint16_t *) &(dev->mapping.exec[addr - dev->host_base]) = val; } @@ -118,7 +133,10 @@ smram_writel(uint32_t addr, uint32_t val, void *priv) smram_t *dev = (smram_t *) priv; uint32_t new_addr = addr - dev->host_base + dev->ram_base; - mem_write_raml(new_addr, val, priv); + if (!use_separate_smram || (new_addr >= 0xa0000)) + mem_write_raml(new_addr, val, priv); + else + *(uint32_t *) &(dev->mapping.exec[addr - dev->host_base]) = val; } @@ -263,6 +281,8 @@ smram_add(void) smram_write,smram_writew,smram_writel, ram, MEM_MAPPING_SMRAM, temp_smram); + smram_set_separate_smram(0); + return temp_smram; } @@ -326,10 +346,21 @@ smram_enable(smram_t *smr, uint32_t host_base, uint32_t ram_base, uint32_t size, smr->size = size; mem_mapping_set_addr(&(smr->mapping), smr->host_base, smr->size); - if (smr->ram_base < (1 << 30)) - mem_mapping_set_exec(&(smr->mapping), ram + smr->ram_base); - else - mem_mapping_set_exec(&(smr->mapping), ram2 + smr->ram_base - (1 << 30)); + if (!use_separate_smram || (smr->ram_base >= 0x000a0000)) { + if (smr->ram_base < (1 << 30)) + mem_mapping_set_exec(&(smr->mapping), ram + smr->ram_base); + else + mem_mapping_set_exec(&(smr->mapping), ram2 + smr->ram_base - (1 << 30)); + } else { + if (smr->ram_base == 0x00030000) + mem_mapping_set_exec(&(smr->mapping), smram); + else if (smr->ram_base == 0x00040000) + mem_mapping_set_exec(&(smr->mapping), smram + 0x10000); + else if (smr->ram_base == 0x00060000) + mem_mapping_set_exec(&(smr->mapping), smram + 0x20000); + else if (smr->ram_base == 0x00070000) + mem_mapping_set_exec(&(smr->mapping), smram + 0x30000); + } smram_map(0, host_base, size, flags_normal); smram_map(1, host_base, size, flags_smm); @@ -364,3 +395,10 @@ smram_state_change(smram_t *smr, int smm, int flags) smram_map(smm, smr->host_base, smr->size, flags); } + + +void +smram_set_separate_smram(uint8_t set) +{ + use_separate_smram = set; +} diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index f06c3d77a..b7680640f 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -593,7 +593,7 @@ CHIPSETOBJ := 82c100.o acc2168.o \ cs4031.o cs8230.o \ ali1429.o ali1489.o ali1531.o ali1541.o ali1543.o ali1621.o ali6117.o \ gc100.o headland.o \ - intel_82335.o intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \ + ims8848.o intel_82335.o intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \ neat.o \ opti283.o opti291.o opti391.o opti495.o opti822.o opti895.o opti5x7.o \ scamp.o scat.o \ From cc043eed5d85f4627a3287f34b35440e4db2cb9c Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 9 Oct 2021 17:38:27 +0200 Subject: [PATCH 87/96] Removed port 2B60 read. --- src/io.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/io.c b/src/io.c index 21ea02f1b..742e601c4 100644 --- a/src/io.c +++ b/src/io.c @@ -319,9 +319,6 @@ inb(uint16_t port) if (port == 0x1ed) ret = 0xfe; - if (port == 0x2b60) - ret = 0x00; - io_log("[%04X:%08X] (%i, %i, %04i) in b(%04X) = %02X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); return(ret); From 7e15229524a0df6d0519bc19b0bf497b68083234 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 9 Oct 2021 22:32:56 +0200 Subject: [PATCH 88/96] Gave the UMC 8810 the required second SMRAM mirror at 4E0A0000-4E0BFFFF. --- src/chipset/umc_hb4.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/chipset/umc_hb4.c b/src/chipset/umc_hb4.c index d147bf5f7..0948a228b 100644 --- a/src/chipset/umc_hb4.c +++ b/src/chipset/umc_hb4.c @@ -148,7 +148,7 @@ typedef struct hb4_t shadow_read, shadow_write, pci_conf[256]; /* PCI Registers */ int mem_state[9]; - smram_t *smram[2]; /* SMRAM Handlers */ + smram_t *smram[3]; /* SMRAM Handlers */ } hb4_t; @@ -237,7 +237,7 @@ void hb4_shadow(hb4_t *dev) { int n = 0; - pclog("SHADOW: %02X%02X\n", dev->pci_conf[0x55], dev->pci_conf[0x54]); + hb4_log("SHADOW: %02X%02X\n", dev->pci_conf[0x55], dev->pci_conf[0x54]); n = hb4_shadow_bios_high(dev); n += hb4_shadow_bios_low(dev); @@ -259,6 +259,8 @@ hb4_smram(hb4_t *dev) 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); /* Bit 5 seems to set data to go to PCI and code to DRAM. The Samsung SPC7700P-LW uses this. */ @@ -274,7 +276,6 @@ static void hb4_write(int func, int addr, uint8_t val, void *priv) { hb4_t *dev = (hb4_t *)priv; - uint8_t old; hb4_log("UM8881: dev->regs[%02x] = %02x POST: %02x \n", addr, val, inb(0x80)); @@ -302,9 +303,8 @@ hb4_write(int func, int addr, uint8_t val, void *priv) break; case 0x53: - old = dev->pci_conf[addr]; dev->pci_conf[addr] = val; - pclog("HB53: %02X\n", val); + hb4_log("HB53: %02X\n", val); break; case 0x55: @@ -409,6 +409,7 @@ hb4_init(const device_t *info) /* SMRAM */ dev->smram[0] = smram_add(); dev->smram[1] = smram_add(); + dev->smram[2] = smram_add(); hb4_reset(dev); From 10a257749ffa163a7cb012fe766e3649438b6f67 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 19 Oct 2021 18:19:29 +0200 Subject: [PATCH 89/96] Fixed Intel PIIX and VIA PIPC trap SMI# function calls. --- src/chipset/intel_piix.c | 2 +- src/chipset/via_pipc.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index a333c52b7..1a278a2c3 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -281,7 +281,7 @@ piix_trap_io(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv) if (*(trap->en_reg) & trap->en_mask) { *(trap->sts_reg) |= trap->sts_mask; - acpi_raise_smi(trap->dev->acpi); + acpi_raise_smi(trap->dev->acpi, 1); } } diff --git a/src/chipset/via_pipc.c b/src/chipset/via_pipc.c index f3112974d..3829e337c 100644 --- a/src/chipset/via_pipc.c +++ b/src/chipset/via_pipc.c @@ -172,7 +172,7 @@ pipc_trap_io_pact(int size, uint16_t addr, uint8_t write, uint8_t val, void *pri *(trap->sts_reg) |= trap->mask; trap->dev->acpi->regs.glbsts |= 0x0001; if (trap->dev->acpi->regs.glben & 0x0001) - acpi_raise_smi(trap->dev->acpi); + acpi_raise_smi(trap->dev->acpi, 1); } } @@ -184,7 +184,7 @@ pipc_io_trap_glb(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv if (*(trap->en_reg) & trap->mask) { *(trap->sts_reg) |= trap->mask; - acpi_raise_smi(trap->dev->acpi); + acpi_raise_smi(trap->dev->acpi, 1); } } From 3ba9c8c9c6ddc08ac054aa464c68d01f95183c67 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 19 Oct 2021 18:23:48 +0200 Subject: [PATCH 90/96] A fix to acpi.c. --- src/acpi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/acpi.c b/src/acpi.c index 0cb2fc9e2..0b9676c81 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -90,6 +90,8 @@ acpi_update_irq(acpi_t *dev) void acpi_raise_smi(void *priv, int do_smi) { + acpi_t *dev = (acpi_t *) priv; + if (dev->regs.glbctl & 0x01) { if ((dev->vendor == VEN_VIA) || (dev->vendor == VEN_VIA_596B)) { if ((!dev->regs.smi_lock || !dev->regs.smi_active)) { From 77d73ed3c29e016dd45e112adec144a43e24ae07 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 26 Oct 2021 01:54:35 +0200 Subject: [PATCH 91/96] Finished the Intel 450KX, changes to the memory and SMRAM API's, removed the ASUS P/I-P6RP4 from the Dev branch, added the CMD646 PCI IDE controller, and fixed some bugs on the CMD640. --- src/chipset/CMakeLists.txt | 6 +- src/chipset/intel_i450kx.c | 630 ++++++++++++++++++--------- src/disk/CMakeLists.txt | 2 +- src/disk/hdc_ide_cmd640.c | 157 ++++--- src/disk/hdc_ide_cmd646.c | 435 ++++++++++++++++++ src/disk/hdc_ide_sff8038i.c | 24 +- src/include/86box/chipset.h | 4 +- src/include/86box/hdc.h | 3 + src/include/86box/hdc_ide_sff8038i.h | 11 +- src/include/86box/machine.h | 2 - src/include/86box/mem.h | 8 + src/include/86box/nvr.h | 1 + src/include/86box/smram.h | 7 + src/machine/CMakeLists.txt | 4 - src/machine/m_at_socket8.c | 14 +- src/machine/machine_table.c | 4 +- src/mem/mem.c | 6 + src/mem/smram.c | 35 +- src/nvr_at.c | 43 +- src/pci.c | 152 ++++++- src/scsi/scsi_cdrom.c | 9 +- src/win/Makefile.mingw | 17 +- 22 files changed, 1269 insertions(+), 305 deletions(-) create mode 100644 src/disk/hdc_ide_cmd646.c diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 770b54006..ce5bded9a 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -15,16 +15,12 @@ add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1429.c ali1489.c ali1531.c ali1541.c ali1543.c ali1621.c ali6117.c headland.c intel_82335.c contaq_82c59x.c cs4031.c intel_420ex.c - intel_4x0.c intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c + intel_4x0.c intel_i450kx.c intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c opti495.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 sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c stpc.c umc_8886.c umc_hb4.c via_apollo.c via_pipc.c vl82c480.c wd76c10.c) -if(I450KX) - target_sources(chipset PRIVATE intel_i450kx.c) -endif() - if(OLIVETTI) target_sources(chipset PRIVATE olivetti_eva.c) endif() \ No newline at end of file diff --git a/src/chipset/intel_i450kx.c b/src/chipset/intel_i450kx.c index 5a89f2659..2696db495 100644 --- a/src/chipset/intel_i450kx.c +++ b/src/chipset/intel_i450kx.c @@ -58,71 +58,95 @@ i450kx_log(const char *fmt, ...) #endif -/* Shadow RAM Flags */ -#define LSB_DECISION (((shadow_value & 1) ? MEM_READ_EXTANY : MEM_READ_INTERNAL) | ((shadow_value & 2) ? MEM_WRITE_EXTANY : MEM_WRITE_INTERNAL)) -#define MSB_DECISION (((shadow_value & 0x10) ? MEM_READ_EXTANY : MEM_READ_INTERNAL) | ((shadow_value & 0x20) ? MEM_WRITE_EXTANY : MEM_WRITE_INTERNAL)) -#define LSB_DECISION_MC (((shadow_value & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((shadow_value & 2) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) -#define MSB_DECISION_MC (((shadow_value & 0x10) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((shadow_value & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) - -/* SMRAM */ -#define SMRAM_ADDR (((dev->pb_pci_conf[0xb9] << 8) | dev->pb_pci_conf[0xb8]) << 17) -#define SMRAM_ADDR_MC (((dev->mc_pci_conf[0xb9] << 8) | dev->mc_pci_conf[0xb8]) << 16) -#define SMRAM_SIZE (((dev->pb_pci_conf[0xbb] >> 4) + 1) * 64) -#define SMRAM_SIZE_MC (((dev->mc_pci_conf[0xbb] >> 4) + 1) * 64) - -/* Miscellaneous */ -#define ENABLE_SEGMENT (MEM_READ_EXTANY | MEM_WRITE_EXTANY) -#define DISABLE_SEGMENT (MEM_READ_DISABLED | MEM_WRITE_DISABLED) - - +/* TODO: Finish the bus index stuff. */ typedef struct i450kx_t { - smram_t *smram; + smram_t * smram[2]; - uint8_t pb_pci_conf[256], mc_pci_conf[256]; + uint8_t pb_pci_conf[256], mc_pci_conf[256]; + uint8_t mem_state[2][256]; + + uint8_t bus_index; } i450kx_t; static void -i450kx_shadow(int is_mc, int cur_reg, uint8_t shadow_value, i450kx_t *dev) +i450kx_map(i450kx_t *dev, int bus, uint32_t addr, uint32_t size, int state) { - if (cur_reg == 0x59) { - mem_set_mem_state_both(0x80000, 0x20000, (is_mc) ? LSB_DECISION_MC : LSB_DECISION); - mem_set_mem_state_both(0xf0000, 0x10000, (is_mc) ? MSB_DECISION_MC : MSB_DECISION); - } else { - mem_set_mem_state_both(0xc0000 + (((cur_reg & 7) - 2) * 0x8000), 0x4000, (is_mc) ? LSB_DECISION_MC : LSB_DECISION); - mem_set_mem_state_both(0xc4000 + (((cur_reg & 7) - 2) * 0x8000), 0x4000, (is_mc) ? MSB_DECISION_MC : MSB_DECISION); + uint32_t base = addr >> 12; + int states[4] = { MEM_READ_EXTANY | MEM_WRITE_EXTANY, MEM_READ_INTERNAL | MEM_WRITE_EXTANY, + MEM_READ_EXTANY | MEM_WRITE_INTERNAL, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL }; + + state &= 3; + if (dev->mem_state[bus][base] != state) { + if (bus) + mem_set_mem_state_bus_both(addr, size, states[state]); + else + mem_set_mem_state_cpu_both(addr, size, states[state]); + dev->mem_state[bus][base] = state; + flushmmucache_nopc(); } - flushmmucache_nopc(); } static void -i450kx_smm(uint32_t smram_addr, uint32_t smram_size, i450kx_t *dev) +i450kx_smram_recalc(i450kx_t *dev, int bus) { - smram_disable_all(); + uint8_t *regs = bus ? dev->pb_pci_conf : dev->mc_pci_conf; + uint32_t addr, size; - if ((smram_addr != 0) && !!(dev->mc_pci_conf[0x57] & 8)) - smram_enable(dev->smram, smram_addr, smram_addr, smram_size, !!(dev->pb_pci_conf[0x57] & 8), 1); + 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 (bus) + smram_enable_ex(dev->smram[bus], addr, addr, size, 0, !!(regs[0x57] & 8), 0, 1); + else + smram_enable_ex(dev->smram[bus], addr, addr, size, !!(regs[0x57] & 8), 0, 1, 0); + } flushmmucache(); } +static void +i450kx_vid_buf_recalc(i450kx_t *dev, int bus) +{ + uint8_t *regs = bus ? dev->pb_pci_conf : dev->mc_pci_conf; + + // int state = (regs[0x58] & 0x02) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_DISABLED | MEM_WRITE_DISABLED); + 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); + else + mem_set_mem_state_cpu_both(0x000a0000, 0x00020000, state); + + flushmmucache_nopc(); +} + + static void pb_write(int func, int addr, uint8_t val, void *priv) { i450kx_t *dev = (i450kx_t *)priv; - switch (addr) { - case 0x04: - dev->pb_pci_conf[addr] &= val & 0xd7; - break; + // 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)); - case 0x06: - dev->pb_pci_conf[addr] = val & 0x80; + if (func == 0) switch (addr) { + case 0x04: + dev->pb_pci_conf[addr] = (dev->pb_pci_conf[addr] & 0x04) | (val & 0x53); + break; + case 0x05: + dev->pb_pci_conf[addr] = val & 0x01; break; case 0x07: + dev->pb_pci_conf[addr] &= ~(val & 0xf9); + break; + case 0x0d: dev->pb_pci_conf[addr] = val; break; @@ -131,63 +155,106 @@ pb_write(int func, int addr, uint8_t val, void *priv) dev->pb_pci_conf[addr] = val & 0xcf; break; - case 0x40: - case 0x41: + case 0x40: case 0x41: dev->pb_pci_conf[addr] = val; break; - case 0x43: dev->pb_pci_conf[addr] = val & 0x80; break; case 0x48: - dev->pb_pci_conf[addr] = val & 6; + dev->pb_pci_conf[addr] = val & 0x06; break; - case 0x4a: - case 0x4b: + case 0x4a: case 0x4b: dev->pb_pci_conf[addr] = val; + // if (addr == 0x4a) + // pci_remap_bus(dev->bus_index, val); break; case 0x4c: - dev->pb_pci_conf[addr] = val & 0xd8; + dev->pb_pci_conf[addr] = (dev->pb_pci_conf[addr] & 0x01) | (val & 0xd8); + break; + + case 0x51: + dev->pb_pci_conf[addr] = val; break; case 0x53: - dev->pb_pci_conf[addr] = val & 2; + dev->pb_pci_conf[addr] = val & 0x02; break; case 0x54: dev->pb_pci_conf[addr] = val & 0x7b; break; - case 0x55: - dev->pb_pci_conf[addr] = val & 2; + dev->pb_pci_conf[addr] = val & 0x03; break; case 0x57: - dev->pb_pci_conf[addr] = val & 8; - i450kx_smm(SMRAM_ADDR, SMRAM_SIZE, dev); + dev->pb_pci_conf[addr] = val & 0x08; + i450kx_smram_recalc(dev, 1); break; case 0x58: - dev->pb_pci_conf[addr] = val & 2; - mem_set_mem_state_both(0xa0000, 0x20000, (val & 2) ? ENABLE_SEGMENT : DISABLE_SEGMENT); + dev->pb_pci_conf[addr] = val & 0x02; + i450kx_vid_buf_recalc(dev, 1); break; - case 0x59: - case 0x5a: - case 0x5b: - case 0x5c: - case 0x5d: - case 0x5e: - case 0x5f: - dev->pb_pci_conf[addr] = val & 0x33; - i450kx_shadow(0, addr, val, dev); + case 0x59: /* PAM0 */ + if ((dev->pb_pci_conf[0x59] ^ val) & 0x0f) + i450kx_map(dev, 1, 0x80000, 0x20000, val & 0x0f); + if ((dev->pb_pci_conf[0x59] ^ val) & 0xf0) { + i450kx_map(dev, 1, 0xf0000, 0x10000, val >> 4); + shadowbios = (val & 0x10); + } + dev->pb_pci_conf[0x59] = val & 0x33; + break; + case 0x5a: /* PAM1 */ + if ((dev->pb_pci_conf[0x5a] ^ val) & 0x0f) + i450kx_map(dev, 1, 0xc0000, 0x04000, val & 0xf); + if ((dev->pb_pci_conf[0x5a] ^ val) & 0xf0) + i450kx_map(dev, 1, 0xc4000, 0x04000, val >> 4); + dev->pb_pci_conf[0x5a] = val & 0x33; + break; + case 0x5b: /*PAM2 */ + if ((dev->pb_pci_conf[0x5b] ^ val) & 0x0f) + i450kx_map(dev, 1, 0xc8000, 0x04000, val & 0xf); + if ((dev->pb_pci_conf[0x5b] ^ val) & 0xf0) + i450kx_map(dev, 1, 0xcc000, 0x04000, val >> 4); + dev->pb_pci_conf[0x5b] = val & 0x33; + break; + case 0x5c: /*PAM3 */ + if ((dev->pb_pci_conf[0x5c] ^ val) & 0x0f) + i450kx_map(dev, 1, 0xd0000, 0x04000, val & 0xf); + if ((dev->pb_pci_conf[0x5c] ^ val) & 0xf0) + i450kx_map(dev, 1, 0xd4000, 0x04000, val >> 4); + dev->pb_pci_conf[0x5c] = val & 0x33; + break; + case 0x5d: /* PAM4 */ + if ((dev->pb_pci_conf[0x5d] ^ val) & 0x0f) + i450kx_map(dev, 1, 0xd8000, 0x04000, val & 0xf); + if ((dev->pb_pci_conf[0x5d] ^ val) & 0xf0) + i450kx_map(dev, 1, 0xdc000, 0x04000, val >> 4); + dev->pb_pci_conf[0x5d] = val & 0x33; + break; + case 0x5e: /* PAM5 */ + if ((dev->pb_pci_conf[0x5e] ^ val) & 0x0f) + i450kx_map(dev, 1, 0xe0000, 0x04000, val & 0xf); + if ((dev->pb_pci_conf[0x5e] ^ val) & 0xf0) + i450kx_map(dev, 1, 0xe4000, 0x04000, val >> 4); + dev->pb_pci_conf[0x5e] = val & 0x33; + break; + case 0x5f: /* PAM6 */ + if ((dev->pb_pci_conf[0x5f] ^ val) & 0x0f) + i450kx_map(dev, 1, 0xe8000, 0x04000, val & 0xf); + if ((dev->pb_pci_conf[0x5f] ^ val) & 0xf0) + i450kx_map(dev, 1, 0xec000, 0x04000, val >> 4); + dev->pb_pci_conf[0x5f] = val & 0x33; break; case 0x70: - dev->pb_pci_conf[addr] = val & 0xfc; + dev->pb_pci_conf[addr] = val & 0xf8; break; case 0x71: @@ -197,47 +264,49 @@ pb_write(int func, int addr, uint8_t val, void *priv) case 0x78: dev->pb_pci_conf[addr] = val & 0xf0; break; - case 0x79: dev->pb_pci_conf[addr] = val & 0xfc; break; - - case 0x7c: - dev->pb_pci_conf[addr] = val & 0x5f; + case 0x7a: + dev->pb_pci_conf[addr] = val; + break; + case 0x7b: + dev->pb_pci_conf[addr] = val & 0x0f; break; + case 0x7c: + dev->pb_pci_conf[addr] = val & 0x9f; + break; case 0x7d: dev->pb_pci_conf[addr] = val & 0x1a; break; - case 0x7e: dev->pb_pci_conf[addr] = val & 0xf0; break; - case 0x7f: - case 0x88: - case 0x89: - case 0x8a: dev->pb_pci_conf[addr] = val; break; + case 0x88: case 0x89: + dev->pb_pci_conf[addr] = val; + break; case 0x8b: dev->pb_pci_conf[addr] = val & 0x80; break; - - case 0x9c: - dev->pb_pci_conf[addr] = val & 1; - break; - - case 0xa4: - dev->pb_pci_conf[addr] = val & 0xf9; - break; - - case 0xa5: - case 0xa6: + case 0x8c: case 0x8d: dev->pb_pci_conf[addr] = val; break; + case 0x9c: + dev->pb_pci_conf[addr] = val & 0x01; + break; + + case 0xa4: + dev->pb_pci_conf[addr] = val & 0xf8; + break; + case 0xa5: case 0xa6: + dev->pb_pci_conf[addr] = val; + break; case 0xa7: dev->pb_pci_conf[addr] = val & 0x0f; break; @@ -245,36 +314,45 @@ pb_write(int func, int addr, uint8_t val, void *priv) case 0xb0: dev->pb_pci_conf[addr] = val & 0xe0; break; - case 0xb1: - dev->pb_pci_conf[addr] = val & 0x1f; + dev->pb_pci_conf[addr] = val & /*0x1a*/ 0x1f; break; case 0xb4: - dev->pb_pci_conf[addr] = val & 0xe8; + dev->pb_pci_conf[addr] = val & 0xe0; break; - case 0xb5: dev->pb_pci_conf[addr] = val & 0x1f; break; - case 0xb8: - case 0xb9: + case 0xb8: case 0xb9: + dev->pb_pci_conf[addr] = val; + i450kx_smram_recalc(dev, 1); + break; case 0xbb: - dev->pb_pci_conf[addr] = !(addr == 0xbb) ? val : (val & 0xf0); - i450kx_smm(SMRAM_ADDR, SMRAM_SIZE, dev); + dev->pb_pci_conf[addr] = val & 0xf0; + i450kx_smram_recalc(dev, 1); + break; + + case 0xbc: + dev->pb_pci_conf[addr] = val & 0x11; + break; + + case 0xc0: + dev->pb_pci_conf[addr] = val & 0xdf; + break; + case 0xc1: + dev->pb_pci_conf[addr] = val & 0x3f; break; case 0xc4: - dev->pb_pci_conf[addr] = val & 5; + dev->pb_pci_conf[addr] &= ~(val & 0x0f); break; - case 0xc5: - dev->pb_pci_conf[addr] = val & 0x0a; + dev->pb_pci_conf[addr] &= ~(val & 0x0a); break; - case 0xc6: - dev->pb_pci_conf[addr] = val & 0x1d; + dev->pb_pci_conf[addr] &= ~(val & 0x1f); break; case 0xc8: @@ -286,7 +364,6 @@ pb_write(int func, int addr, uint8_t val, void *priv) dev->pb_pci_conf[addr] = val; break; } - i450kx_log("i450KX-PB: dev->regs[%02x] = %02x POST: %02x\n", addr, dev->pb_pci_conf[addr], inb(0x80)); } @@ -294,7 +371,30 @@ static uint8_t pb_read(int func, int addr, void *priv) { i450kx_t *dev = (i450kx_t *)priv; - return dev->pb_pci_conf[addr]; + uint8_t ret = 0xff; + + 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)); + + return ret; +} + + +/* A way to use spd_write_drbs_interlaved() and convert the output to what we need. */ +static void +mc_fill_drbs(i450kx_t *dev) +{ + int i; + + spd_write_drbs_interleaved(dev->mc_pci_conf, 0x60, 0x6f, 4); + for (i = 0x60; i <= 0x6f; i++) { + if (i & 0x01) + dev->mc_pci_conf[i] = 0x00; + else + dev->mc_pci_conf[i] &= 0x7f; + } } @@ -303,75 +403,97 @@ mc_write(int func, int addr, uint8_t val, void *priv) { i450kx_t *dev = (i450kx_t *)priv; - switch (addr) - { + // 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) switch (addr) { case 0x4c: dev->mc_pci_conf[addr] = val & 0xdf; break; - case 0x4d: - dev->mc_pci_conf[addr] = val & 0xdf; + dev->mc_pci_conf[addr] = val & 0xff; break; case 0x57: - dev->mc_pci_conf[addr] = val & 8; - i450kx_smm(SMRAM_ADDR, SMRAM_SIZE, dev); + dev->mc_pci_conf[addr] = val & 0x08; + i450kx_smram_recalc(dev, 0); break; case 0x58: - dev->mc_pci_conf[addr] = val & 2; + dev->mc_pci_conf[addr] = val & 0x02; + i450kx_vid_buf_recalc(dev, 0); break; - case 0x59: - case 0x5a: - case 0x5b: - case 0x5c: - case 0x5d: - case 0x5e: - case 0x5f: - dev->mc_pci_conf[addr] = val & 0x33; - i450kx_shadow(1, addr, val, dev); + case 0x59: /* PAM0 */ + if ((dev->mc_pci_conf[0x59] ^ val) & 0x0f) + i450kx_map(dev, 0, 0x80000, 0x20000, val & 0x0f); + if ((dev->mc_pci_conf[0x59] ^ val) & 0xf0) { + i450kx_map(dev, 0, 0xf0000, 0x10000, val >> 4); + shadowbios = (val & 0x10); + } + dev->mc_pci_conf[0x59] = val & 0x33; + break; + case 0x5a: /* PAM1 */ + if ((dev->mc_pci_conf[0x5a] ^ val) & 0x0f) + i450kx_map(dev, 0, 0xc0000, 0x04000, val & 0xf); + if ((dev->mc_pci_conf[0x5a] ^ val) & 0xf0) + i450kx_map(dev, 0, 0xc4000, 0x04000, val >> 4); + dev->mc_pci_conf[0x5a] = val & 0x33; + break; + case 0x5b: /*PAM2 */ + if ((dev->mc_pci_conf[0x5b] ^ val) & 0x0f) + i450kx_map(dev, 0, 0xc8000, 0x04000, val & 0xf); + if ((dev->mc_pci_conf[0x5b] ^ val) & 0xf0) + i450kx_map(dev, 0, 0xcc000, 0x04000, val >> 4); + dev->mc_pci_conf[0x5b] = val & 0x33; + break; + case 0x5c: /*PAM3 */ + if ((dev->mc_pci_conf[0x5c] ^ val) & 0x0f) + i450kx_map(dev, 0, 0xd0000, 0x04000, val & 0xf); + if ((dev->mc_pci_conf[0x5c] ^ val) & 0xf0) + i450kx_map(dev, 0, 0xd4000, 0x04000, val >> 4); + dev->mc_pci_conf[0x5c] = val & 0x33; + break; + case 0x5d: /* PAM4 */ + if ((dev->mc_pci_conf[0x5d] ^ val) & 0x0f) + i450kx_map(dev, 0, 0xd8000, 0x04000, val & 0xf); + if ((dev->mc_pci_conf[0x5d] ^ val) & 0xf0) + i450kx_map(dev, 0, 0xdc000, 0x04000, val >> 4); + dev->mc_pci_conf[0x5d] = val & 0x33; + break; + case 0x5e: /* PAM5 */ + if ((dev->mc_pci_conf[0x5e] ^ val) & 0x0f) + i450kx_map(dev, 0, 0xe0000, 0x04000, val & 0xf); + if ((dev->mc_pci_conf[0x5e] ^ val) & 0xf0) + i450kx_map(dev, 0, 0xe4000, 0x04000, val >> 4); + dev->mc_pci_conf[0x5e] = val & 0x33; + break; + case 0x5f: /* PAM6 */ + if ((dev->mc_pci_conf[0x5f] ^ val) & 0x0f) + i450kx_map(dev, 0, 0xe8000, 0x04000, val & 0xf); + if ((dev->mc_pci_conf[0x5f] ^ val) & 0xf0) + i450kx_map(dev, 0, 0xec000, 0x04000, val >> 4); + dev->mc_pci_conf[0x5f] = val & 0x33; break; - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6a: - case 0x6b: - case 0x6c: - case 0x6d: - case 0x6e: - case 0x6f: - dev->mc_pci_conf[addr] = ((addr & 0x0f) % 2) ? 0 : (val & 0x7f); - spd_write_drbs(dev->mc_pci_conf, 0x60, 0x6f, 4); + case 0x60 ... 0x6f: + dev->mc_pci_conf[addr] = ((addr & 0x0f) & 0x01) ? 0x00 : (val & 0x7f); + mc_fill_drbs(dev); break; - case 0x74: - case 0x75: - case 0x76: - case 0x77: + case 0x74 ... 0x77: dev->mc_pci_conf[addr] = val; break; case 0x78: dev->mc_pci_conf[addr] = val & 0xf0; break; - case 0x79: dev->mc_pci_conf[addr] = val & 0xfe; break; - case 0x7a: dev->mc_pci_conf[addr] = val; break; - case 0x7b: dev->mc_pci_conf[addr] = val & 0x0f; break; @@ -379,45 +501,36 @@ mc_write(int func, int addr, uint8_t val, void *priv) case 0x7c: dev->mc_pci_conf[addr] = val & 0x1f; break; - case 0x7d: dev->mc_pci_conf[addr] = val & 0x0c; break; - case 0x7e: dev->mc_pci_conf[addr] = val & 0xf0; break; - case 0x7f: dev->mc_pci_conf[addr] = val; break; - case 0x88: - case 0x89: + case 0x88: case 0x89: dev->mc_pci_conf[addr] = val; break; - case 0x8b: dev->mc_pci_conf[addr] = val & 0x80; break; - case 0x8c: - case 0x8d: + case 0x8c: case 0x8d: dev->mc_pci_conf[addr] = val; break; case 0xa4: - dev->mc_pci_conf[addr] = val & 1; + dev->mc_pci_conf[addr] = val & 0x01; break; - case 0xa5: dev->pb_pci_conf[addr] = val & 0xf0; break; - case 0xa6: dev->mc_pci_conf[addr] = val; break; - case 0xa7: dev->mc_pci_conf[addr] = val & 0x0f; break; @@ -425,49 +538,56 @@ mc_write(int func, int addr, uint8_t val, void *priv) case 0xa8: dev->mc_pci_conf[addr] = val & 0xfe; break; - - case 0xa9: - case 0xaa: - case 0xab: - case 0xac: - case 0xad: - case 0xae: + case 0xa9 ... 0xab: dev->mc_pci_conf[addr] = val; break; + case 0xac ... 0xae: + dev->mc_pci_conf[addr] = val; + break; case 0xaf: dev->mc_pci_conf[addr] = val & 0x7f; break; - case 0xb8: - case 0xb9: + case 0xb8: case 0xb9: + dev->mc_pci_conf[addr] = val; + i450kx_smram_recalc(dev, 0); + break; case 0xbb: - dev->mc_pci_conf[addr] = !(addr == 0xbb) ? val : (val & 0xf0); - - i450kx_smm(SMRAM_ADDR_MC, SMRAM_SIZE_MC, dev); + dev->mc_pci_conf[addr] = val & 0xf0; + i450kx_smram_recalc(dev, 0); break; case 0xbc: - dev->mc_pci_conf[addr] = val & 1; + dev->mc_pci_conf[addr] = val & 0x01; break; case 0xc0: - dev->mc_pci_conf[addr] = val & 7; + dev->mc_pci_conf[addr] = val & 0x07; break; case 0xc2: - dev->mc_pci_conf[addr] = val & 3; + dev->mc_pci_conf[addr] &= ~(val & 0x03); break; case 0xc4: - dev->mc_pci_conf[addr] = val & 0x3f; + dev->mc_pci_conf[addr] = val & 0xbf; + break; + case 0xc5: + dev->mc_pci_conf[addr] = val & 0x03; break; case 0xc6: - dev->mc_pci_conf[addr] = val & 0x19; + dev->mc_pci_conf[addr] &= ~(val & 0x19); + break; + + case 0xc8: + dev->mc_pci_conf[addr] = val & 0x1f; + break; + case 0xca: case 0xcb: + dev->mc_pci_conf[addr] = val; break; } - i450kx_log("i450KX-MC: dev->regs[%02x] = %02x POST: %02x\n", addr, dev->mc_pci_conf[addr], inb(0x80)); } @@ -475,7 +595,14 @@ static uint8_t mc_read(int func, int addr, void *priv) { i450kx_t *dev = (i450kx_t *)priv; - return dev->mc_pci_conf[addr]; + uint8_t ret = 0xff; + + 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)); + + return ret; } @@ -483,57 +610,168 @@ static void i450kx_reset(void *priv) { i450kx_t *dev = (i450kx_t *)priv; + uint32_t i; - /* CONFLICTS WARNING! We do not program anything on reset due to that */ + // pclog("i450KX: i450kx_reset()\n"); /* Defaults PB */ dev->pb_pci_conf[0x00] = 0x86; dev->pb_pci_conf[0x01] = 0x80; dev->pb_pci_conf[0x02] = 0xc4; dev->pb_pci_conf[0x03] = 0x84; - dev->pb_pci_conf[0x05] = 4; + dev->pb_pci_conf[0x04] = 0x07; + dev->pb_pci_conf[0x05] = 0x00; dev->pb_pci_conf[0x06] = 0x40; - dev->pb_pci_conf[0x07] = 2; - dev->pb_pci_conf[0x08] = 2; - dev->pb_pci_conf[0x0b] = 6; - dev->pb_pci_conf[0x0c] = 8; + dev->pb_pci_conf[0x07] = 0x02; + dev->pb_pci_conf[0x08] = 0x02; + dev->pb_pci_conf[0x09] = 0x00; + dev->pb_pci_conf[0x0a] = 0x00; + dev->pb_pci_conf[0x0b] = 0x06; + dev->pb_pci_conf[0x0c] = 0x08; dev->pb_pci_conf[0x0d] = 0x20; - dev->pb_pci_conf[0x49] = 0x14; - dev->pb_pci_conf[0x4c] = 0x39; - dev->pb_pci_conf[0x58] = 2; - dev->pb_pci_conf[0x59] = 0x30; - dev->pb_pci_conf[0x5a] = 0x33; - dev->pb_pci_conf[0x5b] = 0x33; - dev->pb_pci_conf[0x5c] = 0x33; - dev->pb_pci_conf[0x5d] = 0x33; - dev->pb_pci_conf[0x5e] = 0x33; - dev->pb_pci_conf[0x5f] = 0x33; - dev->pb_pci_conf[0xa4] = 1; + dev->pb_pci_conf[0x0e] = 0x00; + dev->pb_pci_conf[0x0f] = 0x00; + dev->pb_pci_conf[0x40] = 0x00; + dev->pb_pci_conf[0x41] = 0x00; + dev->pb_pci_conf[0x42] = 0x00; + dev->pb_pci_conf[0x43] = 0x00; + dev->pb_pci_conf[0x48] = 0x06; + dev->pb_pci_conf[0x49] = 0x19; + dev->pb_pci_conf[0x4a] = 0x00; + dev->pb_pci_conf[0x4b] = 0x00; + dev->pb_pci_conf[0x4c] = 0x19; + dev->pb_pci_conf[0x51] = 0x80; + dev->pb_pci_conf[0x53] = 0x00; + dev->pb_pci_conf[0x54] = 0x00; + dev->pb_pci_conf[0x55] = 0x00; + dev->pb_pci_conf[0x57] = 0x00; + dev->pb_pci_conf[0x58] = 0x02; + dev->pb_pci_conf[0x70] = 0x00; + dev->pb_pci_conf[0x71] = 0x00; + dev->pb_pci_conf[0x78] = 0x00; + dev->pb_pci_conf[0x79] = 0x00; + dev->pb_pci_conf[0x7a] = 0x00; + dev->pb_pci_conf[0x7b] = 0x00; + dev->pb_pci_conf[0x7c] = 0x00; + dev->pb_pci_conf[0x7d] = 0x00; + dev->pb_pci_conf[0x7e] = 0x00; + dev->pb_pci_conf[0x7f] = 0x00; + dev->pb_pci_conf[0x88] = 0x00; + dev->pb_pci_conf[0x89] = 0x00; + dev->pb_pci_conf[0x8a] = 0x00; + dev->pb_pci_conf[0x8b] = 0x00; + dev->pb_pci_conf[0x8c] = 0x00; + dev->pb_pci_conf[0x8d] = 0x00; + dev->pb_pci_conf[0x8e] = 0x00; + dev->pb_pci_conf[0x8f] = 0x00; + dev->pb_pci_conf[0x9c] = 0x00; + dev->pb_pci_conf[0xa4] = 0x01; dev->pb_pci_conf[0xa5] = 0xc0; dev->pb_pci_conf[0xa6] = 0xfe; - dev->pb_pci_conf[0xc8] = 3; - dev->pb_pci_conf[0xb8] = 5; + dev->pb_pci_conf[0xa7] = 0x00; + /* Note: Do NOT reset these two registers on programmed (TRC) hard reset! */ + // dev->pb_pci_conf[0xb0] = 0x00; + // dev->pb_pci_conf[0xb1] = 0x00; + dev->pb_pci_conf[0xb4] = 0x00; + dev->pb_pci_conf[0xb5] = 0x00; + dev->pb_pci_conf[0xb8] = 0x05; + dev->pb_pci_conf[0xb9] = 0x00; + dev->pb_pci_conf[0xba] = 0x00; + dev->pb_pci_conf[0xbb] = 0x00; + dev->pb_pci_conf[0xbc] = 0x01; + dev->pb_pci_conf[0xc0] = 0x02; + dev->pb_pci_conf[0xc1] = 0x00; + dev->pb_pci_conf[0xc2] = 0x00; + dev->pb_pci_conf[0xc3] = 0x00; + dev->pb_pci_conf[0xc4] = 0x00; + dev->pb_pci_conf[0xc5] = 0x00; + dev->pb_pci_conf[0xc6] = 0x00; + dev->pb_pci_conf[0xc7] = 0x00; + dev->pb_pci_conf[0xc8] = 0x03; + dev->pb_pci_conf[0xc9] = 0x00; + dev->pb_pci_conf[0xca] = 0x00; + dev->pb_pci_conf[0xcb] = 0x00; + + // pci_remap_bus(dev->bus_index, 0x00); + i450kx_smram_recalc(dev, 1); + i450kx_vid_buf_recalc(dev, 1); + pb_write(0, 0x59, 0x30, dev); + for (i = 0x5a; i <= 0x5f; i++) + pb_write(0, i, 0x33, dev); /* Defaults MC */ dev->mc_pci_conf[0x00] = 0x86; dev->mc_pci_conf[0x01] = 0x80; dev->mc_pci_conf[0x02] = 0xc5; dev->mc_pci_conf[0x03] = 0x84; + dev->mc_pci_conf[0x04] = 0x00; + dev->mc_pci_conf[0x05] = 0x00; dev->mc_pci_conf[0x06] = 0x80; - dev->mc_pci_conf[0x08] = 4; - dev->mc_pci_conf[0x0b] = 5; + dev->mc_pci_conf[0x07] = 0x00; + dev->mc_pci_conf[0x08] = 0x04; + dev->mc_pci_conf[0x09] = 0x00; + dev->mc_pci_conf[0x0a] = 0x00; + dev->mc_pci_conf[0x0b] = 0x05; dev->mc_pci_conf[0x49] = 0x14; dev->mc_pci_conf[0x4c] = 0x0b; + dev->mc_pci_conf[0x4d] = 0x08; + dev->mc_pci_conf[0x4e] = 0x00; + dev->mc_pci_conf[0x4f] = 0x00; + dev->mc_pci_conf[0x57] = 0x00; + dev->mc_pci_conf[0x58] = 0x00; + dev->mc_pci_conf[0x74] = 0x00; + dev->mc_pci_conf[0x75] = 0x00; + dev->mc_pci_conf[0x76] = 0x00; + dev->mc_pci_conf[0x77] = 0x00; dev->mc_pci_conf[0x78] = 0x10; - dev->mc_pci_conf[0xa4] = 1; + dev->mc_pci_conf[0x79] = 0x00; + dev->mc_pci_conf[0x7a] = 0x00; + dev->mc_pci_conf[0x7b] = 0x00; + dev->mc_pci_conf[0x7c] = 0x00; + dev->mc_pci_conf[0x7d] = 0x00; + dev->mc_pci_conf[0x7e] = 0x10; + dev->mc_pci_conf[0x7f] = 0x00; + dev->mc_pci_conf[0x88] = 0x00; + dev->mc_pci_conf[0x89] = 0x00; + dev->mc_pci_conf[0x8a] = 0x00; + dev->mc_pci_conf[0x8b] = 0x00; + dev->mc_pci_conf[0x8c] = 0x00; + dev->mc_pci_conf[0x8d] = 0x00; + dev->mc_pci_conf[0x8e] = 0x00; + dev->mc_pci_conf[0x8f] = 0x00; + dev->mc_pci_conf[0xa4] = 0x01; dev->mc_pci_conf[0xa5] = 0xc0; dev->mc_pci_conf[0xa6] = 0xfe; + dev->mc_pci_conf[0xa7] = 0x00; + dev->mc_pci_conf[0xa8] = 0x00; + dev->mc_pci_conf[0xa9] = 0x00; + dev->mc_pci_conf[0xaa] = 0x00; + dev->mc_pci_conf[0xab] = 0x00; dev->mc_pci_conf[0xac] = 0x16; dev->mc_pci_conf[0xad] = 0x35; dev->mc_pci_conf[0xae] = 0xdf; dev->mc_pci_conf[0xaf] = 0x30; dev->mc_pci_conf[0xb8] = 0x0a; - dev->mc_pci_conf[0xbc] = 1; + dev->mc_pci_conf[0xb9] = 0x00; + dev->mc_pci_conf[0xba] = 0x00; + dev->mc_pci_conf[0xbb] = 0x00; + dev->mc_pci_conf[0xbc] = 0x01; + dev->mc_pci_conf[0xc0] = 0x00; + dev->mc_pci_conf[0xc1] = 0x00; + dev->mc_pci_conf[0xc2] = 0x00; + dev->mc_pci_conf[0xc3] = 0x00; + dev->mc_pci_conf[0xc4] = 0x00; + dev->mc_pci_conf[0xc5] = 0x00; + dev->mc_pci_conf[0xc6] = 0x00; + dev->mc_pci_conf[0xc7] = 0x00; + + i450kx_smram_recalc(dev, 0); + i450kx_vid_buf_recalc(dev, 0); + mc_write(0, 0x59, 0x03, dev); + for (i = 0x5a; i <= 0x5f; i++) + mc_write(0, i, 0x00, dev); + for (i = 0x60; i <= 0x6f; i++) + dev->mc_pci_conf[i] = 0x01; } @@ -542,7 +780,8 @@ i450kx_close(void *priv) { i450kx_t *dev = (i450kx_t *)priv; - smram_del(dev->smram); + smram_del(dev->smram[1]); + smram_del(dev->smram[0]); free(dev); } @@ -552,10 +791,11 @@ i450kx_init(const device_t *info) { i450kx_t *dev = (i450kx_t *)malloc(sizeof(i450kx_t)); memset(dev, 0, sizeof(i450kx_t)); - pci_add_card(PCI_ADD_NORTHBRIDGE, pb_read, pb_write, dev); /* Device 19: Intel 450KX PCI Bridge PB */ - pci_add_card(PCI_ADD_NORTHBRIDGE, mc_read, mc_write, dev); /* Device 14: Intel 450KX Memory Controller MC */ + pci_add_card(PCI_ADD_NORTHBRIDGE, pb_read, pb_write, dev); /* Device 19h: Intel 450KX PCI Bridge PB */ + pci_add_card(PCI_ADD_AGPBRIDGE, mc_read, mc_write, dev); /* Device 14h: Intel 450KX Memory Controller MC */ - dev->smram = smram_add(); + dev->smram[0] = smram_add(); + dev->smram[1] = smram_add(); cpu_cache_int_enabled = 1; cpu_cache_ext_enabled = 1; diff --git a/src/disk/CMakeLists.txt b/src/disk/CMakeLists.txt index f0ec758fe..9a5c72e00 100644 --- a/src/disk/CMakeLists.txt +++ b/src/disk/CMakeLists.txt @@ -15,7 +15,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_opti611.c hdc_ide_cmd640.c hdc_ide_sff8038i.c) + hdc_ide.c hdc_ide_opti611.c hdc_ide_cmd640.c hdc_ide_cmd646.c hdc_ide_sff8038i.c) add_library(zip OBJECT zip.c) diff --git a/src/disk/hdc_ide_cmd640.c b/src/disk/hdc_ide_cmd640.c index ad2c739cc..ac6146094 100644 --- a/src/disk/hdc_ide_cmd640.c +++ b/src/disk/hdc_ide_cmd640.c @@ -7,7 +7,7 @@ * This file is part of the 86Box distribution. * * Implementation of the CMD PCI-0640B controller. - + * * Authors: Miran Grca, * * Copyright 2020 Miran Grca. @@ -42,7 +42,8 @@ typedef struct { uint8_t vlb_idx, id, in_cfg, single_channel, - regs[256]; + pci, regs[256]; + uint32_t local; int slot, irq_mode[2], irq_pin, irq_line; } cmd640_t; @@ -51,15 +52,45 @@ typedef struct static int next_id = 0; +#ifdef ENABLE_CMD640_LOG +int cmd640_do_log = ENABLE_CMD640_LOG; +static void +cmd640_log(const char *fmt, ...) +{ + va_list ap; + + if (cmd640_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define cmd640_log(fmt, ...) +#endif + + void cmd640_set_irq(int channel, void *priv) { cmd640_t *dev = (cmd640_t *) priv; - dev->regs[0x50] &= ~0x04; - dev->regs[0x50] |= (channel >> 4); + int irq = !!(channel & 0x40); + + if (channel & 0x01) { + if (!(dev->regs[0x57] & 0x10) || (channel & 0x40)) { + dev->regs[0x57] &= ~0x10; + dev->regs[0x57] |= (channel >> 2); + } + } else { + if (!(dev->regs[0x50] & 0x04) || (channel & 0x40)) { + dev->regs[0x50] &= ~0x04; + dev->regs[0x50] |= (channel >> 4); + } + } channel &= 0x01; - if (dev->regs[0x50] & 0x04) { + if (irq) { if (dev->irq_mode[channel] == 1) pci_set_irq(dev->slot, dev->irq_pin); else @@ -196,6 +227,8 @@ cmd640_vlb_read(uint16_t addr, void *priv) ret = dev->regs[dev->vlb_idx]; if (dev->vlb_idx == 0x50) dev->regs[0x50] &= ~0x04; + else if (dev->vlb_idx == 0x57) + dev->regs[0x57] &= ~0x10; if (dev->regs[0x50] & 0x80) dev->in_cfg = 0; break; @@ -234,6 +267,8 @@ cmd640_pci_write(int func, int addr, uint8_t val, void *priv) { cmd640_t *dev = (cmd640_t *) priv; + cmd640_log("cmd640_pci_write(%i, %02X, %02X)\n", func, addr, val); + if (func == 0x00) switch (addr) { case 0x04: dev->regs[addr] = (val & 0x41); @@ -315,15 +350,20 @@ cmd640_pci_read(int func, int addr, void *priv) ret = dev->regs[addr]; if (addr == 0x50) dev->regs[0x50] &= ~0x04; + else if (addr == 0x57) + dev->regs[0x57] &= ~0x10; } + cmd640_log("cmd640_pci_read(%i, %02X, %02X)\n", func, addr, ret); + return ret; } static void -cmd640_reset(void *p) +cmd640_reset(void *priv) { + cmd640_t *dev = (cmd640_t *) priv; int i = 0; for (i = 0; i < CDROM_NUM; i++) { @@ -342,8 +382,58 @@ cmd640_reset(void *p) mo_reset((scsi_common_t *) mo_drives[i].priv); } - cmd640_set_irq(0x00, p); - cmd640_set_irq(0x01, p); + cmd640_set_irq(0x00, priv); + cmd640_set_irq(0x01, priv); + + memset(dev->regs, 0x00, sizeof(dev->regs)); + + dev->regs[0x50] = 0x02; /* Revision 02 */ + dev->regs[0x50] |= (dev->id << 3); /* Device ID: 00 = 60h, 01 = 61h, 10 = 62h, 11 = 63h */ + + dev->regs[0x59] = 0x40; + + if (dev->pci) { + cmd640_log("dev->local = %08X\n", dev->local); + if ((dev->local & 0xffff) == 0x0a) { + dev->regs[0x50] |= 0x40; /* Enable Base address register R/W; + If 0, they return 0 and are read-only 8 */ + } + + dev->regs[0x00] = 0x95; /* CMD */ + dev->regs[0x01] = 0x10; + dev->regs[0x02] = 0x40; /* PCI-0640B */ + dev->regs[0x03] = 0x06; + dev->regs[0x04] = 0x01; /* Apparently required by the ASUS PCI/I-P5SP4 AND PCI/I-P54SP4 */ + dev->regs[0x07] = 0x02; /* DEVSEL timing: 01 medium */ + dev->regs[0x08] = 0x02; /* Revision 02 */ + dev->regs[0x09] = dev->local; /* Programming interface */ + dev->regs[0x0a] = 0x01; /* IDE controller */ + dev->regs[0x0b] = 0x01; /* Mass storage controller */ + + /* Base addresses (1F0, 3F4, 170, 374) */ + if (dev->regs[0x50] & 0x40) { + dev->regs[0x10] = 0xf1; dev->regs[0x11] = 0x01; + dev->regs[0x14] = 0xf5; dev->regs[0x15] = 0x03; + dev->regs[0x18] = 0x71; dev->regs[0x19] = 0x01; + dev->regs[0x1c] = 0x75; dev->regs[0x1d] = 0x03; + } + + dev->regs[0x3c] = 0x14; /* IRQ 14 */ + dev->regs[0x3d] = 0x01; /* INTA */ + + dev->irq_mode[0] = dev->irq_mode[1] = 0; + dev->irq_pin = PCI_INTA; + dev->irq_line = 14; + } else { + if ((dev->local & 0xffff) == 0x0078) + dev->regs[0x50] |= 0x20; /* 0 = 178h, 17Ch; 1 = 078h, 07Ch */ + + /* If bit 7 is 1, then device ID has to be written on port x78h before + accessing the configuration registers */ + dev->in_cfg = 1; /* Configuration registers are accessible */ + } + + cmd640_ide_handlers(dev); } @@ -366,45 +456,13 @@ cmd640_init(const device_t *info) dev->id = next_id | 0x60; - dev->regs[0x50] = 0x02; /* Revision 02 */ - dev->regs[0x50] |= (next_id << 3); /* Device ID: 00 = 60h, 01 = 61h, 10 = 62h, 11 = 63h */ - - dev->regs[0x59] = 0x40; + dev->pci = !!(info->flags & DEVICE_PCI); + dev->local = info->local; if (info->flags & DEVICE_PCI) { - if ((info->local & 0xffff) == 0x0a) { - dev->regs[0x50] |= 0x40; /* Enable Base address register R/W; - If 0, they return 0 and are read-only 8 */ - } - - dev->regs[0x00] = 0x95; /* CMD */ - dev->regs[0x01] = 0x10; - dev->regs[0x02] = 0x40; /* PCI-0640B */ - dev->regs[0x03] = 0x06; - dev->regs[0x04] = 0x01; /* Apparently required by the ASUS PCI/I-P5SP4 AND PCI/I-P54SP4 */ - dev->regs[0x07] = 0x02; /* DEVSEL timing: 01 medium */ - dev->regs[0x08] = 0x02; /* Revision 02 */ - dev->regs[0x09] = info->local; /* Programming interface */ - dev->regs[0x0a] = 0x01; /* IDE controller */ - dev->regs[0x0b] = 0x01; /* Mass storage controller */ - - /* Base addresses (1F0, 3F4, 170, 374) */ - if (dev->regs[0x50] & 0x40) { - dev->regs[0x10] = 0xf1; dev->regs[0x11] = 0x01; - dev->regs[0x14] = 0xf5; dev->regs[0x15] = 0x03; - dev->regs[0x18] = 0x71; dev->regs[0x19] = 0x01; - dev->regs[0x1c] = 0x75; dev->regs[0x1d] = 0x03; - } - - dev->regs[0x3c] = 0x14; /* IRQ 14 */ - dev->regs[0x3d] = 0x01; /* INTA */ - device_add(&ide_pci_2ch_device); dev->slot = pci_add_card(PCI_ADD_IDE, cmd640_pci_read, cmd640_pci_write, dev); - dev->irq_mode[0] = dev->irq_mode[1] = 0; - dev->irq_pin = PCI_INTA; - dev->irq_line = 14; ide_set_bus_master(0, NULL, cmd640_set_irq, dev); ide_set_bus_master(1, NULL, cmd640_set_irq, dev); @@ -416,12 +474,6 @@ cmd640_init(const device_t *info) // ide_pri_disable(); } else if (info->flags & DEVICE_VLB) { - if ((info->local & 0xffff) == 0x0078) - dev->regs[0x50] |= 0x20; /* 0 = 178h, 17Ch; 1 = 078h, 07Ch */ - /* If bit 7 is 1, then device ID has to be written on port x78h before - accessing the configuration registers */ - dev->in_cfg = 1; /* Configuration register are accessible */ - device_add(&ide_vlb_2ch_device); io_sethandler(info->local & 0xffff, 0x0008, @@ -432,11 +484,10 @@ cmd640_init(const device_t *info) dev->single_channel = !!(info->local & 0x20000); - if (!dev->single_channel) - ide_sec_disable(); - next_id++; + cmd640_reset(dev); + return dev; } @@ -445,7 +496,7 @@ const device_t ide_cmd640_vlb_device = { "CMD PCI-0640B VLB", DEVICE_VLB, 0x0078, - cmd640_init, cmd640_close, NULL, + cmd640_init, cmd640_close, cmd640_reset, { NULL }, NULL, NULL, NULL }; @@ -454,7 +505,7 @@ const device_t ide_cmd640_vlb_178_device = { "CMD PCI-0640B VLB (Port 178h)", DEVICE_VLB, 0x0178, - cmd640_init, cmd640_close, NULL, + cmd640_init, cmd640_close, cmd640_reset, { NULL }, NULL, NULL, NULL }; diff --git a/src/disk/hdc_ide_cmd646.c b/src/disk/hdc_ide_cmd646.c new file mode 100644 index 000000000..4a8e9a176 --- /dev/null +++ b/src/disk/hdc_ide_cmd646.c @@ -0,0 +1,435 @@ +/* + * 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 CMD PCI-0646 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 +{ + uint8_t vlb_idx, single_channel, + in_cfg, regs[256]; + uint32_t local; + int slot, irq_mode[2], + irq_pin; + sff8038i_t *bm[2]; +} cmd646_t; + + +#ifdef ENABLE_CMD646_LOG +int cmd646_do_log = ENABLE_CMD646_LOG; +static void +cmd646_log(const char *fmt, ...) +{ + va_list ap; + + if (cmd646_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define cmd646_log(fmt, ...) +#endif + + +static void +cmd646_set_irq(int channel, void *priv) +{ + cmd646_t *dev = (cmd646_t *) priv; + + if (channel & 0x01) { + if (!(dev->regs[0x57] & 0x10) || (channel & 0x40)) { + dev->regs[0x57] &= ~0x10; + dev->regs[0x57] |= (channel >> 2); + } + } else { + if (!(dev->regs[0x50] & 0x04) || (channel & 0x40)) { + dev->regs[0x50] &= ~0x04; + dev->regs[0x50] |= (channel >> 4); + } + } + + sff_bus_master_set_irq(channel, dev->bm[channel & 0x01]); +} + + +static int +cmd646_bus_master_dma(int channel, uint8_t *data, int transfer_length, int out, void *priv) +{ + cmd646_t *dev = (cmd646_t *) priv; + + return sff_bus_master_dma(channel, data, transfer_length, out, dev->bm[channel & 0x01]); +} + + +static void +cmd646_ide_handlers(cmd646_t *dev) +{ + uint16_t main, side; + int irq_mode[2] = { 0, 0 }; + + ide_pri_disable(); + + if ((dev->regs[0x09] & 0x01) && (dev->regs[0x50] & 0x40)) { + main = (dev->regs[0x11] << 8) | (dev->regs[0x10] & 0xf8); + side = ((dev->regs[0x15] << 8) | (dev->regs[0x14] & 0xfc)) + 2; + } else { + main = 0x1f0; + side = 0x3f6; + } + + ide_set_base(0, main); + ide_set_side(0, side); + + if (dev->regs[0x09] & 0x01) + irq_mode[0] = 1; + + sff_set_irq_mode(dev->bm[0], 0, irq_mode[0]); + sff_set_irq_mode(dev->bm[0], 1, irq_mode[1]); + + if (dev->regs[0x04] & 0x01) + ide_pri_enable(); + + if (dev->single_channel) + return; + + ide_sec_disable(); + + if ((dev->regs[0x09] & 0x04) && (dev->regs[0x50] & 0x40)) { + main = (dev->regs[0x19] << 8) | (dev->regs[0x18] & 0xf8); + side = ((dev->regs[0x1d] << 8) | (dev->regs[0x1c] & 0xfc)) + 2; + } else { + main = 0x170; + side = 0x376; + } + + ide_set_base(1, main); + ide_set_side(1, side); + + if (dev->regs[0x09] & 0x04) + irq_mode[1] = 1; + + sff_set_irq_mode(dev->bm[1], 0, irq_mode[0]); + sff_set_irq_mode(dev->bm[1], 1, irq_mode[1]); + + if ((dev->regs[0x04] & 0x01) && (dev->regs[0x51] & 0x08)) + ide_sec_enable(); + +} + + +static void +cmd646_ide_bm_handlers(cmd646_t *dev) +{ + uint16_t base = (dev->regs[0x20] & 0xf0) | (dev->regs[0x21] << 8); + + sff_bus_master_handler(dev->bm[0], (dev->regs[0x04] & 1), base); + sff_bus_master_handler(dev->bm[1], (dev->regs[0x04] & 1), base + 8); +} + + +static void +cmd646_pci_write(int func, int addr, uint8_t val, void *priv) +{ + cmd646_t *dev = (cmd646_t *) priv; + + cmd646_log("[%04X:%08X] (%08X) cmd646_pci_write(%i, %02X, %02X)\n", CS, cpu_state.pc, ESI, func, addr, val); + + if (func == 0x00) switch (addr) { + case 0x04: + dev->regs[addr] = (val & 0x45); + cmd646_ide_handlers(dev); + break; + case 0x07: + dev->regs[addr] &= ~(val & 0xb1); + break; + case 0x09: + if ((dev->regs[addr] & 0x0a) == 0x0a) { + dev->regs[addr] = (dev->regs[addr] & 0x0a) | (val & 0x05); + dev->irq_mode[0] = !!(val & 0x01); + dev->irq_mode[1] = !!(val & 0x04); + cmd646_ide_handlers(dev); + } + break; + case 0x10: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x10] = (val & 0xf8) | 1; + cmd646_ide_handlers(dev); + } + break; + case 0x11: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x11] = val; + cmd646_ide_handlers(dev); + } + break; + case 0x14: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x14] = (val & 0xfc) | 1; + cmd646_ide_handlers(dev); + } + break; + case 0x15: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x15] = val; + cmd646_ide_handlers(dev); + } + break; + case 0x18: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x18] = (val & 0xf8) | 1; + cmd646_ide_handlers(dev); + } + break; + case 0x19: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x19] = val; + cmd646_ide_handlers(dev); + } + break; + case 0x1c: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x1c] = (val & 0xfc) | 1; + cmd646_ide_handlers(dev); + } + break; + case 0x1d: + if (dev->regs[0x50] & 0x40) { + dev->regs[0x1d] = val; + cmd646_ide_handlers(dev); + } + break; + case 0x20: + dev->regs[0x20] = (val & 0xf0) | 1; + cmd646_ide_bm_handlers(dev); + break; + case 0x21: + dev->regs[0x21] = val; + cmd646_ide_bm_handlers(dev); + break; + case 0x51: + dev->regs[addr] = val & 0xc8; + cmd646_ide_handlers(dev); + break; + case 0x52: case 0x54: case 0x56: case 0x58: + case 0x59: case 0x5b: + dev->regs[addr] = val; + break; + case 0x53: case 0x55: + dev->regs[addr] = val & 0xc0; + break; + case 0x57: + dev->regs[addr] = (dev->regs[addr] & 0x10) | (val & 0xcc); + break; + case 0x70 ... 0x77: + sff_bus_master_write(addr & 0x0f, val, dev->bm[0]); + break; + case 0x78 ... 0x7f: + sff_bus_master_write(addr & 0x0f, val, dev->bm[1]); + break; + } +} + + +static uint8_t +cmd646_pci_read(int func, int addr, void *priv) +{ + cmd646_t *dev = (cmd646_t *) priv; + uint8_t ret = 0xff; + + if (func == 0x00) { + ret = dev->regs[addr]; + + if (addr == 0x50) + dev->regs[0x50] &= ~0x04; + else if (addr == 0x57) + dev->regs[0x57] &= ~0x10; + else if ((addr >= 0x70) && (addr <= 0x77)) + ret = sff_bus_master_read(addr & 0x0f, dev->bm[0]); + else if ((addr >= 0x78) && (addr <= 0x7f)) + ret = sff_bus_master_read(addr & 0x0f, dev->bm[0]); + } + + cmd646_log("[%04X:%08X] (%08X) cmd646_pci_read(%i, %02X, %02X)\n", CS, cpu_state.pc, ESI, func, addr, ret); + + return ret; +} + + +static void +cmd646_reset(void *priv) +{ + cmd646_t *dev = (cmd646_t *) priv; + int i = 0; + + for (i = 0; i < CDROM_NUM; i++) { + if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && + (cdrom[i].ide_channel < 4) && 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 < 4) && 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 < 4) && mo_drives[i].priv) + mo_reset((scsi_common_t *) mo_drives[i].priv); + } + + cmd646_set_irq(0x00, priv); + cmd646_set_irq(0x01, priv); + + memset(dev->regs, 0x00, sizeof(dev->regs)); + + dev->regs[0x00] = 0x95; /* CMD */ + dev->regs[0x01] = 0x10; + dev->regs[0x02] = 0x46; /* PCI-0646 */ + dev->regs[0x03] = 0x06; + dev->regs[0x04] = 0x00; + dev->regs[0x06] = 0x80; + dev->regs[0x07] = 0x02; /* DEVSEL timing: 01 medium */ + dev->regs[0x09] = dev->local; /* Programming interface */ + dev->regs[0x0a] = 0x01; /* IDE controller */ + dev->regs[0x0b] = 0x01; /* Mass storage controller */ + + if ((dev->local & 0xffff) == 0x8a) { + dev->regs[0x50] = 0x40; /* Enable Base address register R/W; + If 0, they return 0 and are read-only 8 */ + + /* Base addresses (1F0, 3F4, 170, 374) */ + dev->regs[0x10] = 0xf1; dev->regs[0x11] = 0x01; + dev->regs[0x14] = 0xf5; dev->regs[0x15] = 0x03; + dev->regs[0x18] = 0x71; dev->regs[0x19] = 0x01; + dev->regs[0x1c] = 0x75; dev->regs[0x1d] = 0x03; + } + + dev->regs[0x20] = 0x01; + + dev->regs[0x3c] = 0x0e; /* IRQ 14 */ + dev->regs[0x3d] = 0x01; /* INTA */ + dev->regs[0x3e] = 0x02; /* Min_Gnt */ + dev->regs[0x3f] = 0x04; /* Max_Iat */ + + if (!dev->single_channel) + dev->regs[0x51] = 0x08; + + dev->regs[0x57] = 0x0c; + dev->regs[0x59] = 0x40; + + dev->irq_mode[0] = dev->irq_mode[1] = 0; + dev->irq_pin = PCI_INTA; + + cmd646_ide_handlers(dev); + cmd646_ide_bm_handlers(dev); +} + + +static void +cmd646_close(void *priv) +{ + cmd646_t *dev = (cmd646_t *) priv; + + free(dev); +} + + +static void * +cmd646_init(const device_t *info) +{ + cmd646_t *dev = (cmd646_t *) malloc(sizeof(cmd646_t)); + memset(dev, 0x00, sizeof(cmd646_t)); + + dev->local = info->local; + + device_add(&ide_pci_2ch_device); + + dev->slot = pci_add_card(PCI_ADD_IDE, cmd646_pci_read, cmd646_pci_write, dev); + + dev->single_channel = !!(info->local & 0x20000); + + dev->bm[0] = device_add_inst(&sff8038i_device, 1); + if (!dev->single_channel) + dev->bm[1] = device_add_inst(&sff8038i_device, 2); + + ide_set_bus_master(0, cmd646_bus_master_dma, cmd646_set_irq, dev); + if (!dev->single_channel) + ide_set_bus_master(1, cmd646_bus_master_dma, cmd646_set_irq, dev); + + sff_set_irq_mode(dev->bm[0], 0, 0); + sff_set_irq_mode(dev->bm[0], 1, 0); + + if (!dev->single_channel) { + sff_set_irq_mode(dev->bm[1], 0, 0); + sff_set_irq_mode(dev->bm[1], 1, 0); + } + + cmd646_reset(dev); + + return dev; +} + + +const device_t ide_cmd646_device = { + "CMD PCI-0646", + DEVICE_PCI, + 0x8a, + cmd646_init, cmd646_close, cmd646_reset, + { NULL }, NULL, NULL, + NULL +}; + +const device_t ide_cmd646_legacy_only_device = { + "CMD PCI-0646 (Legacy Mode Only)", + DEVICE_PCI, + 0x80, + cmd646_init, cmd646_close, cmd646_reset, + { NULL }, NULL, NULL, + NULL +}; + +const device_t ide_cmd646_single_channel_device = { + "CMD PCI-0646", + DEVICE_PCI, + 0x2008a, + cmd646_init, cmd646_close, cmd646_reset, + { NULL }, NULL, NULL, + NULL +}; diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index 44d9ad545..8fe9fec88 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -47,10 +47,10 @@ static int next_id = 0; -static uint8_t sff_bus_master_read(uint16_t port, void *priv); +uint8_t sff_bus_master_read(uint16_t port, void *priv); static uint16_t sff_bus_master_readw(uint16_t port, void *priv); static uint32_t sff_bus_master_readl(uint16_t port, void *priv); -static void sff_bus_master_write(uint16_t port, uint8_t val, void *priv); +void sff_bus_master_write(uint16_t port, uint8_t val, void *priv); static void sff_bus_master_writew(uint16_t port, uint16_t val, void *priv); static void sff_bus_master_writel(uint16_t port, uint32_t val, void *priv); @@ -112,7 +112,7 @@ sff_bus_master_next_addr(sff8038i_t *dev) } -static void +void sff_bus_master_write(uint16_t port, uint8_t val, void *priv) { sff8038i_t *dev = (sff8038i_t *) priv; @@ -138,6 +138,9 @@ sff_bus_master_write(uint16_t port, uint8_t val, void *priv) dev->command = val; break; + case 1: + dev->dma_mode = val & 0x03; + break; case 2: sff_log("sff Status: val = %02X, old = %02X\n", val, dev->status); dev->status &= 0x07; @@ -177,6 +180,7 @@ sff_bus_master_writew(uint16_t port, uint16_t val, void *priv) switch (port & 7) { case 0: + case 1: case 2: sff_bus_master_write(port, val & 0xff, priv); break; @@ -202,6 +206,7 @@ sff_bus_master_writel(uint16_t port, uint32_t val, void *priv) switch (port & 7) { case 0: + case 1: case 2: sff_bus_master_write(port, val & 0xff, priv); break; @@ -214,7 +219,7 @@ sff_bus_master_writel(uint16_t port, uint32_t val, void *priv) } -static uint8_t +uint8_t sff_bus_master_read(uint16_t port, void *priv) { sff8038i_t *dev = (sff8038i_t *) priv; @@ -225,6 +230,9 @@ sff_bus_master_read(uint16_t port, void *priv) case 0: ret = dev->command; break; + case 1: + ret = dev->dma_mode & 0x03; + break; case 2: ret = dev->status & 0x67; break; @@ -257,6 +265,7 @@ sff_bus_master_readw(uint16_t port, void *priv) switch (port & 7) { case 0: + case 1: case 2: ret = (uint16_t) sff_bus_master_read(port, priv); break; @@ -283,6 +292,7 @@ sff_bus_master_readl(uint16_t port, void *priv) switch (port & 7) { case 0: + case 1: case 2: ret = (uint32_t) sff_bus_master_read(port, priv); break; @@ -297,7 +307,7 @@ sff_bus_master_readl(uint16_t port, void *priv) } -static int +int sff_bus_master_dma(int channel, uint8_t *data, int transfer_length, int out, void *priv) { sff8038i_t *dev = (sff8038i_t *) priv; @@ -311,8 +321,10 @@ sff_bus_master_dma(int channel, uint8_t *data, int transfer_length, int out, voi sop = out ? "Read" : "Writ"; #endif - if (!(dev->status & 1)) + if (!(dev->status & 1)) { + sff_log("DMA disabled\n"); return 2; /*DMA disabled*/ + } sff_log("SFF-8038i Bus master %s: %i bytes\n", out ? "write" : "read", transfer_length); diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index 00160ae13..ae97b156e 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -83,10 +83,7 @@ extern const device_t i440bx_device; extern const device_t i440bx_no_agp_device; extern const device_t i440gx_device; extern const device_t i440zx_device; - -#if defined(DEV_BRANCH) && defined(USE_I450KX) extern const device_t i450kx_device; -#endif extern const device_t sio_device; extern const device_t sio_zb_device; @@ -133,6 +130,7 @@ extern const device_t stpc_serial_device; extern const device_t stpc_lpt_device; /* UMC */ +extern const device_t umc_um82c49x_device; extern const device_t umc_8886f_device; extern const device_t umc_8886af_device; extern const device_t umc_hb4_device; diff --git a/src/include/86box/hdc.h b/src/include/86box/hdc.h index 9175dddaf..1008b38c9 100644 --- a/src/include/86box/hdc.h +++ b/src/include/86box/hdc.h @@ -56,6 +56,9 @@ extern const device_t ide_cmd640_vlb_178_device; /* CMD PCI-640B VLB (Port 178h extern const device_t ide_cmd640_pci_device; /* CMD PCI-640B PCI */ extern const device_t ide_cmd640_pci_legacy_only_device; /* CMD PCI-640B PCI (Legacy Mode Only) */ extern const device_t ide_cmd640_pci_single_channel_device; /* CMD PCI-640B PCI (Only primary channel) */ +extern const device_t ide_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 */ diff --git a/src/include/86box/hdc_ide_sff8038i.h b/src/include/86box/hdc_ide_sff8038i.h index 305d2d40c..700684dae 100644 --- a/src/include/86box/hdc_ide_sff8038i.h +++ b/src/include/86box/hdc_ide_sff8038i.h @@ -19,8 +19,10 @@ typedef struct { uint8_t command, status, - ptr0, enabled; - uint16_t base, pad; + ptr0, enabled, + dma_mode, pad, + pad0, pad1; + uint16_t base, pad2; uint32_t ptr, ptr_cur, addr; int count, eot, @@ -39,6 +41,11 @@ extern int sff_bus_master_dma_write(int channel, uint8_t *data, int transfer_len extern void sff_bus_master_set_irq(int channel, void *priv); +extern int sff_bus_master_dma(int channel, uint8_t *data, int transfer_length, int out, void *priv); + +extern void sff_bus_master_write(uint16_t port, uint8_t val, void *priv); +extern uint8_t sff_bus_master_read(uint16_t port, void *priv); + extern void sff_bus_master_reset(sff8038i_t *dev, uint16_t old_base); extern void sff_set_slot(sff8038i_t *dev, int slot); diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index efedfc6e4..2767789b3 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -539,9 +539,7 @@ extern int machine_at_ficva503a_init(const machine_t *); extern int machine_at_sy_5ema_pro_init(const machine_t *); /* m_at_socket8.c */ -#if defined(DEV_BRANCH) && defined(USE_I450KX) extern int machine_at_p6rp4_init(const machine_t *); -#endif extern int machine_at_686nx_init(const machine_t *); extern int machine_at_v60n_init(const machine_t *); diff --git a/src/include/86box/mem.h b/src/include/86box/mem.h index dfcbef242..5d1f6848c 100644 --- a/src/include/86box/mem.h +++ b/src/include/86box/mem.h @@ -145,10 +145,18 @@ mem_set_access(ACCESS_SMM, 0, base, size, access) #define mem_set_mem_state_both(base, size, access) \ mem_set_access(ACCESS_ALL, 0, base, size, access) +#define mem_set_mem_state_cpu_both(base, size, access) \ + mem_set_access(ACCESS_CPU_BOTH, 0, base, size, access) +#define mem_set_mem_state_bus_both(base, size, access) \ + mem_set_access(ACCESS_BUS_BOTH, 0, base, size, access) #define mem_set_mem_state_smram(smm, base, size, is_smram) \ mem_set_access((smm ? ACCESS_SMM : ACCESS_NORMAL), 1, base, size, is_smram) #define mem_set_mem_state_smram_ex(smm, base, size, is_smram) \ mem_set_access((smm ? ACCESS_SMM : ACCESS_NORMAL), 2, base, size, is_smram) +#define mem_set_access_smram_cpu(smm, base, size, is_smram) \ + mem_set_access((smm ? ACCESS_CPU_SMM : ACCESS_CPU), 1, base, size, is_smram) +#define mem_set_access_smram_bus(smm, base, size, is_smram) \ + mem_set_access((smm ? ACCESS_BUS_SMM : ACCESS_BUS), 1, base, size, is_smram) #define flushmmucache_cr3 \ flushmmucache_nopc diff --git a/src/include/86box/nvr.h b/src/include/86box/nvr.h index f1776bf79..386954b54 100644 --- a/src/include/86box/nvr.h +++ b/src/include/86box/nvr.h @@ -95,6 +95,7 @@ extern const device_t piix4_nvr_device; extern const device_t ls486e_nvr_device; extern const device_t ami_apollo_nvr_device; extern const device_t via_nvr_device; +extern const device_t p6rp4_nvr_device; #endif diff --git a/src/include/86box/smram.h b/src/include/86box/smram.h index 6fc89971e..996e5df30 100644 --- a/src/include/86box/smram.h +++ b/src/include/86box/smram.h @@ -39,12 +39,19 @@ extern void smram_recalc_all(int ret); extern void smram_del(smram_t *smr); /* Add a SMRAM mapping. */ extern smram_t *smram_add(void); +/* Set memory state in the specified model (normal or SMM) according to the specified flags, + separately for bus and CPU. */ +extern void smram_map_ex(int bus, int smm, uint32_t addr, uint32_t size, int is_smram); /* Set memory state in the specified model (normal or SMM) according to the specified flags. */ extern void smram_map(int smm, uint32_t addr, uint32_t size, int is_smram); /* Disable a specific SMRAM mapping. */ extern void smram_disable(smram_t *smr); /* Disable all SMRAM mappings. */ extern void smram_disable_all(void); +/* Enable SMRAM mappings according to flags for both normal and SMM modes, separately for bus + and CPU. */ +extern void smram_enable_ex(smram_t *smr, uint32_t host_base, uint32_t ram_base, uint32_t size, + int flags_normal, int flags_normal_bus, int flags_smm, int flags_smm_bus); /* Enable SMRAM mappings according to flags for both normal and SMM modes. */ extern void smram_enable(smram_t *smr, uint32_t host_base, uint32_t ram_base, uint32_t size, int flags_normal, int flags_smm); diff --git a/src/machine/CMakeLists.txt b/src/machine/CMakeLists.txt index 6643566ee..c20d21a75 100644 --- a/src/machine/CMakeLists.txt +++ b/src/machine/CMakeLists.txt @@ -28,10 +28,6 @@ if(HEDAKA) target_compile_definitions(mch PRIVATE USE_HEDAKA) endif() -if(I450KX) - target_compile_definitions(mch PRIVATE USE_I450KX) -endif() - if(LASERXT) target_sources(mch PRIVATE m_xt_laserxt.c) target_compile_definitions(mch PRIVATE USE_LASERXT) diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index ab3bc05b7..8067e17b0 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -30,6 +30,8 @@ #include <86box/hdc_ide.h> #include <86box/keyboard.h> #include <86box/flash.h> +#include <86box/timer.h> +#include <86box/nvr.h> #include <86box/sio.h> #include <86box/hwm.h> #include <86box/spd.h> @@ -37,7 +39,7 @@ #include "cpu.h" #include <86box/machine.h> -#if defined(DEV_BRANCH) && defined(USE_I450KX) + int machine_at_p6rp4_init(const machine_t *model) { @@ -49,11 +51,12 @@ machine_at_p6rp4_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); + device_add(&p6rp4_nvr_device); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x19, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x12, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x14, PCI_CARD_AGPBRIDGE, 0, 0, 0, 0); pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x08, PCI_CARD_IDE, 0, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_NORMAL, 1, 2, 3, 4); @@ -62,16 +65,15 @@ machine_at_p6rp4_init(const machine_t *model) pci_register_slot(0x04, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&i450kx_device); device_add(&sio_zb_device); - // device_add(&keyboard_ps2_ami_pci_device); + device_add(&ide_cmd646_device); /* Input port bit 2 must be 1 or CMOS Setup is disabled. */ device_add(&keyboard_ps2_ami_pci_device); device_add(&fdc37c665_device); - device_add(&ide_cmd640_pci_device); device_add(&intel_flash_bxt_device); return ret; } -#endif + int machine_at_686nx_init(const machine_t *model) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 239fd2f41..0f2479961 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -398,6 +398,8 @@ const machine_t machines[] = { { "[SiS 471] DTK PKM-0038S E-2", "dtk486", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_dtk486_init, NULL }, /* Unknown Epox VLB Socket 3 board, has AMIKey F keyboard BIOS. */ { "[SiS 471] Epox 486SX/DX Green", "ami471", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_ami471_init, NULL }, + /* Has an Intel 82C42PE with Phoenix MultiKey KBC firmware. */ + { "[UMC 491/493] Epson Action Tower 3000", "actiontower3000", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 262144, 1024, 255, machine_at_actiontower3000_init, NULL }, /* 486 machines which utilize the PCI bus */ /* This has an AMIKey-2, which is an updated version of type 'H'. */ @@ -750,10 +752,8 @@ const machine_t machines[] = { /* Socket 8 machines */ /* 450KX */ -#if defined(DEV_BRANCH) && defined(USE_I450KX) /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[i450KX] ASUS P/I-P6RP4", "p6rp4", MACHINE_TYPE_SOCKET8, CPU_PKG_SOCKET8, 0, 60000000, 66666667, 2100, 3500, 1.5, 8.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 524288, 8192, 127, machine_at_p6rp4_init, NULL }, -#endif /* 440FX */ /* Has the SMC FDC73C935's on-chip KBC with Phoenix MultiKey firmware. */ diff --git a/src/mem/mem.c b/src/mem/mem.c index de6e0a60b..da2e1f31e 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -2247,6 +2247,12 @@ mem_mapping_access_allowed(uint32_t flags, uint16_t access) ret = ret && !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_SMRAM); } else ret = !(flags & MEM_MAPPING_EXTERNAL) && !(flags & MEM_MAPPING_SMRAM); + } else { + /* Still allow SMRAM if access is DISABLED but also has CACHE and/or SMRAM flags set. */ + if (access & ACCESS_CACHE) + ret = (flags & MEM_MAPPING_CACHE); + else if (access & ACCESS_SMRAM) + ret = (flags & MEM_MAPPING_SMRAM); } return ret; diff --git a/src/mem/smram.c b/src/mem/smram.c index 8e405af8a..8b1f9fd40 100644 --- a/src/mem/smram.c +++ b/src/mem/smram.c @@ -287,11 +287,24 @@ smram_add(void) } +/* Set memory state in the specified model (normal or SMM) according to the specified flags, + separately for bus and CPU. */ +void +smram_map_ex(int bus, int smm, uint32_t addr, uint32_t size, int is_smram) +{ + if (bus) + mem_set_access_smram_bus(smm, addr, size, is_smram); + else + mem_set_access_smram_cpu(smm, addr, size, is_smram); +} + + /* Set memory state in the specified model (normal or SMM) according to the specified flags. */ void smram_map(int smm, uint32_t addr, uint32_t size, int is_smram) { - mem_set_mem_state_smram(smm, addr, size, is_smram); + smram_map_ex(0, smm, addr, size, is_smram); + smram_map_ex(1, smm, addr, size, is_smram); } @@ -331,9 +344,11 @@ smram_disable_all(void) } -/* Enable SMRAM mappings according to flags for both normal and SMM modes. */ +/* Enable SMRAM mappings according to flags for both normal and SMM modes, separately for bus + and CPU. */ void -smram_enable(smram_t *smr, uint32_t host_base, uint32_t ram_base, uint32_t size, int flags_normal, int flags_smm) +smram_enable_ex(smram_t *smr, uint32_t host_base, uint32_t ram_base, uint32_t size, + int flags_normal, int flags_normal_bus, int flags_smm, int flags_smm_bus) { if (smr == NULL) { fatal("smram_add(): Invalid SMRAM mapping\n"); @@ -362,13 +377,23 @@ smram_enable(smram_t *smr, uint32_t host_base, uint32_t ram_base, uint32_t size, mem_mapping_set_exec(&(smr->mapping), smram + 0x30000); } - smram_map(0, host_base, size, flags_normal); - smram_map(1, host_base, size, flags_smm); + smram_map_ex(0, 0, host_base, size, flags_normal); + smram_map_ex(1, 0, host_base, size, flags_normal_bus); + smram_map_ex(0, 1, host_base, size, flags_smm); + smram_map_ex(1, 1, host_base, size, flags_smm_bus); } else smram_disable(smr); } +/* Enable SMRAM mappings according to flags for both normal and SMM modes. */ +void +smram_enable(smram_t *smr, uint32_t host_base, uint32_t ram_base, uint32_t size, int flags_normal, int flags_smm) +{ + smram_enable_ex(smr, host_base, ram_base, size, flags_normal, flags_normal, flags_smm, flags_smm); +} + + /* Checks if a SMRAM mapping is enabled or not. */ int smram_enabled(smram_t *smr) diff --git a/src/nvr_at.c b/src/nvr_at.c index 1942f1c1f..03f3ea6bb 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -292,7 +292,8 @@ #define FLAG_LS_HACK 0x01 #define FLAG_APOLLO_HACK 0x02 -#define FLAG_PIIX4 0x04 +#define FLAG_P6RP4_HACK 0x04 +#define FLAG_PIIX4 0x08 typedef struct { @@ -755,10 +756,31 @@ nvr_read(uint16_t addr, void *priv) ret = checksum >> 8; else ret = checksum & 0xff; + } else if (!nvr->new && (local->flags & FLAG_P6RP4_HACK)) { + /* The checksum at 3E-3F is for 37-3D and 40-51. */ + for (i = 0x37; i <= 0x3d; i++) + checksum += nvr->regs[i]; + for (i = 0x40; i <= 0x51; i++) { + if (i == 0x43) + checksum += (nvr->regs[i] | 0x02); + else + checksum += nvr->regs[i]; + } + if (local->addr[addr_id] == 0x3e) + ret = checksum >> 8; + else + ret = checksum & 0xff; } else ret = nvr->regs[local->addr[addr_id]]; break; + case 0x43: + if (!nvr->new && (local->flags & FLAG_P6RP4_HACK)) + ret = nvr->regs[local->addr[addr_id]] | 0x02; + else + ret = nvr->regs[local->addr[addr_id]]; + break; + case 0x52: if (!nvr->new && (local->flags & FLAG_APOLLO_HACK)) ret = nvr->regs[local->addr[addr_id]] & 0xf3; @@ -972,8 +994,14 @@ nvr_at_init(const device_t *info) local->flags = 0x00; switch(info->local & 7) { case 0: /* standard AT, no century register */ - nvr->irq = 8; - local->cent = 0xff; + if (info->local == 16) { + local->flags |= FLAG_P6RP4_HACK; + nvr->irq = 8; + local->cent = RTC_CENTURY_AT; + } else { + nvr->irq = 8; + local->cent = 0xff; + } break; case 1: /* standard AT */ @@ -1162,3 +1190,12 @@ const device_t via_nvr_device = { { NULL }, nvr_at_speed_changed, NULL }; + +const device_t p6rp4_nvr_device = { + "ASUS P/I-P6RP4 PC/AT NVRAM", + DEVICE_ISA | DEVICE_AT, + 16, + nvr_at_init, nvr_at_close, nvr_at_reset, + { NULL }, nvr_at_speed_changed, + NULL +}; diff --git a/src/pci.c b/src/pci.c index 37c9976a5..fc6e1e75e 100644 --- a/src/pci.c +++ b/src/pci.c @@ -150,6 +150,80 @@ pci_write(uint16_t port, uint8_t val, void *priv) } +static void +pci_writew(uint16_t port, uint16_t val, void *priv) +{ + uint8_t slot = 0; + + if (in_smm) + pci_log("(%i) %03x write: %02X\n", pci_enable, port, val); + + switch (port) { + case 0xcfc: case 0xcfe: + if (! pci_enable) + return; + + pci_log("Writing %04X to PCI card on bus %i, slot %02X (pci_cards[%i]) (%02X:%02X)...\n", val, pci_bus, pci_card, slot, pci_func, pci_index | (port & 3)); + slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; + if (slot != 0xff) { + if (pci_cards[slot].write) { + pci_log("Writing to PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); + pci_cards[slot].write(pci_func, pci_index | (port & 3), val & 0xff, pci_cards[slot].priv); + pci_cards[slot].write(pci_func, pci_index | (port & 3) | 1, val >> 8, pci_cards[slot].priv); + } +#ifdef ENABLE_PCI_LOG + else + pci_log("Writing to empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); +#endif + } +#ifdef ENABLE_PCI_LOG + else + pci_log("Writing to unassigned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); +#endif + + break; + } +} + + +static void +pci_writel(uint16_t port, uint32_t val, void *priv) +{ + uint8_t slot = 0; + + if (in_smm) + pci_log("(%i) %03x write: %02X\n", pci_enable, port, val); + + switch (port) { + case 0xcfc: + if (! pci_enable) + return; + + pci_log("Writing %08X to PCI card on bus %i, slot %02X (pci_cards[%i]) (%02X:%02X)...\n", val, pci_bus, pci_card, slot, pci_func, pci_index | (port & 3)); + slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; + if (slot != 0xff) { + if (pci_cards[slot].write) { + pci_log("Writing to PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); + pci_cards[slot].write(pci_func, pci_index | (port & 3), val & 0xff, pci_cards[slot].priv); + pci_cards[slot].write(pci_func, pci_index | (port & 3) | 1, (val >> 8) & 0xff, pci_cards[slot].priv); + pci_cards[slot].write(pci_func, pci_index | (port & 3) | 2, (val >> 16) & 0xff, pci_cards[slot].priv); + pci_cards[slot].write(pci_func, pci_index | (port & 3) | 3, (val >> 24) & 0xff, pci_cards[slot].priv); + } +#ifdef ENABLE_PCI_LOG + else + pci_log("Writing to empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); +#endif + } +#ifdef ENABLE_PCI_LOG + else + pci_log("Writing to unassigned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); +#endif + + break; + } +} + + static uint8_t pci_read(uint16_t port, void *priv) { @@ -185,6 +259,82 @@ pci_read(uint16_t port, void *priv) } +static uint16_t +pci_readw(uint16_t port, void *priv) +{ + uint8_t slot = 0; + uint16_t ret = 0xffff; + + if (in_smm) + pci_log("(%i) %03x read\n", pci_enable, port); + + switch (port) { + case 0xcfc: case 0xcfe: + if (! pci_enable) + return 0xff; + + slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; + if (slot != 0xff) { + if (pci_cards[slot].read) { + ret = pci_cards[slot].read(pci_func, pci_index | (port & 3), pci_cards[slot].priv); + ret |= (pci_cards[slot].read(pci_func, pci_index | (port & 3) | 1, pci_cards[slot].priv) << 8); + } +#ifdef ENABLE_PCI_LOG + else + pci_log("Reading from empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); +#endif + } +#ifdef ENABLE_PCI_LOG + else + pci_log("Reading from unasisgned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); +#endif + } + + pci_log("Reading %04X, from PCI card on bus %i, slot %02X (pci_cards[%i]) (%02X:%02X)...\n", ret, pci_bus, pci_card, slot, pci_func, pci_index | (port & 3)); + + return ret; +} + + +static uint32_t +pci_readl(uint16_t port, void *priv) +{ + uint8_t slot = 0; + uint32_t ret = 0xffffffff; + + if (in_smm) + pci_log("(%i) %03x read\n", pci_enable, port); + + switch (port) { + case 0xcfc: case 0xcfe: + if (! pci_enable) + return 0xff; + + slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; + if (slot != 0xff) { + if (pci_cards[slot].read) { + ret = pci_cards[slot].read(pci_func, pci_index | (port & 3), pci_cards[slot].priv); + ret |= (pci_cards[slot].read(pci_func, pci_index | (port & 3) | 1, pci_cards[slot].priv) << 8); + ret |= (pci_cards[slot].read(pci_func, pci_index | (port & 3) | 2, pci_cards[slot].priv) << 16); + ret |= (pci_cards[slot].read(pci_func, pci_index | (port & 3) | 3, pci_cards[slot].priv) << 24); + } +#ifdef ENABLE_PCI_LOG + else + pci_log("Reading from empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); +#endif + } +#ifdef ENABLE_PCI_LOG + else + pci_log("Reading from unasisgned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); +#endif + } + + pci_log("Reading %08X, from PCI card on bus %i, slot %02X (pci_cards[%i]) (%02X:%02X)...\n", ret, pci_bus, pci_card, slot, pci_func, pci_index | (port & 3)); + + return ret; +} + + static void pci_type2_write(uint16_t port, uint8_t val, void *priv); static uint8_t pci_type2_read(uint16_t port, void *priv); @@ -803,7 +953,7 @@ pci_init(int type) io_sethandler(0x0cf8, 1, NULL,NULL,pci_cf8_read, NULL,NULL,pci_cf8_write, NULL); io_sethandler(0x0cfc, 4, - pci_read,NULL,NULL, pci_write,NULL,NULL, NULL); + pci_read,pci_readw,pci_readl, pci_write,pci_writew,pci_writel, NULL); pci_pmc = 1; } else { io_sethandler(0x0cf8, 1, diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index ce9b9852c..a69413596 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -160,6 +160,7 @@ static uint64_t scsi_cdrom_mode_sense_page_flags = (GPMODEP_R_W_ERROR_PAGE | GPMODEP_DISCONNECT_PAGE | GPMODEP_CDROM_PAGE | GPMODEP_CDROM_AUDIO_PAGE | + (1ULL << 0x0fULL) | GPMODEP_CAPABILITIES_PAGE | GPMODEP_ALL_PAGES); @@ -180,7 +181,7 @@ static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_default = { 0, 0 }, { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, { 0x8E, 0xE, 4, 0, 0, 0, 0, 75, 1, 255, 2, 255, 0, 0, 0, 0 }, - { 0, 0 }, + { 0x0F, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, @@ -227,7 +228,7 @@ static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_default_scsi = { 0, 0 }, { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, { 0x8E, 0xE, 5, 4, 0,128, 0, 75, 1, 255, 2, 255, 0, 0, 0, 0 }, - { 0, 0 }, + { 0x0F, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, @@ -261,7 +262,7 @@ static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_changeable = { { { 0, 0 }, { GPMODE_R_W_ERROR_PAGE, 6, 0xFF, 0xFF, 0, 0, 0, 0 }, - { GPMODE_DISCONNECT_PAGE, 0x0e, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }, + { GPMODE_DISCONNECT_PAGE, 0x0E, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, @@ -274,7 +275,7 @@ static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_changeable = { 0, 0 }, { GPMODE_CDROM_PAGE, 6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, { 0x8E, 0xE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0, 0 }, + { 0x0F, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index b7680640f..068562028 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -45,9 +45,6 @@ ifeq ($(DEV_BUILD), y) ifndef HEDAKA HEDAKA := y endif - ifndef I450KX - I450KX := y - endif ifndef LASERXT LASERXT := y endif @@ -109,9 +106,6 @@ else ifndef HEDAKA HEDAKA := n endif - ifndef I450KX - I450KX := n - endif ifndef LASERXT LASERXT := n endif @@ -501,11 +495,6 @@ ifeq ($(HEDAKA), y) OPTS += -DUSE_HEDAKA endif -ifeq ($(I450KX), y) -OPTS += -DUSE_I450KX -DEVBROBJ += intel_i450kx.o -endif - ifeq ($(LASERXT), y) OPTS += -DUSE_LASERXT DEVBROBJ += m_xt_laserxt.o @@ -593,7 +582,8 @@ CHIPSETOBJ := 82c100.o acc2168.o \ cs4031.o cs8230.o \ ali1429.o ali1489.o ali1531.o ali1541.o ali1543.o ali1621.o ali6117.o \ gc100.o headland.o \ - ims8848.o intel_82335.o intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \ + ims8848.o intel_82335.o intel_420ex.o intel_4x0.o intel_i450kx.o intel_sio.o intel_piix.o \ + ioapic.o \ neat.o \ opti283.o opti291.o opti391.o opti495.o opti822.o opti895.o opti5x7.o \ scamp.o scat.o \ @@ -674,7 +664,8 @@ HDDOBJ := hdd.o \ hdc_esdi_at.o hdc_esdi_mca.o \ hdc_xtide.o hdc_ide.o \ hdc_ide_opti611.o \ - hdc_ide_cmd640.o hdc_ide_sff8038i.o + hdc_ide_cmd640.o hdc_ide_cmd646.o \ + hdc_ide_sff8038i.o MINIVHDOBJ := cwalk.o libxml2_encoding.o minivhd_convert.o \ minivhd_create.o minivhd_io.o minivhd_manage.o \ From b0fe3d8f0f3eb9a4b60322db9030713dca13a496 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 26 Oct 2021 20:00:01 +0200 Subject: [PATCH 92/96] Removed the Epson Action Tower 3000. --- src/machine/machine_table.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 0f2479961..a5c9732cf 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -398,8 +398,6 @@ const machine_t machines[] = { { "[SiS 471] DTK PKM-0038S E-2", "dtk486", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_dtk486_init, NULL }, /* Unknown Epox VLB Socket 3 board, has AMIKey F keyboard BIOS. */ { "[SiS 471] Epox 486SX/DX Green", "ami471", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_ami471_init, NULL }, - /* Has an Intel 82C42PE with Phoenix MultiKey KBC firmware. */ - { "[UMC 491/493] Epson Action Tower 3000", "actiontower3000", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL, 1024, 262144, 1024, 255, machine_at_actiontower3000_init, NULL }, /* 486 machines which utilize the PCI bus */ /* This has an AMIKey-2, which is an updated version of type 'H'. */ From 758d8acb63bf5bf9d41c66fc00ee4ec35dfa358e Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 13 Nov 2021 22:57:01 +0100 Subject: [PATCH 93/96] Temporarily reverted all keyboard changes. --- src/device/kbc_at.c | 2324 ------------------------------- src/device/kbd_at.c | 1162 ---------------- src/device/keyboard_at.c | 2834 ++++++++++++++------------------------ src/device/mouse_ps2.c | 55 +- 4 files changed, 1074 insertions(+), 5301 deletions(-) delete mode 100644 src/device/kbc_at.c delete mode 100644 src/device/kbd_at.c diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c deleted file mode 100644 index bb756f67d..000000000 --- a/src/device/kbc_at.c +++ /dev/null @@ -1,2324 +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. - * - * Intel 8042 (AT keyboard controller) emulation. - * - * - * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * EngiNerd - * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2020 EngiNerd. - */ -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include -#include <86box/86box.h> -#include "cpu.h" -#include <86box/timer.h> -#include <86box/io.h> -#include <86box/pic.h> -#include <86box/pit.h> -#include <86box/ppi.h> -#include <86box/mem.h> -#include <86box/device.h> -#include <86box/machine.h> -#include <86box/m_xt_xi8088.h> -#include <86box/m_at_t3100e.h> -#include <86box/fdd.h> -#include <86box/fdc.h> -#include <86box/sound.h> -#include <86box/snd_speaker.h> -#include <86box/video.h> -#include <86box/keyboard.h> - - -#define STAT_PARITY 0x80 -#define STAT_RTIMEOUT 0x40 -#define STAT_TTIMEOUT 0x20 -#define STAT_MFULL 0x20 -#define STAT_UNLOCKED 0x10 -#define STAT_CD 0x08 -#define STAT_SYSFLAG 0x04 -#define STAT_IFULL 0x02 -#define STAT_OFULL 0x01 - -#define RESET_DELAY_TIME 1000 /* 100 ms */ - -#define CCB_UNUSED 0x80 -#define CCB_TRANSLATE 0x40 -#define CCB_PCMODE 0x20 -#define CCB_ENABLEKBD 0x10 -#define CCB_IGNORELOCK 0x08 -#define CCB_SYSTEM 0x04 -#define CCB_ENABLEMINT 0x02 -#define CCB_ENABLEKINT 0x01 - -#define CCB_MASK 0x68 -#define MODE_MASK 0x6c - -#define KBC_TYPE_ISA 0x00 /* AT ISA-based chips */ -#define KBC_TYPE_PS2_1 0x04 /* PS2 type, no refresh */ -/* This only differs in that translation is forced off. */ -#define KBC_TYPE_PS2_2 0x05 /* PS2 on PS/2, type 2 */ -#define KBC_TYPE_MASK 0x07 - -#define KBC_FLAG_PS2 0x04 - -/* We need to redefine this: - Currently, we use bits 3-7 for vendor, we should instead use bits 4-7 - for vendor, 0-3 for revision/variant, and have a dev->ps2 flag controlling - controller mode, normally set according to the flags, but togglable on - AMIKey: - 0000 0000 0x00 IBM, AT - 0000 0001 0x01 MR - 0000 0010 0x02 Xi8088, clone of IBM PS/2 type 1 - 0001 0000 0x10 Olivetti - 0010 0000 0x20 Toshiba - 0011 0000 0x30 Quadtel - 0100 0000 0x40 Phoenix MultiKey/42 - 0101 0000 0x50 AMI KF - 0101 0001 0x51 AMI KH - 0101 0010 0x52 AMIKey - 0101 0011 0x53 AMIKey-2 - 0101 0100 0x54 JetKey (clone of AMI KF/AMIKey) - 0110 0000 0x60 Award - 0110 0001 0x61 Award 286 (has some AMI commands apparently) - 0111 0000 0x70 Siemens -*/ - -/* Standard IBM controller */ -#define KBC_VEN_GENERIC 0x00 -/* All commands are standard PS/2 */ -#define KBC_VEN_IBM_MCA 0x08 -/* Standard IBM commands, differs in input port bits */ -#define KBC_VEN_IBM_PS1 0x10 -/* Olivetti - proprietary commands and port 62h with switches - readout */ -#define KBC_VEN_OLIVETTI 0x20 -/* Toshiba T3100e - has a bunch of proprietary commands, also sets - IFULL on command AA */ -#define KBC_VEN_TOSHIBA 0x28 -/* Standard IBM commands, uses input port as a switches readout */ -#define KBC_VEN_NCR 0x30 -/* Xi8088 - standard IBM commands, has a turbo bit on port 61h, and the - polarity of the video type bit in the input port is inverted */ -#define KBC_VEN_XI8088 0x38 -/* QuadtelKey - currently guesswork */ -#define KBC_VEN_QUADTEL 0x40 -/* Phoenix MultiKey/42 - not yet implemented */ -#define KBC_VEN_PHOENIX 0x48 -/* Generic commands, XI8088-like input port handling of video type, - maybe we just need a flag for that? */ -#define KBC_VEN_ACER 0x50 -/* AMI KF/KH/AMIKey/AMIKey-2 */ -#define KBC_VEN_AMI 0xf0 -/* Standard AMI commands, differs in input port bits */ -#define KBC_VEN_INTEL_AMI 0xf8 -#define KBC_VEN_MASK 0xf8 - - -/* Flags should be fully 32-bit: - Bits 7- 0: Vendor and revision/variant; - Bits 15- 8: Input port mask; - Bits 23-16: Input port bits that are always on; - Bits 31-24: Flags: - Bit 0: Invert P1 video type bit polarity; - Bit 1: Is PS/2; - Bit 2: Translation forced always off. - - So for example, the IBM PS/2 type 1 controller flags would be: 00000010 00000000 11111111 00000000 = 0200ff00 . */ - - -typedef struct { - uint8_t *c_in, *c_data, /* Data to controller */ - *d_in, *d_data, /* Data to device */ - *inhibit; - - void (*process)(void *priv); - void *priv; -} kbc_dev_t; - -typedef struct { - uint8_t status, ib, ob, p1, p2, old_p2, p2_locked, fast_a20_phase, - secr_phase, mem_index, ami_stat, ami_mode, - kbc_in, kbc_cmd, kbc_in_cmd, kbc_poll_phase, kbc_to_send, - kbc_send_pending, kbc_channel, kbc_stat_hi, kbc_wait_for_response, inhibit; - - uint8_t mem_int[0x40], mem[0x240]; - - uint16_t last_irq, kbc_phase; - - uint32_t flags; - - kbc_dev_t * kbc_devs[2]; - - pc_timer_t pulse_cb, send_delay_timer; - - uint8_t (*write60_ven)(void *p, uint8_t val); - uint8_t (*write64_ven)(void *p, uint8_t val); - - void * log; -} atkbc_t; - - -enum -{ - CHANNEL_KBC = 0, - CHANNEL_KBD, - CHANNEL_MOUSE -}; - -enum -{ - KBD_MAIN_LOOP = 0, - KBD_CMD_PROCESS -}; - -enum -{ - MOUSE_MAIN_LOOP_1 = 0, - MOUSE_CMD_PROCESS, - MOUSE_CMD_END, - MOUSE_MAIN_LOOP_2 -}; - -enum { - KBC_MAIN_LOOP = 0, - KBC_RESET = 1, - KBC_WAIT = 4, - KBC_WAIT_FOR_KBD, - KBC_WAIT_FOR_MOUSE, - KBC_WAIT_FOR_BOTH -}; - - -static void kbc_wait(atkbc_t *dev, uint8_t flags); - - -/* Bits 0 - 1 = scan code set, bit 6 = translate or not. */ -uint8_t keyboard_mode = 0x42; - -uint8_t * ami_copr = (uint8_t *) "(C)1994 AMI"; - - -uint8_t mouse_queue[16]; -int mouse_queue_start = 0, mouse_queue_end = 0; -static void (*mouse_write)(uint8_t val, void *priv) = NULL; -static void *mouse_p = NULL; -static uint8_t sc_or = 0; -static atkbc_t *saved_kbc = NULL; - - -/* Non-translated to translated scan codes. */ -static const uint8_t nont_to_t[256] = { - 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58, - 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59, - 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a, - 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b, - 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c, - 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d, - 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e, - 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f, - 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60, - 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61, - 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e, - 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76, - 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b, - 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f, - 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45, - 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54, - 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff -}; - - -#define UISTR_LEN 256 -static char kbc_str[UISTR_LEN]; /* UI output string */ - - -extern void ui_sb_bugui(char *__str); - - -static void -kbc_status(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vsprintf(kbc_str, fmt, ap); - ui_sb_bugui(kbc_str); - va_end(ap); -} - - -#define ENABLE_KBC_AT_LOG 1 -#if (!defined(RELEASE_BUILD) && defined(ENABLE_KBC_AT_LOG)) -int kbc_at_do_log = ENABLE_KBC_AT_LOG; - - -static void -kbc_log(atkbc_t *dev, const char *fmt, ...) -{ - va_list ap; - - if ((dev == NULL) || (dev->log == NULL)) - return; - - if (kbc_at_do_log) { - va_start(ap, fmt); - log_out(dev->log, fmt, ap); - va_end(ap); - } -} -#else -#define kbc_log(dev, fmt, ...) -#endif - - -static void -kbc_send_to_ob(atkbc_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) -{ - uint8_t ch = (channel > 0) ? channel : 1; - uint8_t do_irq = (dev->mem[0x20] & ch); - int translate = (channel == 1) && (keyboard_mode & 0x60); - - if ((channel == 2) && !(dev->flags & KBC_FLAG_PS2)) - return; - - stat_hi |= dev->inhibit; - - if (!dev->kbc_send_pending) { - dev->kbc_send_pending = 1; - dev->kbc_to_send = val; - dev->kbc_channel = channel; - dev->kbc_stat_hi = stat_hi; - return; - } - - if (translate) { - /* Allow for scan code translation. */ - if (val == 0xf0) { - kbc_log(dev, "Translate is on, F0 prefix detected\n"); - sc_or = 0x80; - return; - } - - /* Skip break code if translated make code has bit 7 set. */ - if ((sc_or == 0x80) && (val & 0x80)) { - kbc_log(dev, "Translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val); - sc_or = 0; - return; - } - } - - dev->last_irq = (ch == 2) ? 0x1000 : 0x0002; - if (do_irq) { - kbc_log(dev, "[%04X:%08X] IRQ %i\n", CS, cpu_state.pc, (ch == 2) ? 12 : 1); - picint(dev->last_irq); - } - kbc_log(dev, "%02X coming from channel %i (%i)\n", val, channel, do_irq); - dev->ob = translate ? (nont_to_t[val] | sc_or) : val; - - dev->status = (dev->status & 0x0f) | (stat_hi | (dev->mem[0x20] & STAT_SYSFLAG) | STAT_OFULL); - if (ch == 2) - dev->status |= STAT_MFULL; - - if (translate && (sc_or == 0x80)) - sc_or = 0; -} - - -static void -write_output(atkbc_t *dev, uint8_t val) -{ - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - kbc_log(dev, "Write output port: %02X (old: %02X)\n", val, dev->p2); - - if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) - val |= ((dev->mem[0x20] << 4) & 0x30); - - dev->kbc_devs[0]->inhibit = (val & 0x40); - dev->kbc_devs[1]->inhibit = (val & 0x08); - - if ((dev->p2 ^ val) & 0x20) { /*IRQ 12*/ - if (val & 0x20) { - kbc_log(dev, "write_output(): IRQ 12\n"); - picint(1 << 12); - } else - picintc(1 << 12); - } - if ((dev->p2 ^ val) & 0x10) { /*IRQ 1*/ - if (val & 0x10) { - kbc_log(dev, "write_output(): IRQ 1\n"); - picint(1 << 1); - } else - picintc(1 << 1); - } - if ((dev->p2 ^ val) & 0x02) { /*A20 enable change*/ - mem_a20_key = val & 0x02; - mem_a20_recalc(); - flushmmucache(); - } - if ((dev->p2 ^ val) & 0x01) { /*Reset*/ - if (! (val & 0x01)) { - /* Pin 0 selected. */ - softresetx86(); /*Pulse reset!*/ - cpu_set_edx(); - smbase = is_am486dxl ? 0x00060000 : 0x00030000; - } - } - /* Mask off the A20 stuff because we use mem_a20_key directly for that. */ - dev->p2 = val; -} - - -static void -write_cmd(atkbc_t *dev, uint8_t val) -{ - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - kbc_log(dev, "Write command byte: %02X (old: %02X)\n", val, dev->mem[0x20]); - - /* PS/2 type 2 keyboard controllers always force the XLAT bit to 0. */ - if ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2) - val &= ~CCB_TRANSLATE; - - dev->mem[0x20] = val; - - /* Scan code translate ON/OFF. */ - keyboard_mode &= 0x93; - keyboard_mode |= (val & MODE_MASK); - - kbc_log(dev, "Keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled"); - - /* ISA AT keyboard controllers use bit 5 for keyboard mode (1 = PC/XT, 2 = AT); - PS/2 (and EISA/PCI) keyboard controllers use it as the PS/2 mouse enable switch. - The AMIKEY firmware apparently uses this bit for something else. */ - if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) { - keyboard_mode &= ~CCB_PCMODE; - /* Update the output port to mirror the KBD DIS and AUX DIS bits, if active. */ - write_output(dev, dev->p2); - - kbc_log(dev, "Mouse interrupt is now %s\n", (val & 0x02) ? "enabled" : "disabled"); - } - - kbc_log(dev, "Command byte now: %02X (%02X)\n", dev->mem[0x20], val); - - dev->status = (dev->status & ~STAT_SYSFLAG) | (val & STAT_SYSFLAG); -} - - -static void -pulse_output(atkbc_t *dev, uint8_t mask) -{ - if (mask != 0x0f) { - dev->old_p2 = dev->p2 & ~(0xf0 | mask); - kbc_log(dev, "pulse_output(): Output port now: %02X\n", dev->p2 & (0xf0 | mask | (dev->mem[0x20] & 0x30))); - write_output(dev, dev->p2 & (0xf0 | mask | (dev->mem[0x20] & 0x30))); - timer_set_delay_u64(&dev->pulse_cb, 6ULL * TIMER_USEC); - } -} - - -static void -set_enable_kbd(atkbc_t *dev, uint8_t enable) -{ - dev->mem[0x20] &= 0xef; - dev->mem[0x20] |= (enable ? 0x00 : 0x10); -} - - -static void -set_enable_mouse(atkbc_t *dev, uint8_t enable) -{ - dev->mem[0x20] &= 0xdf; - dev->mem[0x20] |= (enable ? 0x00 : 0x20); -} - - -static void -kbc_transmit(atkbc_t *dev, uint8_t val) -{ - kbc_send_to_ob(dev, val, 0, 0x00); -} - - -static void -kbc_command(atkbc_t *dev) -{ - uint8_t mask, val = dev->ib; - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - int bad = 1; - - if ((dev->kbc_phase > 0) && (dev->kbc_cmd == 0xac)) { - if (dev-> kbc_phase < 16) - kbc_transmit(dev, dev->mem[dev->kbc_phase]); - else if (dev-> kbc_phase == 16) - kbc_transmit(dev, (dev->p1 & 0xf0) | 0x80); - else if (dev-> kbc_phase == 17) - kbc_transmit(dev, dev->p2); - else if (dev-> kbc_phase == 18) - kbc_transmit(dev, dev->status); - - dev->kbc_phase++; - if (dev->kbc_phase == 19) { - dev->kbc_phase = 0; - dev->kbc_cmd = 0x00; - } - return; - } else if ((dev->kbc_phase > 0) && (dev->kbc_cmd == 0xa0) && (kbc_ven >= KBC_VEN_AMI)) { - val = ami_copr[dev->kbc_phase]; - kbc_transmit(dev, val); - if (val == 0x00) { - dev->kbc_phase = 0; - dev->kbc_cmd = 0x00; - } else - dev->kbc_phase++; - return; - } else if ((dev->kbc_in > 0) && (dev->kbc_cmd == 0xa5) && (dev->flags & KBC_FLAG_PS2)) { - /* load security */ - kbc_log(dev, "Load security\n"); - dev->mem[0x50 + dev->kbc_in - 0x01] = val; - if ((dev->kbc_in == 0x80) && (val != 0x00)) { - /* Security string too long, set it to 0x00. */ - dev->mem[0x50] = 0x00; - dev->kbc_in = 0; - dev->kbc_cmd = 0; - } else if (val == 0x00) { - /* Security string finished. */ - dev->kbc_in = 0; - dev->kbc_cmd = 0; - } else /* Increase pointer and request another byte. */ - dev->kbc_in++; - return; - } - - /* If the written port is 64, go straight to the beginning of the command. */ - if (!(dev->status & STAT_CD) && dev->kbc_in) { - /* Write data to controller. */ - dev->kbc_in = 0; - dev->kbc_phase = 0; - - switch (dev->kbc_cmd) { - case 0x60 ... 0x7f: - if (dev->kbc_cmd == 0x60) - write_cmd(dev, val); - else - dev->mem[(dev->kbc_cmd & 0x1f) + 0x20] = val; - break; - - case 0xc7: /* or input port with system data */ - dev->p1 |= val; - break; - - case 0xcb: /* set keyboard mode */ - kbc_log(dev, "New AMIKey mode: %02X\n", val); - dev->ami_mode = val; - dev->flags &= ~KBC_FLAG_PS2; - if (val & 1) - dev->flags |= KBC_FLAG_PS2; -#if (!defined(RELEASE_BUILD) && defined(ENABLE_KBD_AT_LOG)) - log_set_dev_name(dev->kbc_log, (dev->flags & KBC_FLAG_PS2) ? "AT KBC" : "PS/2 KBC"); -#endif - break; - - case 0xd1: /* write output port */ - if (dev->p2_locked) { - /*If keyboard controller lines P22-P23 are blocked, - we force them to remain unchanged.*/ - val &= ~0x0c; - val |= (dev->p2 & 0x0c); - } - kbc_log(dev, "Write %02X to output port\n", val); - write_output(dev, val); - break; - - case 0xd2: /* write to keyboard output buffer */ - kbc_log(dev, "Write %02X to keyboard output buffer\n", val); - /* Should be channel 1, but we send to 0 to avoid translation, - since bytes output using this command do *NOT* get translated. */ - kbc_send_to_ob(dev, val, 0, 0x00); - break; - - case 0xd3: /* write to mouse output buffer */ - kbc_log(dev, "Write %02X to mouse output buffer\n", val); - if (dev->flags & KBC_FLAG_PS2) - kbc_send_to_ob(dev, val, 2, 0x00); - break; - - case 0xd4: /* write to mouse */ - kbc_log(dev, "Write %02X to mouse\n", val); - - if (dev->flags & KBC_FLAG_PS2) { - set_enable_mouse(dev, 1); - dev->mem[0x20] &= ~0x20; - if (dev->kbc_devs[1] && !dev->kbc_devs[1]->c_in) { - kbc_log(dev, "Transmitting %02X to mouse...\n", dev->ib); - dev->kbc_devs[1]->d_data = val; - dev->kbc_devs[1]->d_in = 1; - dev->kbc_wait_for_response = 2; - } else - kbc_send_to_ob(dev, 0xfe, 2, 0x40); - } - break; - - default: - /* - * Run the vendor-specific handler - * if we have one. Otherwise, or if - * it returns an error, log a bad - * controller command. - */ - if (dev->write60_ven) - bad = dev->write60_ven(dev, val); - - if (bad) - kbc_log(dev, "Bad controller command %02x data %02x\n", dev->kbc_cmd, val); - } - } else { - /* Controller command. */ - kbc_log(dev, "Controller command: %02X\n", val); - dev->kbc_in = 0; - dev->kbc_phase = 0; - - switch (val) { - /* Read data from KBC memory. */ - case 0x20 ... 0x3f: - kbc_transmit(dev, dev->mem[(val & 0x1f) + 0x20]); - break; - - /* Write data to KBC memory. */ - case 0x60 ... 0x7f: - dev->kbc_in = 1; - break; - - case 0xaa: /* self-test */ - kbc_log(dev, "Self-test\n"); - write_output(dev, (dev->flags & KBC_FLAG_PS2) ? 0x4b : 0xcf); - - /* Always reinitialize all queues - the real hardware pulls keyboard and mouse - clocks high, which stops keyboard scanning. */ - dev->in_cmd = dev->mouse_in_cmd = 0; - dev->status &= ~STAT_OFULL; - dev->last_irq = 0; - dev->kbc_phase = 0; - - /* Phoenix MultiKey should have 0x60 | STAT_SYSFLAG. */ - if (dev->flags & KBC_FLAG_PS2) - write_cmd(dev, 0x30 | STAT_SYSFLAG); - else - write_cmd(dev, 0x10 | STAT_SYSFLAG); - kbc_transmit(dev, 0x55); - break; - - case 0xab: /* interface test */ - kbc_log(dev, "Interface test\n"); - /* No error. */ - kbc_transmit(dev, 0x00); - break; - - case 0xac: /* diagnostic dump */ - kbc_log(dev, "Diagnostic dump\n"); - kbc_transmit(dev, dev->mem[0x20]); - dev->kbc_phase = 1; - break; - - case 0xad: /* disable keyboard */ - kbc_log(dev, "Disable keyboard\n"); - set_enable_kbd(dev, 0); - break; - - case 0xae: /* enable keyboard */ - kbc_log(dev, "Enable keyboard\n"); - set_enable_kbd(dev, 1); - break; - - case 0xc7: /* or input port with system data */ - kbc_log(dev, "Phoenix - or input port with system data\n"); - dev->kbc_in = 1; - break; - - case 0xca: /* read keyboard mode */ - kbc_log(dev, "AMI - Read keyboard mode\n"); - kbc_transmit(dev, dev->ami_mode); - break; - - case 0xcb: /* set keyboard mode */ - kbc_log(dev, "ATkbc: AMI - Set keyboard mode\n"); - dev->kbc_in = 1; - break; - - case 0xd0: /* read output port */ - kbc_log(dev, "Read output port\n"); - mask = 0xff; - if (dev->mem[0x20] & 0x10) - mask &= 0xbf; - if ((dev->flags & KBC_FLAG_PS2) && (dev->mem[0x20] & 0x20)) - mask &= 0xf7; - kbc_transmit(dev, dev->p2 & mask); - break; - - case 0xd1: /* write output port */ - kbc_log(dev, "Write output port\n"); - dev->kbc_in = 1; - break; - - case 0xd2: /* write keyboard output buffer */ - kbc_log(dev, "Write keyboard output buffer\n"); - if (dev->flags & KBC_FLAG_PS2) - dev->kbc_in = 1; - else - kbc_transmit(dev, 0x00); /* NCR */ - break; - - case 0xdd: /* disable A20 address line */ - case 0xdf: /* enable A20 address line */ - kbc_log(dev, "%sable A20\n", (val == 0xdd) ? "Dis": "En"); - write_output(dev, (dev->p2 & 0xfd) | (val & 0x02)); - break; - - case 0xe0: /* read test inputs */ - kbc_log(dev, "Read test inputs\n"); - kbc_transmit(dev, 0x00); - break; - - default: - /* - * Unrecognized controller command. - * - * If we have a vendor-specific handler, run - * that. Otherwise, or if that handler fails, - * log a bad command. - */ - if (dev->write64_ven) - bad = dev->write64_ven(dev, val); - - if (bad) - kbc_log(dev, "Bad controller command %02X\n", val); - } - - /* If the command needs data, remember the command. */ - if (dev->kbc_in || (dev->kbc_phase > 0)) - dev->kbc_cmd = val; - } -} - - -static void -kbc_dev_data_to_ob(atkbc_t *dev, uint8_t channel) -{ - if (channel == 0) - return; - - dev->kbc_devs[channel - 1]->c_in = 0; - kbc_log(dev, "Forwarding %02X from channel %i...\n", dev->kbc_devs[channel - 1]->c_data, channel); - kbc_send_to_ob(dev, dev->kbc_devs[channel - 1]->c_data, channel, 0x00); -} - - -static void -kbc_main_loop_scan(atkbc_t *dev) -{ - uint8_t port_dis = dev->mem[0x20] & 0x30; - uint8_t ps2 = (dev->flags & KBC_FLAG_PS2); - - if (!ps2) - port_dis |= 0x20; - - if (!(dev->status & STAT_OFULL)) { - if (port_dis & 0x20) { - if (!(port_dis & 0x10)) { - kbc_log(dev, "kbc_process(): Main loop, Scan: AUX DIS, KBD EN\n"); - /* Enable communication with keyboard. */ - dev->p2 &= 0xbf; - dev->kbc_devs[0]->inhibit = 0; - kbc_wait(dev, 1); - } else - kbc_log(dev, "kbc_process(): Main loop, Scan: AUX DIS, KBD DIS\n"); - } else { - /* Enable communication with mouse. */ - dev->p2 &= 0xf7; - dev->kbc_devs[1]->inhibit = 0; - if (dev->mem[0x20] & 0x10) { - kbc_log(dev, "kbc_process(): Main loop, Scan: AUX EN , KBD DIS\n"); - kbc_wait(dev, 2); - } else { - /* Enable communication with keyboard. */ - kbc_log(dev, "kbc_process(): Main loop, Scan: AUX EN , KBD EN\n"); - dev->p2 &= 0xbf; - dev->kbc_devs[0]->inhibit = 0; - kbc_wait(dev, 3); - } - } - } else - kbc_log(dev, "kbc_process(): Main loop, Scan: IBF not full and OBF full, do nothing\n"); -} - - -static uint8_t -kbc_reset_cmd(atkbc_t *dev) -{ - uint8_t ret = 0; - - if ((dev->status & STAT_CD) || (dev->kbc_poll_phase == KBC_WAIT_FOR_NOBF)) { - kbc_log(dev, " Resetting command\n"); - dev->kbc_phase = 0; - dev->kbc_in = 0; - dev->kbc_in_cmd = 0; - dev->kbc_poll_phase = KBC_MAIN_LOOP; - ret = 1; - } - - return ret; -} - - -static uint8_t -kbc_process_cmd(atkbdt_t *dev, uint8_t restart) -{ - uint8_t ret = 0; - - if (restart) - dev->kbc_in_cmd = 1; - kbc_command(dev); - - if ((dev->kbc_phase == 0) && !dev->kbc_in) - dev->kbc_in_cmd = 0; - else - ret = 1; - - dev->kbc_poll_phase = KBC_MAIN_LOOP; - if (!dev->kbc_wait_for_response && !(dev->status & STAT_OFULL)) - kbc_main_loop_scan(dev); - - return ret; -} - - -static void -kbc_process_ib(atkbc_t *dev) -{ - if ((dev->status & STAT_CD) || (kbc->flags & KBC_FLAG_PS2) || !(dev->status & STAT_OFULL)) - dev->status &= ~STAT_IFULL; - - if (dev->status & STAT_CD) - (void) kbc_process_cmd(dev, 1); - else if ((kbc->flags & KBC_FLAG_PS2) || !(dev->status & STAT_OFULL)) - /* The AT KBC does *NOT* send data to the keyboard if OBF. */ - set_enable_mouse(dev, 1); - dev->mem[0x20] &= ~0x10; - if (dev->kbc_devs[0] && !dev->kbc_devs[0]->c_in) { - dev->kbc_devs[0]->d_data = val; - dev->kbc_devs[0]->d_in = 1; - dev->kbc_wait_for_response = 1; - } else - kbc_send_to_ob(dev, 0xfe, 1, 0x40); - - dev->kbc_poll_phase = KBC_MAIN_LOOP; - if (!dev->kbc_wait_for_response && !(dev->status & STAT_OFULL)) - kbc_main_loop_scan(dev); - } -} - - -static void -kbc_wait(atkbc_t *dev, uint8_t flags) -{ - if ((flags & 1) && dev->kbc_devs[0]->c_in) { - /* Disable communication with mouse. */ - dev->p2 |= 0x08; - dev->kbc_devs[1]->inhibit = 1; - /* Send keyboard byte to host. */ - kbc_dev_data_to_ob(dev, CHANNEL_KBD); - dev->kbc_poll_phase = KBC_MAIN_LOOP; - } else if ((flags & 2) && dev->kbc_devs[1]->c_in) { - /* Disable communication with keyboard. */ - dev->p2 |= 0x40; - dev->kbc_devs[0]->inhibit = 1; - /* Send mouse byte to host. */ - kbc_dev_data_to_ob(dev, CHANNEL_MOUSE); - dev->kbc_poll_phase = KBC_MAIN_LOOP; - } else if (dev->status & STAT_IFULL) { - /* Disable communication with keyboard and mouse. */ - dev->p2 |= 0x48; - dev->kbc_devs[0]->inhibit = dev->kbc_devs[1]->inhibit = 1; - kbc_process_ib(dev); - } else - dev->kbc_poll_phase = KBC_WAIT | flags; -} - - -/* Controller processing */ -static void -kbc_process(atkbc_t *dev) -{ - /* If we're waiting for the response from the keyboard or mouse, do nothing - until the device has repsonded back. */ - if (dev->kbc_wait_for_response > 0) { - if (dev->kbc_devs[dev->kbc_wait_for_response - 1]->c_in) - dev->kbc_wait_for_response = 0; - else - return; - } - - if (dev->kbc_send_pending) { - kbc_log(dev, "Sending delayed %02X on channel %i with high status %02X\n", - dev->kbc_to_send, dev->kbc_channel, dev->kbc_stat_hi); - kbc_send_to_ob(dev, dev->kbc_to_send, dev->kbc_channel, dev->kbc_stat_hi); - dev->kbc_send_pending = 0; - } - - /* Make absolutely sure to do nothing if OBF is full and IBF is empty. */ - if ((dev->kbc_poll_phase == KBC_RESET) || (dev->kbc_poll_phase >= KBC_WAIT_FOR_NIBF) || - !(dev->status & STAT_OFULL) || (dev->status & STAT_IFULL)) switch (dev->kbc_poll_phase) { - case KBC_RESET: - kbc_log(dev, "kbc_process(): Reset loop()\n"); - - if (dev->status & STAT_IFULL) { - dev->status &= ~STAT_IFULL; - - if ((dev->status & STAT_CD) && (dev->ib == 0xaa)) { - (void) kbc_process_cmd(dev, 1); - dev->kbc_poll_phase = KBC_MAIN_LOOP; - } - } - break; - case KBC_MAIN_LOOP: - if (dev->status & STAT_IFULL) { - kbc_log(dev, "kbc_process(): Main loop, IBF full, process\n"); - kbc_process_ib(dev); - } else - kbc_main_loop_scan(dev); - break; - case KBC_SCAN_KBD: - case KBC_SCAN_MOUSE: - case KBC_SCAN_BOTH: - kbc_log(dev, "kbc_process(): Scan: Phase %i\n", dev->kbc_poll_phase); - kbc_wait(dev, dev->kbc_poll_phase & 3); - break; - case KBC_WAIT_FOR_NOBF: - kbc_log(dev, "kbc_process(): Waiting for !OBF\n"); - - if (dev->status & STAT_IFULL) { - /* Host writing a command aborts the current command. */ - (void) !kbc_reset_cmd(dev); - - /* Process the input buffer. */ - kbc_process_ib(dev); - } else if (!dev->status & STAT_OFULL) { - /* Not aborted and OBF cleared - process command. */ - kbc_log(dev, " Continuing commmand\n"); - - if (kbc_process_cmd(dev, 0)) - return; - } - break; - case KBC_WAIT_FOR_IBF: - kbc_log(dev, "kbc_process(): Waiting for IBF\n"); - - if (dev->status & STAT_IFULL) { - /* IBF, process if port 60h, otherwise abort the current command. */ - dev->status &= ~STAT_IFULL; - - if (!kbc_reset_cmd(dev)) - kbc_log(dev, " Continuing commmand\n"); - - /* Process command. */ - if (kbc_process_cmd(dev, 0)) - return; - } - break; - default: - kbc_log(dev, "kbc_process(): Invalid phase %i\n", dev->kbc_poll_phase); - break; - } -} - - -static void -kbd_poll(void *priv) -{ - atkbc_t *dev = (atkbc_t *) priv; - uint8_t i; - - if (dev == NULL) - return; - - timer_advance_u64(&dev->send_delay_timer, (100ULL * TIMER_USEC)); - - /* Device processing */ - for (i = 0; i < 2; i++) { - if (dev->kbc_devs[i] && dev->kbd_devs[i]->priv && dev->kbd_devs[i]->process) - dev->kbc_devs[i]->process(dev->kbc_devs[i]->priv); - } - - /* Controller processing */ - kbc_process(dev); -} - - -static void -pulse_poll(void *priv) -{ - atkbc_t *dev = (atkbc_t *)priv; - - kbc_log(dev, "pulse_poll(): Output port now: %02X\n", dev->p2 | dev->old_p2); - write_output(dev, dev->p2 | dev->old_p2); -} - - -static uint8_t -write64_generic(void *priv, uint8_t val) -{ - atkbc_t *dev = (atkbc_t *)priv; - uint8_t current_drive, fixed_bits; - uint8_t kbc_ven = 0x0; - kbc_ven = dev->flags & KBC_VEN_MASK; - - switch (val) { - case 0xa4: /* check if password installed */ - if (dev->flags & KBC_FLAG_PS2) { - kbc_log(dev, "Check if password installed\n"); - kbc_transmit(dev, (dev->mem[0x50] == 0x00) ? 0xf1 : 0xfa); - return 0; - } - break; - - case 0xa5: /* load security */ - if (dev->flags & KBC_FLAG_PS2) { - kbc_log(dev, "Load security\n"); - dev->kbc_in = 1; - return 0; - } - break; - - case 0xa7: /* disable mouse port */ - if (dev->flags & KBC_FLAG_PS2) { - kbc_log(dev, "Disable mouse port\n"); - return 0; - } - break; - - case 0xa8: /*Enable mouse port*/ - if (dev->flags & KBC_FLAG_PS2) { - kbc_log(dev, "Enable mouse port\n"); - return 0; - } - break; - - case 0xa9: /*Test mouse port*/ - kbc_log(dev, "Test mouse port\n"); - if (dev->flags & KBC_FLAG_PS2) { - /* No error, this is testing the channel 2 interface. */ - kbc_transmit(dev, 0x00); - return 0; - } - break; - - case 0xaf: /* read keyboard version */ - kbc_log(dev, "Read keyboard version\n"); - kbc_transmit(dev, 0x00); - return 0; - - case 0xc0: /* read input port */ - /* IBM PS/1: - Bit 2 and 4 ignored (we return always 0), - Bit 6 must 1 for 5.25" floppy drive, 0 for 3.5". - Intel AMI: - Bit 2 ignored (we return always 1), - Bit 4 must be 1, - Bit 6 must be 1 or else error in SMM. - Acer: - Bit 2 must be 0, - Bit 4 must be 0, - Bit 6 ignored. - P6RP4: - Bit 2 must be 1 or CMOS setup is disabled. */ - kbc_log(dev, "Read input port\n"); - fixed_bits = 4; - /* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */ - if (kbc_ven == KBC_VEN_INTEL_AMI) - fixed_bits |= 0x40; - if (kbc_ven == KBC_VEN_IBM_PS1) { - current_drive = fdc_get_current_drive(); - kbc_transmit(dev, dev->p1 | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00)); - dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc) | (fdd_is_525(current_drive) ? 0x40 : 0x00); - } else if (kbc_ven == KBC_VEN_NCR) { - /* switch settings - * bit 7: keyboard disable - * bit 6: display type (0 color, 1 mono) - * bit 5: power-on default speed (0 high, 1 low) - * bit 4: sense RAM size (0 unsupported, 1 512k on system board) - * bit 3: coprocessor detect - * bit 2: unused - * bit 1: high/auto speed - * bit 0: dma mode - */ - kbc_transmit(dev, (dev->p1 | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf); - dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc); - } else { - if ((dev->flags & KBC_FLAG_PS2) && ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI)) - kbc_transmit(dev, (dev->p1 | fixed_bits) & (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0xeb : 0xef)); - else - kbc_transmit(dev, dev->p1 | fixed_bits); - dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc); - } - return 0; - - case 0xd3: /* write mouse output buffer */ - if (dev->flags & KBC_FLAG_PS2) { - kbc_log(dev, "Write mouse output buffer\n"); - dev->kbc_in = 1; - return 0; - } - break; - - case 0xd4: /* write to mouse */ - kbc_log(dev, "Write to mouse\n"); - dev->kbc_in = 1; - return 0; - - case 0xf0 ... 0xff: - kbc_log(dev, "Pulse %01X\n", val & 0x0f); - pulse_output(dev, val & 0x0f); - return 0; - } - - kbc_log(dev, "Bad command %02X\n", val); - return 1; -} - - -static uint8_t -write60_ami(void *priv, uint8_t val) -{ - atkbc_t *dev = (atkbc_t *)priv; - uint16_t index = 0x00c0; - - switch(dev->kbc_cmd) { - /* 0x40 - 0x5F are aliases for 0x60 - 0x7F */ - case 0x40 ... 0x5f: - kbc_log(dev, "AMI - Alias write to %08X\n", dev->kbc_cmd); - if (dev->kbc_cmd == 0x40) - write_cmd(dev, val); - else - dev->mem[(dev->kbc_cmd & 0x1f) + 0x20] = val; - return 0; - - case 0xaf: /* set extended controller RAM */ - kbc_log(dev, "AMI - Set extended controller RAM, input phase %i\n", dev->secr_phase); - if (dev->secr_phase == 0) { - dev->mem_index = val; - dev->kbc_in = 1; - dev->secr_phase++; - } else if (dev->secr_phase == 1) { - if (dev->mem_index == 0x20) - write_cmd(dev, val); - else - dev->mem[dev->mem_index] = val; - dev->secr_phase = 0; - } - return 0; - - case 0xb8: - kbc_log(dev, "AMIKey-3 - Memory index %02X\n", val); - dev->mem_index = val; - return 0; - - case 0xbb: - kbc_log(dev, "AMIKey-3 - write %02X to memory index %02X\n", val, dev->mem_index); - if (dev->mem_index >= 0x80) { - switch (dev->mem[0x9b] & 0xc0) { - case 0x00: - index = 0x0080; - break; - case 0x40: case 0x80: - index = 0x0000; - break; - case 0xc0: - index = 0x0100; - break; - } - dev->mem[index + dev->mem_index] = val; - } else if (dev->mem_index == 0x60) - write_cmd(dev, val); - else if (dev->mem_index == 0x42) - dev->status = val; - else if (dev->mem_index >= 0x40) - dev->mem[dev->mem_index - 0x40] = val; - else - dev->mem_int[dev->mem_index] = val; - return 0; - - case 0xbd: - kbc_log(dev, "AMIKey-3 - write %02X to config index %02X\n", val, dev->mem_index); - switch (dev->mem_index) { - case 0x00: /* STAT8042 */ - dev->status = val; - break; - case 0x01: /* Password_ptr */ - dev->mem[0x1c] = val; - break; - case 0x02: /* Wakeup_Tsk_Reg */ - dev->mem[0x1e] = val; - break; - case 0x03: /* CCB */ - write_cmd(dev, val); - break; - case 0x04: /* Debounce_time */ - dev->mem[0x4d] = val; - break; - case 0x05: /* Pulse_Width */ - dev->mem[0x4e] = val; - break; - case 0x06: /* Pk_sel_byte */ - dev->mem[0x4c] = val; - break; - case 0x07: /* Func_Tsk_Reg */ - dev->mem[0x7e] = val; - break; - case 0x08: /* TypematicRate */ - dev->mem[0x80] = val; - break; - case 0x09: /* Led_Flag_Byte */ - dev->mem[0x81] = val; - break; - case 0x0a: /* Kbms_Command_St */ - dev->mem[0x87] = val; - break; - case 0x0b: /* Delay_Count_Byte */ - dev->mem[0x86] = val; - break; - case 0x0c: /* KBC_Flags */ - dev->mem[0x9b] = val; - break; - case 0x0d: /* SCODE_HK1 */ - dev->mem[0x50] = val; - break; - case 0x0e: /* SCODE_HK2 */ - dev->mem[0x51] = val; - break; - case 0x0f: /* SCODE_HK3 */ - dev->mem[0x52] = val; - break; - case 0x10: /* SCODE_HK4 */ - dev->mem[0x53] = val; - break; - case 0x11: /* SCODE_HK5 */ - dev->mem[0x54] = val; - break; - case 0x12: /* SCODE_HK6 */ - dev->mem[0x55] = val; - break; - case 0x13: /* TASK_HK1 */ - dev->mem[0x56] = val; - break; - case 0x14: /* TASK_HK2 */ - dev->mem[0x57] = val; - break; - case 0x15: /* TASK_HK3 */ - dev->mem[0x58] = val; - break; - case 0x16: /* TASK_HK4 */ - dev->mem[0x59] = val; - break; - case 0x17: /* TASK_HK5 */ - dev->mem[0x5a] = val; - break; - /* The next 4 bytes have uncertain correspondences. */ - case 0x18: /* Batt_Poll_delay_Time */ - dev->mem[0x5b] = val; - break; - case 0x19: /* Batt_Alarm_Reg1 */ - dev->mem[0x5c] = val; - break; - case 0x1a: /* Batt_Alarm_Reg2 */ - dev->mem[0x5d] = val; - break; - case 0x1b: /* Batt_Alarm_Tsk_Reg */ - dev->mem[0x5e] = val; - break; - case 0x1c: /* Kbc_State1 */ - dev->mem[0x9d] = val; - break; - case 0x1d: /* Aux_Config */ - dev->mem[0x75] = val; - break; - case 0x1e: /* Kbc_State3 */ - dev->mem[0x73] = val; - break; - } - return 0; - - case 0xc1: /* write input port */ - kbc_log(dev, "AMI MegaKey - write %02X to input port\n", val); - dev->p1 = val; - return 0; - - case 0xcb: /* set keyboard mode */ - kbc_log(dev, "AMI - Set keyboard mode\n"); - return 0; - } - - return 1; -} - - -static uint8_t -write64_ami(void *priv, uint8_t val) -{ - atkbc_t *dev = (atkbc_t *)priv; - uint16_t index = 0x00c0; - - switch (val) { - case 0x00 ... 0x1f: - kbc_log(dev, "AMI - Alias read from %08X\n", val); - kbc_transmit(dev, dev->mem[val + 0x20]); - return 0; - - case 0x40 ... 0x5f: - kbc_log(dev, "AMI - Alias write to %08X\n", dev->kbc_cmd); - dev->kbc_in = 1; - return 0; - - case 0xa0: /* copyright message */ - kbc_log(dev, "AMI - Get copyright message\n"); - kbc_transmit(dev, ami_copr[0]); - dev->kbc_phase = 1; - return 0; - - case 0xa1: /* get controller version */ - kbc_log(dev, "AMI - Get controller version\n"); - // kbc_transmit(dev, 'H'); - kbc_transmit(dev, '5'); - return 0; - - case 0xa2: /* clear keyboard controller lines P22/P23 */ - if (!(dev->flags & KBC_FLAG_PS2)) { - kbc_log(dev, "AMI - Clear KBC lines P22 and P23\n"); - write_output(dev, dev->p2 & 0xf3); - kbc_transmit(dev, 0x00); - return 0; - } - break; - - case 0xa3: /* set keyboard controller lines P22/P23 */ - if (!(dev->flags & KBC_FLAG_PS2)) { - kbc_log(dev, "AMI - Set KBC lines P22 and P23\n"); - write_output(dev, dev->p2 | 0x0c); - kbc_transmit(dev, 0x00); - return 0; - } - break; - - case 0xa4: /* write clock = low */ - if (!(dev->flags & KBC_FLAG_PS2)) { - kbc_log(dev, "AMI - Write clock = low\n"); - dev->ami_stat &= 0xfe; - return 0; - } - break; - - case 0xa5: /* write clock = high */ - if (!(dev->flags & KBC_FLAG_PS2)) { - kbc_log(dev, "AMI - Write clock = high\n"); - dev->ami_stat |= 0x01; - return 0; - } - break; - - case 0xa6: /* read clock */ - if (!(dev->flags & KBC_FLAG_PS2)) { - kbc_log(dev, "AMI - Read clock\n"); - kbc_transmit(dev, !!(dev->ami_stat & 1)); - return 0; - } - break; - - case 0xa7: /* write cache bad */ - if (!(dev->flags & KBC_FLAG_PS2)) { - kbc_log(dev, "AMI - Write cache bad\n"); - dev->ami_stat &= 0xfd; - return 0; - } - break; - - case 0xa8: /* write cache good */ - if (!(dev->flags & KBC_FLAG_PS2)) { - kbc_log(dev, "AMI - Write cache good\n"); - dev->ami_stat |= 0x02; - return 0; - } - break; - - case 0xa9: /* read cache */ - if (!(dev->flags & KBC_FLAG_PS2)) { - kbc_log(dev, "AMI - Read cache\n"); - kbc_transmit(dev, !!(dev->ami_stat & 2)); - return 0; - } - break; - - case 0xaf: /* set extended controller RAM */ - kbc_log(dev, "AMI - Set extended controller RAM\n"); - dev->kbc_in = 1; - return 0; - - case 0xb0 ... 0xb3: - /* set KBC lines P10-P13 (input port bits 0-3) low */ - kbc_log(dev, "AMI - Set KBC lines P10-P13 (input port bits 0-3) low\n"); - if (!(dev->flags & KBC_FLAG_PS2) || (val > 0xb1)) { - dev->p1 &= ~(1 << (val & 0x03)); - } - kbc_transmit(dev, 0x00); - return 0; - - case 0xb4: case 0xb5: - /* set KBC lines P22-P23 (output port bits 2-3) low */ - kbc_log(dev, "AMI - Set KBC lines P22-P23 (output port bits 2-3) low\n"); - if (!(dev->flags & KBC_FLAG_PS2)) - write_output(dev, dev->p2 & ~(4 << (val & 0x01))); - kbc_transmit(dev, 0x00); - return 0; - -#if 0 - case 0xb8 ... 0xbb: -#else - case 0xb9: -#endif - /* set KBC lines P10-P13 (input port bits 0-3) high */ - kbc_log(dev, "AMI - Set KBC lines P10-P13 (input port bits 0-3) high\n"); - if (!(dev->flags & KBC_FLAG_PS2) || (val > 0xb9)) { - dev->p1 |= (1 << (val & 0x03)); - kbc_transmit(dev, 0x00); - } - return 0; - - case 0xb8: - kbc_log(dev, "AMIKey-3 - memory index\n"); - dev->kbc_in = 1; - return 0; - - case 0xba: - kbc_log(dev, "AMIKey-3 - read %02X memory from index %02X\n", dev->mem[dev->mem_index], dev->mem_index); - if (dev->mem_index >= 0x80) { - switch (dev->mem[0x9b] & 0xc0) { - case 0x00: - index = 0x0080; - break; - case 0x40: case 0x80: - index = 0x0000; - break; - case 0xc0: - index = 0x0100; - break; - } - kbc_transmit(dev, dev->mem[index + dev->mem_index]); - } else if (dev->mem_index == 0x42) - kbc_transmit(dev, dev->status); - else if (dev->mem_index >= 0x40) - kbc_transmit(dev, dev->mem[dev->mem_index - 0x40]); - else - kbc_transmit(dev, dev->mem_int[dev->mem_index]); - return 0; - - case 0xbb: - kbc_log(dev, "AMIKey-3 - write to memory index %02X\n", dev->mem_index); - dev->kbc_in = 1; - return 0; - -#if 0 - case 0xbc: case 0xbd: - /* set KBC lines P22-P23 (output port bits 2-3) high */ - kbc_log(dev, "AMI - Set KBC lines P22-P23 (output port bits 2-3) high\n"); - if (!(dev->flags & KBC_FLAG_PS2)) - write_output(dev, dev->p2 | (4 << (val & 0x01))); - kbc_transmit(dev, 0x00); - return 0; -#endif - - case 0xbc: - switch (dev->mem_index) { - case 0x00: /* STAT8042 */ - kbc_transmit(dev, dev->status); - break; - case 0x01: /* Password_ptr */ - kbc_transmit(dev, dev->mem[0x1c]); - break; - case 0x02: /* Wakeup_Tsk_Reg */ - kbc_transmit(dev, dev->mem[0x1e]); - break; - case 0x03: /* CCB */ - kbc_transmit(dev, dev->mem[0x20]); - break; - case 0x04: /* Debounce_time */ - kbc_transmit(dev, dev->mem[0x4d]); - break; - case 0x05: /* Pulse_Width */ - kbc_transmit(dev, dev->mem[0x4e]); - break; - case 0x06: /* Pk_sel_byte */ - kbc_transmit(dev, dev->mem[0x4c]); - break; - case 0x07: /* Func_Tsk_Reg */ - kbc_transmit(dev, dev->mem[0x7e]); - break; - case 0x08: /* TypematicRate */ - kbc_transmit(dev, dev->mem[0x80]); - break; - case 0x09: /* Led_Flag_Byte */ - kbc_transmit(dev, dev->mem[0x81]); - break; - case 0x0a: /* Kbms_Command_St */ - kbc_transmit(dev, dev->mem[0x87]); - break; - case 0x0b: /* Delay_Count_Byte */ - kbc_transmit(dev, dev->mem[0x86]); - break; - case 0x0c: /* KBC_Flags */ - kbc_transmit(dev, dev->mem[0x9b]); - break; - case 0x0d: /* SCODE_HK1 */ - kbc_transmit(dev, dev->mem[0x50]); - break; - case 0x0e: /* SCODE_HK2 */ - kbc_transmit(dev, dev->mem[0x51]); - break; - case 0x0f: /* SCODE_HK3 */ - kbc_transmit(dev, dev->mem[0x52]); - break; - case 0x10: /* SCODE_HK4 */ - kbc_transmit(dev, dev->mem[0x53]); - break; - case 0x11: /* SCODE_HK5 */ - kbc_transmit(dev, dev->mem[0x54]); - break; - case 0x12: /* SCODE_HK6 */ - kbc_transmit(dev, dev->mem[0x55]); - break; - case 0x13: /* TASK_HK1 */ - kbc_transmit(dev, dev->mem[0x56]); - break; - case 0x14: /* TASK_HK2 */ - kbc_transmit(dev, dev->mem[0x57]); - break; - case 0x15: /* TASK_HK3 */ - kbc_transmit(dev, dev->mem[0x58]); - break; - case 0x16: /* TASK_HK4 */ - kbc_transmit(dev, dev->mem[0x59]); - break; - case 0x17: /* TASK_HK5 */ - kbc_transmit(dev, dev->mem[0x5a]); - break; - /* The next 4 bytes have uncertain correspondences. */ - case 0x18: /* Batt_Poll_delay_Time */ - kbc_transmit(dev, dev->mem[0x5b]); - break; - case 0x19: /* Batt_Alarm_Reg1 */ - kbc_transmit(dev, dev->mem[0x5c]); - break; - case 0x1a: /* Batt_Alarm_Reg2 */ - kbc_transmit(dev, dev->mem[0x5d]); - break; - case 0x1b: /* Batt_Alarm_Tsk_Reg */ - kbc_transmit(dev, dev->mem[0x5e]); - break; - case 0x1c: /* Kbc_State1 */ - kbc_transmit(dev, dev->mem[0x9d]); - break; - case 0x1d: /* Aux_Config */ - kbc_transmit(dev, dev->mem[0x75]); - break; - case 0x1e: /* Kbc_State3 */ - kbc_transmit(dev, dev->mem[0x73]); - break; - default: - kbc_transmit(dev, 0x00); - break; - } - kbc_log(dev, "AMIKey-3 - read from config index %02X\n", dev->mem_index); - return 0; - - case 0xbd: - kbc_log(dev, "AMIKey-3 - write to config index %02X\n", dev->mem_index); - dev->kbc_in = 1; - return 0; - - case 0xc1: /* write input port */ - kbc_log(dev, "AMIKey-3 - write input port\n"); - dev->kbc_in = 1; - return 0; - - case 0xc8: case 0xc9: - /* - * (un)block KBC lines P22/P23 - * (allow command D1 to change bits 2/3 of the output port) - */ - kbc_log(dev, "AMI - %slock KBC lines P22 and P23\n", (val & 1) ? "B" : "Unb"); - dev->p2_locked = (val & 1); - return 0; - - case 0xef: /* ??? - sent by AMI486 */ - kbc_log(dev, "??? - sent by AMI486\n"); - return 0; - } - - return write64_generic(dev, val); -} - - -static uint8_t -write64_ibm_mca(void *priv, uint8_t val) -{ - atkbc_t *dev = (atkbc_t *)priv; - - switch (val) { - case 0xc1: /*Copy bits 0 to 3 of input port to status bits 4 to 7*/ - kbc_log(dev, "Copy bits 0 to 3 of input port to status bits 4 to 7\n"); - dev->status &= 0x0f; - dev->status |= ((((dev->p1 & 0xfc) | 0x84) & 0x0f) << 4); - return 0; - - case 0xc2: /*Copy bits 4 to 7 of input port to status bits 4 to 7*/ - kbc_log(dev, "Copy bits 4 to 7 of input port to status bits 4 to 7\n"); - dev->status &= 0x0f; - dev->status |= (((dev->p1 & 0xfc) | 0x84) & 0xf0); - return 0; - - case 0xaf: - kbc_log(dev, "Bad KBC command AF\n"); - return 1; - - case 0xf0 ... 0xff: - kbc_log(dev, "Pulse: %01X\n", (val & 0x03) | 0x0c); - pulse_output(dev, (val & 0x03) | 0x0c); - return 0; - } - - return write64_generic(dev, val); -} - - -static uint8_t -write60_quadtel(void *priv, uint8_t val) -{ - atkbc_t *dev = (atkbc_t *)priv; - - switch(dev->kbc_cmd) { - case 0xcf: /*??? - sent by MegaPC BIOS*/ - kbc_log(dev, "??? - sent by MegaPC BIOS\n"); - return 0; - } - - return 1; -} - - -static uint8_t -write64_olivetti(void *priv, uint8_t val) -{ - atkbc_t *dev = (atkbc_t *)priv; - - switch (val) { - /* This appears to be a clone of "Read input port", in which case, the bis would be: - 7: M290 (AT KBC): - Keyboard lock (1 = unlocked, 0 = locked); - M300 (PS/2 KBC): - Bus expansion board present (1 = present, 0 = not present); - 6: Usually: - Display (1 = MDA, 0 = CGA, but can have its polarity inverted); - 5: Manufacturing jumper (1 = not installed, 0 = installed (infinite loop)); - 4: RAM on motherboard (1 = 256 kB, 0 = 512 kB - which machine actually uses this?); - 3: Fast Ram check (if inactive keyboard works erratically); - 2: Keyboard fuse present - This appears to be in-line with PS/2: 1 = no power, 0 = keyboard power normal; - 1: M290 (AT KBC): - Unused; - M300 (PS/2 KBC): - Mouse data in; - 0: M290 (AT KBC): - Unused; - M300 (PS/2 KBC): - Key data in. - */ - case 0x80: /* Olivetti-specific command */ - /* - * bit 7: bus expansion board present (M300) / keyboard unlocked (M290) - * bits 4-6: ??? - * bit 3: fast ram check (if inactive keyboard works erratically) - * bit 2: keyboard fuse present - * bits 0-1: ??? - */ - kbc_transmit(dev, 0x0c | (is386 ? 0x00 : 0x80)); - return 0; - } - - return write64_generic(dev, val); -} - - -static uint8_t -write64_quadtel(void *priv, uint8_t val) -{ - atkbc_t *dev = (atkbc_t *)priv; - - switch (val) { - case 0xaf: - kbc_log(dev, "Bad KBC command AF\n"); - return 1; - - case 0xcf: /*??? - sent by MegaPC BIOS*/ - kbc_log(dev, "??? - sent by MegaPC BIOS\n"); - dev->kbc_in = 1; - return 0; - } - - return write64_generic(dev, val); -} - - -static uint8_t -write60_toshiba(void *priv, uint8_t val) -{ - atkbc_t *dev = (atkbc_t *)priv; - - switch(dev->kbc_cmd) { - case 0xb6: /* T3100e - set color/mono switch */ - kbc_log(dev, "T3100e - Set color/mono switch\n"); - t3100e_mono_set(val); - return 0; - } - - return 1; -} - - -static uint8_t -write64_toshiba(void *priv, uint8_t val) -{ - atkbc_t *dev = (atkbc_t *)priv; - - switch (val) { - case 0xaf: - kbc_log(dev, "Bad KBC command AF\n"); - return 1; - - case 0xb0: /* T3100e: Turbo on */ - kbc_log(dev, "T3100e: Turbo on\n"); - t3100e_turbo_set(1); - return 0; - - case 0xb1: /* T3100e: Turbo off */ - kbc_log(dev, "T3100e: Turbo off\n"); - t3100e_turbo_set(0); - return 0; - - case 0xb2: /* T3100e: Select external display */ - kbc_log(dev, "T3100e: Select external display\n"); - t3100e_display_set(0x00); - return 0; - - case 0xb3: /* T3100e: Select internal display */ - kcd_log("T3100e: Select internal display\n"); - t3100e_display_set(0x01); - return 0; - - case 0xb4: /* T3100e: Get configuration / status */ - kbc_log(dev, "T3100e: Get configuration / status\n"); - kbc_transmit(dev, t3100e_config_get()); - return 0; - - case 0xb5: /* T3100e: Get colour / mono byte */ - kbc_log(dev, "T3100e: Get colour / mono byte\n"); - kbc_transmit(dev, t3100e_mono_get()); - return 0; - - case 0xb6: /* T3100e: Set colour / mono byte */ - kbc_log(dev, "T3100e: Set colour / mono byte\n"); - dev->kbc_in = 1; - return 0; - - case 0xb7: /* T3100e: Emulate PS/2 keyboard */ - case 0xb8: /* T3100e: Emulate AT keyboard */ - dev->flags &= ~KBC_FLAG_PS2; - if (val == 0xb7) { - kbc_log(dev, "T3100e: Emulate PS/2 keyboard\n"); - dev->flags |= KBC_FLAG_PS2; - } else - kbc_log(dev, "T3100e: Emulate AT keyboard\n"); -#if (!defined(RELEASE_BUILD) && defined(ENABLE_KBD_AT_LOG)) - log_set_dev_name(dev->kbc_log, (dev->flags & KBC_FLAG_PS2) ? "AT KBC" : "PS/2 KBC"); -#endif - return 0; - - case 0xbb: /* T3100e: Read 'Fn' key. - Return it for right Ctrl and right Alt; on the real - T3100e, these keystrokes could only be generated - using 'Fn'. */ - kbc_log(dev, "T3100e: Read 'Fn' key\n"); - if (keyboard_recv(0xb8) || /* Right Alt */ - keyboard_recv(0x9d)) /* Right Ctrl */ - kbc_transmit(dev, 0x04); - else - kbc_transmit(dev, 0x00); - return 0; - - case 0xbc: /* T3100e: Reset Fn+Key notification */ - kbc_log(dev, "T3100e: Reset Fn+Key notification\n"); - t3100e_notify_set(0x00); - return 0; - - case 0xc0: /*Read input port*/ - kbc_log(dev, "Read input port\n"); - - /* The T3100e returns all bits set except bit 6 which - * is set by t3100e_mono_set() */ - dev->p1 = (t3100e_mono_get() & 1) ? 0xff : 0xbf; - kbc_transmit(dev, dev->p1); - return 0; - - } - - return write64_generic(dev, val); -} - - -static void -kbc_write(uint16_t port, uint8_t val, void *priv) -{ - atkbc_t *dev = (atkbc_t *)priv; - - kbc_log(dev, "[%04X:%08X] write(%04X, %02X)\n", CS, cpu_state.pc, port, val); - - switch (port) { - case 0x60: - dev->status = (dev->status & ~STAT_CD) | STAT_IFULL; - dev->ib = val; - // kbd_status("Write %02X: %02X, Status = %02X\n", port, val, dev->status); - -#if 0 - if ((dev->fast_a20_phase == 1)/* && ((val == 0xdd) || (val == 0xdf))*/) { - dev->status &= ~STAT_IFULL; - write_output(dev, val); - dev->fast_a20_phase = 0; - } -#endif - break; - case 0x64: - dev->status |= (STAT_CD | STAT_IFULL); - dev->ib = val; - // kbd_status("Write %02X: %02X, Status = %02X\n", port, val, dev->status); - -#if 0 - if (val == 0xd1) { - dev->status &= ~STAT_IFULL; - dev->fast_a20_phase = 1; - } else if (val == 0xfe) { - dev->status &= ~STAT_IFULL; - pulse_output(dev, 0x0e); - } else if ((val == 0xad) || (val == 0xae)) { - dev->status &= ~STAT_IFULL; - if (val & 0x01) - dev->mem[0x20] |= 0x10; - else - dev->mem[0x20] &= ~0x10; - } else if (val == 0xa1) { - dev->status &= ~STAT_IFULL; - kbc_send_to_ob(dev, 'H', 0, 0x00); - } -#endif - break; - } -} - - -static uint8_t -kbc_read(uint16_t port, void *priv) -{ - atkbc_t *dev = (atkbc_t *)priv; - uint8_t ret = 0xff; - - // if (dev->flags & KBC_FLAG_PS2) - // cycles -= ISA_CYCLES(8); - - switch (port) { - case 0x60: - ret = dev->ob; - dev->status &= ~STAT_OFULL; - picintc(dev->last_irq); - dev->last_irq = 0; - break; - - case 0x64: - ret = dev->status; - break; - - default: - kbc_log(dev, "Reading unknown port %02X\n", port); - break; - } - - kbc_log(dev, "[%04X:%08X] read(%04X) = %02X\n",CS, cpu_state.pc, port, ret); - - return(ret); -} - - -static void -kbc_reset(void *priv) -{ - atkbc_t *dev = (atkbc_t *)priv; - int i; - uint8_t kbc_ven = 0x0; - kbc_ven = dev->flags & KBC_VEN_MASK; - - dev->status = STAT_UNLOCKED; - dev->mem[0x20] = 0x01; - dev->mem[0x20] |= CCB_TRANSLATE; - write_output(dev, 0xcf); - dev->last_irq = 0; - dev->secr_phase = 0; - dev->in = 0; - dev->ami_mode = !!(dev->flags & KBC_FLAG_PS2); - - /* Set up the correct Video Type bits. */ - dev->p1 = video_is_mda() ? 0xf0 : 0xb0; - if ((kbc_ven == KBC_VEN_XI8088) || (kbc_ven == KBC_VEN_ACER)) - dev->p1 ^= 0x40; - if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) - dev->inhibit = ((dev->p1 & 0x80) >> 3); - else - dev->inhibit = 0x10; - kbc_log(dev, "Input port = %02x\n", dev->p1); - - keyboard_mode = 0x02 | (dev->mem[0x20] & CCB_TRANSLATE); - - /* Enable keyboard, disable mouse. */ - set_enable_kbd(dev, 1); - keyboard_scan = 1; - set_enable_mouse(dev, 0); - mouse_scan = 0; - - dev->ob = 0xff; - - sc_or = 0; - - dev->mem[0x31] = 0xfe; -} - - -/* Reset the AT keyboard - this is needed for the PCI TRC and is done - until a better solution is found. */ -void -keyboard_at_reset(void) -{ - kbc_reset(SavedKbd); -} - - -void -kbc_dev_attach(kbc_dev_t *kbc_dev, int channel) -{ - if ((channel < 1) || (channel > 2)) - log_fatal(saved_kbc->log, "Attaching device to invalid channel %i\n", channel); - else { - kbc_log(saved_kbc, "Attaching device to channel %i\n", channel); - saved_kbc->kbc_devs[channel - 1] = kbc_dev; - } -} - - -static void -kbc_close(void *priv) -{ - atkbc_t *dev = (atkbc_t *)priv; - - kbc_reset(dev); - - /* Stop timers. */ - timer_disable(&dev->send_delay_timer); - -#if (!defined(RELEASE_BUILD) && defined(ENABLE_KBC_AT_LOG)) - log_close(dev->log); -#endif - - free(dev); -} - - -static void * -kbc_init(const device_t *info) -{ - atkbc_t *dev; - - dev = (atkbc_t *)malloc(sizeof(atkbc_t)); - memset(dev, 0x00, sizeof(atkbc_t)); - - dev->flags = info->local; - - video_reset(gfxcard); - dev->kbc_poll_phase = KBC_RESET; - - io_sethandler(0x0060, 1, kbc_read, NULL, NULL, kbc_write, NULL, NULL, dev); - io_sethandler(0x0064, 1, kbc_read, NULL, NULL, kbc_write, NULL, NULL, dev); - - timer_add(&dev->send_delay_timer, kbd_poll, dev, 1); - timer_add(&dev->pulse_cb, pulse_poll, dev, 0); - -#if (!defined(RELEASE_BUILD) && defined(ENABLE_KBC_AT_LOG)) - dev->kbc_log = log_open((dev->flags & KBC_FLAG_PS2) ? "AT KBC" : "PS/2 KBC"); -#endif - - dev->write60_ven = NULL; - dev->write64_ven = NULL; - - switch(dev->flags & KBC_VEN_MASK) { - case KBC_VEN_ACER: - case KBC_VEN_GENERIC: - case KBC_VEN_NCR: - case KBC_VEN_IBM_PS1: - case KBC_VEN_XI8088: - dev->write64_ven = write64_generic; - break; - - case KBC_VEN_OLIVETTI: - /* The Olivetti controller is a special case - starts directly in the - main loop instead of the reset loop. */ - dev->kbc_poll_phase = KBC_MAIN_LOOP; - dev->write64_ven = write64_olivetti; - break; - - case KBC_VEN_AMI: - case KBC_VEN_INTEL_AMI: - dev->write60_ven = write60_ami; - dev->write64_ven = write64_ami; - break; - - case KBC_VEN_IBM_MCA: - dev->write64_ven = write64_ibm_mca; - break; - - case KBC_VEN_QUADTEL: - dev->write60_ven = write60_quadtel; - dev->write64_ven = write64_quadtel; - break; - - case KBC_VEN_TOSHIBA: - dev->write60_ven = write60_toshiba; - dev->write64_ven = write64_toshiba; - break; - } - - kbc_reset(dev); - - /* Local variable, needed for device attaching. */ - saved_kbc = dev; - - /* Add the actual keyboard. */ - device_add(&keyboard_at_kbd_device); - - return(dev); -} - - -const device_t keyboard_at_device = { - "PC/AT Keyboard", - 0, - KBC_TYPE_ISA | KBC_VEN_GENERIC, - kbc_init, - kbc_close, - kbc_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_at_ami_device = { - "PC/AT Keyboard (AMI)", - 0, - KBC_TYPE_ISA | KBC_VEN_AMI, - kbc_init, - kbc_close, - kbc_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_at_toshiba_device = { - "PC/AT Keyboard (Toshiba)", - 0, - KBC_TYPE_ISA | KBC_VEN_TOSHIBA, - kbc_init, - kbc_close, - kbc_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_at_olivetti_device = { - "PC/AT Keyboard (Olivetti)", - 0, - KBC_TYPE_ISA | KBC_VEN_OLIVETTI, - kbc_init, - kbc_close, - kbc_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_at_ncr_device = { - "PC/AT Keyboard (NCR)", - 0, - KBC_TYPE_ISA | KBC_VEN_NCR, - kbc_init, - kbc_close, - kbc_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_device = { - "PS/2 Keyboard", - 0, - KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, - kbc_init, - kbc_close, - kbc_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_ps1_device = { - "PS/2 Keyboard (IBM PS/1)", - 0, - KBC_TYPE_PS2_1 | KBC_VEN_IBM_PS1, - kbc_init, - kbc_close, - kbc_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_ps1_pci_device = { - "PS/2 Keyboard (IBM PS/1)", - DEVICE_PCI, - KBC_TYPE_PS2_1 | KBC_VEN_IBM_PS1, - kbc_init, - kbc_close, - kbc_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_xi8088_device = { - "PS/2 Keyboard (Xi8088)", - 0, - KBC_TYPE_PS2_1 | KBC_VEN_XI8088, - kbc_init, - kbc_close, - kbc_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_ami_device = { - "PS/2 Keyboard (AMI)", - 0, - KBC_TYPE_PS2_1 | KBC_VEN_AMI, - kbc_init, - kbc_close, - kbc_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_olivetti_device = { - "PS/2 Keyboard (Olivetti)", - 0, - KBC_TYPE_PS2_1 | KBC_VEN_OLIVETTI, - kbc_init, - kbc_close, - kbc_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_mca_device = { - "PS/2 Keyboard", - 0, - KBC_TYPE_PS2_1 | KBC_VEN_IBM_MCA, - kbc_init, - kbc_close, - kbc_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_mca_2_device = { - "PS/2 Keyboard", - 0, - KBC_TYPE_PS2_2 | KBC_VEN_IBM_MCA, - kbc_init, - kbc_close, - kbc_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_quadtel_device = { - "PS/2 Keyboard (Quadtel/MegaPC)", - 0, - KBC_TYPE_PS2_1 | KBC_VEN_QUADTEL, - kbc_init, - kbc_close, - kbc_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_pci_device = { - "PS/2 Keyboard", - DEVICE_PCI, - KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, - kbc_init, - kbc_close, - kbc_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_ami_pci_device = { - "PS/2 Keyboard (AMI)", - DEVICE_PCI, - KBC_TYPE_PS2_1 | KBC_VEN_AMI, - kbc_init, - kbc_close, - kbc_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_intel_ami_pci_device = { - "PS/2 Keyboard (AMI)", - DEVICE_PCI, - KBC_TYPE_PS2_1 | KBC_VEN_INTEL_AMI, - kbc_init, - kbc_close, - kbc_reset, - { NULL }, NULL, NULL, NULL -}; - -const device_t keyboard_ps2_acer_pci_device = { - "PS/2 Keyboard (Acer 90M002A)", - DEVICE_PCI, - KBC_TYPE_PS2_1 | KBC_VEN_ACER, - kbc_init, - kbc_close, - kbc_reset, - { NULL }, NULL, NULL, NULL -}; - - -void -keyboard_at_set_mouse(void (*func)(uint8_t val, void *priv), void *priv) -{ -} - - -void -keyboard_at_adddata_mouse(uint8_t val) -{ - return; -} - - -void -keyboard_at_adddata_mouse_direct(uint8_t val) -{ - return; -} - - -void -keyboard_at_adddata_mouse_cmd(uint8_t val) -{ - return; -} - - -void -keyboard_at_mouse_reset(void) -{ - return; -} - - -uint8_t -keyboard_at_mouse_pos(void) -{ - return ((mouse_queue_end - mouse_queue_start) & 0xf); -} - - -int -keyboard_at_fixed_channel(void) -{ - return 0x000; -} - - -void -keyboard_at_set_mouse_scan(uint8_t val) -{ - atkbc_t *dev = SavedKbd; - uint8_t temp_mouse_scan = val ? 1 : 0; - - if (temp_mouse_scan == !(dev->mem[0x20] & 0x20)) - return; - - set_enable_mouse(dev, val ? 1 : 0); - - kbc_log(dev, "Mouse scan %sabled via PCI\n", mouse_scan ? "en" : "dis"); -} - - -uint8_t -keyboard_at_get_mouse_scan(void) -{ - atkbc_t *dev = SavedKbd; - - return((dev->mem[0x20] & 0x20) ? 0x00 : 0x10); -} - - -void -keyboard_at_set_a20_key(int state) -{ - atkbc_t *dev = SavedKbd; - - write_output(dev, (dev->p2 & 0xfd) | ((!!state) << 1)); -} - - -void -keyboard_at_set_mode(int ps2) -{ - atkbc_t *dev = SavedKbd; - - if (ps2) - dev->flags |= KBC_FLAG_PS2; - else - dev->flags &= ~KBC_FLAG_PS2; -} diff --git a/src/device/kbd_at.c b/src/device/kbd_at.c deleted file mode 100644 index f24177d37..000000000 --- a/src/device/kbd_at.c +++ /dev/null @@ -1,1162 +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. - * - * Intel 8042 (AT keyboard controller) emulation. - * - * - * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * EngiNerd - * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2020 EngiNerd. - */ -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include -#include <86box/86box.h> -#include <86box/timer.h> -#include <86box/device.h> -#include <86box/log.h> -#include <86box/keyboard.h> - - -// static uint8_t key_queue[16]; -// static int key_queue_start = 0, key_queue_end = 0; -// static uint8_t kbd_last_scan_code; - -typedef struct { - uint8_t in, cmd, in_cmd, state, last_byte; - - uint8_t queue[16]; - - uint16_t phase; - - int quueue_start, queue_end; - - void * log; - - kbc_dev_t kd; -} atkbd_t; - - -enum -{ - CHANNEL_KBC = 0, - CHANNEL_KBD, - CHANNEL_MOUSE -}; - -enum -{ - KBD_MAIN_LOOP = 0, - KBD_CMD_PROCESS -}; - -enum -{ - MOUSE_MAIN_LOOP_1 = 0, - MOUSE_CMD_PROCESS, - MOUSE_CMD_END, - MOUSE_MAIN_LOOP_2 -}; - -enum { - KBC_MAIN_LOOP = 0, - KBC_RESET = 1, - KBC_WAIT = 4, - KBC_WAIT_FOR_KBD, - KBC_WAIT_FOR_MOUSE, - KBC_WAIT_FOR_BOTH -}; - - -static void kbd_cmd_process(atkbd_t *dev); - - -/* bit 0 = repeat, bit 1 = makes break code? */ -uint8_t keyboard_set3_flags[512]; -uint8_t keyboard_set3_all_repeat; -uint8_t keyboard_set3_all_break; - - -static atkbd_t *SavedKbd = NULL; // FIXME: remove!!! --FvK - - -#ifdef USE_SET1 -static const scancode scancode_set1[512] = { - { { 0},{ 0} }, { { 0x01,0},{ 0x81,0} }, { { 0x02,0},{ 0x82,0} }, { { 0x03,0},{ 0x83,0} }, /*000*/ - { { 0x04,0},{ 0x84,0} }, { { 0x05,0},{ 0x85,0} }, { { 0x06,0},{ 0x86,0} }, { { 0x07,0},{ 0x87,0} }, /*004*/ - { { 0x08,0},{ 0x88,0} }, { { 0x09,0},{ 0x89,0} }, { { 0x0a,0},{ 0x8a,0} }, { { 0x0b,0},{ 0x8b,0} }, /*008*/ - { { 0x0c,0},{ 0x8c,0} }, { { 0x0d,0},{ 0x8d,0} }, { { 0x0e,0},{ 0x8e,0} }, { { 0x0f,0},{ 0x8f,0} }, /*00c*/ - { { 0x10,0},{ 0x90,0} }, { { 0x11,0},{ 0x91,0} }, { { 0x12,0},{ 0x92,0} }, { { 0x13,0},{ 0x93,0} }, /*010*/ - { { 0x14,0},{ 0x94,0} }, { { 0x15,0},{ 0x95,0} }, { { 0x16,0},{ 0x96,0} }, { { 0x17,0},{ 0x97,0} }, /*014*/ - { { 0x18,0},{ 0x98,0} }, { { 0x19,0},{ 0x99,0} }, { { 0x1a,0},{ 0x9a,0} }, { { 0x1b,0},{ 0x9b,0} }, /*018*/ - { { 0x1c,0},{ 0x9c,0} }, { { 0x1d,0},{ 0x9d,0} }, { { 0x1e,0},{ 0x9e,0} }, { { 0x1f,0},{ 0x9f,0} }, /*01c*/ - { { 0x20,0},{ 0xa0,0} }, { { 0x21,0},{ 0xa1,0} }, { { 0x22,0},{ 0xa2,0} }, { { 0x23,0},{ 0xa3,0} }, /*020*/ - { { 0x24,0},{ 0xa4,0} }, { { 0x25,0},{ 0xa5,0} }, { { 0x26,0},{ 0xa6,0} }, { { 0x27,0},{ 0xa7,0} }, /*024*/ - { { 0x28,0},{ 0xa8,0} }, { { 0x29,0},{ 0xa9,0} }, { { 0x2a,0},{ 0xaa,0} }, { { 0x2b,0},{ 0xab,0} }, /*028*/ - { { 0x2c,0},{ 0xac,0} }, { { 0x2d,0},{ 0xad,0} }, { { 0x2e,0},{ 0xae,0} }, { { 0x2f,0},{ 0xaf,0} }, /*02c*/ - { { 0x30,0},{ 0xb0,0} }, { { 0x31,0},{ 0xb1,0} }, { { 0x32,0},{ 0xb2,0} }, { { 0x33,0},{ 0xb3,0} }, /*030*/ - { { 0x34,0},{ 0xb4,0} }, { { 0x35,0},{ 0xb5,0} }, { { 0x36,0},{ 0xb6,0} }, { { 0x37,0},{ 0xb7,0} }, /*034*/ - { { 0x38,0},{ 0xb8,0} }, { { 0x39,0},{ 0xb9,0} }, { { 0x3a,0},{ 0xba,0} }, { { 0x3b,0},{ 0xbb,0} }, /*038*/ - { { 0x3c,0},{ 0xbc,0} }, { { 0x3d,0},{ 0xbd,0} }, { { 0x3e,0},{ 0xbe,0} }, { { 0x3f,0},{ 0xbf,0} }, /*03c*/ - { { 0x40,0},{ 0xc0,0} }, { { 0x41,0},{ 0xc1,0} }, { { 0x42,0},{ 0xc2,0} }, { { 0x43,0},{ 0xc3,0} }, /*040*/ - { { 0x44,0},{ 0xc4,0} }, { { 0x45,0},{ 0xc5,0} }, { { 0x46,0},{ 0xc6,0} }, { { 0x47,0},{ 0xc7,0} }, /*044*/ - { { 0x48,0},{ 0xc8,0} }, { { 0x49,0},{ 0xc9,0} }, { { 0x4a,0},{ 0xca,0} }, { { 0x4b,0},{ 0xcb,0} }, /*048*/ - { { 0x4c,0},{ 0xcc,0} }, { { 0x4d,0},{ 0xcd,0} }, { { 0x4e,0},{ 0xce,0} }, { { 0x4f,0},{ 0xcf,0} }, /*04c*/ - { { 0x50,0},{ 0xd0,0} }, { { 0x51,0},{ 0xd1,0} }, { { 0x52,0},{ 0xd2,0} }, { { 0x53,0},{ 0xd3,0} }, /*050*/ - { { 0x54,0},{ 0xd4,0} }, { { 0x55,0},{ 0xd5,0} }, { { 0x56,0},{ 0xd6,0} }, { { 0x57,0},{ 0xd7,0} }, /*054*/ - { { 0x58,0},{ 0xd8,0} }, { { 0x59,0},{ 0xd9,0} }, { { 0x5a,0},{ 0xda,0} }, { { 0x5b,0},{ 0xdb,0} }, /*058*/ - { { 0x5c,0},{ 0xdc,0} }, { { 0x5d,0},{ 0xdd,0} }, { { 0x5e,0},{ 0xde,0} }, { { 0x5f,0},{ 0xdf,0} }, /*05c*/ - { { 0x60,0},{ 0xe0,0} }, { { 0x61,0},{ 0xe1,0} }, { { 0x62,0},{ 0xe2,0} }, { { 0x63,0},{ 0xe3,0} }, /*060*/ - { { 0x64,0},{ 0xe4,0} }, { { 0x65,0},{ 0xe5,0} }, { { 0x66,0},{ 0xe6,0} }, { { 0x67,0},{ 0xe7,0} }, /*064*/ - { { 0x68,0},{ 0xe8,0} }, { { 0x69,0},{ 0xe9,0} }, { { 0x6a,0},{ 0xea,0} }, { { 0x6b,0},{ 0xeb,0} }, /*068*/ - { { 0x6c,0},{ 0xec,0} }, { { 0x6d,0},{ 0xed,0} }, { { 0x6e,0},{ 0xee,0} }, { { 0x6f,0},{ 0xef,0} }, /*06c*/ - { { 0x70,0},{ 0xf0,0} }, { { 0x71,0},{ 0xf1,0} }, { { 0x72,0},{ 0xf2,0} }, { { 0x73,0},{ 0xf3,0} }, /*070*/ - { { 0x74,0},{ 0xf4,0} }, { { 0x75,0},{ 0xf5,0} }, { { 0x76,0},{ 0xf6,0} }, { { 0x77,0},{ 0xf7,0} }, /*074*/ - { { 0x78,0},{ 0xf8,0} }, { { 0x79,0},{ 0xf9,0} }, { { 0x7a,0},{ 0xfa,0} }, { { 0x7b,0},{ 0xfb,0} }, /*078*/ - { { 0x7c,0},{ 0xfc,0} }, { { 0x7d,0},{ 0xfd,0} }, { { 0x7e,0},{ 0xfe,0} }, { { 0x7f,0},{ 0xff,0} }, /*07c*/ - - { { 0x80,0},{ 0} }, { { 0x81,0},{ 0} }, { { 0x82,0},{ 0} }, { { 0},{ 0} }, /*080*/ - { { 0},{ 0} }, { { 0x85,0},{ 0} }, { { 0x86,0},{ 0} }, { { 0x87,0},{ 0} }, /*084*/ - { { 0x88,0},{ 0} }, { { 0x89,0},{ 0} }, { { 0x8a,0},{ 0} }, { { 0x8b,0},{ 0} }, /*088*/ - { { 0x8c,0},{ 0} }, { { 0x8d,0},{ 0} }, { { 0x8e,0},{ 0} }, { { 0x8f,0},{ 0} }, /*08c*/ - { { 0x90,0},{ 0} }, { { 0x91,0},{ 0} }, { { 0x92,0},{ 0} }, { { 0x93,0},{ 0} }, /*090*/ - { { 0x94,0},{ 0} }, { { 0x95,0},{ 0} }, { { 0x96,0},{ 0} }, { { 0x97,0},{ 0} }, /*094*/ - { { 0x98,0},{ 0} }, { { 0x99,0},{ 0} }, { { 0x9a,0},{ 0} }, { { 0x9b,0},{ 0} }, /*098*/ - { { 0x9c,0},{ 0} }, { { 0x9d,0},{ 0} }, { { 0x9e,0},{ 0} }, { { 0x9f,0},{ 0} }, /*09c*/ - { { 0xa0,0},{ 0} }, { { 0xa1,0},{ 0} }, { { 0xa2,0},{ 0} }, { { 0xa3,0},{ 0} }, /*0a0*/ - { { 0xa4,0},{ 0} }, { { 0xa5,0},{ 0} }, { { 0xa6,0},{ 0} }, { { 0xa7,0},{ 0} }, /*0a4*/ - { { 0xa8,0},{ 0} }, { { 0xa9,0},{ 0} }, { { 0xaa,0},{ 0} }, { { 0xab,0},{ 0} }, /*0a8*/ - { { 0xac,0},{ 0} }, { { 0xad,0},{ 0} }, { { 0xae,0},{ 0} }, { { 0xaf,0},{ 0} }, /*0ac*/ - { { 0xb0,0},{ 0} }, { { 0xb1,0},{ 0} }, { { 0xb2,0},{ 0} }, { { 0xb3,0},{ 0} }, /*0b0*/ - { { 0xb4,0},{ 0} }, { { 0xb5,0},{ 0} }, { { 0xb6,0},{ 0} }, { { 0xb7,0},{ 0} }, /*0b4*/ - { { 0xb8,0},{ 0} }, { { 0xb9,0},{ 0} }, { { 0xba,0},{ 0} }, { { 0xbb,0},{ 0} }, /*0b8*/ - { { 0xbc,0},{ 0} }, { { 0xbd,0},{ 0} }, { { 0xbe,0},{ 0} }, { { 0xbf,0},{ 0} }, /*0bc*/ - { { 0xc0,0},{ 0} }, { { 0xc1,0},{ 0} }, { { 0xc2,0},{ 0} }, { { 0xc3,0},{ 0} }, /*0c0*/ - { { 0xc4,0},{ 0} }, { { 0xc5,0},{ 0} }, { { 0xc6,0},{ 0} }, { { 0xc7,0},{ 0} }, /*0c4*/ - { { 0xc8,0},{ 0} }, { { 0xc9,0},{ 0} }, { { 0xca,0},{ 0} }, { { 0xcb,0},{ 0} }, /*0c8*/ - { { 0xcc,0},{ 0} }, { { 0xcd,0},{ 0} }, { { 0xce,0},{ 0} }, { { 0xcf,0},{ 0} }, /*0cc*/ - { { 0xd0,0},{ 0} }, { { 0xd1,0},{ 0} }, { { 0xd2,0},{ 0} }, { { 0xd3,0},{ 0} }, /*0d0*/ - { { 0xd4,0},{ 0} }, { { 0xd5,0},{ 0} }, { { 0xd6,0},{ 0} }, { { 0xd7,0},{ 0} }, /*0d4*/ - { { 0xd8,0},{ 0} }, { { 0xd9,0},{ 0} }, { { 0xda,0},{ 0} }, { { 0xdb,0},{ 0} }, /*0d8*/ - { { 0xdc,0},{ 0} }, { { 0xdd,0},{ 0} }, { { 0xde,0},{ 0} }, { { 0xdf,0},{ 0} }, /*0dc*/ - { { 0xe0,0},{ 0} }, { { 0xe1,0},{ 0} }, { { 0xe2,0},{ 0} }, { { 0xe3,0},{ 0} }, /*0e0*/ - { { 0xe4,0},{ 0} }, { { 0xe5,0},{ 0} }, { { 0xe6,0},{ 0} }, { { 0xe7,0},{ 0} }, /*0e4*/ - { { 0xe8,0},{ 0} }, { { 0xe9,0},{ 0} }, { { 0xea,0},{ 0} }, { { 0xeb,0},{ 0} }, /*0e8*/ - { { 0xec,0},{ 0} }, { { 0xed,0},{ 0} }, { { 0xee,0},{ 0} }, { { 0xef,0},{ 0} }, /*0ec*/ - { { 0},{ 0} }, { { 0xf1,0},{ 0} }, { { 0xf2,0},{ 0} }, { { 0xf3,0},{ 0} }, /*0f0*/ - { { 0xf4,0},{ 0} }, { { 0xf5,0},{ 0} }, { { 0xf6,0},{ 0} }, { { 0xf7,0},{ 0} }, /*0f4*/ - { { 0xf8,0},{ 0} }, { { 0xf9,0},{ 0} }, { { 0xfa,0},{ 0} }, { { 0xfb,0},{ 0} }, /*0f8*/ - { { 0xfc,0},{ 0} }, { { 0xfd,0},{ 0} }, { { 0xfe,0},{ 0} }, { { 0xff,0},{ 0} }, /*0fc*/ - - { {0xe1,0x1d,0},{0xe1, 0x9d,0} }, { {0xe0,0x01,0},{0xe0, 0x81,0} }, { {0xe0,0x02,0},{0xe0, 0x82,0} }, { {0xe0,0x03,0},{0xe0, 0x83,0} }, /*100*/ - { {0xe0,0x04,0},{0xe0, 0x84,0} }, { {0xe0,0x05,0},{0xe0, 0x85,0} }, { {0xe0,0x06,0},{0xe0, 0x86,0} }, { {0xe0,0x07,0},{0xe0, 0x87,0} }, /*104*/ - { {0xe0,0x08,0},{0xe0, 0x88,0} }, { {0xe0,0x09,0},{0xe0, 0x89,0} }, { {0xe0,0x0a,0},{0xe0, 0x8a,0} }, { {0xe0,0x0b,0},{0xe0, 0x8b,0} }, /*108*/ - { {0xe0,0x0c,0},{0xe0, 0x8c,0} }, { { 0},{ 0} }, { {0xe0,0x0e,0},{0xe0, 0x8e,0} }, { {0xe0,0x0f,0},{0xe0, 0x8f,0} }, /*10c*/ - { {0xe0,0x10,0},{0xe0, 0x90,0} }, { {0xe0,0x11,0},{0xe0, 0x91,0} }, { {0xe0,0x12,0},{0xe0, 0x92,0} }, { {0xe0,0x13,0},{0xe0, 0x93,0} }, /*110*/ - { {0xe0,0x14,0},{0xe0, 0x94,0} }, { {0xe0,0x15,0},{0xe0, 0x95,0} }, { {0xe0,0x16,0},{0xe0, 0x96,0} }, { {0xe0,0x17,0},{0xe0, 0x97,0} }, /*114*/ - { {0xe0,0x18,0},{0xe0, 0x98,0} }, { {0xe0,0x19,0},{0xe0, 0x99,0} }, { {0xe0,0x1a,0},{0xe0, 0x9a,0} }, { {0xe0,0x1b,0},{0xe0, 0x9b,0} }, /*118*/ - { {0xe0,0x1c,0},{0xe0, 0x9c,0} }, { {0xe0,0x1d,0},{0xe0, 0x9d,0} }, { {0xe0,0x1e,0},{0xe0, 0x9e,0} }, { {0xe0,0x1f,0},{0xe0, 0x9f,0} }, /*11c*/ - { {0xe0,0x20,0},{0xe0, 0xa0,0} }, { {0xe0,0x21,0},{0xe0, 0xa1,0} }, { {0xe0,0x22,0},{0xe0, 0xa2,0} }, { {0xe0,0x23,0},{0xe0, 0xa3,0} }, /*120*/ - { {0xe0,0x24,0},{0xe0, 0xa4,0} }, { {0xe0,0x25,0},{0xe0, 0xa5,0} }, { {0xe0,0x26,0},{0xe0, 0xa6,0} }, { { 0},{ 0} }, /*124*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*128*/ - { {0xe0,0x2c,0},{0xe0, 0xac,0} }, { {0xe0,0x2d,0},{0xe0, 0xad,0} }, { {0xe0,0x2e,0},{0xe0, 0xae,0} }, { {0xe0,0x2f,0},{0xe0, 0xaf,0} }, /*12c*/ - { {0xe0,0x30,0},{0xe0, 0xb0,0} }, { {0xe0,0x31,0},{0xe0, 0xb1,0} }, { {0xe0,0x32,0},{0xe0, 0xb2,0} }, { { 0},{ 0} }, /*130*/ - { {0xe0,0x34,0},{0xe0, 0xb4,0} }, { {0xe0,0x35,0},{0xe0, 0xb5,0} }, { { 0},{ 0} }, { {0xe0,0x37,0},{0xe0, 0xb7,0} }, /*134*/ - { {0xe0,0x38,0},{0xe0, 0xb8,0} }, { { 0},{ 0} }, { {0xe0,0x3a,0},{0xe0, 0xba,0} }, { {0xe0,0x3b,0},{0xe0, 0xbb,0} }, /*138*/ - { {0xe0,0x3c,0},{0xe0, 0xbc,0} }, { {0xe0,0x3d,0},{0xe0, 0xbd,0} }, { {0xe0,0x3e,0},{0xe0, 0xbe,0} }, { {0xe0,0x3f,0},{0xe0, 0xbf,0} }, /*13c*/ - { {0xe0,0x40,0},{0xe0, 0xc0,0} }, { {0xe0,0x41,0},{0xe0, 0xc1,0} }, { {0xe0,0x42,0},{0xe0, 0xc2,0} }, { {0xe0,0x43,0},{0xe0, 0xc3,0} }, /*140*/ - { {0xe0,0x44,0},{0xe0, 0xc4,0} }, { { 0},{ 0} }, { {0xe0,0x46,0},{0xe0, 0xc6,0} }, { {0xe0,0x47,0},{0xe0, 0xc7,0} }, /*144*/ - { {0xe0,0x48,0},{0xe0, 0xc8,0} }, { {0xe0,0x49,0},{0xe0, 0xc9,0} }, { { 0},{ 0} }, { {0xe0,0x4b,0},{0xe0, 0xcb,0} }, /*148*/ - { {0xe0,0x4c,0},{0xe0, 0xcc,0} }, { {0xe0,0x4d,0},{0xe0, 0xcd,0} }, { {0xe0,0x4e,0},{0xe0, 0xce,0} }, { {0xe0,0x4f,0},{0xe0, 0xcf,0} }, /*14c*/ - { {0xe0,0x50,0},{0xe0, 0xd0,0} }, { {0xe0,0x51,0},{0xe0, 0xd1,0} }, { {0xe0,0x52,0},{0xe0, 0xd2,0} }, { {0xe0,0x53,0},{0xe0, 0xd3,0} }, /*150*/ - { { 0},{ 0} }, { {0xe0,0x55,0},{0xe0, 0xd5,0} }, { { 0},{ 0} }, { {0xe0,0x57,0},{0xe0, 0xd7,0} }, /*154*/ - { {0xe0,0x58,0},{0xe0, 0xd8,0} }, { {0xe0,0x59,0},{0xe0, 0xd9,0} }, { {0xe0,0x5a,0},{0xe0, 0xaa,0} }, { {0xe0,0x5b,0},{0xe0, 0xdb,0} }, /*158*/ - { {0xe0,0x5c,0},{0xe0, 0xdc,0} }, { {0xe0,0x5d,0},{0xe0, 0xdd,0} }, { {0xe0,0x5e,0},{0xe0, 0xee,0} }, { {0xe0,0x5f,0},{0xe0, 0xdf,0} }, /*15c*/ - { { 0},{ 0} }, { {0xe0,0x61,0},{0xe0, 0xe1,0} }, { {0xe0,0x62,0},{0xe0, 0xe2,0} }, { {0xe0,0x63,0},{0xe0, 0xe3,0} }, /*160*/ - { {0xe0,0x64,0},{0xe0, 0xe4,0} }, { {0xe0,0x65,0},{0xe0, 0xe5,0} }, { {0xe0,0x66,0},{0xe0, 0xe6,0} }, { {0xe0,0x67,0},{0xe0, 0xe7,0} }, /*164*/ - { {0xe0,0x68,0},{0xe0, 0xe8,0} }, { {0xe0,0x69,0},{0xe0, 0xe9,0} }, { {0xe0,0x6a,0},{0xe0, 0xea,0} }, { {0xe0,0x6b,0},{0xe0, 0xeb,0} }, /*168*/ - { {0xe0,0x6c,0},{0xe0, 0xec,0} }, { {0xe0,0x6d,0},{0xe0, 0xed,0} }, { {0xe0,0x6e,0},{0xe0, 0xee,0} }, { { 0},{ 0} }, /*16c*/ - { {0xe0,0x70,0},{0xe0, 0xf0,0} }, { {0xe0,0x71,0},{0xe0, 0xf1,0} }, { {0xe0,0x72,0},{0xe0, 0xf2,0} }, { {0xe0,0x73,0},{0xe0, 0xf3,0} }, /*170*/ - { {0xe0,0x74,0},{0xe0, 0xf4,0} }, { {0xe0,0x75,0},{0xe0, 0xf5,0} }, { { 0},{ 0} }, { {0xe0,0x77,0},{0xe0, 0xf7,0} }, /*174*/ - { {0xe0,0x78,0},{0xe0, 0xf8,0} }, { {0xe0,0x79,0},{0xe0, 0xf9,0} }, { {0xe0,0x7a,0},{0xe0, 0xfa,0} }, { {0xe0,0x7b,0},{0xe0, 0xfb,0} }, /*178*/ - { {0xe0,0x7c,0},{0xe0, 0xfc,0} }, { {0xe0,0x7d,0},{0xe0, 0xfd,0} }, { {0xe0,0x7e,0},{0xe0, 0xfe,0} }, { {0xe0,0x7f,0},{0xe0, 0xff,0} }, /*17c*/ - - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*180*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*184*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*188*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*18c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*190*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*194*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*198*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*19c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1ac*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1cc*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1dc*/ - { { 0},{ 0} }, { {0xe0,0xe1,0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xee,0},{ 0} }, { { 0},{ 0} }, /*1ec*/ - { { 0},{ 0} }, { {0xe0,0xf1,0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{ 0} }, { {0xe0,0xff,0},{ 0} } /*1fc*/ -}; -#endif - -static const scancode scancode_set2[512] = { - { { 0},{ 0} }, { { 0x76,0},{ 0xF0,0x76,0} }, { { 0x16,0},{ 0xF0,0x16,0} }, { { 0x1E,0},{ 0xF0,0x1E,0} }, /*000*/ - { { 0x26,0},{ 0xF0,0x26,0} }, { { 0x25,0},{ 0xF0,0x25,0} }, { { 0x2E,0},{ 0xF0,0x2E,0} }, { { 0x36,0},{ 0xF0,0x36,0} }, /*004*/ - { { 0x3D,0},{ 0xF0,0x3D,0} }, { { 0x3E,0},{ 0xF0,0x3E,0} }, { { 0x46,0},{ 0xF0,0x46,0} }, { { 0x45,0},{ 0xF0,0x45,0} }, /*008*/ - { { 0x4E,0},{ 0xF0,0x4E,0} }, { { 0x55,0},{ 0xF0,0x55,0} }, { { 0x66,0},{ 0xF0,0x66,0} }, { { 0x0D,0},{ 0xF0,0x0D,0} }, /*00c*/ - { { 0x15,0},{ 0xF0,0x15,0} }, { { 0x1D,0},{ 0xF0,0x1D,0} }, { { 0x24,0},{ 0xF0,0x24,0} }, { { 0x2D,0},{ 0xF0,0x2D,0} }, /*010*/ - { { 0x2C,0},{ 0xF0,0x2C,0} }, { { 0x35,0},{ 0xF0,0x35,0} }, { { 0x3C,0},{ 0xF0,0x3C,0} }, { { 0x43,0},{ 0xF0,0x43,0} }, /*014*/ - { { 0x44,0},{ 0xF0,0x44,0} }, { { 0x4D,0},{ 0xF0,0x4D,0} }, { { 0x54,0},{ 0xF0,0x54,0} }, { { 0x5B,0},{ 0xF0,0x5B,0} }, /*018*/ - { { 0x5A,0},{ 0xF0,0x5A,0} }, { { 0x14,0},{ 0xF0,0x14,0} }, { { 0x1C,0},{ 0xF0,0x1C,0} }, { { 0x1B,0},{ 0xF0,0x1B,0} }, /*01c*/ - { { 0x23,0},{ 0xF0,0x23,0} }, { { 0x2B,0},{ 0xF0,0x2B,0} }, { { 0x34,0},{ 0xF0,0x34,0} }, { { 0x33,0},{ 0xF0,0x33,0} }, /*020*/ - { { 0x3B,0},{ 0xF0,0x3B,0} }, { { 0x42,0},{ 0xF0,0x42,0} }, { { 0x4B,0},{ 0xF0,0x4B,0} }, { { 0x4C,0},{ 0xF0,0x4C,0} }, /*024*/ - { { 0x52,0},{ 0xF0,0x52,0} }, { { 0x0E,0},{ 0xF0,0x0E,0} }, { { 0x12,0},{ 0xF0,0x12,0} }, { { 0x5D,0},{ 0xF0,0x5D,0} }, /*028*/ - { { 0x1A,0},{ 0xF0,0x1A,0} }, { { 0x22,0},{ 0xF0,0x22,0} }, { { 0x21,0},{ 0xF0,0x21,0} }, { { 0x2A,0},{ 0xF0,0x2A,0} }, /*02c*/ - { { 0x32,0},{ 0xF0,0x32,0} }, { { 0x31,0},{ 0xF0,0x31,0} }, { { 0x3A,0},{ 0xF0,0x3A,0} }, { { 0x41,0},{ 0xF0,0x41,0} }, /*030*/ - { { 0x49,0},{ 0xF0,0x49,0} }, { { 0x4A,0},{ 0xF0,0x4A,0} }, { { 0x59,0},{ 0xF0,0x59,0} }, { { 0x7C,0},{ 0xF0,0x7C,0} }, /*034*/ - { { 0x11,0},{ 0xF0,0x11,0} }, { { 0x29,0},{ 0xF0,0x29,0} }, { { 0x58,0},{ 0xF0,0x58,0} }, { { 0x05,0},{ 0xF0,0x05,0} }, /*038*/ - { { 0x06,0},{ 0xF0,0x06,0} }, { { 0x04,0},{ 0xF0,0x04,0} }, { { 0x0C,0},{ 0xF0,0x0C,0} }, { { 0x03,0},{ 0xF0,0x03,0} }, /*03c*/ - { { 0x0B,0},{ 0xF0,0x0B,0} }, { { 0x83,0},{ 0xF0,0x83,0} }, { { 0x0A,0},{ 0xF0,0x0A,0} }, { { 0x01,0},{ 0xF0,0x01,0} }, /*040*/ - { { 0x09,0},{ 0xF0,0x09,0} }, { { 0x77,0},{ 0xF0,0x77,0} }, { { 0x7E,0},{ 0xF0,0x7E,0} }, { { 0x6C,0},{ 0xF0,0x6C,0} }, /*044*/ - { { 0x75,0},{ 0xF0,0x75,0} }, { { 0x7D,0},{ 0xF0,0x7D,0} }, { { 0x7B,0},{ 0xF0,0x7B,0} }, { { 0x6B,0},{ 0xF0,0x6B,0} }, /*048*/ - { { 0x73,0},{ 0xF0,0x73,0} }, { { 0x74,0},{ 0xF0,0x74,0} }, { { 0x79,0},{ 0xF0,0x79,0} }, { { 0x69,0},{ 0xF0,0x69,0} }, /*04c*/ - { { 0x72,0},{ 0xF0,0x72,0} }, { { 0x7A,0},{ 0xF0,0x7A,0} }, { { 0x70,0},{ 0xF0,0x70,0} }, { { 0x71,0},{ 0xF0,0x71,0} }, /*050*/ - { { 0x84,0},{ 0xF0,0x84,0} }, { { 0x60,0},{ 0xF0,0x60,0} }, { { 0x61,0},{ 0xF0,0x61,0} }, { { 0x78,0},{ 0xF0,0x78,0} }, /*054*/ - { { 0x07,0},{ 0xF0,0x07,0} }, { { 0x0F,0},{ 0xF0,0x0F,0} }, { { 0x17,0},{ 0xF0,0x17,0} }, { { 0x1F,0},{ 0xF0,0x1F,0} }, /*058*/ - { { 0x27,0},{ 0xF0,0x27,0} }, { { 0x2F,0},{ 0xF0,0x2F,0} }, { { 0x37,0},{ 0xF0,0x37,0} }, { { 0x3F,0},{ 0xF0,0x3F,0} }, /*05c*/ - { { 0x47,0},{ 0xF0,0x47,0} }, { { 0x4F,0},{ 0xF0,0x4F,0} }, { { 0x56,0},{ 0xF0,0x56,0} }, { { 0x5E,0},{ 0xF0,0x5E,0} }, /*060*/ - { { 0x08,0},{ 0xF0,0x08,0} }, { { 0x10,0},{ 0xF0,0x10,0} }, { { 0x18,0},{ 0xF0,0x18,0} }, { { 0x20,0},{ 0xF0,0x20,0} }, /*064*/ - { { 0x28,0},{ 0xF0,0x28,0} }, { { 0x30,0},{ 0xF0,0x30,0} }, { { 0x38,0},{ 0xF0,0x38,0} }, { { 0x40,0},{ 0xF0,0x40,0} }, /*068*/ - { { 0x48,0},{ 0xF0,0x48,0} }, { { 0x50,0},{ 0xF0,0x50,0} }, { { 0x57,0},{ 0xF0,0x57,0} }, { { 0x6F,0},{ 0xF0,0x6F,0} }, /*06c*/ - { { 0x13,0},{ 0xF0,0x13,0} }, { { 0x19,0},{ 0xF0,0x19,0} }, { { 0x39,0},{ 0xF0,0x39,0} }, { { 0x51,0},{ 0xF0,0x51,0} }, /*070*/ - { { 0x53,0},{ 0xF0,0x53,0} }, { { 0x5C,0},{ 0xF0,0x5C,0} }, { { 0x5F,0},{ 0xF0,0x5F,0} }, { { 0x62,0},{ 0xF0,0x62,0} }, /*074*/ - { { 0x63,0},{ 0xF0,0x63,0} }, { { 0x64,0},{ 0xF0,0x64,0} }, { { 0x65,0},{ 0xF0,0x65,0} }, { { 0x67,0},{ 0xF0,0x67,0} }, /*078*/ - { { 0x68,0},{ 0xF0,0x68,0} }, { { 0x6A,0},{ 0xF0,0x6A,0} }, { { 0x6D,0},{ 0xF0,0x6D,0} }, { { 0x6E,0},{ 0xF0,0x6E,0} }, /*07c*/ - - { { 0x80,0},{ 0xf0,0x80,0} }, { { 0x81,0},{ 0xf0,0x81,0} }, { { 0x82,0},{ 0xf0,0x82,0} }, { { 0},{ 0} }, /*080*/ - { { 0},{ 0} }, { { 0x85,0},{ 0xf0,0x54,0} }, { { 0x86,0},{ 0xf0,0x86,0} }, { { 0x87,0},{ 0xf0,0x87,0} }, /*084*/ - { { 0x88,0},{ 0xf0,0x88,0} }, { { 0x89,0},{ 0xf0,0x89,0} }, { { 0x8a,0},{ 0xf0,0x8a,0} }, { { 0x8b,0},{ 0xf0,0x8b,0} }, /*088*/ - { { 0x8c,0},{ 0xf0,0x8c,0} }, { { 0x8d,0},{ 0xf0,0x8d,0} }, { { 0x8e,0},{ 0xf0,0x8e,0} }, { { 0x8f,0},{ 0xf0,0x8f,0} }, /*08c*/ - { { 0x90,0},{ 0xf0,0x90,0} }, { { 0x91,0},{ 0xf0,0x91,0} }, { { 0x92,0},{ 0xf0,0x92,0} }, { { 0x93,0},{ 0xf0,0x93,0} }, /*090*/ - { { 0x94,0},{ 0xf0,0x94,0} }, { { 0x95,0},{ 0xf0,0x95,0} }, { { 0x96,0},{ 0xf0,0x96,0} }, { { 0x97,0},{ 0xf0,0x97,0} }, /*094*/ - { { 0x98,0},{ 0xf0,0x98,0} }, { { 0x99,0},{ 0xf0,0x99,0} }, { { 0x9a,0},{ 0xf0,0x9a,0} }, { { 0x9b,0},{ 0xf0,0x9b,0} }, /*098*/ - { { 0x9c,0},{ 0xf0,0x9c,0} }, { { 0x9d,0},{ 0xf0,0x9d,0} }, { { 0x9e,0},{ 0xf0,0x9e,0} }, { { 0x9f,0},{ 0xf0,0x9f,0} }, /*09c*/ - { { 0xa0,0},{ 0xf0,0xa0,0} }, { { 0xa1,0},{ 0xf0,0xa1,0} }, { { 0xa2,0},{ 0xf0,0xa2,0} }, { { 0xa3,0},{ 0xf0,0xa3,0} }, /*0a0*/ - { { 0xa4,0},{ 0xf0,0xa4,0} }, { { 0xa5,0},{ 0xf0,0xa5,0} }, { { 0xa6,0},{ 0xf0,0xa6,0} }, { { 0xa7,0},{ 0xf0,0xa7,0} }, /*0a4*/ - { { 0xa8,0},{ 0xf0,0xa8,0} }, { { 0xa9,0},{ 0xf0,0xa9,0} }, { { 0xaa,0},{ 0xf0,0xaa,0} }, { { 0xab,0},{ 0xf0,0xab,0} }, /*0a8*/ - { { 0xac,0},{ 0xf0,0xac,0} }, { { 0xad,0},{ 0xf0,0xad,0} }, { { 0xae,0},{ 0xf0,0xae,0} }, { { 0xaf,0},{ 0xf0,0xaf,0} }, /*0ac*/ - { { 0xb0,0},{ 0xf0,0xb0,0} }, { { 0xb1,0},{ 0xf0,0xb1,0} }, { { 0xb2,0},{ 0xf0,0xb2,0} }, { { 0xb3,0},{ 0xf0,0xb3,0} }, /*0b0*/ - { { 0xb4,0},{ 0xf0,0xb4,0} }, { { 0xb5,0},{ 0xf0,0xb5,0} }, { { 0xb6,0},{ 0xf0,0xb6,0} }, { { 0xb7,0},{ 0xf0,0xb7,0} }, /*0b4*/ - { { 0xb8,0},{ 0xf0,0xb8,0} }, { { 0xb9,0},{ 0xf0,0xb9,0} }, { { 0xba,0},{ 0xf0,0xba,0} }, { { 0xbb,0},{ 0xf0,0xbb,0} }, /*0b8*/ - { { 0xbc,0},{ 0xf0,0xbc,0} }, { { 0xbd,0},{ 0xf0,0xbd,0} }, { { 0xbe,0},{ 0xf0,0xbe,0} }, { { 0xbf,0},{ 0xf0,0xbf,0} }, /*0bc*/ - { { 0xc0,0},{ 0xf0,0xc0,0} }, { { 0xc1,0},{ 0xf0,0xc1,0} }, { { 0xc2,0},{ 0xf0,0xc2,0} }, { { 0xc3,0},{ 0xf0,0xc3,0} }, /*0c0*/ - { { 0xc4,0},{ 0xf0,0xc4,0} }, { { 0xc5,0},{ 0xf0,0xc5,0} }, { { 0xc6,0},{ 0xf0,0xc6,0} }, { { 0xc7,0},{ 0xf0,0xc7,0} }, /*0c4*/ - { { 0xc8,0},{ 0xf0,0xc8,0} }, { { 0xc9,0},{ 0xf0,0xc9,0} }, { { 0xca,0},{ 0xf0,0xca,0} }, { { 0xcb,0},{ 0xf0,0xcb,0} }, /*0c8*/ - { { 0xcc,0},{ 0xf0,0xcc,0} }, { { 0xcd,0},{ 0xf0,0xcd,0} }, { { 0xce,0},{ 0xf0,0xce,0} }, { { 0xcf,0},{ 0xf0,0xcf,0} }, /*0cc*/ - { { 0xd0,0},{ 0xf0,0xd0,0} }, { { 0xd1,0},{ 0xf0,0xd0,0} }, { { 0xd2,0},{ 0xf0,0xd2,0} }, { { 0xd3,0},{ 0xf0,0xd3,0} }, /*0d0*/ - { { 0xd4,0},{ 0xf0,0xd4,0} }, { { 0xd5,0},{ 0xf0,0xd5,0} }, { { 0xd6,0},{ 0xf0,0xd6,0} }, { { 0xd7,0},{ 0xf0,0xd7,0} }, /*0d4*/ - { { 0xd8,0},{ 0xf0,0xd8,0} }, { { 0xd9,0},{ 0xf0,0xd9,0} }, { { 0xda,0},{ 0xf0,0xda,0} }, { { 0xdb,0},{ 0xf0,0xdb,0} }, /*0d8*/ - { { 0xdc,0},{ 0xf0,0xdc,0} }, { { 0xdd,0},{ 0xf0,0xdd,0} }, { { 0xde,0},{ 0xf0,0xde,0} }, { { 0xdf,0},{ 0xf0,0xdf,0} }, /*0dc*/ - { { 0xe0,0},{ 0xf0,0xe0,0} }, { { 0xe1,0},{ 0xf0,0xe1,0} }, { { 0xe2,0},{ 0xf0,0xe2,0} }, { { 0xe3,0},{ 0xf0,0xe3,0} }, /*0e0*/ - { { 0xe4,0},{ 0xf0,0xe4,0} }, { { 0xe5,0},{ 0xf0,0xe5,0} }, { { 0xe6,0},{ 0xf0,0xe6,0} }, { { 0xe7,0},{ 0xf0,0xe7,0} }, /*0e4*/ - { { 0xe8,0},{ 0xf0,0xe8,0} }, { { 0xe9,0},{ 0xf0,0xe9,0} }, { { 0xea,0},{ 0xf0,0xea,0} }, { { 0xeb,0},{ 0xf0,0xeb,0} }, /*0e8*/ - { { 0xec,0},{ 0xf0,0xec,0} }, { { 0xed,0},{ 0xf0,0xed,0} }, { { 0xee,0},{ 0xf0,0xee,0} }, { { 0xef,0},{ 0xf0,0xef,0} }, /*0ec*/ - { { 0},{ 0} }, { { 0xf1,0},{ 0xf0,0xf1,0} }, { { 0xf2,0},{ 0xf0,0xf2,0} }, { { 0xf3,0},{ 0xf0,0xf3,0} }, /*0f0*/ - { { 0xf4,0},{ 0xf0,0xf4,0} }, { { 0xf5,0},{ 0xf0,0xf5,0} }, { { 0xf6,0},{ 0xf0,0xf6,0} }, { { 0xf7,0},{ 0xf0,0xf7,0} }, /*0f4*/ - { { 0xf8,0},{ 0xf0,0xf8,0} }, { { 0xf9,0},{ 0xf0,0xf9,0} }, { { 0xfa,0},{ 0xf0,0xfa,0} }, { { 0xfb,0},{ 0xf0,0xfb,0} }, /*0f8*/ - { { 0xfc,0},{ 0xf0,0xfc,0} }, { { 0xfd,0},{ 0xf0,0xfd,0} }, { { 0xfe,0},{ 0xf0,0xfe,0} }, { { 0xff,0},{ 0xf0,0xff,0} }, /*0fc*/ - - { {0xe1,0x14,0},{0xe1,0xf0,0x14,0} }, { {0xe0,0x76,0},{0xe0,0xF0,0x76,0} }, { {0xe0,0x16,0},{0xe0,0xF0,0x16,0} }, { {0xe0,0x1E,0},{0xe0,0xF0,0x1E,0} }, /*100*/ - { {0xe0,0x26,0},{0xe0,0xF0,0x26,0} }, { {0xe0,0x25,0},{0xe0,0xF0,0x25,0} }, { {0xe0,0x2E,0},{0xe0,0xF0,0x2E,0} }, { {0xe0,0x36,0},{0xe0,0xF0,0x36,0} }, /*104*/ - { {0xe0,0x3D,0},{0xe0,0xF0,0x3D,0} }, { {0xe0,0x3E,0},{0xe0,0xF0,0x3E,0} }, { {0xe0,0x46,0},{0xe0,0xF0,0x46,0} }, { {0xe0,0x45,0},{0xe0,0xF0,0x45,0} }, /*108*/ - { {0xe0,0x4E,0},{0xe0,0xF0,0x4E,0} }, { { 0},{ 0} }, { {0xe0,0x66,0},{0xe0,0xF0,0x66,0} }, { {0xe0,0x0D,0},{0xe0,0xF0,0x0D,0} }, /*10c*/ - { {0xe0,0x15,0},{0xe0,0xF0,0x15,0} }, { {0xe0,0x1D,0},{0xe0,0xF0,0x1D,0} }, { {0xe0,0x24,0},{0xe0,0xF0,0x24,0} }, { {0xe0,0x2D,0},{0xe0,0xF0,0x2D,0} }, /*110*/ - { {0xe0,0x2C,0},{0xe0,0xF0,0x2C,0} }, { {0xe0,0x35,0},{0xe0,0xF0,0x35,0} }, { {0xe0,0x3C,0},{0xe0,0xF0,0x3C,0} }, { {0xe0,0x43,0},{0xe0,0xF0,0x43,0} }, /*114*/ - { {0xe0,0x44,0},{0xe0,0xF0,0x44,0} }, { {0xe0,0x4D,0},{0xe0,0xF0,0x4D,0} }, { {0xe0,0x54,0},{0xe0,0xF0,0x54,0} }, { {0xe0,0x5B,0},{0xe0,0xF0,0x5B,0} }, /*118*/ - { {0xe0,0x5A,0},{0xe0,0xF0,0x5A,0} }, { {0xe0,0x14,0},{0xe0,0xF0,0x14,0} }, { {0xe0,0x1C,0},{0xe0,0xF0,0x1C,0} }, { {0xe0,0x1B,0},{0xe0,0xF0,0x1B,0} }, /*11c*/ - { {0xe0,0x23,0},{0xe0,0xF0,0x23,0} }, { {0xe0,0x2B,0},{0xe0,0xF0,0x2B,0} }, { {0xe0,0x34,0},{0xe0,0xF0,0x34,0} }, { {0xe0,0x33,0},{0xe0,0xF0,0x33,0} }, /*120*/ - { {0xe0,0x3B,0},{0xe0,0xF0,0x3B,0} }, { {0xe0,0x42,0},{0xe0,0xF0,0x42,0} }, { {0xe0,0x4B,0},{0xe0,0xF0,0x4B,0} }, { { 0},{ 0} }, /*124*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*128*/ - { {0xe0,0x1A,0},{0xe0,0xF0,0x1A,0} }, { {0xe0,0x22,0},{0xe0,0xF0,0x22,0} }, { {0xe0,0x21,0},{0xe0,0xF0,0x21,0} }, { {0xe0,0x2A,0},{0xe0,0xF0,0x2A,0} }, /*12c*/ - { {0xe0,0x32,0},{0xe0,0xF0,0x32,0} }, { {0xe0,0x31,0},{0xe0,0xF0,0x31,0} }, { {0xe0,0x3A,0},{0xe0,0xF0,0x3A,0} }, { { 0},{ 0} }, /*130*/ - { {0xe0,0x49,0},{0xe0,0xF0,0x49,0} }, { {0xe0,0x4A,0},{0xe0,0xF0,0x4A,0} }, { { 0},{ 0} }, { {0xe0,0x7C,0},{0xe0,0xF0,0x7C,0} }, /*134*/ - { {0xe0,0x11,0},{0xe0,0xF0,0x11,0} }, { { 0},{ 0} }, { {0xe0,0x58,0},{0xe0,0xF0,0x58,0} }, { {0xe0,0x05,0},{0xe0,0xF0,0x05,0} }, /*138*/ - { {0xe0,0x06,0},{0xe0,0xF0,0x06,0} }, { {0xe0,0x04,0},{0xe0,0xF0,0x04,0} }, { {0xe0,0x0C,0},{0xe0,0xF0,0x0C,0} }, { {0xe0,0x03,0},{0xe0,0xF0,0x03,0} }, /*13c*/ - { {0xe0,0x0B,0},{0xe0,0xF0,0x0B,0} }, { {0xe0,0x02,0},{0xe0,0xF0,0x02,0} }, { {0xe0,0x0A,0},{0xe0,0xF0,0x0A,0} }, { {0xe0,0x01,0},{0xe0,0xF0,0x01,0} }, /*140*/ - { {0xe0,0x09,0},{0xe0,0xF0,0x09,0} }, { { 0},{ 0} }, { {0xe0,0x7E,0},{0xe0,0xF0,0x7E,0} }, { {0xe0,0x6C,0},{0xe0,0xF0,0x6C,0} }, /*144*/ - { {0xe0,0x75,0},{0xe0,0xF0,0x75,0} }, { {0xe0,0x7D,0},{0xe0,0xF0,0x7D,0} }, { { 0},{ 0} }, { {0xe0,0x6B,0},{0xe0,0xF0,0x6B,0} }, /*148*/ - { {0xe0,0x73,0},{0xe0,0xF0,0x73,0} }, { {0xe0,0x74,0},{0xe0,0xF0,0x74,0} }, { {0xe0,0x79,0},{0xe0,0xF0,0x79,0} }, { {0xe0,0x69,0},{0xe0,0xF0,0x69,0} }, /*14c*/ - { {0xe0,0x72,0},{0xe0,0xF0,0x72,0} }, { {0xe0,0x7A,0},{0xe0,0xF0,0x7A,0} }, { {0xe0,0x70,0},{0xe0,0xF0,0x70,0} }, { {0xe0,0x71,0},{0xe0,0xF0,0x71,0} }, /*150*/ - { { 0},{ 0} }, { {0xe0,0x60,0},{0xe0,0xF0,0x60,0} }, { { 0},{ 0} }, { {0xe0,0x78,0},{0xe0,0xF0,0x78,0} }, /*154*/ - { {0xe0,0x07,0},{0xe0,0xF0,0x07,0} }, { {0xe0,0x0F,0},{0xe0,0xF0,0x0F,0} }, { {0xe0,0x17,0},{0xe0,0xF0,0x17,0} }, { {0xe0,0x1F,0},{0xe0,0xF0,0x1F,0} }, /*158*/ - { {0xe0,0x27,0},{0xe0,0xF0,0x27,0} }, { {0xe0,0x2F,0},{0xe0,0xF0,0x2F,0} }, { {0xe0,0x37,0},{0xe0,0xF0,0x37,0} }, { {0xe0,0x3F,0},{0xe0,0xF0,0x3F,0} }, /*15c*/ - { { 0},{ 0} }, { {0xe0,0x4F,0},{0xe0,0xF0,0x4F,0} }, { {0xe0,0x56,0},{0xe0,0xF0,0x56,0} }, { {0xe0,0x5E,0},{0xe0,0xF0,0x5E,0} }, /*160*/ - { {0xe0,0x08,0},{0xe0,0xF0,0x08,0} }, { {0xe0,0x10,0},{0xe0,0xF0,0x10,0} }, { {0xe0,0x18,0},{0xe0,0xF0,0x18,0} }, { {0xe0,0x20,0},{0xe0,0xF0,0x20,0} }, /*164*/ - { {0xe0,0x28,0},{0xe0,0xF0,0x28,0} }, { {0xe0,0x30,0},{0xe0,0xF0,0x30,0} }, { {0xe0,0x38,0},{0xe0,0xF0,0x38,0} }, { {0xe0,0x40,0},{0xe0,0xF0,0x40,0} }, /*168*/ - { {0xe0,0x48,0},{0xe0,0xF0,0x48,0} }, { {0xe0,0x50,0},{0xe0,0xF0,0x50,0} }, { {0xe0,0x57,0},{0xe0,0xF0,0x57,0} }, { { 0},{ 0} }, /*16c*/ - { {0xe0,0x13,0},{0xe0,0xF0,0x13,0} }, { {0xe0,0x19,0},{0xe0,0xF0,0x19,0} }, { {0xe0,0x39,0},{0xe0,0xF0,0x39,0} }, { {0xe0,0x51,0},{0xe0,0xF0,0x51,0} }, /*170*/ - { {0xe0,0x53,0},{0xe0,0xF0,0x53,0} }, { {0xe0,0x5C,0},{0xe0,0xF0,0x5C,0} }, { { 0},{ 0} }, { {0xe0,0x62,0},{0xe0,0xF0,0x62,0} }, /*174*/ - { {0xe0,0x63,0},{0xe0,0xF0,0x63,0} }, { {0xe0,0x64,0},{0xe0,0xF0,0x64,0} }, { {0xe0,0x65,0},{0xe0,0xF0,0x65,0} }, { {0xe0,0x67,0},{0xe0,0xF0,0x67,0} }, /*178*/ - { {0xe0,0x68,0},{0xe0,0xF0,0x68,0} }, { {0xe0,0x6A,0},{0xe0,0xF0,0x6A,0} }, { {0xe0,0x6D,0},{0xe0,0xF0,0x6D,0} }, { {0xe0,0x6E,0},{0xe0,0xF0,0x6E,0} }, /*17c*/ - - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*180*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*184*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*188*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*18c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*190*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*194*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*198*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*19c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1ac*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1cc*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1dc*/ - { { 0},{ 0} }, { {0xe0,0xe1,0},{0xe0,0xF0,0xE1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xee,0},{0xe0,0xF0,0xEE,0} }, { { 0},{ 0} }, /*1ec*/ - { { 0},{ 0} }, { {0xe0,0xf1,0},{0xe0,0xF0,0xF1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{0xe0,0xF0,0xFE,0} }, { {0xe0,0xff,0},{0xe0,0xF0,0xFF,0} } /*1fc*/ -}; - -static const scancode scancode_set3[512] = { - { { 0},{ 0} }, { { 0x08,0},{ 0xf0,0x08,0} }, { { 0x16,0},{ 0xf0,0x16,0} }, { { 0x1E,0},{ 0xf0,0x1E,0} }, /*000*/ - { { 0x26,0},{ 0xf0,0x26,0} }, { { 0x25,0},{ 0xf0,0x25,0} }, { { 0x2E,0},{ 0xf0,0x2E,0} }, { { 0x36,0},{ 0xf0,0x36,0} }, /*004*/ - { { 0x3D,0},{ 0xf0,0x3D,0} }, { { 0x3E,0},{ 0xf0,0x3E,0} }, { { 0x46,0},{ 0xf0,0x46,0} }, { { 0x45,0},{ 0xf0,0x45,0} }, /*008*/ - { { 0x4E,0},{ 0xf0,0x4E,0} }, { { 0x55,0},{ 0xf0,0x55,0} }, { { 0x66,0},{ 0xf0,0x66,0} }, { { 0x0D,0},{ 0xf0,0x0D,0} }, /*00c*/ - { { 0x15,0},{ 0xf0,0x15,0} }, { { 0x1D,0},{ 0xf0,0x1D,0} }, { { 0x24,0},{ 0xf0,0x24,0} }, { { 0x2D,0},{ 0xf0,0x2D,0} }, /*010*/ - { { 0x2C,0},{ 0xf0,0x2C,0} }, { { 0x35,0},{ 0xf0,0x35,0} }, { { 0x3C,0},{ 0xf0,0x3C,0} }, { { 0x43,0},{ 0xf0,0x43,0} }, /*014*/ - { { 0x44,0},{ 0xf0,0x44,0} }, { { 0x4D,0},{ 0xf0,0x4D,0} }, { { 0x54,0},{ 0xf0,0x54,0} }, { { 0x5B,0},{ 0xf0,0x5B,0} }, /*018*/ - { { 0x5A,0},{ 0xf0,0x5A,0} }, { { 0x11,0},{ 0xf0,0x11,0} }, { { 0x1C,0},{ 0xf0,0x1C,0} }, { { 0x1B,0},{ 0xf0,0x1B,0} }, /*01c*/ - { { 0x23,0},{ 0xf0,0x23,0} }, { { 0x2B,0},{ 0xf0,0x2B,0} }, { { 0x34,0},{ 0xf0,0x34,0} }, { { 0x33,0},{ 0xf0,0x33,0} }, /*020*/ - { { 0x3B,0},{ 0xf0,0x3B,0} }, { { 0x42,0},{ 0xf0,0x42,0} }, { { 0x4B,0},{ 0xf0,0x4B,0} }, { { 0x4C,0},{ 0xf0,0x4C,0} }, /*024*/ - { { 0x52,0},{ 0xf0,0x52,0} }, { { 0x0E,0},{ 0xf0,0x0E,0} }, { { 0x12,0},{ 0xf0,0x12,0} }, { { 0x5C,0},{ 0xf0,0x5C,0} }, /*028*/ - { { 0x1A,0},{ 0xf0,0x1A,0} }, { { 0x22,0},{ 0xf0,0x22,0} }, { { 0x21,0},{ 0xf0,0x21,0} }, { { 0x2A,0},{ 0xf0,0x2A,0} }, /*02c*/ - { { 0x32,0},{ 0xf0,0x32,0} }, { { 0x31,0},{ 0xf0,0x31,0} }, { { 0x3A,0},{ 0xf0,0x3A,0} }, { { 0x41,0},{ 0xf0,0x41,0} }, /*030*/ - { { 0x49,0},{ 0xf0,0x49,0} }, { { 0x4A,0},{ 0xf0,0x4A,0} }, { { 0x59,0},{ 0xf0,0x59,0} }, { { 0x7E,0},{ 0xf0,0x7E,0} }, /*034*/ - { { 0x19,0},{ 0xf0,0x19,0} }, { { 0x29,0},{ 0xf0,0x29,0} }, { { 0x14,0},{ 0xf0,0x14,0} }, { { 0x07,0},{ 0xf0,0x07,0} }, /*038*/ - { { 0x0F,0},{ 0xf0,0x0F,0} }, { { 0x17,0},{ 0xf0,0x17,0} }, { { 0x1F,0},{ 0xf0,0x1F,0} }, { { 0x27,0},{ 0xf0,0x27,0} }, /*03c*/ - { { 0x2F,0},{ 0xf0,0x2F,0} }, { { 0x37,0},{ 0xf0,0x37,0} }, { { 0x3F,0},{ 0xf0,0x3F,0} }, { { 0x47,0},{ 0xf0,0x47,0} }, /*040*/ - { { 0x4F,0},{ 0xf0,0x4F,0} }, { { 0x76,0},{ 0xf0,0x76,0} }, { { 0x5F,0},{ 0xf0,0x5F,0} }, { { 0x6C,0},{ 0xf0,0x6C,0} }, /*044*/ - { { 0x75,0},{ 0xf0,0x75,0} }, { { 0x7D,0},{ 0xf0,0x7D,0} }, { { 0x84,0},{ 0xf0,0x84,0} }, { { 0x6B,0},{ 0xf0,0x6B,0} }, /*048*/ - { { 0x73,0},{ 0xf0,0x73,0} }, { { 0x74,0},{ 0xf0,0x74,0} }, { { 0x7C,0},{ 0xf0,0x7C,0} }, { { 0x69,0},{ 0xf0,0x69,0} }, /*04c*/ - { { 0x72,0},{ 0xf0,0x72,0} }, { { 0x7A,0},{ 0xf0,0x7A,0} }, { { 0x70,0},{ 0xf0,0x70,0} }, { { 0x71,0},{ 0xf0,0x71,0} }, /*050*/ - { { 0x57,0},{ 0xf0,0x57,0} }, { { 0x60,0},{ 0xf0,0x60,0} }, { { 0},{ 0} }, { { 0x56,0},{ 0xf0,0x56,0} }, /*054*/ - { { 0x5E,0},{ 0xf0,0x5E,0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*058*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*05c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*060*/ - { { 0},{ 0} }, { { 0x10,0},{ 0xf0,0x10,0} }, { { 0x18,0},{ 0xf0,0x18,0} }, { { 0x20,0},{ 0xf0,0x20,0} }, /*064*/ - { { 0x28,0},{ 0xf0,0x28,0} }, { { 0x30,0},{ 0xf0,0x30,0} }, { { 0x38,0},{ 0xf0,0x38,0} }, { { 0x40,0},{ 0xf0,0x40,0} }, /*068*/ - { { 0x48,0},{ 0xf0,0x48,0} }, { { 0x50,0},{ 0xf0,0x50,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*06c*/ - { { 0x87,0},{ 0xf0,0x87,0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0x51,0},{ 0xf0,0x51,0} }, /*070*/ - { { 0x53,0},{ 0xf0,0x53,0} }, { { 0x5C,0},{ 0xf0,0x5C,0} }, { { 0},{ 0} }, { { 0x62,0},{ 0xf0,0x62,0} }, /*074*/ - { { 0x63,0},{ 0xf0,0x63,0} }, { { 0x86,0},{ 0xf0,0x86,0} }, { { 0},{ 0} }, { { 0x85,0},{ 0xf0,0x85,0} }, /*078*/ - { { 0x68,0},{ 0xf0,0x68,0} }, { { 0x13,0},{ 0xf0,0x13,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*07c*/ - - { { 0x80,0},{ 0xf0,0x80,0} }, { { 0x81,0},{ 0xf0,0x81,0} }, { { 0x82,0},{ 0xf0,0x82,0} }, { { 0},{ 0} }, /*080*/ - { { 0},{ 0} }, { { 0x85,0},{ 0xf0,0x54,0} }, { { 0x86,0},{ 0xf0,0x86,0} }, { { 0x87,0},{ 0xf0,0x87,0} }, /*084*/ - { { 0x88,0},{ 0xf0,0x88,0} }, { { 0x89,0},{ 0xf0,0x89,0} }, { { 0x8a,0},{ 0xf0,0x8a,0} }, { { 0x8b,0},{ 0xf0,0x8b,0} }, /*088*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0x8e,0},{ 0xf0,0x8e,0} }, { { 0x8f,0},{ 0xf0,0x8f,0} }, /*08c*/ - { { 0x90,0},{ 0xf0,0x90,0} }, { { 0x91,0},{ 0xf0,0x91,0} }, { { 0x92,0},{ 0xf0,0x92,0} }, { { 0x93,0},{ 0xf0,0x93,0} }, /*090*/ - { { 0x94,0},{ 0xf0,0x94,0} }, { { 0x95,0},{ 0xf0,0x95,0} }, { { 0x96,0},{ 0xf0,0x96,0} }, { { 0x97,0},{ 0xf0,0x97,0} }, /*094*/ - { { 0x98,0},{ 0xf0,0x98,0} }, { { 0x99,0},{ 0xf0,0x99,0} }, { { 0x9a,0},{ 0xf0,0x9a,0} }, { { 0x9b,0},{ 0xf0,0x9b,0} }, /*098*/ - { { 0x9c,0},{ 0xf0,0x9c,0} }, { { 0x9d,0},{ 0xf0,0x9d,0} }, { { 0x9e,0},{ 0xf0,0x9e,0} }, { { 0x9f,0},{ 0xf0,0x9f,0} }, /*09c*/ - { { 0xa0,0},{ 0xf0,0xa0,0} }, { { 0xa1,0},{ 0xf0,0xa1,0} }, { { 0xa2,0},{ 0xf0,0xa2,0} }, { { 0xa3,0},{ 0xf0,0xa3,0} }, /*0a0*/ - { { 0xa4,0},{ 0xf0,0xa4,0} }, { { 0xa5,0},{ 0xf0,0xa5,0} }, { { 0xa6,0},{ 0xf0,0xa6,0} }, { { 0xa7,0},{ 0xf0,0xa7,0} }, /*0a4*/ - { { 0xa8,0},{ 0xf0,0xa8,0} }, { { 0xa9,0},{ 0xf0,0xa9,0} }, { { 0xaa,0},{ 0xf0,0xaa,0} }, { { 0xab,0},{ 0xf0,0xab,0} }, /*0a8*/ - { { 0xac,0},{ 0xf0,0xac,0} }, { { 0xad,0},{ 0xf0,0xad,0} }, { { 0xae,0},{ 0xf0,0xae,0} }, { { 0xaf,0},{ 0xf0,0xaf,0} }, /*0ac*/ - { { 0xb0,0},{ 0xf0,0xb0,0} }, { { 0xb1,0},{ 0xf0,0xb1,0} }, { { 0xb2,0},{ 0xf0,0xb2,0} }, { { 0xb3,0},{ 0xf0,0xb3,0} }, /*0b0*/ - { { 0xb4,0},{ 0xf0,0xb4,0} }, { { 0xb5,0},{ 0xf0,0xb5,0} }, { { 0xb6,0},{ 0xf0,0xb6,0} }, { { 0xb7,0},{ 0xf0,0xb7,0} }, /*0b4*/ - { { 0xb8,0},{ 0xf0,0xb8,0} }, { { 0xb9,0},{ 0xf0,0xb9,0} }, { { 0xba,0},{ 0xf0,0xba,0} }, { { 0xbb,0},{ 0xf0,0xbb,0} }, /*0b8*/ - { { 0xbc,0},{ 0xf0,0xbc,0} }, { { 0xbd,0},{ 0xf0,0xbd,0} }, { { 0xbe,0},{ 0xf0,0xbe,0} }, { { 0xbf,0},{ 0xf0,0xbf,0} }, /*0bc*/ - { { 0xc0,0},{ 0xf0,0xc0,0} }, { { 0xc1,0},{ 0xf0,0xc1,0} }, { { 0xc2,0},{ 0xf0,0xc2,0} }, { { 0xc3,0},{ 0xf0,0xc3,0} }, /*0c0*/ - { { 0xc4,0},{ 0xf0,0xc4,0} }, { { 0xc5,0},{ 0xf0,0xc5,0} }, { { 0xc6,0},{ 0xf0,0xc6,0} }, { { 0xc7,0},{ 0xf0,0xc7,0} }, /*0c4*/ - { { 0xc8,0},{ 0xf0,0xc8,0} }, { { 0xc9,0},{ 0xf0,0xc9,0} }, { { 0xca,0},{ 0xf0,0xca,0} }, { { 0xcb,0},{ 0xf0,0xcb,0} }, /*0c8*/ - { { 0xcc,0},{ 0xf0,0xcc,0} }, { { 0xcd,0},{ 0xf0,0xcd,0} }, { { 0xce,0},{ 0xf0,0xce,0} }, { { 0xcf,0},{ 0xf0,0xcf,0} }, /*0cc*/ - { { 0xd0,0},{ 0xf0,0xd0,0} }, { { 0xd1,0},{ 0xf0,0xd0,0} }, { { 0xd2,0},{ 0xf0,0xd2,0} }, { { 0xd3,0},{ 0xf0,0xd3,0} }, /*0d0*/ - { { 0xd4,0},{ 0xf0,0xd4,0} }, { { 0xd5,0},{ 0xf0,0xd5,0} }, { { 0xd6,0},{ 0xf0,0xd6,0} }, { { 0xd7,0},{ 0xf0,0xd7,0} }, /*0d4*/ - { { 0xd8,0},{ 0xf0,0xd8,0} }, { { 0xd9,0},{ 0xf0,0xd9,0} }, { { 0xda,0},{ 0xf0,0xda,0} }, { { 0xdb,0},{ 0xf0,0xdb,0} }, /*0d8*/ - { { 0xdc,0},{ 0xf0,0xdc,0} }, { { 0xdd,0},{ 0xf0,0xdd,0} }, { { 0xde,0},{ 0xf0,0xde,0} }, { { 0xdf,0},{ 0xf0,0xdf,0} }, /*0dc*/ - { { 0xe0,0},{ 0xf0,0xe0,0} }, { { 0xe1,0},{ 0xf0,0xe1,0} }, { { 0xe2,0},{ 0xf0,0xe2,0} }, { { 0xe3,0},{ 0xf0,0xe3,0} }, /*0e0*/ - { { 0xe4,0},{ 0xf0,0xe4,0} }, { { 0xe5,0},{ 0xf0,0xe5,0} }, { { 0xe6,0},{ 0xf0,0xe6,0} }, { { 0xe7,0},{ 0xf0,0xe7,0} }, /*0e4*/ - { { 0xe8,0},{ 0xf0,0xe8,0} }, { { 0xe9,0},{ 0xf0,0xe9,0} }, { { 0xea,0},{ 0xf0,0xea,0} }, { { 0xeb,0},{ 0xf0,0xeb,0} }, /*0e8*/ - { { 0xec,0},{ 0xf0,0xec,0} }, { { 0xed,0},{ 0xf0,0xed,0} }, { { 0xee,0},{ 0xf0,0xee,0} }, { { 0xef,0},{ 0xf0,0xef,0} }, /*0ec*/ - { { 0},{ 0} }, { { 0xf1,0},{ 0xf0,0xf1,0} }, { { 0xf2,0},{ 0xf0,0xf2,0} }, { { 0xf3,0},{ 0xf0,0xf3,0} }, /*0f0*/ - { { 0xf4,0},{ 0xf0,0xf4,0} }, { { 0xf5,0},{ 0xf0,0xf5,0} }, { { 0xf6,0},{ 0xf0,0xf6,0} }, { { 0xf7,0},{ 0xf0,0xf7,0} }, /*0f4*/ - { { 0xf8,0},{ 0xf0,0xf8,0} }, { { 0xf9,0},{ 0xf0,0xf9,0} }, { { 0xfa,0},{ 0xf0,0xfa,0} }, { { 0xfb,0},{ 0xf0,0xfb,0} }, /*0f8*/ - { { 0xfc,0},{ 0xf0,0xfc,0} }, { { 0xfd,0},{ 0xf0,0xfd,0} }, { { 0xfe,0},{ 0xf0,0xfe,0} }, { { 0xff,0},{ 0xf0,0xff,0} }, /*0fc*/ - - { { 0x62,0},{ 0xF0,0x62,0} }, { {0xe0,0x76,0},{0xe0,0xF0,0x76,0} }, { {0xe0,0x16,0},{0xe0,0xF0,0x16,0} }, { {0xe0,0x1E,0},{0xe0,0xF0,0x1E,0} }, /*100*/ - { {0xe0,0x26,0},{0xe0,0xF0,0x26,0} }, { {0xe0,0x25,0},{0xe0,0xF0,0x25,0} }, { {0xe0,0x2E,0},{0xe0,0xF0,0x2E,0} }, { {0xe0,0x36,0},{0xe0,0xF0,0x36,0} }, /*104*/ - { {0xe0,0x3D,0},{0xe0,0xF0,0x3D,0} }, { {0xe0,0x3E,0},{0xe0,0xF0,0x3E,0} }, { {0xe0,0x46,0},{0xe0,0xF0,0x46,0} }, { {0xe0,0x45,0},{0xe0,0xF0,0x45,0} }, /*108*/ - { {0xe0,0x4E,0},{0xe0,0xF0,0x4E,0} }, { { 0},{ 0} }, { {0xe0,0x66,0},{0xe0,0xF0,0x66,0} }, { {0xe0,0x0D,0},{0xe0,0xF0,0x0D,0} }, /*10c*/ - { {0xe0,0x15,0},{0xe0,0xF0,0x15,0} }, { {0xe0,0x1D,0},{0xe0,0xF0,0x1D,0} }, { {0xe0,0x24,0},{0xe0,0xF0,0x24,0} }, { {0xe0,0x2D,0},{0xe0,0xF0,0x2D,0} }, /*110*/ - { {0xe0,0x2C,0},{0xe0,0xF0,0x2C,0} }, { {0xe0,0x35,0},{0xe0,0xF0,0x35,0} }, { {0xe0,0x3C,0},{0xe0,0xF0,0x3C,0} }, { {0xe0,0x43,0},{0xe0,0xF0,0x43,0} }, /*114*/ - { {0xe0,0x44,0},{0xe0,0xF0,0x44,0} }, { {0xe0,0x4D,0},{0xe0,0xF0,0x4D,0} }, { {0xe0,0x54,0},{0xe0,0xF0,0x54,0} }, { {0xe0,0x5B,0},{0xe0,0xF0,0x5B,0} }, /*118*/ - { { 0x79,0},{ 0xf0,0x79,0} }, { { 0x58,0},{ 0xf0,0x58,0} }, { {0xe0,0x1C,0},{0xe0,0xF0,0x1C,0} }, { {0xe0,0x1B,0},{0xe0,0xF0,0x1B,0} }, /*11c*/ - { {0xe0,0x23,0},{0xe0,0xF0,0x23,0} }, { {0xe0,0x2B,0},{0xe0,0xF0,0x2B,0} }, { {0xe0,0x34,0},{0xe0,0xF0,0x34,0} }, { {0xe0,0x33,0},{0xe0,0xF0,0x33,0} }, /*120*/ - { {0xe0,0x3B,0},{0xe0,0xF0,0x3B,0} }, { {0xe0,0x42,0},{0xe0,0xF0,0x42,0} }, { {0xe0,0x4B,0},{0xe0,0xF0,0x4B,0} }, { { 0},{ 0} }, /*124*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*128*/ - { {0xe0,0x1A,0},{0xe0,0xF0,0x1A,0} }, { {0xe0,0x22,0},{0xe0,0xF0,0x22,0} }, { {0xe0,0x21,0},{0xe0,0xF0,0x21,0} }, { {0xe0,0x2A,0},{0xe0,0xF0,0x2A,0} }, /*12c*/ - { {0xe0,0x32,0},{0xe0,0xF0,0x32,0} }, { {0xe0,0x31,0},{0xe0,0xF0,0x31,0} }, { {0xe0,0x3A,0},{0xe0,0xF0,0x3A,0} }, { { 0},{ 0} }, /*130*/ - { {0xe0,0x49,0},{0xe0,0xF0,0x49,0} }, { { 0x77,0},{ 0xf0,0x77,0} }, { { 0},{ 0} }, { { 0x57,0},{ 0xf0,0x57,0} }, /*134*/ - { { 0x39,0},{ 0xf0,0x39,0} }, { { 0},{ 0} }, { {0xe0,0x58,0},{0xe0,0xF0,0x58,0} }, { {0xe0,0x05,0},{0xe0,0xF0,0x05,0} }, /*138*/ - { {0xe0,0x06,0},{0xe0,0xF0,0x06,0} }, { {0xe0,0x04,0},{0xe0,0xF0,0x04,0} }, { {0xe0,0x0C,0},{0xe0,0xF0,0x0C,0} }, { {0xe0,0x03,0},{0xe0,0xF0,0x03,0} }, /*13c*/ - { {0xe0,0x0B,0},{0xe0,0xF0,0x0B,0} }, { {0xe0,0x02,0},{0xe0,0xF0,0x02,0} }, { {0xe0,0x0A,0},{0xe0,0xF0,0x0A,0} }, { {0xe0,0x01,0},{0xe0,0xF0,0x01,0} }, /*140*/ - { {0xe0,0x09,0},{0xe0,0xF0,0x09,0} }, { { 0},{ 0} }, { {0xe0,0x7E,0},{0xe0,0xF0,0x7E,0} }, { { 0x6E,0},{ 0xf0,0x6E,0} }, /*144*/ - { { 0x63,0},{ 0xf0,0x63,0} }, { { 0x6F,0},{ 0xf0,0x6F,0} }, { { 0},{ 0} }, { { 0x61,0},{ 0xf0,0x61,0} }, /*148*/ - { {0xe0,0x73,0},{0xe0,0xF0,0x73,0} }, { { 0x6A,0},{ 0xf0,0x6A,0} }, { {0xe0,0x79,0},{0xe0,0xF0,0x79,0} }, { { 0x65,0},{ 0xf0,0x65,0} }, /*14c*/ - { { 0x60,0},{ 0xf0,0x60,0} }, { { 0x6D,0},{ 0xf0,0x6D,0} }, { { 0x67,0},{ 0xf0,0x67,0} }, { { 0x64,0},{ 0xf0,0x64,0} }, /*150*/ - { { 0xd4,0},{ 0xf0,0xD4,0} }, { {0xe0,0x60,0},{0xe0,0xF0,0x60,0} }, { { 0},{ 0} }, { {0xe0,0x78,0},{0xe0,0xF0,0x78,0} }, /*154*/ - { {0xe0,0x07,0},{0xe0,0xF0,0x07,0} }, { {0xe0,0x0F,0},{0xe0,0xF0,0x0F,0} }, { {0xe0,0x17,0},{0xe0,0xF0,0x17,0} }, { { 0x8B,0},{ 0xf0,0x8B,0} }, /*158*/ - { { 0x8C,0},{ 0xf0,0x8C,0} }, { { 0x8D,0},{ 0xf0,0x8D,0} }, { { 0},{ 0} }, { { 0x7F,0},{ 0xf0,0x7F,0} }, /*15c*/ - { { 0},{ 0} }, { {0xe0,0x4F,0},{0xe0,0xF0,0x4F,0} }, { {0xe0,0x56,0},{0xe0,0xF0,0x56,0} }, { { 0},{ 0} }, /*160*/ - { {0xe0,0x08,0},{0xe0,0xF0,0x08,0} }, { {0xe0,0x10,0},{0xe0,0xF0,0x10,0} }, { {0xe0,0x18,0},{0xe0,0xF0,0x18,0} }, { {0xe0,0x20,0},{0xe0,0xF0,0x20,0} }, /*164*/ - { {0xe0,0x28,0},{0xe0,0xF0,0x28,0} }, { {0xe0,0x30,0},{0xe0,0xF0,0x30,0} }, { {0xe0,0x38,0},{0xe0,0xF0,0x38,0} }, { {0xe0,0x40,0},{0xe0,0xF0,0x40,0} }, /*168*/ - { {0xe0,0x48,0},{0xe0,0xF0,0x48,0} }, { {0xe0,0x50,0},{0xe0,0xF0,0x50,0} }, { {0xe0,0x57,0},{0xe0,0xF0,0x57,0} }, { { 0},{ 0} }, /*16c*/ - { {0xe0,0x13,0},{0xe0,0xF0,0x13,0} }, { {0xe0,0x19,0},{0xe0,0xF0,0x19,0} }, { {0xe0,0x39,0},{0xe0,0xF0,0x39,0} }, { {0xe0,0x51,0},{0xe0,0xF0,0x51,0} }, /*170*/ - { {0xe0,0x53,0},{0xe0,0xF0,0x53,0} }, { {0xe0,0x5C,0},{0xe0,0xF0,0x5C,0} }, { { 0},{ 0} }, { {0xe0,0x62,0},{0xe0,0xF0,0x62,0} }, /*174*/ - { {0xe0,0x63,0},{0xe0,0xF0,0x63,0} }, { {0xe0,0x64,0},{0xe0,0xF0,0x64,0} }, { {0xe0,0x65,0},{0xe0,0xF0,0x65,0} }, { {0xe0,0x67,0},{0xe0,0xF0,0x67,0} }, /*178*/ - { {0xe0,0x68,0},{0xe0,0xF0,0x68,0} }, { {0xe0,0x6A,0},{0xe0,0xF0,0x6A,0} }, { {0xe0,0x6D,0},{0xe0,0xF0,0x6D,0} }, { {0xe0,0x6E,0},{0xe0,0xF0,0x6E,0} }, /*17c*/ - - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*180*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*184*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*188*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*18c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*190*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*194*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*198*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*19c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1ac*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1cc*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1dc*/ - { { 0},{ 0} }, { {0xe0,0xe1,0},{0xe0,0xF0,0xE1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xee,0},{0xe0,0xF0,0xEE,0} }, { { 0},{ 0} }, /*1ec*/ - { { 0},{ 0} }, { {0xe0,0xf1,0},{0xe0,0xF0,0xF1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{0xe0,0xF0,0xFE,0} }, { {0xe0,0xff,0},{0xe0,0xF0,0xFF,0} } /*1fc*/ -}; - - -static void add_data_kbd(uint16_t val); - - -#if (!defined(RELEASE_BUILD) && defined(ENABLE_KBD_AT_LOG)) -int kbd_at_do_log = ENABLE_KBD_AT_LOG; - - -static void -kbd_log(atkbd_t *dev, const char *fmt, ...) -{ - va_list ap; - - if ((dev == NULL) || (dev->log == NULL)) - return; - - if (kbd_at_do_log) { - va_start(ap, fmt); - log_out(dev->log, fmt, ap); - va_end(ap); - } -} -#else -#define kbd_log(dev, fmt, ...) -#endif - - -/* TODO: Get rid of keyboard_mode entirely - keyboard.c just need to know which scan codes to - send break codes for and which to repeat. - The break code stuff, though, might also be doable on the AT keyboard side, if F0 F0 - is never sent. */ -static void -set_scancode_map(atkbd_t *dev) -{ - switch (keyboard_mode & 3) { -#ifdef USE_SET1 - case 1: - default: - keyboard_set_table(scancode_set1); - break; -#else - default: -#endif - case 2: - keyboard_set_table(scancode_set2); - break; - - case 3: - keyboard_set_table(scancode_set3); - break; - } - - if (keyboard_mode & 0x20) -#ifdef USE_SET1 - keyboard_set_table(scancode_set1); -#else - keyboard_set_table(scancode_set2); -#endif -} - - - -/* TODO: Move the queues to the device. */ -static void -kbc_queue_reset(uint8_t channel) -{ - if (channel == 2) { - mouse_queue_start = mouse_queue_end = 0; - memset(mouse_queue, 0x00, sizeof(mouse_queue)); - } else if (channel == 1) { - dev->queue_start = dev->queue_end = 0; - memset(dev->queue, 0x00, sizeof(dev->queue)); - } -} - - -static void -add_data_kbd_queue(atkbd_t *dev, uint8_t val) -{ - if (!keyboard_scan || (dev->queue_end >= 16)) { - kbd_log(dev, "Unable to add to queue, conditions: %i, %i\n", !keyboard_scan, (dev->queue_end >= 16)); - return; - } - - kbd_log(dev, "dev->queue[%02X] = %02X;\n", dev->queue_end, val); - dev->queue[dev->queue_end] = val; - dev->queue_end = (dev->queue_end + 1) & 0xf; -} - - -static void -kbd_send_to_host(atkbd_t *dev, uint8_t val) -{ - dev->kd.c_in = 1; - dev->kd.c_data = val; - - dev->last_byte = val; -} - - -static void -kbd_reset(atkbd_t *dev) -{ - kbc_queue_reset(1); - dev->kd.c_in = 0x00; - /* TODO: Move this to the keyboard struct. */ - dev->last_byte = 0x00; - - /* Set scan code set to 2. */ - keyboard_mode = (keyboard_mode & 0xfc) | 0x02; - set_scancode_map(dev); - - dev->phase = 0; - dev->in = 0; - - memset(keyboard_set3_flags, 0, 512); -} - - -static void -kbd_command(atkbd_t *dev) -{ - uint8_t val = dev->kd.d_data; - - if ((dev->phase > 0) && (dev->cmd == 0xff)) { - dev->phase++; - if (dev->phase == RESET_DELAY_TIME) { - kbd_send_to_host(dev, 0xaa); - dev->phase = 0; - dev->cmd = 0x00; - } - return; - } - - if (dev->phase == 2) { - dev->phase = 0; - - switch (dev->cmd) { - case 0xf2: - kbd_send_to_host(dev, 0x83); - break; - default: - log_fatal(dev->log, "Invalid command for phase 2: %02X\n", dev->cmd); - break; - } - - /* Keyboard command is now done. */ - if (dev->phase == 0) - dev->cmd = 0x00; - return; - } else if (dev->phase == 1) { - dev->phase = 0; - - switch (dev->cmd) { - case 0xf0: - kbd_log(dev, "Get scan code set: %02X\n", keyboard_mode & 3); - kbd_send_to_host(dev, keyboard_mode & 3); - break; - case 0xf2: - kbd_send_to_host(dev, 0xab); - dev->phase = 2; - break; - default: - log_fatal(dev->log, "Invalid command for phase 1: %02X\n", dev->cmd); - break; - } - - /* Keyboard command is now done. */ - if (dev->phase == 0) - dev->cmd = 0x00; - return; - } - - if (dev->in && (val < 0xed)) { - dev->in = 0; - dev->phase = 0; - - switch (dev->cmd) { - case 0xed: /* set/reset LEDs */ - kbd_log(dev, "Set LEDs: %02X\n", val); - kbd_send_to_host(dev, 0xfa); - break; - - case 0xf0: /* get/set scancode set */ - kbd_send_to_host(dev, 0xfa); - if (val == 0) - dev->phase = 1; - else { - if ((val <= 3) && (val != 1)) { - keyboard_mode &= 0xfc; - keyboard_mode |= (val & 3); - kbd_log(dev, "Scan code set now: %02X\n", val); - } - set_scancode_map(dev); - } - break; - - case 0xf3: /* set typematic rate/delay */ - kbd_send_to_host(dev, 0xfa); - break; - - default: - kbd_log(dev, "Bad keyboard 0060 write %02X command %02X\n", val, dev->cmd); - kbd_send_to_host(dev, 0xfe); - break; - } - - /* Keyboard command is now done. */ - if (dev->phase == 0) - dev->cmd = 0x00; - } else { - /* No keyboard command in progress. */ - dev->in = 0; - dev->cmd = 0x00; - dev->phase = 0; - - switch (val) { - case 0x00: - kbd_log(dev, "Command 00\n"); - kbd_send_to_host(dev, 0xfa); - break; - - case 0x05: /*??? - sent by NT 4.0*/ - kbd_log(dev, "Command 05 (NT 4.0)\n"); - kbd_send_to_host(dev, 0xfe); - break; - - case 0xed: /* set/reset LEDs */ - kbd_log(dev, "Set/reset LEDs\n"); - kbd_send_to_host(dev, 0xfa); - - dev->in = 1; - break; - - case 0xee: /* diagnostic echo */ - kbd_log(dev, "Diagnostic echo\n"); - kbd_send_to_host(dev, 0xee); - break; - - case 0xef: /* NOP (reserved for future use) */ - kbd_log(dev, "NOP (reserved for future use)\n"); - break; - - case 0xf0: /* get/set scan code set */ - kbd_log(dev, "Get/set scan code set\n"); - kbd_send_to_host(dev, 0xfa); - dev->in = 1; - break; - - case 0xf2: /* read ID */ - /* Fixed as translation will be done in add_data_kbd(). */ - kbd_log(dev, "Read keyboard ID\n"); - /* TODO: After keyboard type selection is implemented, make this - return the correct keyboard ID for the selected type. */ - kbd_send_to_host(dev, 0xfa); - dev->phase = 1; - break; - - case 0xf3: /* set typematic rate/delay */ - kbd_log(dev, "Set typematic rate/delay\n"); - kbd_send_to_host(dev, 0xfa); - dev->in = 1; - break; - - case 0xf4: /* enable keyboard */ - kbd_log(dev, "Enable keyboard\n"); - kbd_send_to_host(dev, 0xfa); - keyboard_scan = 1; - break; - - case 0xf5: /* set defaults and disable keyboard */ - case 0xf6: /* set defaults */ - kbd_log(dev, "Set defaults%s\n", (val == 0xf6) ? "" : " and disable keyboard"); - keyboard_scan = (val == 0xf6); - kbd_log(dev, "val = %02X, keyboard_scan = %i, dev->mem[0x20] = %02X\n", - val, keyboard_scan, dev->mem[0x20]); - kbd_send_to_host(dev, 0xfa); - - keyboard_set3_all_break = 0; - keyboard_set3_all_repeat = 0; - memset(keyboard_set3_flags, 0, 512); - keyboard_mode = (keyboard_mode & 0xfc) | 0x02; - set_scancode_map(dev); - break; - - case 0xf7: /* set all keys to repeat */ - kbd_log(dev, "Set all keys to repeat\n"); - kbd_send_to_host(dev, 0xfa); - keyboard_set3_all_break = 1; - break; - - case 0xf8: /* set all keys to give make/break codes */ - kbd_log(dev, "Set all keys to give make/break codes\n"); - kbd_send_to_host(dev, 0xfa); - keyboard_set3_all_break = 1; - break; - - case 0xf9: /* set all keys to give make codes only */ - kbd_log(dev, "Set all keys to give make codes only\n"); - kbd_send_to_host(dev, 0xfa); - keyboard_set3_all_break = 0; - break; - - case 0xfa: /* set all keys to repeat and give make/break codes */ - kbd_log(dev, "Set all keys to repeat and give make/break codes\n"); - kbd_send_to_host(dev, 0xfa); - keyboard_set3_all_repeat = 1; - keyboard_set3_all_break = 1; - break; - - case 0xfe: /* resend last scan code */ - kbd_log(dev, "Reset last scan code\n"); - kbd_send_to_host(dev, dev->last_byte); - break; - - case 0xff: /* reset */ - kbd_log(dev, "Reset\n"); - kbd_reset(dev); - kbd_send_to_host(dev, 0xfa); - dev->phase = 1; - break; - - default: - kbd_log(dev, "Bad keyboard command %02X\n", val); - kbd_send_to_host(dev, 0xfe); - } - - /* If command needs data, remember command. */ - if ((dev->in == 1) || (dev->phase > 0)) - dev->cmd = val; - } -} - - -static void -kbd_do_command(atkbd_t *dev) -{ - kbd_command(dev); - if (dev->kd.d_in) - dev->state = KBD_CMD_PROCESS; - else if ((dev->phase == 0) && !dev->in) { - dev->in_cmd = 0; - if (dev->kd.d_data != 0xf5) - keyboard_scan = 1; - dev->state = KBD_MAIN_LOOP; - } else { - keyboard_scan = 0; - dev->in_cmd = 1; - dev->state = KBD_CMD_PROCESS; - } -} - - -static void -kbd_nack(atkbd_t *dev) -{ - kbd_send_to_host(dev, 0xfe); - dev->state = KBD_MAIN_LOOP; -} - - -static void -kbd_main_loop(atkbd_t *dev) -{ - uint8_t scan = !dev->kd.inhibit && keyboard_scan; - - if (dev->kd.d_in) { - dev->kd.d_in = 0; - kbd_cmd_process(dev); - } else if (scan && (dev->queue_start != dev->queue_end)) { - /* Scan here. */ - kbd_log(dev, "Get %02X from FIFO\n", dev->queue[dev->queue_start]); - kbd_send_to_host(dev, dev->queue[dev->queue_start]); - dev->queue_start = (dev->queue_start + 1) & 0xf; - } -} - - -static void -kbd_cmd_process(atkbd_t *dev) -{ - uint8_t written = dev->kd.d_in; - - /* We want data, nothing has been written yet, return. */ - if (dev->in && !dev->kd.d_in) - return; - - dev->kd.d_in = 0; - - if (!written && !keyboard_scan && dev->in_cmd && (dev->phase > 0)) { - kbd_log(dev, "Keyboard not written, not scanning, in command, and phase > 0\n"); - kbd_do_command(dev); - } else if (dev->kd.d_data == 0xfe) { - kbd_log(dev, "Send last byte: %02X\n", dev->last_byte); - kbd_send_to_host(dev, dev->last_byte); - dev->state = KBD_MAIN_LOOP; - } else if (dev->kd.d_data == 0xee) { - kbd_log(dev, "Diagnostic echo: EE\n"); - kbd_send_to_host(dev, 0xee); - dev->state = KBD_MAIN_LOOP; - } else if (dev->kd.d_data >= 0xed) { - kbd_log(dev, "Command %02X\n", dev->kd.d_data); - if (!keyboard_scan && dev->in_cmd && (dev->cmd == 0xed)) { - kbd_log(dev, "Not scanning, in command, old command is ED\n"); - keyboard_scan = 1; - dev->in_cmd = 0; - } - kbd_do_command(dev); - } else { - if (!keyboard_scan && dev->in_cmd) { - if ((dev->cmd == 0xf3) && (dev->kd.d_data & 0x80)) { - kbd_log(dev, "Command F3 data %02X has bit 7 set\n", dev->kd.d_data); - kbd_nack(dev); - } else { - kbd_log(dev, "Command %02X data %02X\n", dev->cmd, dev->kd.d_data); - kbd_do_command(dev); - } - } else { - kbd_log(dev, "Scanning or not in command, NACK\n"); - kbd_nack(dev); - } - } -} - - -/* Keyboard processing */ -static void -kbd_process(atkbd_t *dev) -{ - /* The real 8048 keyboard firmware stops transmitting if host wants to transmit. */ - if (dev->kd.c_in && dev->kd.d_in) - dev->kd.c_in = 0; - - /* The host has either acknowledged the transmitted byte or we have not transmitted anything (yet). */ - if (!dev->kd.c_in) switch (dev->state) { - case KBD_MAIN_LOOP: - kbd_main_loop(dev); - break; - case KBD_CMD_PROCESS: - kbd_cmd_process(dev); - break; - } -} - - -static void -add_data_vals(atkbd_t *dev, uint8_t *val, uint8_t len) -{ - int i; - - for (i = 0; i < len; i++) - add_data_kbd_queue(dev, val[i]); -} - - -static void -add_data_kbd(uint16_t val) -{ - atkbd_t *dev = SavedKbd; - uint8_t fake_shift[4]; - uint8_t num_lock = 0, shift_states = 0; - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - - if (dev->in || (dev->phase > 0)) - return; - - keyboard_get_states(NULL, &num_lock, NULL); - shift_states = keyboard_get_shift() & STATE_SHIFT_MASK; - - /* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */ - if ((dev != NULL) && (kbc_ven == KBC_VEN_TOSHIBA) && (keyboard_recv(0xb8) || keyboard_recv(0x9d)) && - (val >= 0x4f) && (val <= 0x54) && (val != 0x4e)) - t3100e_notify_set((val + 2) & 0x0f); - - switch(val) { - case FAKE_LSHIFT_ON: - kbd_log(dev, "Fake left shift on, scan code: "); - if (num_lock) { - if (shift_states) { - kbd_log(dev, "N/A (one or both shifts on)\n"); - break; - } else { - /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ - switch(keyboard_mode & 0x02) { - case 1: - fake_shift[0] = 0xe0; fake_shift[1] = 0x2a; - add_data_vals(dev, fake_shift, 2); - break; - - case 2: - fake_shift[0] = 0xe0; fake_shift[1] = 0x12; - add_data_vals(dev, fake_shift, 2); - break; - - default: - kbd_log(dev, "N/A (scan code set %i)\n", keyboard_mode & 0x02); - break; - } - } - } else { - if (shift_states & STATE_LSHIFT) { - /* Num lock off and left shift pressed. */ - switch(keyboard_mode & 0x02) { - case 1: - fake_shift[0] = 0xe0; fake_shift[1] = 0xaa; - add_data_vals(dev, fake_shift, 2); - break; - - case 2: - fake_shift[0] = 0xe0; fake_shift[1] = 0xf0; fake_shift[2] = 0x12; - add_data_vals(dev, fake_shift, 3); - break; - - default: - kbd_log(dev, "N/A (scan code set %i)\n", keyboard_mode & 0x02); - break; - } - } - if (shift_states & STATE_RSHIFT) { - /* Num lock off and right shift pressed. */ - switch(keyboard_mode & 0x02) { - case 1: - fake_shift[0] = 0xe0; fake_shift[1] = 0xb6; - add_data_vals(dev, fake_shift, 2); - break; - - case 2: - fake_shift[0] = 0xe0; fake_shift[1] = 0xf0; fake_shift[2] = 0x59; - add_data_vals(dev, fake_shift, 3); - break; - - default: - kbd_log(dev, "N/A (scan code set %i)\n", keyboard_mode & 0x02); - break; - } - } - kbd_log(dev, shift_states ? "" : "N/A (both shifts off)\n"); - } - break; - - case FAKE_LSHIFT_OFF: - kbd_log(dev, "Fake left shift off, scan code: "); - if (num_lock) { - if (shift_states) { - kbd_log(dev, "N/A (one or both shifts on)\n"); - break; - } else { - /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ - switch(keyboard_mode & 0x02) { - case 1: - fake_shift[0] = 0xe0; fake_shift[1] = 0xaa; - add_data_vals(dev, fake_shift, 2); - break; - - case 2: - fake_shift[0] = 0xe0; fake_shift[1] = 0xf0; fake_shift[2] = 0x12; - add_data_vals(dev, fake_shift, 3); - break; - - default: - kbd_log(dev, "N/A (scan code set %i)\n", keyboard_mode & 0x02); - break; - } - } - } else { - if (shift_states & STATE_LSHIFT) { - /* Num lock off and left shift pressed. */ - switch(keyboard_mode & 0x02) { - case 1: - fake_shift[0] = 0xe0; fake_shift[1] = 0x2a; - add_data_vals(dev, fake_shift, 2); - break; - - case 2: - fake_shift[0] = 0xe0; fake_shift[1] = 0x12; - add_data_vals(dev, fake_shift, 2); - break; - - default: - kbd_log(dev, "N/A (scan code set %i)\n", keyboard_mode & 0x02); - break; - } - } - if (shift_states & STATE_RSHIFT) { - /* Num lock off and right shift pressed. */ - switch(keyboard_mode & 0x02) { - case 1: - fake_shift[0] = 0xe0; fake_shift[1] = 0x36; - add_data_vals(dev, fake_shift, 2); - break; - - case 2: - fake_shift[0] = 0xe0; fake_shift[1] = 0x59; - add_data_vals(dev, fake_shift, 2); - break; - - default: - kbd_log(dev, "N/A (scan code set %i)\n", keyboard_mode & 0x02); - break; - } - } - kbd_log(dev, shift_states ? "" : "N/A (both shifts off)\n"); - } - break; - - default: - add_data_kbd_queue(dev, val); - break; - } -} - - -static void -kbd_close(void *priv) -{ - atkbd_t *dev = (atkbd_t *)priv; - - kbd_reset(dev); - - keyboard_scan = 0; - keyboard_send = NULL; - - /* Disable the scancode maps. */ - keyboard_set_table(NULL); - -#if (!defined(RELEASE_BUILD) && defined(ENABLE_KBD_AT_LOG)) - log_close(dev->log); -#endif - - kbc_dev_attach(NULL, 1); - - SavedKbd = NULL; - free(dev); -} - - -static void * -kbd_init(const device_t *info) -{ - atkbd_t *dev; - - dev = (atkbd_t *)malloc(sizeof(atkbd_t)); - memset(dev, 0x00, sizeof(atkbd_t)); - - kbc_dev_attach(&(dev->kd), 1); - - kbd_send_to_host(dev, 0xaa); - - keyboard_send = add_data_kbd; - -#if (!defined(RELEASE_BUILD) && defined(ENABLE_KBD_AT_LOG)) - dev->kbd_log = log_open("AT KBD"); -#endif - - kbd_reset(dev); - - /* We need this, sadly. */ - SavedKbd = dev; - - return(dev); -} - - -const device_t keyboard_at_kbd_device = { - "PC/AT Keyboard (Actual keyboard!)", - 0, - 0, - kbd_init, - kbd_close, - kbd_reset, - { NULL }, NULL, NULL, NULL -}; diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 6a3d9c370..81455f5a6 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -57,7 +57,9 @@ #define STAT_IFULL 0x02 #define STAT_OFULL 0x01 -#define RESET_DELAY_TIME 1000 /* 100 ms */ +#define PS2_REFRESH_TIME (16 * TIMER_USEC) + +#define RESET_DELAY_TIME (100 * 10) /* 600ms */ #define CCB_UNUSED 0x80 #define CCB_TRANSLATE 0x40 @@ -72,136 +74,50 @@ #define MODE_MASK 0x6c #define KBC_TYPE_ISA 0x00 /* AT ISA-based chips */ -#define KBC_TYPE_PS2_1 0x04 /* PS2 type, no refresh */ -/* This only differs in that translation is forced off. */ -#define KBC_TYPE_PS2_2 0x05 /* PS2 on PS/2, type 2 */ -#define KBC_TYPE_MASK 0x07 +#define KBC_TYPE_PS2_NOREF 0x01 /* PS2 type, no refresh */ +#define KBC_TYPE_PS2_1 0x02 /* PS2 on PS/2, type 1 */ +#define KBC_TYPE_PS2_2 0x03 /* PS2 on PS/2, type 2 */ +#define KBC_TYPE_MASK 0x03 -#define KBC_FLAG_PS2 0x04 - -/* We need to redefine this: - Currently, we use bits 3-7 for vendor, we should instead use bits 4-7 - for vendor, 0-3 for revision/variant, and have a dev->ps2 flag controlling - controller mode, normally set according to the flags, but togglable on - AMIKey: - 0000 0000 0x00 IBM, AT - 0000 0001 0x01 MR - 0000 0010 0x02 Xi8088, clone of IBM PS/2 type 1 - 0001 0000 0x10 Olivetti - 0010 0000 0x20 Toshiba - 0011 0000 0x30 Quadtel - 0100 0000 0x40 Phoenix MultiKey/42 - 0101 0000 0x50 AMI KF - 0101 0001 0x51 AMI KH - 0101 0010 0x52 AMIKey - 0101 0011 0x53 AMIKey-2 - 0101 0100 0x54 JetKey (clone of AMI KF/AMIKey) - 0110 0000 0x60 Award - 0110 0001 0x61 Award 286 (has some AMI commands apparently) - 0111 0000 0x70 Siemens -*/ - -/* Standard IBM controller */ #define KBC_VEN_GENERIC 0x00 -/* All commands are standard PS/2 */ +#define KBC_VEN_AMI 0x04 #define KBC_VEN_IBM_MCA 0x08 -/* Standard IBM commands, differs in input port bits */ -#define KBC_VEN_IBM_PS1 0x10 -/* Olivetti - proprietary commands and port 62h with switches - readout */ -#define KBC_VEN_OLIVETTI 0x20 -/* Toshiba T3100e - has a bunch of proprietary commands, also sets - IFULL on command AA */ -#define KBC_VEN_TOSHIBA 0x28 -/* Standard IBM commands, uses input port as a switches readout */ -#define KBC_VEN_NCR 0x30 -/* Xi8088 - standard IBM commands, has a turbo bit on port 61h, and the - polarity of the video type bit in the input port is inverted */ -#define KBC_VEN_XI8088 0x38 -/* QuadtelKey - currently guesswork */ -#define KBC_VEN_QUADTEL 0x40 -/* Phoenix MultiKey/42 - not yet implemented */ -#define KBC_VEN_PHOENIX 0x48 -/* Generic commands, XI8088-like input port handling of video type, - maybe we just need a flag for that? */ -#define KBC_VEN_ACER 0x50 -/* AMI KF/KH/AMIKey/AMIKey-2 */ -#define KBC_VEN_AMI 0xf0 -/* Standard AMI commands, differs in input port bits */ -#define KBC_VEN_INTEL_AMI 0xf8 -#define KBC_VEN_MASK 0xf8 - - -/* Flags should be fully 32-bit: - Bits 7- 0: Vendor and revision/variant; - Bits 15- 8: Input port mask; - Bits 23-16: Input port bits that are always on; - Bits 31-24: Flags: - Bit 0: Invert P1 video type bit polarity; - Bit 1: Is PS/2; - Bit 2: Translation forced always off. - - So for example, the IBM PS/2 type 1 controller flags would be: 00000010 00000000 11111111 00000000 = 0200ff00 . */ +#define KBC_VEN_QUADTEL 0x0c +#define KBC_VEN_TOSHIBA 0x10 +#define KBC_VEN_XI8088 0x14 +#define KBC_VEN_IBM_PS1 0x18 +#define KBC_VEN_ACER 0x1c +#define KBC_VEN_INTEL_AMI 0x20 +#define KBC_VEN_OLIVETTI 0x24 +#define KBC_VEN_NCR 0x28 +#define KBC_VEN_SAMSUNG 0x2c +#define KBC_VEN_MASK 0x3c typedef struct { - uint8_t status, ib, ob, p1, p2, old_p2, p2_locked, fast_a20_phase, - secr_phase, mem_index, ami_stat, ami_mode, - kbc_in, kbc_cmd, kbc_in_cmd, kbc_poll_phase, kbc_to_send, - kbc_send_pending, kbc_channel, kbc_stat_hi, kbc_wait_for_response, inhibit, - kbd_in, kbd_cmd, kbd_in_cmd, kbd_written, kbd_data, kbd_poll_phase, kbd_inhibit, - mouse_in, mouse_cmd, mouse_in_cmd, mouse_written, mouse_data, mouse_poll_phase, mouse_inhibit, - kbc_written[3], kbc_data[3]; + uint8_t command, status, old_status, out, old_out, secr_phase, + mem_addr, input_port, output_port, old_output_port, + key_command, output_locked, ami_stat, want60, + wantirq, key_wantdata, refresh, first_write, + ami_flags, pad[7]; - uint8_t mem_int[0x40], mem[0x240]; + uint8_t mem[0x100]; - uint16_t last_irq, kbc_phase, kbd_phase, mouse_phase; + int last_irq, old_last_irq, + reset_delay, + out_new, out_delayed; uint32_t flags; - pc_timer_t pulse_cb, send_delay_timer; + pc_timer_t refresh_time, pulse_cb; uint8_t (*write60_ven)(void *p, uint8_t val); uint8_t (*write64_ven)(void *p, uint8_t val); + + pc_timer_t send_delay_timer; } atkbd_t; -enum -{ - CHANNEL_KBC = 0, - CHANNEL_KBD, - CHANNEL_MOUSE -}; - -enum -{ - KBD_MAIN_LOOP = 0, - KBD_CMD_PROCESS -}; - -enum -{ - MOUSE_MAIN_LOOP_1 = 0, - MOUSE_CMD_PROCESS, - MOUSE_CMD_END, - MOUSE_MAIN_LOOP_2 -}; - -enum { - KBC_MAIN_LOOP = 0, - KBC_RESET = 1, - KBC_WAIT = 4, - KBC_WAIT_FOR_KBD, - KBC_WAIT_FOR_MOUSE, - KBC_WAIT_FOR_BOTH -}; - - -static void kbd_cmd_process(atkbd_t *dev); - -static void kbc_wait(atkbd_t *dev, uint8_t flags); - - /* bit 0 = repeat, bit 1 = makes break code? */ uint8_t keyboard_set3_flags[512]; uint8_t keyboard_set3_all_repeat; @@ -210,9 +126,9 @@ uint8_t keyboard_set3_all_break; /* Bits 0 - 1 = scan code set, bit 6 = translate or not. */ uint8_t keyboard_mode = 0x42; -uint8_t * ami_copr = (uint8_t *) "(C)1994 AMI"; - +static uint8_t key_ctrl_queue[16]; +static int key_ctrl_queue_start = 0, key_ctrl_queue_end = 0; static uint8_t key_queue[16]; static int key_queue_start = 0, key_queue_end = 0; uint8_t mouse_queue[16]; @@ -653,27 +569,9 @@ static const scancode scancode_set3[512] = { }; -#define UISTR_LEN 256 -static char kbd_str[UISTR_LEN]; /* UI output string */ static void add_data_kbd(uint16_t val); -extern void ui_sb_bugui(char *__str); - - -static void -kbd_status(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vsprintf(kbd_str, fmt, ap); - ui_sb_bugui(kbd_str); - va_end(ap); -} - - -// #define ENABLE_KEYBOARD_AT_LOG 1 #ifdef ENABLE_KEYBOARD_AT_LOG int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG; @@ -734,6 +632,9 @@ kbc_queue_reset(uint8_t channel) } else if (channel == 1) { key_queue_start = key_queue_end = 0; memset(key_queue, 0x00, sizeof(key_queue)); + } else { + key_ctrl_queue_start = key_ctrl_queue_end = 0; + memset(key_ctrl_queue, 0x00, sizeof(key_ctrl_queue)); } } @@ -741,6 +642,15 @@ kbc_queue_reset(uint8_t channel) static void kbc_queue_add(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) { + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + + if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) + stat_hi |= ((dev->input_port & 0x80) ? 0x10 : 0x00); + else + stat_hi |= 0x10; + + dev->status = (dev->status & 0x0f) | stat_hi; + if (channel == 2) { kbd_log("ATkbc: mouse_queue[%02X] = %02X;\n", mouse_queue_end, val); mouse_queue[mouse_queue_end] = val; @@ -749,1054 +659,83 @@ kbc_queue_add(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); key_queue[key_queue_end] = val; key_queue_end = (key_queue_end + 1) & 0xf; - } else - fatal("Adding %02X to invalid channel %02X\n", val, channel); + } else { + kbd_log("ATkbc: key_ctrl_queue[%02X] = %02X;\n", key_ctrl_queue_end, val); + key_ctrl_queue[key_ctrl_queue_end] = val; + key_ctrl_queue_end = (key_ctrl_queue_end + 1) & 0xf; + } +} + + +static void +add_to_kbc_queue_front(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) +{ + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + + if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) + stat_hi |= ((dev->input_port & 0x80) ? 0x10 : 0x00); + else + stat_hi |= 0x10; + + kbd_log("ATkbc: Adding %02X to front...\n", val); + dev->wantirq = 0; + if (channel == 2) { + if (dev->mem[0] & 0x02) + picint(0x1000); + dev->last_irq = 0x1000; + } else { + if (dev->mem[0] & 0x01) + picint(2); + dev->last_irq = 2; + } + dev->out = val; + if (channel == 2) + dev->status = (dev->status & ~STAT_IFULL) | (STAT_OFULL | STAT_MFULL) | stat_hi; + else + dev->status = (dev->status & ~(STAT_IFULL | STAT_MFULL)) | STAT_OFULL | stat_hi; } static void add_data_kbd_queue(atkbd_t *dev, int direct, uint8_t val) { - if ((!keyboard_scan && !direct) || (key_queue_end >= 16)) { - kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i\n", !keyboard_scan, (key_queue_end >= 16)); + if ((!keyboard_scan && !direct) || (dev->reset_delay > 0) || (key_queue_end >= 16)) { + kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i, %i\n", !keyboard_scan, (dev->reset_delay > 0), (key_queue_end >= 16)); return; } - - kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); + kbd_log("ATkbc: key_queue[%02X] = %02X;\n", key_queue_end, val); kbc_queue_add(dev, val, 1, 0x00); kbd_last_scan_code = val; } -static void -kbc_send(atkbd_t *dev, uint8_t val, uint8_t channel) -{ - dev->kbc_written[channel] = 1; - dev->kbc_data[channel] = val; -} - static void -kbd_send_to_host(atkbd_t *dev, uint8_t val) +add_data_kbd_direct(atkbd_t *dev, uint8_t val) { - kbc_send(dev, val, CHANNEL_KBD); -} + int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); + int translate = (keyboard_mode & 0x40); + uint8_t send; - -static void -kbd_chip_reset(atkbd_t *dev) -{ - kbc_queue_reset(1); - dev->kbc_written[1] = 0x00; - kbd_last_scan_code = 0x00; - - /* Set scan code set to 2. */ - keyboard_mode = (keyboard_mode & 0xfc) | 0x02; - set_scancode_map(dev); - - dev->kbd_phase = 0; - dev->kbd_in = 0; -} - - -static void -kbd_command(atkbd_t *dev) -{ - uint8_t val = dev->kbd_data; - - if ((dev->kbd_phase > 0) && (dev->kbd_cmd == 0xff)) { - dev->kbd_phase++; - if (dev->kbd_phase == RESET_DELAY_TIME) { - kbd_send_to_host(dev, 0xaa); - dev->kbd_phase = 0; - dev->kbd_cmd = 0x00; - } - return; - } - - if (dev->kbd_phase == 2) { - dev->kbd_phase = 0; - - switch (dev->kbd_cmd) { - case 0xf2: - kbd_send_to_host(dev, 0x83); - break; - default: - fatal("Invalid command for phase 2: %02X\n", dev->kbd_cmd); - break; - } - - /* Keyboard command is now done. */ - if (dev->kbd_phase == 0) - dev->kbd_cmd = 0x00; - return; - } else if (dev->kbd_phase == 1) { - dev->kbd_phase = 0; - - switch (dev->kbd_cmd) { - case 0xf0: - kbd_log("Get scan code set: %02X\n", keyboard_mode & 3); - kbd_send_to_host(dev, keyboard_mode & 3); - break; - case 0xf2: - kbd_send_to_host(dev, 0xab); - dev->kbd_phase = 2; - break; - default: - fatal("Invalid command for phase 1: %02X\n", dev->kbd_cmd); - break; - } - - /* Keyboard command is now done. */ - if (dev->kbd_phase == 0) - dev->kbd_cmd = 0x00; - return; - } - - if (dev->kbd_in && (val < 0xed)) { - dev->kbd_in = 0; - dev->kbd_phase = 0; - - switch (dev->kbd_cmd) { - case 0xed: /* set/reset LEDs */ - kbd_log("ATkbd: set LEDs [%02x]\n", val); - kbd_send_to_host(dev, 0xfa); - break; - - case 0xf0: /* get/set scancode set */ - kbd_send_to_host(dev, 0xfa); - if (val == 0) - dev->kbd_phase = 1; - else { - if ((val <= 3) && (val != 1)) { - keyboard_mode &= 0xfc; - keyboard_mode |= (val & 3); - kbd_log("Scan code set now: %02X\n", val); - } - set_scancode_map(dev); - } - break; - - case 0xf3: /* set typematic rate/delay */ - kbd_send_to_host(dev, 0xfa); - break; - - default: - kbd_log("ATkbd: bad keyboard 0060 write %02X command %02X\n", val, dev->kbd_cmd); - kbd_send_to_host(dev, 0xfe); - break; - } - - /* Keyboard command is now done. */ - if (dev->kbd_phase == 0) - dev->kbd_cmd = 0x00; - } else { - /* No keyboard command in progress. */ - dev->kbd_in = 0; - dev->kbd_cmd = 0x00; - dev->kbd_phase = 0; - - switch (val) { - case 0x00: - kbd_log("ATkbd: command 00\n"); - kbd_send_to_host(dev, 0xfa); - break; - - case 0x05: /*??? - sent by NT 4.0*/ - kbd_log("ATkbd: command 05 (NT 4.0)\n"); - kbd_send_to_host(dev, 0xfe); - break; - - case 0xed: /* set/reset LEDs */ - kbd_log("ATkbd: set/reset leds\n"); - kbd_send_to_host(dev, 0xfa); - - dev->kbd_in = 1; - break; - - case 0xee: /* diagnostic echo */ - kbd_log("ATkbd: ECHO\n"); - kbd_send_to_host(dev, 0xee); - break; - - case 0xef: /* NOP (reserved for future use) */ - kbd_log("ATkbd: NOP\n"); - break; - - case 0xf0: /* get/set scan code set */ - kbd_log("ATkbd: scan code set\n"); - kbd_send_to_host(dev, 0xfa); - dev->kbd_in = 1; - break; - - case 0xf2: /* read ID */ - /* Fixed as translation will be done in add_data_kbd(). */ - kbd_log("ATkbd: read keyboard id\n"); - /* TODO: After keyboard type selection is implemented, make this - return the correct keyboard ID for the selected type. */ - kbd_send_to_host(dev, 0xfa); - dev->kbd_phase = 1; - break; - - case 0xf3: /* set typematic rate/delay */ - kbd_log("ATkbd: set typematic rate/delay\n"); - kbd_send_to_host(dev, 0xfa); - dev->kbd_in = 1; - break; - - case 0xf4: /* enable keyboard */ - kbd_log("ATkbd: enable keyboard\n"); - kbd_send_to_host(dev, 0xfa); - keyboard_scan = 1; - break; - - case 0xf5: /* set defaults and disable keyboard */ - case 0xf6: /* set defaults */ - kbd_log("ATkbd: set defaults%s\n", (val == 0xf6) ? "" : " and disable keyboard"); - keyboard_scan = (val == 0xf6); - kbd_log("val = %02X, keyboard_scan = %i, dev->mem[0x20] = %02X\n", - val, keyboard_scan, dev->mem[0x20]); - kbd_send_to_host(dev, 0xfa); - - keyboard_set3_all_break = 0; - keyboard_set3_all_repeat = 0; - memset(keyboard_set3_flags, 0, 512); - keyboard_mode = (keyboard_mode & 0xfc) | 0x02; - set_scancode_map(dev); - break; - - case 0xf7: /* set all keys to repeat */ - kbd_log("ATkbd: set all keys to repeat\n"); - kbd_send_to_host(dev, 0xfa); - keyboard_set3_all_break = 1; - break; - - case 0xf8: /* set all keys to give make/break codes */ - kbd_log("ATkbd: set all keys to give make/break codes\n"); - kbd_send_to_host(dev, 0xfa); - keyboard_set3_all_break = 1; - break; - - case 0xf9: /* set all keys to give make codes only */ - kbd_log("ATkbd: set all keys to give make codes only\n"); - kbd_send_to_host(dev, 0xfa); - keyboard_set3_all_break = 0; - break; - - case 0xfa: /* set all keys to repeat and give make/break codes */ - kbd_log("ATkbd: set all keys to repeat and give make/break codes\n"); - kbd_send_to_host(dev, 0xfa); - keyboard_set3_all_repeat = 1; - keyboard_set3_all_break = 1; - break; - - case 0xfe: /* resend last scan code */ - kbd_log("ATkbd: reset last scan code\n"); - kbd_send_to_host(dev, kbd_last_scan_code); - break; - - case 0xff: /* reset */ - kbd_log("ATkbd: kbd reset\n"); - kbd_chip_reset(dev); - kbd_send_to_host(dev, 0xfa); - dev->kbd_phase = 1; - break; - - default: - kbd_log("ATkbd: bad keyboard command %02X\n", val); - kbd_send_to_host(dev, 0xfe); - } - - /* If command needs data, remember command. */ - if ((dev->kbd_in == 1) || (dev->kbd_phase > 0)) - dev->kbd_cmd = val; - } -} - - -static void -kbd_do_command(atkbd_t *dev) -{ - kbd_command(dev); - if (dev->kbd_written) - dev->kbd_poll_phase = KBD_CMD_PROCESS; - else if ((dev->kbd_phase == 0) && !dev->kbd_in) { - dev->kbd_in_cmd = 0; - if (dev->kbd_data != 0xf5) - keyboard_scan = 1; - dev->kbd_poll_phase = KBD_MAIN_LOOP; - } else { - keyboard_scan = 0; - dev->kbd_in_cmd = 1; - dev->kbd_poll_phase = KBD_CMD_PROCESS; - } -} - - -static void -kbd_nack(atkbd_t *dev) -{ - kbd_send_to_host(dev, 0xfe); - dev->kbd_poll_phase = KBD_MAIN_LOOP; -} - - -static void -kbd_main_loop(atkbd_t *dev) -{ - uint8_t scan = !dev->kbd_inhibit && keyboard_scan; - - if (dev->kbd_written) { - dev->kbd_written = 0; - kbd_cmd_process(dev); - } else if (scan && (key_queue_start != key_queue_end)) { - /* Scan here. */ - kbd_log("ATkbd: Get %02X from FIFO\n", key_queue[key_queue_start]); - kbd_send_to_host(dev, key_queue[key_queue_start]); - key_queue_start = (key_queue_start + 1) & 0xf; - } -} - - -static void -kbd_cmd_process(atkbd_t *dev) -{ - uint8_t written = dev->kbd_written; - - /* We want data, nothing has been written yet, return. */ - if (dev->kbd_in && !dev->kbd_written) + if (dev->reset_delay) return; - dev->kbd_written = 0; + translate = translate || (keyboard_mode & 0x40) || xt_mode; + translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); - if (!written && !keyboard_scan && dev->kbd_in_cmd && (dev->kbd_phase > 0)) { - kbd_log("ATkbd: Keyboard not written, not scanning, in command, and phase > 0\n"); - kbd_do_command(dev); - } else if (dev->kbd_data == 0xfe) { - kbd_log("ATkbd: Send last byte %02X\n", kbd_last_scan_code); - kbd_send_to_host(dev, kbd_last_scan_code); - dev->kbd_poll_phase = KBD_MAIN_LOOP; - } else if (dev->kbd_data == 0xee) { - kbd_log("ATkbd: Echo EE\n"); - kbd_send_to_host(dev, 0xee); - dev->kbd_poll_phase = KBD_MAIN_LOOP; - } else if (dev->kbd_data >= 0xed) { - kbd_log("ATkbd: Command %02X\n", dev->kbd_data); - if (!keyboard_scan && dev->kbd_in_cmd && (dev->kbd_cmd == 0xed)) { - kbd_log("ATkbd: Not scanning, in command, old command is ED\n"); - keyboard_scan = 1; - dev->kbd_in_cmd = 0; - } - kbd_do_command(dev); - } else { - if (!keyboard_scan && dev->kbd_in_cmd) { - if ((dev->kbd_cmd == 0xf3) && (dev->kbd_data & 0x80)) { - kbd_log("ATkbd: Command F3 data %02X has bit 7 set\n", dev->kbd_data); - kbd_nack(dev); - } else { - kbd_log("ATkbd: Command %02X data %02X\n", dev->kbd_cmd, dev->kbd_data); - kbd_do_command(dev); - } - } else { - kbd_log("ATkbd: Scanning or not in command, NACK\n"); - kbd_nack(dev); - } - } -} + if (translate) + send = nont_to_t[val]; + else + send = val; - -/* Keyboard processing */ -static void -kbd_process(atkbd_t *dev) -{ - /* The real 8048 keyboard firmware stops transmitting if host wants to transmit. */ - if (dev->kbc_written[1] && dev->kbd_written) - dev->kbc_written[1] = 0; - - /* The host has either acknowledged the transmitted byte or we have not transmitted anything (yet). */ - if (!dev->kbc_written[1]) switch (dev->kbd_poll_phase) { - case KBD_MAIN_LOOP: - kbd_main_loop(dev); - break; - case KBD_CMD_PROCESS: - kbd_cmd_process(dev); - break; - } + add_data_kbd_queue(dev, 1, send); } static void -kbc_send_to_ob(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) +add_data_kbd_raw(atkbd_t *dev, uint8_t val) { - uint8_t ch = (channel > 0) ? channel : 1; - uint8_t do_irq = (dev->mem[0x20] & ch); - int translate = (channel == 1) && (keyboard_mode & 0x60); - - if ((channel == 2) && !(dev->flags & KBC_FLAG_PS2)) - return; - - stat_hi |= dev->inhibit; - - if (!dev->kbc_send_pending) { - dev->kbc_send_pending = 1; - dev->kbc_to_send = val; - dev->kbc_channel = channel; - dev->kbc_stat_hi = stat_hi; - return; - } - - if (translate) { - /* Allow for scan code translation. */ - if (val == 0xf0) { - kbd_log("ATkbd: translate is on, F0 prefix detected\n"); - sc_or = 0x80; - return; - } - - /* Skip break code if translated make code has bit 7 set. */ - if ((sc_or == 0x80) && (val & 0x80)) { - kbd_log("ATkbd: translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val); - sc_or = 0; - return; - } - } - - dev->last_irq = (ch == 2) ? 0x1000 : 0x0002; - if (do_irq) { - kbd_log("[%04X:%08X] ATKbc: IRQ %i\n", CS, cpu_state.pc, (ch == 2) ? 12 : 1); - picint(dev->last_irq); - } - kbd_log("ATkbc: %02X coming from channel %i (%i)\n", val, channel, do_irq); - dev->ob = translate ? (nont_to_t[val] | sc_or) : val; - - dev->status = (dev->status & 0x0f) | (stat_hi | (dev->mem[0x20] & STAT_SYSFLAG) | STAT_OFULL); - if (ch == 2) - dev->status |= STAT_MFULL; - - if (translate && (sc_or == 0x80)) - sc_or = 0; -} - - -static void -write_output(atkbd_t *dev, uint8_t val) -{ - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - uint8_t old = dev->p2; - - kbd_log("ATkbc: write output port: %02X (old: %02X)\n", val, dev->p2); - - if (!(dev->flags & KBC_FLAG_PS2)) - val |= ((dev->mem[0x20] << 4) & 0x10); - - dev->kbd_inhibit = (val & 0x40); - dev->mouse_inhibit = (val & 0x08); - - /* IRQ 12 */ - if ((old ^ val) & 0x20) { - if (val & 0x20) { - kbd_log("ATkbc: write_output(): IRQ 12\n"); - picint(1 << 12); - } else - picintc(1 << 12); - } - - /* IRQ 1 */ - if ((old ^ val) & 0x10) { - if (val & 0x10) { - kbd_log("ATkbc: write_output(): IRQ 1\n"); - picint(1 << 1); - } else - picintc(1 << 1); - } - - /* A20 enable change */ - if ((old ^ val) & 0x02) { - mem_a20_key = val & 0x02; - mem_a20_recalc(); - flushmmucache(); - } - - /* Do this here to avoid an infinite reset loop. */ - dev->p2 = val; - - /* 0 holds the CPU in the RESET state, 1 releases it. To simplify this, - we just do everything on release. */ - if ((val & 0x01) && !(old & 0x01)) { - if (val & 0x01) { - /* Pin 0 selected. */ - pclog("write_output(): Pulse reset!\n"); - softresetx86(); /*Pulse reset!*/ - cpu_set_edx(); - } - } -} - - -static void -write_cmd(atkbd_t *dev, uint8_t val) -{ - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - kbd_log("ATkbc: write command byte: %02X (old: %02X)\n", val, dev->mem[0x20]); - - /* PS/2 type 2 keyboard controllers always force the XLAT bit to 0. */ - if ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2) - val &= ~CCB_TRANSLATE; - - dev->mem[0x20] = val; - - /* Scan code translate ON/OFF. */ - keyboard_mode &= 0x93; - keyboard_mode |= (val & MODE_MASK); - - kbd_log("ATkbc: keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled"); - - /* ISA AT keyboard controllers use bit 5 for keyboard mode (1 = PC/XT, 2 = AT); - PS/2 (and EISA/PCI) keyboard controllers use it as the PS/2 mouse enable switch. - The AMIKEY firmware apparently uses this bit for something else. */ - if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) { - keyboard_mode &= ~CCB_PCMODE; - - kbd_log("ATkbc: mouse interrupt is now %s\n", (val & 0x02) ? "enabled" : "disabled"); - } - - if (!(dev->flags & KBC_FLAG_PS2)) { - /* Update the output port to mirror the KBD DIS and AUX DIS bits, if active. */ - write_output(dev, dev->p2); - } - - kbd_log("Command byte now: %02X (%02X)\n", dev->mem[0x20], val); - - dev->status = (dev->status & ~STAT_SYSFLAG) | (val & STAT_SYSFLAG); -} - - -static void -pulse_output(atkbd_t *dev, uint8_t mask) -{ - if (mask != 0x0f) { - dev->old_p2 = dev->p2 & ~(0xf0 | mask); - kbd_log("pulse_output(): Output port now: %02X\n", dev->p2 & (0xf0 | mask | (dev->mem[0x20] & 0x30))); - write_output(dev, dev->p2 & (0xf0 | mask | (dev->mem[0x20] & 0x30))); - timer_set_delay_u64(&dev->pulse_cb, 6ULL * TIMER_USEC); - } -} - - -static void -set_enable_kbd(atkbd_t *dev, uint8_t enable) -{ - dev->mem[0x20] &= 0xef; - dev->mem[0x20] |= (enable ? 0x00 : 0x10); -} - - -static void -set_enable_mouse(atkbd_t *dev, uint8_t enable) -{ - dev->mem[0x20] &= 0xdf; - dev->mem[0x20] |= (enable ? 0x00 : 0x20); -} - - -static void -kbc_transmit(atkbd_t *dev, uint8_t val) -{ - kbc_send_to_ob(dev, val, 0, 0x00); -} - - -static void -kbc_command(atkbd_t *dev) -{ - uint8_t mask, val = dev->ib; - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - int bad = 1; - - if ((dev->kbc_phase > 0) && (dev->kbc_cmd == 0xac)) { - if (dev-> kbc_phase < 16) - kbc_transmit(dev, dev->mem[dev->kbc_phase]); - else if (dev-> kbc_phase == 16) - kbc_transmit(dev, (dev->p1 & 0xf0) | 0x80); - else if (dev-> kbc_phase == 17) - kbc_transmit(dev, dev->p2); - else if (dev-> kbc_phase == 18) - kbc_transmit(dev, dev->status); - - dev->kbc_phase++; - if (dev->kbc_phase == 19) { - dev->kbc_phase = 0; - dev->kbc_cmd = 0x00; - } - return; - } else if ((dev->kbc_phase > 0) && (dev->kbc_cmd == 0xa0) && (kbc_ven >= KBC_VEN_AMI)) { - val = ami_copr[dev->kbc_phase]; - kbc_transmit(dev, val); - if (val == 0x00) { - dev->kbc_phase = 0; - dev->kbc_cmd = 0x00; - } else - dev->kbc_phase++; - return; - } else if ((dev->kbc_in > 0) && (dev->kbc_cmd == 0xa5) && (dev->flags & KBC_FLAG_PS2)) { - /* load security */ - kbd_log("ATkbc: load security\n"); - dev->mem[0x50 + dev->kbc_in - 0x01] = val; - if ((dev->kbc_in == 0x80) && (val != 0x00)) { - /* Security string too long, set it to 0x00. */ - dev->mem[0x50] = 0x00; - dev->kbc_in = 0; - dev->kbc_cmd = 0; - } else if (val == 0x00) { - /* Security string finished. */ - dev->kbc_in = 0; - dev->kbc_cmd = 0; - } else /* Increase pointer and request another byte. */ - dev->kbc_in++; - return; - } - - /* If the written port is 64, go straight to the beginning of the command. */ - if (!(dev->status & STAT_CD) && dev->kbc_in) { - /* Write data to controller. */ - dev->kbc_in = 0; - dev->kbc_phase = 0; - - switch (dev->kbc_cmd) { - case 0x60 ... 0x7f: - if (dev->kbc_cmd == 0x60) - write_cmd(dev, val); - else - dev->mem[(dev->kbc_cmd & 0x1f) + 0x20] = val; - break; - - case 0xc7: /* or input port with system data */ - dev->p1 |= val; - break; - - case 0xcb: /* set keyboard mode */ - kbd_log("New AMIKey mode: %02X\n", val); - dev->ami_mode = val; - dev->flags &= ~KBC_FLAG_PS2; - if (val & 1) - dev->flags |= KBC_FLAG_PS2; - break; - - case 0xd1: /* write output port */ - kbd_log("ATkbc: write output port\n"); - if (dev->p2_locked) { - /*If keyboard controller lines P22-P23 are blocked, - we force them to remain unchanged.*/ - val &= ~0x0c; - val |= (dev->p2 & 0x0c); - } - write_output(dev, val); - break; - - case 0xd2: /* write to keyboard output buffer */ - kbd_log("ATkbc: write to keyboard output buffer\n"); - // kbc_send_to_ob(dev, val, 1, 0x00); - /* Should be channel 1, but we send to 0 to avoid translation, - since bytes output using this command do *NOT* get translated. */ - kbc_send_to_ob(dev, val, 0, 0x00); - break; - - case 0xd3: /* write to mouse output buffer */ - kbd_log("ATkbc: write to mouse output buffer\n"); - if (dev->flags & KBC_FLAG_PS2) - kbc_send_to_ob(dev, val, 2, 0x00); - break; - - case 0xd4: /* write to mouse */ - kbd_log("ATkbc: write to mouse (%02X)\n", val); - - if (dev->flags & KBC_FLAG_PS2) { - set_enable_mouse(dev, 1); - dev->mem[0x20] &= ~0x20; - if (mouse_write && !dev->kbc_written[2]) { - kbd_log("ATkbc: Sending %02X to mouse...\n", dev->ib); - dev->mouse_data = val; - dev->mouse_written = 1; - dev->kbc_wait_for_response = 2; - } else - kbc_send_to_ob(dev, 0xfe, 2, 0x40); - } - break; - - default: - /* - * Run the vendor-specific handler - * if we have one. Otherwise, or if - * it returns an error, log a bad - * controller command. - */ - if (dev->write60_ven) - bad = dev->write60_ven(dev, val); - -#ifdef ENABLE_KEYBOARD_AT_LOG - if (bad) - kbd_log("ATkbc: bad controller command %02x data %02x\n", dev->kbc_cmd, val); -#endif - } - } else { - /* Controller command. */ - kbd_log("ATkbc: Controller command: %02X\n", val); - dev->kbc_in = 0; - dev->kbc_phase = 0; - - switch (val) { - /* Read data from KBC memory. */ - case 0x20 ... 0x3f: - kbc_transmit(dev, dev->mem[(val & 0x1f) + 0x20]); - break; - - /* Write data to KBC memory. */ - case 0x60 ... 0x7f: - dev->kbc_in = 1; - break; - - case 0xaa: /* self-test */ - kbd_log("ATkbc: self-test\n"); - write_output(dev, (dev->flags & KBC_FLAG_PS2) ? 0x4b : 0xcf); - - /* Always reinitialize all queues - the real hardware pulls keyboard and mouse - clocks high, which stops keyboard scanning. */ - kbd_log("ATkbc: self-test reinitialization\n"); - dev->kbd_in_cmd = dev->mouse_in_cmd = 0; - dev->status &= ~STAT_OFULL; - dev->last_irq = 0; - dev->kbc_phase = 0; - - /* Phoenix MultiKey should have 0x60 | STAT_SYSFLAG. */ - if (dev->flags & KBC_FLAG_PS2) - write_cmd(dev, 0x30 | STAT_SYSFLAG); - else - write_cmd(dev, 0x10 | STAT_SYSFLAG); - kbc_transmit(dev, 0x55); - break; - - case 0xab: /* interface test */ - kbd_log("ATkbc: interface test\n"); - /* No error. */ - kbc_transmit(dev, 0x00); - break; - - case 0xac: /* diagnostic dump */ - kbd_log("ATkbc: diagnostic dump\n"); - kbc_transmit(dev, dev->mem[0x20]); - dev->kbc_phase = 1; - break; - - case 0xad: /* disable keyboard */ - kbd_log("ATkbc: disable keyboard\n"); - set_enable_kbd(dev, 0); - break; - - case 0xae: /* enable keyboard */ - kbd_log("ATkbc: enable keyboard\n"); - set_enable_kbd(dev, 1); - break; - - case 0xc7: /* or input port with system data */ - kbd_log("ATkbc: Phoenix - or input port with system data\n"); - dev->kbc_in = 1; - break; - - case 0xca: /* read keyboard mode */ - kbd_log("ATkbc: AMI - read keyboard mode\n"); - kbc_transmit(dev, dev->ami_mode); - break; - - case 0xcb: /* set keyboard mode */ - kbd_log("ATkbc: AMI - set keyboard mode\n"); - dev->kbc_in = 1; - break; - - case 0xd0: /* read output port */ - kbd_log("ATkbc: read output port\n"); - mask = 0xff; - if (!(dev->flags & KBC_FLAG_PS2) && (dev->mem[0x20] & 0x10)) - mask &= 0xbf; - kbc_transmit(dev, dev->p2 & mask); - break; - - case 0xd1: /* write output port */ - kbd_log("ATkbc: write output port\n"); - dev->kbc_in = 1; - break; - - case 0xd2: /* write keyboard output buffer */ - kbd_log("ATkbc: write keyboard output buffer\n"); - if (dev->flags & KBC_FLAG_PS2) - dev->kbc_in = 1; - else - kbc_transmit(dev, 0x00); /* NCR */ - break; - - case 0xdd: /* disable A20 address line */ - case 0xdf: /* enable A20 address line */ - kbd_log("ATkbc: %sable A20\n", (val == 0xdd) ? "dis": "en"); - write_output(dev, (dev->p2 & 0xfd) | (val & 0x02)); - break; - - case 0xe0: /* read test inputs */ - kbd_log("ATkbc: read test inputs\n"); - kbc_transmit(dev, 0x00); - break; - - case 0xe1: case 0xea: - kbd_log("ATkbc: setting P23-P21 to %01X\n", val & 0x0e); - write_output(dev, (dev->p2 & 0xf1) | (val & 0x0e)); - break; - - default: - /* - * Unrecognized controller command. - * - * If we have a vendor-specific handler, run - * that. Otherwise, or if that handler fails, - * log a bad command. - */ - if (dev->write64_ven) - bad = dev->write64_ven(dev, val); - - kbd_log(bad ? "ATkbc: bad controller command %02X\n" : "", val); - } - - /* If the command needs data, remember the command. */ - if (dev->kbc_in || (dev->kbc_phase > 0)) - dev->kbc_cmd = val; - } -} - - -static void -kbc_dev_data_to_ob(atkbd_t *dev, uint8_t channel) -{ - dev->kbc_written[channel] = 0; - kbd_log("ATkbd: Forwarding %02X from channel %i...\n", dev->kbc_data[channel], channel); - kbc_send_to_ob(dev, dev->kbc_data[channel], channel, 0x00); -} - - -static void -kbc_main_loop_scan(atkbd_t *dev) -{ - uint8_t port_dis = dev->mem[0x20] & 0x30; - uint8_t ps2 = (dev->flags & KBC_FLAG_PS2); - - if (!ps2) - port_dis |= 0x20; - - if (!(dev->status & STAT_OFULL)) { - if (port_dis & 0x20) { - if (!(port_dis & 0x10)) { - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Main loop\n" - "ATkbc: Scan: AUX DIS, KBD EN\n"); - // kbd_log("ATkbc: Scan: AUX DIS, KBD EN\n"); - /* Enable communication with keyboard. */ - dev->p2 &= 0xbf; - dev->kbd_inhibit = 0; - kbc_wait(dev, 1); - } -#ifdef ENABLE_KEYBOARD_AT_LOG - else { - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Main loop\n" - "ATkbc: Scan: AUX DIS, KBD DIS\n"); - // kbd_log("ATkbc: Scan: AUX DIS, KBD DIS\n"); - } -#endif - } else { - /* Enable communication with mouse. */ - dev->p2 &= 0xf7; - dev->mouse_inhibit = 0; - if (dev->mem[0x20] & 0x10) { - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Main loop\n" - "ATkbc: Scan: AUX EN , KBD DIS\n"); - // kbd_log("ATkbc: Scan: AUX EN , KBD DIS\n"); - kbc_wait(dev, 2); - } else { - /* Enable communication with keyboard. */ - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Main loop\n" - "ATkbc: Scan: AUX EN , KBD EN\n"); - // kbd_log("ATkbc: Scan: AUX EN , KBD EN\n"); - dev->p2 &= 0xbf; - dev->kbd_inhibit = 0; - kbc_wait(dev, 3); - } - } - } -#ifdef ENABLE_KEYBOARD_AT_LOG - else { - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Main loop\n" - "ATkbc: Scan: IBF not full and OBF full, do nothing\n"); - // kbd_log("ATkbc: Scan: IBF not full and OBF full, do nothing\n"); - } -#endif -} - - -static void -kbc_process_ib(atkbd_t *dev) -{ - dev->status &= ~STAT_IFULL; - - if (dev->status & STAT_CD) { - dev->kbc_in_cmd = 1; - kbc_command(dev); - - if ((dev->kbc_phase == 0) && !dev->kbc_in) - dev->kbc_in_cmd = 0; - else - return; - } else { - dev->mem[0x20] &= ~0x10; - dev->kbd_data = dev->ib; - dev->kbd_written = 1; - dev->kbc_wait_for_response = 1; - } - - dev->kbc_poll_phase = KBC_MAIN_LOOP; - if (!dev->kbc_wait_for_response) - kbc_main_loop_scan(dev); -} - - -static void -kbc_wait(atkbd_t *dev, uint8_t flags) -{ - if ((flags & 1) && dev->kbc_written[1]) { - /* Disable communication with mouse. */ - dev->p2 |= 0x08; - dev->mouse_inhibit = 1; - /* Send keyboard byte to host. */ - kbc_dev_data_to_ob(dev, CHANNEL_KBD); - dev->kbc_poll_phase = KBC_MAIN_LOOP; - } else if ((flags & 2) && dev->kbc_written[2]) { - /* Disable communication with keyboard. */ - dev->p2 |= 0x40; - dev->kbd_inhibit = 1; - /* Send mouse byte to host. */ - kbc_dev_data_to_ob(dev, CHANNEL_MOUSE); - dev->kbc_poll_phase = KBC_MAIN_LOOP; - } else if (dev->status & STAT_IFULL) { - /* Disable communication with keyboard and mouse. */ - dev->p2 |= 0x48; - dev->kbd_inhibit = dev->mouse_inhibit = 1; - kbc_process_ib(dev); - } else - dev->kbc_poll_phase = KBC_WAIT | flags; -} - - -/* Controller processing */ -static void -kbc_process(atkbd_t *dev) -{ - // kbd_log("ATkbc: kbc_process()\n"); - - /* If we're waiting for the response from the keyboard or mouse, do nothing - until the device has repsonded back. */ - if (dev->kbc_wait_for_response > 0) { - if (dev->kbc_written[dev->kbc_wait_for_response]) - dev->kbc_wait_for_response = 0; - else - return; - } - - if (dev->kbc_send_pending) { - kbd_log("ATkbc: Sending delayed %02X on channel %i with high status %02X\n", - dev->kbc_to_send, dev->kbc_channel, dev->kbc_stat_hi); - kbc_send_to_ob(dev, dev->kbc_to_send, dev->kbc_channel, dev->kbc_stat_hi); - dev->kbc_send_pending = 0; - } - - if (dev->kbc_poll_phase == KBC_RESET) { - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Reset loop()\n"); - - if (dev->status & STAT_IFULL) { - dev->status &= ~STAT_IFULL; - - if ((dev->status & STAT_CD) && (dev->ib == 0xaa)) { - dev->kbc_in_cmd = 1; - kbc_command(dev); - - if ((dev->kbc_phase == 0) && !dev->kbc_in) - dev->kbc_in_cmd = 0; - - dev->kbc_poll_phase = KBC_MAIN_LOOP; - } - } - - return; - } - - if (dev->kbc_in_cmd || (dev->kbc_phase > 0) || dev->kbc_in) { - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: In a command\n"); - if (!dev->kbc_in && (dev->status & STAT_OFULL)) { - kbd_log("ATkbc: !dev->kbc_in && (dev->status & STAT_OFULL)\n"); - return; /* We do not want input and we're waiting for the host to read the data - we transmitted, but it has not done that yet, do nothing. */ - } else if (dev->kbc_in && !(dev->status & STAT_IFULL)) { - kbd_log("ATkbc: dev->kbc_in && !(dev->status & STAT_IFULL)\n"); - return; /* We want input and the host has not provided us with any yet, do nothing. */ - } -#ifdef ENABLE_KEYBOARD_AT_LOG - else - kbd_log("ATkbc: Normal condition\n"); -#endif - - if (dev->status & STAT_IFULL) { - dev->status &= ~STAT_IFULL; - - if (dev->status & STAT_CD) { - kbd_log("ATkbc: Resetting command\n"); - dev->kbc_phase = 0; - dev->kbc_in = 0; - } - } - - /* Process command. */ - kbc_command(dev); - - if ((dev->kbc_phase == 0) && !dev->kbc_in) - dev->kbc_in_cmd = 0; - else - return; - - if (!(dev->status & STAT_OFULL)) - kbc_main_loop_scan(dev); - /* Make absolutely sure to do nothing if OBF is full and IBF is empty. */ - } else if (!(dev->status & STAT_OFULL) || (dev->status & STAT_IFULL)) switch (dev->kbc_poll_phase) { - case KBC_MAIN_LOOP: - // kbd_log("ATkbc: Main loop\n"); - if (dev->status & STAT_IFULL) { - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Main loop\n" - "ATkbc: IBF full, process\n"); - kbc_process_ib(dev); - } else - kbc_main_loop_scan(dev); - break; - case KBC_WAIT_FOR_KBD: - case KBC_WAIT_FOR_MOUSE: - case KBC_WAIT_FOR_BOTH: - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Scan: Phase %i\n", dev->kbc_poll_phase); - kbc_wait(dev, dev->kbc_poll_phase & 3); - break; - default: - kbd_log("ATkbc: kbc_process()\n" - "ATkbc: Scan: Invalid phase %i\n", dev->kbc_poll_phase); - break; - } + add_data_kbd_queue(dev, 1, val); } @@ -1804,29 +743,105 @@ static void kbd_poll(void *priv) { atkbd_t *dev = (atkbd_t *)priv; +#ifdef ENABLE_KEYBOARD_AT_LOG + const uint8_t channels[4] = { 1, 2, 0, 0 }; +#endif timer_advance_u64(&dev->send_delay_timer, (100ULL * TIMER_USEC)); - /* We process all three devices at the same time, in an arbitrary order. */ + if (dev->out_new != -1 && !dev->last_irq) { + dev->wantirq = 0; + if (dev->out_new & 0x100) { + if (dev->mem[0] & 0x02) + picint(0x1000); + kbd_log("ATkbc: %02X coming from channel 2\n"); + dev->out = dev->out_new & 0xff; + dev->out_new = -1; + dev->status = (dev->status & ~STAT_IFULL) | (STAT_OFULL | STAT_MFULL); + dev->last_irq = 0x1000; + } else { + if (dev->mem[0] & 0x01) + picint(2); + kbd_log("ATkbc: %02X coming from channel %i\n", dev->out_new & 0xff, channels[(dev->out_new >> 8) & 0x03]); + dev->out = dev->out_new & 0xff; + dev->out_new = -1; + dev->status = (dev->status & ~(STAT_IFULL | STAT_MFULL)) | STAT_OFULL; + dev->last_irq = 2; + } + } - /* Keyboard processing */ - kbd_process(dev); + if (dev->out_new == -1 && !(dev->status & STAT_OFULL) && key_ctrl_queue_start != key_ctrl_queue_end) { + kbd_log("ATkbc: %02X on channel 0\n", key_ctrl_queue[key_ctrl_queue_start]); + dev->out_new = key_ctrl_queue[key_ctrl_queue_start] | 0x200; + key_ctrl_queue_start = (key_ctrl_queue_start + 1) & 0xf; + } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && dev->out_delayed != -1) { + kbd_log("ATkbc: %02X delayed on channel %i\n", dev->out_delayed & 0xff, channels[(dev->out_delayed >> 8) & 0x03]); + dev->out_new = dev->out_delayed; + dev->out_delayed = -1; + } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && mouse_queue_start != mouse_queue_end) { + kbd_log("ATkbc: %02X on channel 2\n", mouse_queue[mouse_queue_start]); + dev->out_new = mouse_queue[mouse_queue_start] | 0x100; + mouse_queue_start = (mouse_queue_start + 1) & 0xf; + } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && !(dev->mem[0] & 0x10) && key_queue_start != key_queue_end) { + kbd_log("ATkbc: %02X on channel 1\n", key_queue[key_queue_start]); + dev->out_new = key_queue[key_queue_start]; + key_queue_start = (key_queue_start + 1) & 0xf; + } - /* TODO: Mouse processing */ - // mouse_process(dev); + if (dev->reset_delay) { + dev->reset_delay--; + if (!dev->reset_delay) { + kbd_log("ATkbc: Sending AA on keyboard reset...\n"); + add_data_kbd_direct(dev, 0xaa); + } + } +} - /* Controller processing */ - kbc_process(dev); + +static void +add_data(atkbd_t *dev, uint8_t val) +{ + kbd_log("ATkbc: add to queue\n"); + + kbd_log("ATkbc: key_ctrl_queue[%02X] = %02X;\n", key_ctrl_queue_end, val); + kbc_queue_add(dev, val, 0, 0x00); + + if (!(dev->out_new & 0x300)) { + dev->out_delayed = dev->out_new; + dev->out_new = -1; + } } static void add_data_vals(atkbd_t *dev, uint8_t *val, uint8_t len) { + int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); + int translate = (keyboard_mode & 0x40); int i; + uint8_t or = 0; + uint8_t send; - for (i = 0; i < len; i++) - add_data_kbd_queue(dev, 0, val[i]); + if (dev->reset_delay) + return; + + translate = translate || (keyboard_mode & 0x40) || xt_mode; + translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); + + for (i = 0; i < len; i++) { + if (translate) { + if (val[i] == 0xf0) { + or = 0x80; + continue; + } + send = nont_to_t[val[i]] | or; + if (or == 0x80) + or = 0; + } else + send = val[i]; + + add_data_kbd_queue(dev, 0, send); + } } @@ -1834,21 +849,56 @@ static void add_data_kbd(uint16_t val) { atkbd_t *dev = SavedKbd; + int xt_mode = (keyboard_mode & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); + int translate = (keyboard_mode & 0x40); uint8_t fake_shift[4]; uint8_t num_lock = 0, shift_states = 0; uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - if (dev->kbd_in || (dev->kbd_phase > 0)) + if (dev->reset_delay) return; + translate = translate || (keyboard_mode & 0x40) || xt_mode; + translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); + keyboard_get_states(NULL, &num_lock, NULL); shift_states = keyboard_get_shift() & STATE_SHIFT_MASK; - /* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */ - if ((dev != NULL) && (kbc_ven == KBC_VEN_TOSHIBA) && (keyboard_recv(0xb8) || keyboard_recv(0x9d)) && - (val >= 0x4f) && (val <= 0x54) && (val != 0x4e)) - t3100e_notify_set((val + 2) & 0x0f); + /* Allow for scan code translation. */ + if (translate && (val == 0xf0)) { + kbd_log("ATkbd: translate is on, F0 prefix detected\n"); + sc_or = 0x80; + return; + } + /* Skip break code if translated make code has bit 7 set. */ + if (translate && (sc_or == 0x80) && (val & 0x80)) { + kbd_log("ATkbd: translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val); + sc_or = 0; + return; + } + + /* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */ + if ((dev != NULL) && (kbc_ven == KBC_VEN_TOSHIBA) && + (keyboard_recv(0xb8) || keyboard_recv(0x9d))) switch (val) { + case 0x4f: t3100e_notify_set(0x01); break; /* End */ + case 0x50: t3100e_notify_set(0x02); break; /* Down */ + case 0x51: t3100e_notify_set(0x03); break; /* PgDn */ + case 0x52: t3100e_notify_set(0x04); break; /* Ins */ + case 0x53: t3100e_notify_set(0x05); break; /* Del */ + case 0x54: t3100e_notify_set(0x06); break; /* SysRQ */ + case 0x45: t3100e_notify_set(0x07); break; /* NumLock */ + case 0x46: t3100e_notify_set(0x08); break; /* ScrLock */ + case 0x47: t3100e_notify_set(0x09); break; /* Home */ + case 0x48: t3100e_notify_set(0x0a); break; /* Up */ + case 0x49: t3100e_notify_set(0x0b); break; /* PgUp */ + case 0x4A: t3100e_notify_set(0x0c); break; /* Keypad -*/ + case 0x4B: t3100e_notify_set(0x0d); break; /* Left */ + case 0x4C: t3100e_notify_set(0x0e); break; /* KP 5 */ + case 0x4D: t3100e_notify_set(0x0f); break; /* Right */ + } + + kbd_log("ATkbd: translate is %s, ", translate ? "on" : "off"); switch(val) { case FAKE_LSHIFT_ON: kbd_log("fake left shift on, scan code: "); @@ -1981,7 +1031,18 @@ add_data_kbd(uint16_t val) break; default: - add_data_kbd_queue(dev, 0, val); +#ifdef ENABLE_KEYBOARD_AT_LOG + kbd_log("scan code: "); + if (translate) { + kbd_log("%02X (original: ", (nont_to_t[val] | sc_or)); + if (sc_or == 0x80) + kbd_log("F0 "); + kbd_log("%02X)\n", val); + } else + kbd_log("%02X\n", val); +#endif + + add_data_kbd_queue(dev, 0, translate ? (nont_to_t[val] | sc_or) : val); break; } @@ -1990,13 +1051,124 @@ add_data_kbd(uint16_t val) } +static void +write_output(atkbd_t *dev, uint8_t val) +{ + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + kbd_log("ATkbc: write output port: %02X (old: %02X)\n", val, dev->output_port); + + if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF)) + val |= ((dev->mem[0] << 4) & 0x10); + + if ((dev->output_port ^ val) & 0x20) { /*IRQ 12*/ + if (val & 0x20) + picint(1 << 12); + else + picintc(1 << 12); + } + if ((dev->output_port ^ val) & 0x10) { /*IRQ 1*/ + if (val & 0x10) + picint(1 << 1); + else + picintc(1 << 1); + } + if ((dev->output_port ^ val) & 0x02) { /*A20 enable change*/ + mem_a20_key = val & 0x02; + mem_a20_recalc(); + flushmmucache(); + } + if ((dev->output_port ^ val) & 0x01) { /*Reset*/ + if (! (val & 0x01)) { + /* Pin 0 selected. */ + softresetx86(); /*Pulse reset!*/ + cpu_set_edx(); + smbase = is_am486dxl ? 0x00060000 : 0x00030000; + } + } + /* Mask off the A20 stuff because we use mem_a20_key directly for that. */ + dev->output_port = val; +} + + +static void +write_cmd(atkbd_t *dev, uint8_t val) +{ + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + kbd_log("ATkbc: write command byte: %02X (old: %02X)\n", val, dev->mem[0]); + + if ((val & 1) && (dev->status & STAT_OFULL)) + dev->wantirq = 1; + if (!(val & 1) && dev->wantirq) + dev->wantirq = 0; + + /* PS/2 type 2 keyboard controllers always force the XLAT bit to 0. */ + if ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2) { + val &= ~CCB_TRANSLATE; + dev->mem[0] &= ~CCB_TRANSLATE; + } + + /* Scan code translate ON/OFF. */ + keyboard_mode &= 0x93; + keyboard_mode |= (val & MODE_MASK); + + kbd_log("ATkbc: keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled"); + + /* ISA AT keyboard controllers use bit 5 for keyboard mode (1 = PC/XT, 2 = AT); + PS/2 (and EISA/PCI) keyboard controllers use it as the PS/2 mouse enable switch. + The AMIKEY firmware apparently uses this bit for something else. */ + if ((kbc_ven == KBC_VEN_AMI) || + ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) { + keyboard_mode &= ~CCB_PCMODE; + + kbd_log("ATkbc: mouse interrupt is now %s\n", (val & 0x02) ? "enabled" : "disabled"); + } + + if ((kbc_ven == KBC_VEN_AMI) || ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF)) { + /* Update the output port to mirror the KBD DIS and AUX DIS bits, if active. */ + write_output(dev, dev->output_port); + } + + kbd_log("Command byte now: %02X (%02X)\n", dev->mem[0], val); + + dev->status = (dev->status & ~STAT_SYSFLAG) | (val & STAT_SYSFLAG); +} + + +static void +pulse_output(atkbd_t *dev, uint8_t mask) +{ + if (mask != 0x0f) { + dev->old_output_port = dev->output_port & ~(0xf0 | mask); + kbd_log("pulse_output(): Output port now: %02X\n", dev->output_port & (0xf0 | mask)); + write_output(dev, dev->output_port & (0xf0 | mask)); + timer_set_delay_u64(&dev->pulse_cb, 6ULL * TIMER_USEC); + } +} + + static void pulse_poll(void *priv) { atkbd_t *dev = (atkbd_t *)priv; - kbd_log("pulse_poll(): Output port now: %02X\n", dev->p2 | dev->old_p2); - write_output(dev, dev->p2 | dev->old_p2); + kbd_log("pulse_poll(): Output port now: %02X\n", dev->output_port | dev->old_output_port); + write_output(dev, dev->output_port | dev->old_output_port); +} + + +static void +set_enable_kbd(atkbd_t *dev, uint8_t enable) +{ + dev->mem[0] &= 0xef; + dev->mem[0] |= (enable ? 0x00 : 0x10); +} + + +static void +set_enable_mouse(atkbd_t *dev, uint8_t enable) +{ + dev->mem[0] &= 0xdf; + dev->mem[0] |= (enable ? 0x00 : 0x20); } @@ -2005,72 +1177,49 @@ write64_generic(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; uint8_t current_drive, fixed_bits; - uint8_t kbc_ven = 0x0; - kbc_ven = dev->flags & KBC_VEN_MASK; + uint8_t kbc_ven = 0x0; + kbc_ven = dev->flags & KBC_VEN_MASK; + switch (val) { case 0xa4: /* check if password installed */ - if (dev->flags & KBC_FLAG_PS2) { + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: check if password installed\n"); - kbc_transmit(dev, (dev->mem[0x50] == 0x00) ? 0xf1 : 0xfa); - return 0; - } - break; - - case 0xa5: /* load security */ - if (dev->flags & KBC_FLAG_PS2) { - kbd_log("ATkbc: load security\n"); - dev->kbc_in = 1; + add_data(dev, 0xf1); return 0; } break; case 0xa7: /* disable mouse port */ - if (dev->flags & KBC_FLAG_PS2) { + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: disable mouse port\n"); - // kbc_transmit(dev, 0); + set_enable_mouse(dev, 0); return 0; } break; case 0xa8: /*Enable mouse port*/ - if (dev->flags & KBC_FLAG_PS2) { + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: enable mouse port\n"); - // kbc_transmit(dev, 1); + set_enable_mouse(dev, 1); return 0; } break; case 0xa9: /*Test mouse port*/ kbd_log("ATkbc: test mouse port\n"); - if (dev->flags & KBC_FLAG_PS2) { - /* No error, this is testing the channel 2 interface. */ - kbc_transmit(dev, 0x00); + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + add_data(dev, 0x00); /* no error, this is testing the channel 2 interface */ return 0; } break; case 0xaf: /* read keyboard version */ kbd_log("ATkbc: read keyboard version\n"); - kbc_transmit(dev, 0x00); + add_data(dev, 0x00); return 0; case 0xc0: /* read input port */ - /* IBM PS/1: - Bit 2 and 4 ignored (we return always 0), - Bit 6 must 1 for 5.25" floppy drive, 0 for 3.5". - Intel AMI: - Bit 2 ignored (we return always 1), - Bit 4 must be 1, - Bit 6 must be 1 or else error in SMM. - Acer: - Bit 2 must be 0 (and Acer V10 disables CMOS setup if it's 1), - Bit 4 must be 0, - Bit 6 ignored. - Packard Bell PB450: - Bit 2 must be 1. - P6RP4: - Bit 2 must be 1 or CMOS setup is disabled. */ kbd_log("ATkbc: read input port\n"); fixed_bits = 4; /* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */ @@ -2078,8 +1227,11 @@ write64_generic(void *priv, uint8_t val) fixed_bits |= 0x40; if (kbc_ven == KBC_VEN_IBM_PS1) { current_drive = fdc_get_current_drive(); - kbc_transmit(dev, dev->p1 | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00)); - dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc) | (fdd_is_525(current_drive) ? 0x40 : 0x00); + add_to_kbc_queue_front(dev, dev->input_port | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00), + 0, 0x00); + dev->input_port = ((dev->input_port + 1) & 3) | + (dev->input_port & 0xfc) | + (fdd_is_525(current_drive) ? 0x40 : 0x00); } else if (kbc_ven == KBC_VEN_NCR) { /* switch settings * bit 7: keyboard disable @@ -2091,34 +1243,39 @@ write64_generic(void *priv, uint8_t val) * bit 1: high/auto speed * bit 0: dma mode */ - kbc_transmit(dev, (dev->p1 | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf); - dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc); + add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf, + 0, 0x00); + dev->input_port = ((dev->input_port + 1) & 3) | + (dev->input_port & 0xfc); } else { - pclog("[%04X:%08X] Reading %02X from input port\n", CS, cpu_state.pc, ((dev->p1 | fixed_bits) & 0xf0) | 0x0c); - if ((dev->flags & KBC_FLAG_PS2) && ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI)) - // kbc_transmit(dev, ((dev->p1 | fixed_bits) & 0xf0) | 0x0c); - kbc_transmit(dev, ((dev->p1 | fixed_bits) & 0xf0) | 0x08); - // kbc_transmit(dev, (dev->p1 | fixed_bits) & (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0xeb : 0xef)); + if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) && + ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI)) + add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits) & + (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0xeb : 0xef), 0, 0x00); else - kbc_transmit(dev, dev->p1 | fixed_bits); - dev->p1 = ((dev->p1 + 1) & 3) | (dev->p1 & 0xfc); + add_to_kbc_queue_front(dev, dev->input_port | fixed_bits, 0, 0x00); + dev->input_port = ((dev->input_port + 1) & 3) | + (dev->input_port & 0xfc); } return 0; case 0xd3: /* write mouse output buffer */ - if (dev->flags & KBC_FLAG_PS2) { + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: write mouse output buffer\n"); - dev->kbc_in = 1; + dev->want60 = 1; return 0; } break; case 0xd4: /* write to mouse */ kbd_log("ATkbc: write to mouse\n"); - dev->kbc_in = 1; + dev->want60 = 1; return 0; - case 0xf0 ... 0xff: + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: kbd_log("ATkbc: pulse %01X\n", val & 0x0f); pulse_output(dev, val & 0x0f); return 0; @@ -2133,170 +1290,38 @@ static uint8_t write60_ami(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; - uint16_t index = 0x00c0; - switch(dev->kbc_cmd) { - /* 0x40 - 0x5F are aliases for 0x60 - 0x7F */ - case 0x40 ... 0x5f: - kbd_log("ATkbc: AMI - alias write to %08X\n", dev->kbc_cmd); - if (dev->kbc_cmd == 0x40) + switch(dev->command) { + /* 0x40 - 0x5F are aliases for 0x60-0x7F */ + case 0x40: case 0x41: case 0x42: case 0x43: + case 0x44: case 0x45: case 0x46: case 0x47: + case 0x48: case 0x49: case 0x4a: case 0x4b: + 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: case 0x5f: + kbd_log("ATkbc: AMI - alias write to %08X\n", dev->command); + dev->mem[dev->command & 0x1f] = val; + if (dev->command == 0x60) write_cmd(dev, val); - else - dev->mem[(dev->kbc_cmd & 0x1f) + 0x20] = val; return 0; case 0xaf: /* set extended controller RAM */ - kbd_log("ATkbc: AMI - set extended controller RAM, input phase %i\n", dev->secr_phase); - if (dev->secr_phase == 0) { - dev->mem_index = val; - dev->kbc_in = 1; - dev->secr_phase++; - } else if (dev->secr_phase == 1) { - if (dev->mem_index == 0x20) - write_cmd(dev, val); - else - dev->mem[dev->mem_index] = val; + kbd_log("ATkbc: AMI - set extended controller RAM\n"); + if (dev->secr_phase == 1) { + dev->mem_addr = val; + dev->want60 = 1; + dev->secr_phase = 2; + } else if (dev->secr_phase == 2) { + dev->mem[dev->mem_addr] = val; dev->secr_phase = 0; } return 0; - case 0xb8: - kbd_log("ATkbc: AMI MegaKey - memory index %02X\n", val); - dev->mem_index = val; - return 0; - - case 0xbb: - kbd_log("ATkbc: AMI MegaKey - write %02X to memory index %02X\n", val, dev->mem_index); - if (dev->mem_index >= 0x80) { - switch (dev->mem[0x9b] & 0xc0) { - case 0x00: - index = 0x0080; - break; - case 0x40: case 0x80: - index = 0x0000; - break; - case 0xc0: - index = 0x0100; - break; - } - dev->mem[index + dev->mem_index] = val; - } else if (dev->mem_index == 0x60) - write_cmd(dev, val); - else if (dev->mem_index == 0x42) - dev->status = val; - else if (dev->mem_index >= 0x40) - dev->mem[dev->mem_index - 0x40] = val; - else - dev->mem_int[dev->mem_index] = val; - return 0; - - case 0xbd: - kbd_log("ATkbc: AMI MegaKey - write %02X to config index %02X\n", val, dev->mem_index); - switch (dev->mem_index) { - case 0x00: /* STAT8042 */ - dev->status = val; - break; - case 0x01: /* Password_ptr */ - dev->mem[0x1c] = val; - break; - case 0x02: /* Wakeup_Tsk_Reg */ - dev->mem[0x1e] = val; - break; - case 0x03: /* CCB */ - write_cmd(dev, val); - break; - case 0x04: /* Debounce_time */ - dev->mem[0x4d] = val; - break; - case 0x05: /* Pulse_Width */ - dev->mem[0x4e] = val; - break; - case 0x06: /* Pk_sel_byte */ - dev->mem[0x4c] = val; - break; - case 0x07: /* Func_Tsk_Reg */ - dev->mem[0x7e] = val; - break; - case 0x08: /* TypematicRate */ - dev->mem[0x80] = val; - break; - case 0x09: /* Led_Flag_Byte */ - dev->mem[0x81] = val; - break; - case 0x0a: /* Kbms_Command_St */ - dev->mem[0x87] = val; - break; - case 0x0b: /* Delay_Count_Byte */ - dev->mem[0x86] = val; - break; - case 0x0c: /* KBC_Flags */ - dev->mem[0x9b] = val; - break; - case 0x0d: /* SCODE_HK1 */ - dev->mem[0x50] = val; - break; - case 0x0e: /* SCODE_HK2 */ - dev->mem[0x51] = val; - break; - case 0x0f: /* SCODE_HK3 */ - dev->mem[0x52] = val; - break; - case 0x10: /* SCODE_HK4 */ - dev->mem[0x53] = val; - break; - case 0x11: /* SCODE_HK5 */ - dev->mem[0x54] = val; - break; - case 0x12: /* SCODE_HK6 */ - dev->mem[0x55] = val; - break; - case 0x13: /* TASK_HK1 */ - dev->mem[0x56] = val; - break; - case 0x14: /* TASK_HK2 */ - dev->mem[0x57] = val; - break; - case 0x15: /* TASK_HK3 */ - dev->mem[0x58] = val; - break; - case 0x16: /* TASK_HK4 */ - dev->mem[0x59] = val; - break; - case 0x17: /* TASK_HK5 */ - dev->mem[0x5a] = val; - break; - /* The next 4 bytes have uncertain correspondences. */ - case 0x18: /* Batt_Poll_delay_Time */ - dev->mem[0x5b] = val; - break; - case 0x19: /* Batt_Alarm_Reg1 */ - dev->mem[0x5c] = val; - break; - case 0x1a: /* Batt_Alarm_Reg2 */ - dev->mem[0x5d] = val; - break; - case 0x1b: /* Batt_Alarm_Tsk_Reg */ - dev->mem[0x5e] = val; - break; - case 0x1c: /* Kbc_State1 */ - dev->mem[0x9d] = val; - break; - case 0x1d: /* Aux_Config */ - dev->mem[0x75] = val; - break; - case 0x1e: /* Kbc_State3 */ - dev->mem[0x73] = val; - break; - } - return 0; - - case 0xc1: /* write input port */ - kbd_log("ATkbc: AMI MegaKey - write %02X to input port\n", val); - dev->p1 = val; - return 0; - case 0xcb: /* set keyboard mode */ kbd_log("ATkbc: AMI - set keyboard mode\n"); + dev->ami_flags = val; return 0; } @@ -2308,50 +1333,62 @@ static uint8_t write64_ami(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; - uint16_t index = 0x00c0; switch (val) { - case 0x00 ... 0x1f: + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x18: case 0x19: case 0x1a: case 0x1b: + case 0x1c: case 0x1d: case 0x1e: case 0x1f: kbd_log("ATkbc: AMI - alias read from %08X\n", val); - kbc_transmit(dev, dev->mem[val + 0x20]); + add_data(dev, dev->mem[val]); return 0; - case 0x40 ... 0x5f: - kbd_log("ATkbc: AMI - alias write to %08X\n", dev->kbc_cmd); - dev->kbc_in = 1; + case 0x40: case 0x41: case 0x42: case 0x43: + case 0x44: case 0x45: case 0x46: case 0x47: + case 0x48: case 0x49: case 0x4a: case 0x4b: + 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: case 0x5f: + kbd_log("ATkbc: AMI - alias write to %08X\n", dev->command); + dev->want60 = 1; return 0; case 0xa0: /* copyright message */ - kbc_transmit(dev, ami_copr[0]); - dev->kbc_phase = 1; - return 0; + add_data(dev, 0x28); + add_data(dev, 0x00); + break; case 0xa1: /* get controller version */ kbd_log("ATkbc: AMI - get controller version\n"); - kbc_transmit(dev, 'H'); - // kbc_transmit(dev, 'Z'); + add_data(dev, 'H'); return 0; case 0xa2: /* clear keyboard controller lines P22/P23 */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - clear KBC lines P22 and P23\n"); - write_output(dev, dev->p2 & 0xf3); - kbc_transmit(dev, 0x00); + write_output(dev, dev->output_port & 0xf3); + add_data(dev, 0x00); return 0; } break; case 0xa3: /* set keyboard controller lines P22/P23 */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - set KBC lines P22 and P23\n"); - write_output(dev, dev->p2 | 0x0c); - kbc_transmit(dev, 0x00); + write_output(dev, dev->output_port | 0x0c); + add_data(dev, 0x00); return 0; } break; case 0xa4: /* write clock = low */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - write clock = low\n"); dev->ami_stat &= 0xfe; return 0; @@ -2359,7 +1396,7 @@ write64_ami(void *priv, uint8_t val) break; case 0xa5: /* write clock = high */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - write clock = high\n"); dev->ami_stat |= 0x01; return 0; @@ -2367,15 +1404,15 @@ write64_ami(void *priv, uint8_t val) break; case 0xa6: /* read clock */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - read clock\n"); - kbc_transmit(dev, !!(dev->ami_stat & 1)); + add_data(dev, !!(dev->ami_stat & 1)); return 0; } break; case 0xa7: /* write cache bad */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - write cache bad\n"); dev->ami_stat &= 0xfd; return 0; @@ -2383,7 +1420,7 @@ write64_ami(void *priv, uint8_t val) break; case 0xa8: /* write cache good */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - write cache good\n"); dev->ami_stat |= 0x02; return 0; @@ -2391,237 +1428,68 @@ write64_ami(void *priv, uint8_t val) break; case 0xa9: /* read cache */ - if (!(dev->flags & KBC_FLAG_PS2)) { + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { kbd_log("ATkbc: AMI - read cache\n"); - kbc_transmit(dev, !!(dev->ami_stat & 2)); + add_data(dev, !!(dev->ami_stat & 2)); return 0; } break; case 0xaf: /* set extended controller RAM */ kbd_log("ATkbc: set extended controller RAM\n"); - dev->kbc_in = 1; + dev->want60 = 1; + dev->secr_phase = 1; return 0; - case 0xb0 ... 0xb3: + case 0xb0: case 0xb1: case 0xb2: case 0xb3: /* set KBC lines P10-P13 (input port bits 0-3) low */ kbd_log("ATkbc: set KBC lines P10-P13 (input port bits 0-3) low\n"); - if (!(dev->flags & KBC_FLAG_PS2) || (val > 0xb1)) { - dev->p1 &= ~(1 << (val & 0x03)); - } - kbc_transmit(dev, 0x00); + if (!PCI || (val > 0xb1)) + dev->input_port &= ~(1 << (val & 0x03)); + add_data(dev, 0x00); return 0; case 0xb4: case 0xb5: /* set KBC lines P22-P23 (output port bits 2-3) low */ kbd_log("ATkbc: set KBC lines P22-P23 (output port bits 2-3) low\n"); - if (!(dev->flags & KBC_FLAG_PS2)) - write_output(dev, dev->p2 & ~(4 << (val & 0x01))); - kbc_transmit(dev, 0x00); + if (! PCI) + write_output(dev, dev->output_port & ~(4 << (val & 0x01))); + add_data(dev, 0x00); return 0; -#if 0 - case 0xb8 ... 0xbb: -#else - case 0xb9: -#endif + case 0xb8: case 0xb9: case 0xba: case 0xbb: /* set KBC lines P10-P13 (input port bits 0-3) high */ kbd_log("ATkbc: set KBC lines P10-P13 (input port bits 0-3) high\n"); - if (!(dev->flags & KBC_FLAG_PS2) || (val > 0xb9)) { - dev->p1 |= (1 << (val & 0x03)); - kbc_transmit(dev, 0x00); + if (!PCI || (val > 0xb9)) { + dev->input_port |= (1 << (val & 0x03)); + add_data(dev, 0x00); } return 0; - case 0xb8: - kbd_log("ATkbc: AMI MegaKey - memory index\n"); - dev->kbc_in = 1; - return 0; - - case 0xba: - kbd_log("ATkbc: AMI MegaKey - read %02X memory from index %02X\n", dev->mem[dev->mem_index], dev->mem_index); - if (dev->mem_index >= 0x80) { - switch (dev->mem[0x9b] & 0xc0) { - case 0x00: - index = 0x0080; - break; - case 0x40: case 0x80: - index = 0x0000; - break; - case 0xc0: - index = 0x0100; - break; - } - kbc_transmit(dev, dev->mem[index + dev->mem_index]); - } else if (dev->mem_index == 0x42) - kbc_transmit(dev, dev->status); - else if (dev->mem_index >= 0x40) - kbc_transmit(dev, dev->mem[dev->mem_index - 0x40]); - else - kbc_transmit(dev, dev->mem_int[dev->mem_index]); - return 0; - - case 0xbb: - kbd_log("ATkbc: AMI MegaKey - write to memory index %02X\n", dev->mem_index); - dev->kbc_in = 1; - return 0; - -#if 0 case 0xbc: case 0xbd: /* set KBC lines P22-P23 (output port bits 2-3) high */ kbd_log("ATkbc: set KBC lines P22-P23 (output port bits 2-3) high\n"); - if (!(dev->flags & KBC_FLAG_PS2)) - write_output(dev, dev->p2 | (4 << (val & 0x01))); - kbc_transmit(dev, 0x00); - return 0; -#endif - - case 0xbc: - switch (dev->mem_index) { - case 0x00: /* STAT8042 */ - kbc_transmit(dev, dev->status); - break; - case 0x01: /* Password_ptr */ - kbc_transmit(dev, dev->mem[0x1c]); - break; - case 0x02: /* Wakeup_Tsk_Reg */ - kbc_transmit(dev, dev->mem[0x1e]); - break; - case 0x03: /* CCB */ - kbc_transmit(dev, dev->mem[0x20]); - break; - case 0x04: /* Debounce_time */ - kbc_transmit(dev, dev->mem[0x4d]); - break; - case 0x05: /* Pulse_Width */ - kbc_transmit(dev, dev->mem[0x4e]); - break; - case 0x06: /* Pk_sel_byte */ - kbc_transmit(dev, dev->mem[0x4c]); - break; - case 0x07: /* Func_Tsk_Reg */ - kbc_transmit(dev, dev->mem[0x7e]); - break; - case 0x08: /* TypematicRate */ - kbc_transmit(dev, dev->mem[0x80]); - break; - case 0x09: /* Led_Flag_Byte */ - kbc_transmit(dev, dev->mem[0x81]); - break; - case 0x0a: /* Kbms_Command_St */ - kbc_transmit(dev, dev->mem[0x87]); - break; - case 0x0b: /* Delay_Count_Byte */ - kbc_transmit(dev, dev->mem[0x86]); - break; - case 0x0c: /* KBC_Flags */ - kbc_transmit(dev, dev->mem[0x9b]); - break; - case 0x0d: /* SCODE_HK1 */ - kbc_transmit(dev, dev->mem[0x50]); - break; - case 0x0e: /* SCODE_HK2 */ - kbc_transmit(dev, dev->mem[0x51]); - break; - case 0x0f: /* SCODE_HK3 */ - kbc_transmit(dev, dev->mem[0x52]); - break; - case 0x10: /* SCODE_HK4 */ - kbc_transmit(dev, dev->mem[0x53]); - break; - case 0x11: /* SCODE_HK5 */ - kbc_transmit(dev, dev->mem[0x54]); - break; - case 0x12: /* SCODE_HK6 */ - kbc_transmit(dev, dev->mem[0x55]); - break; - case 0x13: /* TASK_HK1 */ - kbc_transmit(dev, dev->mem[0x56]); - break; - case 0x14: /* TASK_HK2 */ - kbc_transmit(dev, dev->mem[0x57]); - break; - case 0x15: /* TASK_HK3 */ - kbc_transmit(dev, dev->mem[0x58]); - break; - case 0x16: /* TASK_HK4 */ - kbc_transmit(dev, dev->mem[0x59]); - break; - case 0x17: /* TASK_HK5 */ - kbc_transmit(dev, dev->mem[0x5a]); - break; - /* The next 4 bytes have uncertain correspondences. */ - case 0x18: /* Batt_Poll_delay_Time */ - kbc_transmit(dev, dev->mem[0x5b]); - break; - case 0x19: /* Batt_Alarm_Reg1 */ - kbc_transmit(dev, dev->mem[0x5c]); - break; - case 0x1a: /* Batt_Alarm_Reg2 */ - kbc_transmit(dev, dev->mem[0x5d]); - break; - case 0x1b: /* Batt_Alarm_Tsk_Reg */ - kbc_transmit(dev, dev->mem[0x5e]); - break; - case 0x1c: /* Kbc_State1 */ - kbc_transmit(dev, dev->mem[0x9d]); - break; - case 0x1d: /* Aux_Config */ - kbc_transmit(dev, dev->mem[0x75]); - break; - case 0x1e: /* Kbc_State3 */ - kbc_transmit(dev, dev->mem[0x73]); - break; - default: - kbc_transmit(dev, 0x00); - break; - } - kbd_log("ATkbc: AMI MegaKey - read from config index %02X\n", dev->mem_index); + if (! PCI) + write_output(dev, dev->output_port | (4 << (val & 0x01))); + add_data(dev, 0x00); return 0; - case 0xbd: - kbd_log("ATkbc: AMI MegaKey - write to config index %02X\n", dev->mem_index); - dev->kbc_in = 1; - return 0; - - case 0xc1: /* write input port */ - kbd_log("ATkbc: AMI MegaKey - write input port\n"); - dev->kbc_in = 1; - return 0; - - case 0xc4: - /* set KBC line P14 low */ - kbd_log("ATkbc: set KBC line P14 (input port bit 4) low\n"); - dev->p1 &= 0xef; - kbc_transmit(dev, 0x00); - return 0; - case 0xc5: - /* set KBC line P15 low */ - kbd_log("ATkbc: set KBC line P15 (input port bit 5) low\n"); - dev->p1 &= 0xdf; - kbc_transmit(dev, 0x00); - return 0; - - case 0xc8: case 0xc9: + case 0xc8: /* - * (un)block KBC lines P22/P23 + * unblock KBC lines P22/P23 * (allow command D1 to change bits 2/3 of the output port) */ - kbd_log("ATkbc: AMI - %sblock KBC lines P22 and P23\n", (val & 1) ? "" : "un"); - dev->p2_locked = (val & 1); + kbd_log("ATkbc: AMI - unblock KBC lines P22 and P23\n"); + dev->output_locked = 1; return 0; - case 0xcc: - /* set KBC line P14 high */ - kbd_log("ATkbc: set KBC line P14 (input port bit 4) high\n"); - dev->p1 |= 0x10; - kbc_transmit(dev, 0x00); - return 0; - case 0xcd: - /* set KBC line P15 high */ - kbd_log("ATkbc: set KBC line P15 (input port bit 5) high\n"); - dev->p1 |= 0x20; - kbc_transmit(dev, 0x00); + case 0xc9: + /* + * block KBC lines P22/P23 + * (disallow command D1 from changing bits 2/3 of the port) + */ + kbd_log("ATkbc: AMI - block KBC lines P22 and P23\n"); + dev->output_locked = 1; return 0; case 0xef: /* ??? - sent by AMI486 */ @@ -2642,20 +1510,23 @@ write64_ibm_mca(void *priv, uint8_t val) case 0xc1: /*Copy bits 0 to 3 of input port to status bits 4 to 7*/ kbd_log("ATkbc: copy bits 0 to 3 of input port to status bits 4 to 7\n"); dev->status &= 0x0f; - dev->status |= ((((dev->p1 & 0xfc) | 0x84) & 0x0f) << 4); + dev->status |= ((((dev->input_port & 0xfc) | 0x84) & 0x0f) << 4); return 0; case 0xc2: /*Copy bits 4 to 7 of input port to status bits 4 to 7*/ kbd_log("ATkbc: copy bits 4 to 7 of input port to status bits 4 to 7\n"); dev->status &= 0x0f; - dev->status |= (((dev->p1 & 0xfc) | 0x84) & 0xf0); + dev->status |= (((dev->input_port & 0xfc) | 0x84) & 0xf0); return 0; case 0xaf: kbd_log("ATkbc: bad KBC command AF\n"); return 1; - case 0xf0 ... 0xff: + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: kbd_log("ATkbc: pulse: %01X\n", (val & 0x03) | 0x0c); pulse_output(dev, (val & 0x03) | 0x0c); return 0; @@ -2670,7 +1541,7 @@ write60_quadtel(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; - switch(dev->kbc_cmd) { + switch(dev->command) { case 0xcf: /*??? - sent by MegaPC BIOS*/ kbd_log("ATkbc: ??? - sent by MegaPC BIOS\n"); return 0; @@ -2679,34 +1550,12 @@ write60_quadtel(void *priv, uint8_t val) return 1; } - static uint8_t write64_olivetti(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; switch (val) { - /* This appears to be a clone of "Read input port", in which case, the bis would be: - 7: M290 (AT KBC): - Keyboard lock (1 = unlocked, 0 = locked); - M300 (PS/2 KBC): - Bus expansion board present (1 = present, 0 = not present); - 6: Usually: - Display (1 = MDA, 0 = CGA, but can have its polarity inverted); - 5: Manufacturing jumper (1 = not installed, 0 = installed (infinite loop)); - 4: RAM on motherboard (1 = 256 kB, 0 = 512 kB - which machine actually uses this?); - 3: Fast Ram check (if inactive keyboard works erratically); - 2: Keyboard fuse present - This appears to be in-line with PS/2: 1 = no power, 0 = keyboard power normal; - 1: M290 (AT KBC): - Unused; - M300 (PS/2 KBC): - Mouse data in; - 0: M290 (AT KBC): - Unused; - M300 (PS/2 KBC): - Key data in. - */ case 0x80: /* Olivetti-specific command */ /* * bit 7: bus expansion board present (M300) / keyboard unlocked (M290) @@ -2715,9 +1564,11 @@ write64_olivetti(void *priv, uint8_t val) * bit 2: keyboard fuse present * bits 0-1: ??? */ - kbc_transmit(dev, 0x0c | (is386 ? 0x00 : 0x80)); + add_to_kbc_queue_front(dev, (0x0c | ((is386) ? 0x00 : 0x80)) & 0xdf, 0, 0x00); + dev->input_port = ((dev->input_port + 1) & 3) | + (dev->input_port & 0xfc); return 0; - } + } return write64_generic(dev, val); } @@ -2735,7 +1586,7 @@ write64_quadtel(void *priv, uint8_t val) case 0xcf: /*??? - sent by MegaPC BIOS*/ kbd_log("ATkbc: ??? - sent by MegaPC BIOS\n"); - dev->kbc_in = 1; + dev->want60 = 1; return 0; } @@ -2748,7 +1599,7 @@ write60_toshiba(void *priv, uint8_t val) { atkbd_t *dev = (atkbd_t *)priv; - switch(dev->kbc_cmd) { + switch(dev->command) { case 0xb6: /* T3100e - set color/mono switch */ kbd_log("ATkbc: T3100e - set color/mono switch\n"); t3100e_mono_set(val); @@ -2791,30 +1642,29 @@ write64_toshiba(void *priv, uint8_t val) case 0xb4: /* T3100e: Get configuration / status */ kbd_log("ATkbc: T3100e: Get configuration / status\n"); - kbc_transmit(dev, t3100e_config_get()); + add_data(dev, t3100e_config_get()); return 0; case 0xb5: /* T3100e: Get colour / mono byte */ kbd_log("ATkbc: T3100e: Get colour / mono byte\n"); - kbc_transmit(dev, t3100e_mono_get()); + add_data(dev, t3100e_mono_get()); return 0; case 0xb6: /* T3100e: Set colour / mono byte */ kbd_log("ATkbc: T3100e: Set colour / mono byte\n"); - dev->kbc_in = 1; + dev->want60 = 1; return 0; case 0xb7: /* T3100e: Emulate PS/2 keyboard */ case 0xb8: /* T3100e: Emulate AT keyboard */ - dev->flags &= ~KBC_FLAG_PS2; + dev->flags &= ~KBC_TYPE_MASK; if (val == 0xb7) { kbd_log("ATkbc: T3100e: Emulate PS/2 keyboard\n"); - dev->flags |= KBC_FLAG_PS2; - } -#ifdef ENABLE_KEYBOARD_AT_LOG - else + dev->flags |= KBC_TYPE_PS2_NOREF; + } else { kbd_log("ATkbc: T3100e: Emulate AT keyboard\n"); -#endif + dev->flags |= KBC_TYPE_ISA; + } return 0; case 0xbb: /* T3100e: Read 'Fn' key. @@ -2824,9 +1674,8 @@ write64_toshiba(void *priv, uint8_t val) kbd_log("ATkbc: T3100e: Read 'Fn' key\n"); if (keyboard_recv(0xb8) || /* Right Alt */ keyboard_recv(0x9d)) /* Right Ctrl */ - kbc_transmit(dev, 0x04); - else - kbc_transmit(dev, 0x00); + add_data(dev, 0x04); + else add_data(dev, 0x00); return 0; case 0xbc: /* T3100e: Reset Fn+Key notification */ @@ -2839,8 +1688,8 @@ write64_toshiba(void *priv, uint8_t val) /* The T3100e returns all bits set except bit 6 which * is set by t3100e_mono_set() */ - dev->p1 = (t3100e_mono_get() & 1) ? 0xff : 0xbf; - kbc_transmit(dev, dev->p1); + dev->input_port = (t3100e_mono_get() & 1) ? 0xff : 0xbf; + add_data(dev, dev->input_port); return 0; } @@ -2853,52 +1702,423 @@ static void kbd_write(uint16_t port, uint8_t val, void *priv) { atkbd_t *dev = (atkbd_t *)priv; + int i = 0, bad = 1; + uint8_t mask, kbc_ven = 0x0; + kbc_ven = dev->flags & KBC_VEN_MASK; - kbd_log("[%04X:%08X] ATkbc: write(%04X, %02X)\n", CS, cpu_state.pc, port, val); + if ((kbc_ven == KBC_VEN_XI8088) && (port == 0x63)) + port = 0x61; + + kbd_log((port == 0x61) ? "" : "ATkbc: write(%04X, %02X)\n", port, val); switch (port) { case 0x60: - dev->status = (dev->status & ~STAT_CD) | STAT_IFULL; - dev->ib = val; - // kbd_status("Write %02X: %02X, Status = %02X\n", port, val, dev->status); + dev->status &= ~STAT_CD; + if (dev->want60) { + /* Write data to controller. */ + dev->want60 = 0; -#if 0 - if ((dev->fast_a20_phase == 1)/* && ((val == 0xdd) || (val == 0xdf))*/) { - dev->status &= ~STAT_IFULL; - write_output(dev, val); - dev->fast_a20_phase = 0; + switch (dev->command) { + case 0x60: case 0x61: case 0x62: case 0x63: + case 0x64: case 0x65: case 0x66: case 0x67: + case 0x68: case 0x69: case 0x6a: case 0x6b: + case 0x6c: case 0x6d: case 0x6e: case 0x6f: + case 0x70: case 0x71: case 0x72: case 0x73: + case 0x74: case 0x75: case 0x76: case 0x77: + case 0x78: case 0x79: case 0x7a: case 0x7b: + case 0x7c: case 0x7d: case 0x7e: case 0x7f: + dev->mem[dev->command & 0x1f] = val; + if (dev->command == 0x60) + write_cmd(dev, val); + break; + + case 0xd1: /* write output port */ + kbd_log("ATkbc: write output port\n"); + if (dev->output_locked) { + /*If keyboard controller lines P22-P23 are blocked, + we force them to remain unchanged.*/ + val &= ~0x0c; + val |= (dev->output_port & 0x0c); + } + write_output(dev, val); + break; + + case 0xd2: /* write to keyboard output buffer */ + kbd_log("ATkbc: write to keyboard output buffer\n"); + add_to_kbc_queue_front(dev, val, 0, 0x00); + break; + + case 0xd3: /* write to mouse output buffer */ + kbd_log("ATkbc: write to mouse output buffer\n"); + if (mouse_write && ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) + keyboard_at_adddata_mouse(val); + break; + + case 0xd4: /* write to mouse */ + kbd_log("ATkbc: write to mouse (%02X)\n", val); + + if (val == 0xbb) + break; + + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + set_enable_mouse(dev, 1); + if (mouse_write) + mouse_write(val, mouse_p); + else + add_to_kbc_queue_front(dev, 0xfe, 2, 0x40); + } + break; + + default: + /* + * Run the vendor-specific handler + * if we have one. Otherwise, or if + * it returns an error, log a bad + * controller command. + */ + if (dev->write60_ven) + bad = dev->write60_ven(dev, val); + + if (bad) { + kbd_log("ATkbc: bad controller command %02x data %02x\n", dev->command, val); + add_data_kbd(0xfe); + } + } + } else { + /* Write data to keyboard. */ + dev->mem[0] &= ~0x10; + + if (dev->key_wantdata) { + dev->key_wantdata = 0; + + /* + * Several system BIOSes and OS device drivers + * mess up with this, and repeat the command + * code many times. Fun! + */ + if (val == dev->key_command) { + /* Respond NAK and ignore it. */ + add_data_kbd(0xfe); + dev->key_command = 0x00; + break; + } + + switch (dev->key_command) { + case 0xed: /* set/reset LEDs */ + add_data_kbd_direct(dev, 0xfa); + kbd_log("ATkbd: set LEDs [%02x]\n", val); + break; + + case 0xf0: /* get/set scancode set */ + add_data_kbd_direct(dev, 0xfa); + if (val == 0) { + kbd_log("Get scan code set: %02X\n", keyboard_mode & 3); + add_data_kbd_direct(dev, keyboard_mode & 3); + } else { + if ((val <= 3) && (val != 1)) { + keyboard_mode &= 0xfc; + keyboard_mode |= (val & 3); + kbd_log("Scan code set now: %02X\n", val); + } + set_scancode_map(dev); + } + break; + + case 0xf3: /* set typematic rate/delay */ + add_data_kbd_direct(dev, 0xfa); + break; + + default: + kbd_log("ATkbd: bad keyboard 0060 write %02X command %02X\n", val, dev->key_command); + add_data_kbd_direct(dev, 0xfe); + break; + } + + /* Keyboard command is now done. */ + dev->key_command = 0x00; + } else { + /* No keyboard command in progress. */ + dev->key_command = 0x00; + + set_enable_kbd(dev, 1); + + switch (val) { + case 0x00: + kbd_log("ATkbd: command 00\n"); + add_data_kbd_direct(dev, 0xfa); + break; + + case 0x05: /*??? - sent by NT 4.0*/ + kbd_log("ATkbd: command 05 (NT 4.0)\n"); + add_data_kbd_direct(dev, 0xfe); + break; + + /* Sent by Pentium-era AMI BIOS'es.*/ + case 0x71: case 0x82: + kbd_log("ATkbd: Pentium-era AMI BIOS command %02X\n", val); + break; + + case 0xed: /* set/reset LEDs */ + kbd_log("ATkbd: set/reset leds\n"); + add_data_kbd_direct(dev, 0xfa); + + dev->key_wantdata = 1; + break; + + case 0xee: /* diagnostic echo */ + kbd_log("ATkbd: ECHO\n"); + add_data_kbd_direct(dev, 0xee); + break; + + case 0xef: /* NOP (reserved for future use) */ + kbd_log("ATkbd: NOP\n"); + break; + + case 0xf0: /* get/set scan code set */ + kbd_log("ATkbd: scan code set\n"); + add_data_kbd_direct(dev, 0xfa); + dev->key_wantdata = 1; + break; + + case 0xf2: /* read ID */ + /* Fixed as translation will be done in add_data_kbd(). */ + kbd_log("ATkbd: read keyboard id\n"); + /* TODO: After keyboard type selection is implemented, make this + return the correct keyboard ID for the selected type. */ + add_data_kbd_direct(dev, 0xfa); + add_data_kbd_direct(dev, 0xab); + add_data_kbd_direct(dev, 0x83); + break; + + case 0xf3: /* set typematic rate/delay */ + kbd_log("ATkbd: set typematic rate/delay\n"); + add_data_kbd_direct(dev, 0xfa); + dev->key_wantdata = 1; + break; + + case 0xf4: /* enable keyboard */ + kbd_log("ATkbd: enable keyboard\n"); + add_data_kbd_direct(dev, 0xfa); + keyboard_scan = 1; + break; + + case 0xf5: /* set defaults and disable keyboard */ + case 0xf6: /* set defaults */ + kbd_log("ATkbd: set defaults%s\n", (val == 0xf6) ? "" : " and disable keyboard"); + keyboard_scan = (val == 0xf6); + kbd_log("val = %02X, keyboard_scan = %i, dev->mem[0] = %02X\n", + val, keyboard_scan, dev->mem[0]); + add_data_kbd_direct(dev, 0xfa); + + keyboard_set3_all_break = 0; + keyboard_set3_all_repeat = 0; + memset(keyboard_set3_flags, 0, 512); + keyboard_mode = (keyboard_mode & 0xfc) | 0x02; + set_scancode_map(dev); + break; + + case 0xf7: /* set all keys to repeat */ + kbd_log("ATkbd: set all keys to repeat\n"); + add_data_kbd_direct(dev, 0xfa); + keyboard_set3_all_break = 1; + break; + + case 0xf8: /* set all keys to give make/break codes */ + kbd_log("ATkbd: set all keys to give make/break codes\n"); + add_data_kbd_direct(dev, 0xfa); + keyboard_set3_all_break = 1; + break; + + case 0xf9: /* set all keys to give make codes only */ + kbd_log("ATkbd: set all keys to give make codes only\n"); + add_data_kbd_direct(dev, 0xfa); + keyboard_set3_all_break = 0; + break; + + case 0xfa: /* set all keys to repeat and give make/break codes */ + kbd_log("ATkbd: set all keys to repeat and give make/break codes\n"); + add_data_kbd_direct(dev, 0xfa); + keyboard_set3_all_repeat = 1; + keyboard_set3_all_break = 1; + break; + + case 0xfe: /* resend last scan code */ + kbd_log("ATkbd: reset last scan code\n"); + add_data_kbd_raw(dev, kbd_last_scan_code); + break; + + case 0xff: /* reset */ + kbd_log("ATkbd: kbd reset\n"); + kbc_queue_reset(1); + kbd_last_scan_code = 0x00; + add_data_kbd_direct(dev, 0xfa); + + /* Set scan code set to 2. */ + keyboard_mode = (keyboard_mode & 0xfc) | 0x02; + set_scancode_map(dev); + + dev->reset_delay = RESET_DELAY_TIME; + break; + + default: + kbd_log("ATkbd: bad keyboard command %02X\n", val); + add_data_kbd_direct(dev, 0xfe); + } + + /* If command needs data, remember command. */ + if (dev->key_wantdata == 1) + dev->key_command = val; + } } -#endif break; - case 0x64: - dev->status |= (STAT_CD | STAT_IFULL); - dev->ib = val; - // kbd_status("Write %02X: %02X, Status = %02X\n", port, val, dev->status); -#if 0 - if (val == 0xd1) { - dev->status &= ~STAT_IFULL; - dev->fast_a20_phase = 1; - } else if (val == 0xfe) { - dev->status &= ~STAT_IFULL; - pulse_output(dev, 0x0e); - } else if ((val == 0xad) || (val == 0xae)) { - dev->status &= ~STAT_IFULL; - if (val & 0x01) - dev->mem[0x20] |= 0x10; - else - dev->mem[0x20] &= ~0x10; - } else if (val == 0xa1) { - dev->status &= ~STAT_IFULL; - kbc_send_to_ob(dev, 'H', 0, 0x00); + case 0x61: + ppi.pb = (ppi.pb & 0x10) | (val & 0x0f); + + speaker_update(); + speaker_gated = val & 1; + speaker_enable = val & 2; + if (speaker_enable) + was_speaker_enable = 1; + pit_ctr_set_gate(&pit->counters[2], val & 1); + + if (kbc_ven == KBC_VEN_XI8088) + xi8088_turbo_set(!!(val & 0x04)); + break; + + case 0x64: + /* Controller command. */ + dev->want60 = 0; + dev->status |= STAT_CD; + + switch (val) { + /* Read data from KBC memory. */ + case 0x20: case 0x21: case 0x22: case 0x23: + case 0x24: case 0x25: case 0x26: case 0x27: + case 0x28: case 0x29: case 0x2a: case 0x2b: + case 0x2c: case 0x2d: case 0x2e: case 0x2f: + case 0x30: case 0x31: case 0x32: case 0x33: + case 0x34: case 0x35: case 0x36: case 0x37: + case 0x38: case 0x39: case 0x3a: case 0x3b: + case 0x3c: case 0x3d: case 0x3e: case 0x3f: + add_data(dev, dev->mem[val & 0x1f]); + break; + + /* Write data to KBC memory. */ + case 0x60: case 0x61: case 0x62: case 0x63: + case 0x64: case 0x65: case 0x66: case 0x67: + case 0x68: case 0x69: case 0x6a: case 0x6b: + case 0x6c: case 0x6d: case 0x6e: case 0x6f: + case 0x70: case 0x71: case 0x72: case 0x73: + case 0x74: case 0x75: case 0x76: case 0x77: + case 0x78: case 0x79: case 0x7a: case 0x7b: + case 0x7c: case 0x7d: case 0x7e: case 0x7f: + dev->want60 = 1; + break; + + case 0xaa: /* self-test */ + kbd_log("ATkbc: self-test\n"); + if ((kbc_ven == KBC_VEN_TOSHIBA) || (kbc_ven == KBC_VEN_SAMSUNG)) + dev->status |= STAT_IFULL; + write_output(dev, ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x4b : 0xcf); + + /* Always reinitialize all queues - the real hardware pulls keyboard and mouse + clocks high, which stops keyboard scanning. */ + kbd_log("ATkbc: self-test reinitialization\n"); + dev->out_new = dev->out_delayed = -1; + for (i = 0; i < 3; i++) + kbc_queue_reset(i); + kbd_last_scan_code = 0x00; + dev->status &= ~STAT_OFULL; + dev->last_irq = dev->old_last_irq = 0; + + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) + write_cmd(dev, 0x30 | STAT_SYSFLAG); + else + write_cmd(dev, 0x10 | STAT_SYSFLAG); + add_data(dev, 0x55); + break; + + case 0xab: /* interface test */ + kbd_log("ATkbc: interface test\n"); + add_data(dev, 0x00); /*no error*/ + break; + + case 0xac: /* diagnostic dump */ + kbd_log("ATkbc: diagnostic dump\n"); + for (i = 0; i < 16; i++) + add_data(dev, dev->mem[i]); + add_data(dev, (dev->input_port & 0xf0) | 0x80); + add_data(dev, dev->output_port); + add_data(dev, dev->status); + break; + + case 0xad: /* disable keyboard */ + kbd_log("ATkbc: disable keyboard\n"); + set_enable_kbd(dev, 0); + break; + + case 0xae: /* enable keyboard */ + kbd_log("ATkbc: enable keyboard\n"); + set_enable_kbd(dev, 1); + break; + + case 0xca: /* read keyboard mode */ + kbd_log("ATkbc: AMI - read keyboard mode\n"); + add_data(dev, dev->ami_flags); + break; + + case 0xcb: /* set keyboard mode */ + kbd_log("ATkbc: AMI - set keyboard mode\n"); + dev->want60 = 1; + break; + + case 0xd0: /* read output port */ + kbd_log("ATkbc: read output port\n"); + mask = 0xff; + if (((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) && (dev->mem[0] & 0x10)) + mask &= 0xbf; + add_to_kbc_queue_front(dev, dev->output_port & mask, 0, 0x00); + break; + + case 0xd1: /* write output port */ + kbd_log("ATkbc: write output port\n"); + dev->want60 = 1; + break; + + case 0xd2: /* write keyboard output buffer */ + kbd_log("ATkbc: write keyboard output buffer\n"); + dev->want60 = 1; + break; + + case 0xdd: /* disable A20 address line */ + case 0xdf: /* enable A20 address line */ + kbd_log("ATkbc: %sable A20\n", (val == 0xdd) ? "dis": "en"); + write_output(dev, (dev->output_port & 0xfd) | (val & 0x02)); + break; + + case 0xe0: /* read test inputs */ + kbd_log("ATkbc: read test inputs\n"); + add_data(dev, 0x00); + break; + + default: + /* + * Unrecognized controller command. + * + * If we have a vendor-specific handler, run + * that. Otherwise, or if that handler fails, + * log a bad command. + */ + if (dev->write64_ven) + bad = dev->write64_ven(dev, val); + + kbd_log(bad ? "ATkbc: bad controller command %02X\n" : "", val); } -#else - /* if (val == 0xa1) { - dev->status &= ~STAT_IFULL; - kbc_send_to_ob(dev, 'H', 0, 0x00); - } */ - // kbc_process(dev); -#endif + + /* If the command needs data, remember the command. */ + if (dev->want60) + dev->command = val; break; } } @@ -2909,20 +2129,83 @@ kbd_read(uint16_t port, void *priv) { atkbd_t *dev = (atkbd_t *)priv; uint8_t ret = 0xff; + uint8_t kbc_ven = 0x0; + kbc_ven = dev->flags & KBC_VEN_MASK; - // if (dev->flags & KBC_FLAG_PS2) - // cycles -= ISA_CYCLES(8); + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) + cycles -= ISA_CYCLES(8); + + if ((kbc_ven == KBC_VEN_XI8088) && (port == 0x63)) + port = 0x61; switch (port) { case 0x60: - ret = dev->ob; + ret = dev->out; dev->status &= ~STAT_OFULL; picintc(dev->last_irq); dev->last_irq = 0; break; + case 0x61: + ret = ppi.pb & ~0xe0; + if (ppispeakon) + ret |= 0x20; + if ((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) { + if (dev->refresh) + ret |= 0x10; + else + ret &= ~0x10; + } + if (kbc_ven == KBC_VEN_XI8088) { + if (xi8088_turbo_get()) + ret |= 0x04; + else + ret &= ~0x04; + } + break; + + case 0x62: + ret = 0xff; + if (kbc_ven == KBC_VEN_OLIVETTI) { + /* SWA on Olivetti M240 mainboard (off=1) */ + ret = 0x00; + if (ppi.pb & 0x8) { + /* Switches 4, 5 - floppy drives (number) */ + int i, fdd_count = 0; + for (i = 0; i < FDD_NUM; i++) { + if (fdd_get_flags(i)) + fdd_count++; + } + if (!fdd_count) + ret |= 0x00; + else + ret |= ((fdd_count - 1) << 2); + /* Switches 6, 7 - monitor type */ + if (video_is_mda()) + ret |= 0x3; + else if (video_is_cga()) + ret |= 0x2; /* 0x10 would be 40x25 */ + else + ret |= 0x0; + } else { + /* bit 2 always on */ + ret |= 0x4; + /* Switch 8 - 8087 FPU. */ + if (hasfpu) + ret |= 0x02; + } + } + break; case 0x64: - ret = dev->status; + ret = (dev->status & 0xfb); + if (dev->mem[0] & STAT_SYSFLAG) + ret |= STAT_SYSFLAG; + /* Only clear the transmit timeout flag on non-PS/2 controllers, as on + PS/2 controller, it is the keyboard/mouse output source bit. */ + // dev->status &= ~STAT_RTIMEOUT; + if (((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) && + (kbc_ven != KBC_VEN_IBM_MCA)) + dev->status &= ~STAT_TTIMEOUT; break; default: @@ -2930,57 +2213,48 @@ kbd_read(uint16_t port, void *priv) break; } - kbd_log("[%04X:%08X] ATkbc: read(%04X) = %02X\n",CS, cpu_state.pc, port, ret); + kbd_log((port == 0x61) ? "" : "ATkbc: read(%04X) = %02X\n", port, ret); return(ret); } +static void +kbd_refresh(void *priv) +{ + atkbd_t *dev = (atkbd_t *)priv; + + dev->refresh = !dev->refresh; + timer_advance_u64(&dev->refresh_time, PS2_REFRESH_TIME); +} + + static void kbd_reset(void *priv) { atkbd_t *dev = (atkbd_t *)priv; - - if (dev == NULL) - return; - - dev->status &= ~(STAT_IFULL | STAT_OFULL | STAT_CD); - dev->last_irq = 0; - picintc(1 << 1); - picintc(1 << 12); - dev->secr_phase = 0; - dev->kbd_in = 0; - dev->ob = 0xff; - - sc_or = 0; -} - - -static void -kbd_power_on(atkbd_t *dev) -{ int i; uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - kbd_reset(dev); - + dev->first_write = 1; + // dev->status = STAT_UNLOCKED | STAT_CD; dev->status = STAT_UNLOCKED; - /* Write the value here first, so that we don't hit a pulse reset. */ - dev->p2 = 0xcf; + dev->mem[0] = 0x01; + dev->mem[0] |= CCB_TRANSLATE; + dev->wantirq = 0; write_output(dev, 0xcf); - dev->mem[0x20] = 0x01; - dev->mem[0x20] |= CCB_TRANSLATE; - dev->ami_mode = !!(dev->flags & KBC_FLAG_PS2); + dev->last_irq = dev->old_last_irq = 0; + dev->secr_phase = 0; + dev->key_wantdata = 0; /* Set up the correct Video Type bits. */ - dev->p1 = video_is_mda() ? 0xf0 : 0xb0; if ((kbc_ven == KBC_VEN_XI8088) || (kbc_ven == KBC_VEN_ACER)) - dev->p1 ^= 0x40; - if ((kbc_ven == KBC_VEN_AMI) || (dev->flags & KBC_FLAG_PS2)) - dev->inhibit = ((dev->p1 & 0x80) >> 3); + dev->input_port = video_is_mda() ? 0xb0 : 0xf0; else - dev->inhibit = 0x10; - kbd_log("ATkbc: input port = %02x\n", dev->p1); + dev->input_port = video_is_mda() ? 0xf0 : 0xb0; + kbd_log("ATkbc: input port = %02x\n", dev->input_port); + + keyboard_mode = 0x02 | (dev->mem[0] & CCB_TRANSLATE); /* Enable keyboard, disable mouse. */ set_enable_kbd(dev, 1); @@ -2988,16 +2262,18 @@ kbd_power_on(atkbd_t *dev) set_enable_mouse(dev, 0); mouse_scan = 0; - dev->mem[0x31] = 0xfe; - - keyboard_mode = 0x02 | (dev->mem[0x20] & CCB_TRANSLATE); - - for (i = 1; i <= 2; i++) + dev->out_new = dev->out_delayed = -1; + for (i = 0; i < 3; i++) kbc_queue_reset(i); + kbd_last_scan_code = 0; + + sc_or = 0; memset(keyboard_set3_flags, 0, 512); set_scancode_map(dev); + + dev->ami_flags = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x01 : 0x00); } @@ -3019,6 +2295,7 @@ kbd_close(void *priv) /* Stop timers. */ timer_disable(&dev->send_delay_timer); + timer_disable(&dev->refresh_time); keyboard_scan = 0; keyboard_send = NULL; @@ -3042,14 +2319,17 @@ kbd_init(const device_t *info) dev->flags = info->local; video_reset(gfxcard); - dev->kbc_poll_phase = KBC_RESET; - kbd_send_to_host(dev, 0xaa); + kbd_reset(dev); - io_sethandler(0x0060, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); - io_sethandler(0x0064, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); + io_sethandler(0x0060, 5, + kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); keyboard_send = add_data_kbd; timer_add(&dev->send_delay_timer, kbd_poll, dev, 1); + + if ((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) + timer_add(&dev->refresh_time, kbd_refresh, dev, 1); + timer_add(&dev->pulse_cb, pulse_poll, dev, 0); dev->write60_ven = NULL; @@ -3065,14 +2345,12 @@ kbd_init(const device_t *info) break; case KBC_VEN_OLIVETTI: - /* The Olivetti controller is a special case - starts directly in the - main loop instead of the reset loop. */ - dev->kbc_poll_phase = KBC_MAIN_LOOP; dev->write64_ven = write64_olivetti; break; case KBC_VEN_AMI: case KBC_VEN_INTEL_AMI: + case KBC_VEN_SAMSUNG: dev->write60_ven = write60_ami; dev->write64_ven = write64_ami; break; @@ -3092,8 +2370,6 @@ kbd_init(const device_t *info) break; } - kbd_power_on(dev); - /* We need this, sadly. */ SavedKbd = dev; @@ -3121,6 +2397,16 @@ const device_t keyboard_at_ami_device = { { NULL }, NULL, NULL, NULL }; +const device_t keyboard_at_samsung_device = { + "PC/AT Keyboard (Samsung)", + 0, + KBC_TYPE_ISA | KBC_VEN_SAMSUNG, + kbd_init, + kbd_close, + kbd_reset, + { NULL }, NULL, NULL, NULL +}; + const device_t keyboard_at_toshiba_device = { "PC/AT Keyboard (Toshiba)", 0, @@ -3152,6 +2438,16 @@ const device_t keyboard_at_ncr_device = { }; const device_t keyboard_ps2_device = { + "PS/2 Keyboard", + 0, + KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC, + kbd_init, + kbd_close, + kbd_reset, + { NULL }, NULL, NULL, NULL +}; + +const device_t keyboard_ps2_ps2_device = { "PS/2 Keyboard", 0, KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, @@ -3164,7 +2460,7 @@ const device_t keyboard_ps2_device = { const device_t keyboard_ps2_ps1_device = { "PS/2 Keyboard (IBM PS/1)", 0, - KBC_TYPE_PS2_1 | KBC_VEN_IBM_PS1, + KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1, kbd_init, kbd_close, kbd_reset, @@ -3174,7 +2470,7 @@ const device_t keyboard_ps2_ps1_device = { const device_t keyboard_ps2_ps1_pci_device = { "PS/2 Keyboard (IBM PS/1)", DEVICE_PCI, - KBC_TYPE_PS2_1 | KBC_VEN_IBM_PS1, + KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1, kbd_init, kbd_close, kbd_reset, @@ -3194,7 +2490,7 @@ const device_t keyboard_ps2_xi8088_device = { const device_t keyboard_ps2_ami_device = { "PS/2 Keyboard (AMI)", 0, - KBC_TYPE_PS2_1 | KBC_VEN_AMI, + KBC_TYPE_PS2_NOREF | KBC_VEN_AMI, kbd_init, kbd_close, kbd_reset, @@ -3204,7 +2500,7 @@ const device_t keyboard_ps2_ami_device = { const device_t keyboard_ps2_olivetti_device = { "PS/2 Keyboard (Olivetti)", 0, - KBC_TYPE_PS2_1 | KBC_VEN_OLIVETTI, + KBC_TYPE_PS2_NOREF | KBC_VEN_OLIVETTI, kbd_init, kbd_close, kbd_reset, @@ -3234,7 +2530,7 @@ const device_t keyboard_ps2_mca_2_device = { const device_t keyboard_ps2_quadtel_device = { "PS/2 Keyboard (Quadtel/MegaPC)", 0, - KBC_TYPE_PS2_1 | KBC_VEN_QUADTEL, + KBC_TYPE_PS2_NOREF | KBC_VEN_QUADTEL, kbd_init, kbd_close, kbd_reset, @@ -3244,7 +2540,7 @@ const device_t keyboard_ps2_quadtel_device = { const device_t keyboard_ps2_pci_device = { "PS/2 Keyboard", DEVICE_PCI, - KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, + KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC, kbd_init, kbd_close, kbd_reset, @@ -3254,7 +2550,7 @@ const device_t keyboard_ps2_pci_device = { const device_t keyboard_ps2_ami_pci_device = { "PS/2 Keyboard (AMI)", DEVICE_PCI, - KBC_TYPE_PS2_1 | KBC_VEN_AMI, + KBC_TYPE_PS2_NOREF | KBC_VEN_AMI, kbd_init, kbd_close, kbd_reset, @@ -3264,7 +2560,7 @@ const device_t keyboard_ps2_ami_pci_device = { const device_t keyboard_ps2_intel_ami_pci_device = { "PS/2 Keyboard (AMI)", DEVICE_PCI, - KBC_TYPE_PS2_1 | KBC_VEN_INTEL_AMI, + KBC_TYPE_PS2_NOREF | KBC_VEN_INTEL_AMI, kbd_init, kbd_close, kbd_reset, @@ -3274,7 +2570,7 @@ const device_t keyboard_ps2_intel_ami_pci_device = { const device_t keyboard_ps2_acer_pci_device = { "PS/2 Keyboard (Acer 90M002A)", DEVICE_PCI, - KBC_TYPE_PS2_1 | KBC_VEN_ACER, + KBC_TYPE_PS2_NOREF | KBC_VEN_ACER, kbd_init, kbd_close, kbd_reset, @@ -3285,8 +2581,17 @@ const device_t keyboard_ps2_acer_pci_device = { void keyboard_at_set_mouse(void (*func)(uint8_t val, void *priv), void *priv) { - // mouse_write = func; - // mouse_p = priv; + mouse_write = func; + mouse_p = priv; +} + + +void +keyboard_at_adddata_keyboard_raw(uint8_t val) +{ + atkbd_t *dev = SavedKbd; + + add_data_kbd_queue(dev, 0, val); } @@ -3299,30 +2604,10 @@ keyboard_at_adddata_mouse(uint8_t val) } -void -keyboard_at_adddata_mouse_direct(uint8_t val) -{ - // atkbd_t *dev = SavedKbd; - - return; -} - - -void -keyboard_at_adddata_mouse_cmd(uint8_t val) -{ - // atkbd_t *dev = SavedKbd; - - return; -} - - void keyboard_at_mouse_reset(void) { - // atkbd_t *dev = SavedKbd; - - return; + kbc_queue_reset(2); } @@ -3333,22 +2618,13 @@ keyboard_at_mouse_pos(void) } -int -keyboard_at_fixed_channel(void) -{ - // atkbd_t *dev = SavedKbd; - - return 0x000; -} - - void keyboard_at_set_mouse_scan(uint8_t val) { atkbd_t *dev = SavedKbd; uint8_t temp_mouse_scan = val ? 1 : 0; - if (temp_mouse_scan == !(dev->mem[0x20] & 0x20)) + if (temp_mouse_scan == !(dev->mem[0] & 0x20)) return; set_enable_mouse(dev, val ? 1 : 0); @@ -3362,7 +2638,7 @@ keyboard_at_get_mouse_scan(void) { atkbd_t *dev = SavedKbd; - return((dev->mem[0x20] & 0x20) ? 0x00 : 0x10); + return((dev->mem[0] & 0x20) ? 0x00 : 0x10); } @@ -3371,17 +2647,5 @@ keyboard_at_set_a20_key(int state) { atkbd_t *dev = SavedKbd; - write_output(dev, (dev->p2 & 0xfd) | ((!!state) << 1)); -} - - -void -keyboard_at_set_mode(int ps2) -{ - atkbd_t *dev = SavedKbd; - - if (ps2) - dev->flags |= KBC_FLAG_PS2; - else - dev->flags &= ~KBC_FLAG_PS2; + write_output(dev, (dev->output_port & 0xfd) | ((!!state) << 1)); } diff --git a/src/device/mouse_ps2.c b/src/device/mouse_ps2.c index 649182ca5..a28a085ff 100644 --- a/src/device/mouse_ps2.c +++ b/src/device/mouse_ps2.c @@ -93,8 +93,6 @@ ps2_write(uint8_t val, void *priv) mouse_t *dev = (mouse_t *)priv; uint8_t temp; - pclog("ps2_write(%02X)\n", val); - if (dev->flags & FLAG_CTRLDAT) { dev->flags &= ~FLAG_CTRLDAT; @@ -104,16 +102,16 @@ ps2_write(uint8_t val, void *priv) switch (dev->command) { case 0xe8: /* set mouse resolution */ dev->resolution = val; - keyboard_at_adddata_mouse_cmd(0xfa); + keyboard_at_adddata_mouse(0xfa); break; case 0xf3: /* set sample rate */ dev->sample_rate = val; - keyboard_at_adddata_mouse_cmd(0xfa); /* Command response */ + keyboard_at_adddata_mouse(0xfa); /* Command response */ break; default: - keyboard_at_adddata_mouse_cmd(0xfc); + keyboard_at_adddata_mouse(0xfc); } } else { dev->command = val; @@ -121,21 +119,21 @@ ps2_write(uint8_t val, void *priv) switch (dev->command) { case 0xe6: /* set scaling to 1:1 */ dev->flags &= ~FLAG_SCALED; - keyboard_at_adddata_mouse_cmd(0xfa); + keyboard_at_adddata_mouse(0xfa); break; case 0xe7: /* set scaling to 2:1 */ dev->flags |= FLAG_SCALED; - keyboard_at_adddata_mouse_cmd(0xfa); + keyboard_at_adddata_mouse(0xfa); break; case 0xe8: /* set mouse resolution */ dev->flags |= FLAG_CTRLDAT; - keyboard_at_adddata_mouse_cmd(0xfa); + keyboard_at_adddata_mouse(0xfa); break; case 0xe9: /* status request */ - keyboard_at_adddata_mouse_cmd(0xfa); + keyboard_at_adddata_mouse(0xfa); temp = (dev->flags & 0x30); if (mouse_buttons & 0x01) temp |= 0x01; @@ -143,13 +141,13 @@ ps2_write(uint8_t val, void *priv) temp |= 0x02; if (mouse_buttons & 0x04) temp |= 0x03; - keyboard_at_adddata_mouse_cmd(temp); - keyboard_at_adddata_mouse_cmd(dev->resolution); - keyboard_at_adddata_mouse_cmd(dev->sample_rate); + keyboard_at_adddata_mouse(temp); + keyboard_at_adddata_mouse(dev->resolution); + keyboard_at_adddata_mouse(dev->sample_rate); break; case 0xeb: /* Get mouse data */ - keyboard_at_adddata_mouse_cmd(0xfa); + keyboard_at_adddata_mouse(0xfa); temp = 0; if (dev->x < 0) @@ -162,36 +160,36 @@ ps2_write(uint8_t val, void *priv) temp |= 2; if ((mouse_buttons & 4) && (dev->flags & FLAG_INTELLI)) temp |= 4; - keyboard_at_adddata_mouse_cmd(temp); - keyboard_at_adddata_mouse_cmd(dev->x & 0xff); - keyboard_at_adddata_mouse_cmd(dev->y & 0xff); + keyboard_at_adddata_mouse(temp); + keyboard_at_adddata_mouse(dev->x & 0xff); + keyboard_at_adddata_mouse(dev->y & 0xff); if (dev->flags & FLAG_INTMODE) - keyboard_at_adddata_mouse_cmd(dev->z); + keyboard_at_adddata_mouse(dev->z); break; case 0xf2: /* read ID */ - keyboard_at_adddata_mouse_cmd(0xfa); + keyboard_at_adddata_mouse(0xfa); if (dev->flags & FLAG_INTMODE) - keyboard_at_adddata_mouse_cmd(0x03); + keyboard_at_adddata_mouse(0x03); else - keyboard_at_adddata_mouse_cmd(0x00); + keyboard_at_adddata_mouse(0x00); break; case 0xf3: /* set command mode */ dev->flags |= FLAG_CTRLDAT; - keyboard_at_adddata_mouse_cmd(0xfa); /* ACK for command byte */ + keyboard_at_adddata_mouse(0xfa); /* ACK for command byte */ break; case 0xf4: /* enable */ dev->flags |= FLAG_ENABLED; mouse_scan = 1; - keyboard_at_adddata_mouse_cmd(0xfa); + keyboard_at_adddata_mouse(0xfa); break; case 0xf5: /* disable */ dev->flags &= ~FLAG_ENABLED; mouse_scan = 0; - keyboard_at_adddata_mouse_cmd(0xfa); + keyboard_at_adddata_mouse(0xfa); break; case 0xf6: /* set defaults */ @@ -201,15 +199,15 @@ mouse_reset: dev->flags &= 0x88; mouse_scan = 1; keyboard_at_mouse_reset(); - keyboard_at_adddata_mouse_cmd(0xfa); + keyboard_at_adddata_mouse(0xfa); if (dev->command == 0xff) { - keyboard_at_adddata_mouse_cmd(0xaa); - keyboard_at_adddata_mouse_cmd(0x00); + keyboard_at_adddata_mouse(0xaa); + keyboard_at_adddata_mouse(0x00); } break; default: - keyboard_at_adddata_mouse_cmd(0xfe); + keyboard_at_adddata_mouse(0xfe); } } @@ -241,9 +239,6 @@ ps2_poll(int x, int y, int z, int b, void *priv) return(0xff); #endif - if ((keyboard_at_fixed_channel() & 0xf00) == 0x200) - return(0xff); - if (!mouse_scan) return(0xff); From bfb3c0c324bd3fbdf1cdc4c3183e14a679226809 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 13 Nov 2021 23:15:28 +0100 Subject: [PATCH 94/96] Fixed the intendation mess in cpu/x86seg.c, removed port 61h handling from keyboard/keyboard_at.c, and fixed a function with undeclared type in win/win.c. --- src/cpu/x86seg.c | 284 +++++++++++++++++++-------------------- src/device/keyboard_at.c | 100 +------------- src/win/win.c | 1 + 3 files changed, 148 insertions(+), 237 deletions(-) diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index 8f5798ddb..bd1d1b864 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -942,173 +942,173 @@ void loadcscall(uint16_t seg) segdat[2] = (segdat[2] & ~(3 << (5+8))) | (CPL << (5+8)); } else /* On non-conforming segments, set RPL = CPL */ seg = (seg & 0xfffc) | CPL; - CS = seg; - do_seg_load(&cpu_state.seg_cs, segdat); - if ((CPL == 3) && (oldcpl != 3)) - flushmmucache_cr3(); + CS = seg; + do_seg_load(&cpu_state.seg_cs, segdat); + if ((CPL == 3) && (oldcpl != 3)) + flushmmucache_cr3(); #ifdef USE_NEW_DYNAREC - oldcpl = CPL; + oldcpl = CPL; #endif #ifdef ENABLE_X86SEG_LOG - x86seg_log("Complete\n"); + x86seg_log("Complete\n"); #endif - cycles -= timing_call_pm; - } else { - type = segdat[2] & 0x0f00; - x86seg_log("Type %03X\n", type); - switch (type) { - case 0x0400: /* Call gate */ - case 0x0c00: /* 386 Call gate */ - x86seg_log("Callgate %08X\n", cpu_state.pc); - cgate32 = (type & 0x0800); - cgate16 = !cgate32; + cycles -= timing_call_pm; + } else { + type = segdat[2] & 0x0f00; + x86seg_log("Type %03X\n", type); + switch (type) { + case 0x0400: /* Call gate */ + case 0x0c00: /* 386 Call gate */ + x86seg_log("Callgate %08X\n", cpu_state.pc); + cgate32 = (type & 0x0800); + cgate16 = !cgate32; #ifndef USE_NEW_DYNAREC - oldcs = CS; + oldcs = CS; #endif - count = segdat[2] & 0x001f; - if (DPL < CPL) { - x86gpf("loadcscall(): ex DPL < CPL",seg & 0xfffc); - return; - } - if (DPL < (seg & 0x0003)) { - x86gpf("loadcscall(): ex DPL < RPL", seg & 0xfffc); - return; - } - if (!(segdat[2] & 0x8000)) { - x86np("Call gate not present", seg & 0xfffc); - return; - } - seg2 = segdat[1]; + count = segdat[2] & 0x001f; + if (DPL < CPL) { + x86gpf("loadcscall(): ex DPL < CPL",seg & 0xfffc); + return; + } + if (DPL < (seg & 0x0003)) { + x86gpf("loadcscall(): ex DPL < RPL", seg & 0xfffc); + return; + } + if (!(segdat[2] & 0x8000)) { + x86np("Call gate not present", seg & 0xfffc); + return; + } + seg2 = segdat[1]; - x86seg_log("New address : %04X:%08X\n", seg2, newpc); + x86seg_log("New address : %04X:%08X\n", seg2, newpc); - if (!(seg2 & 0xfffc)) { - x86gpf("loadcscall(): ex selector is NULL", 0); - return; - } - addr = seg2 & 0xfff8; - dt = (seg2 & 0x0004) ? &ldt : &gdt; - if ((addr + 7) > dt->limit) { - x86gpf("loadcscall(): ex Selector > DT limit", seg2 & 0xfff8); - return; - } - addr += dt->base; - read_descriptor(addr, segdat, segdat32, 1); - if (cpu_state.abrt) - return; + if (!(seg2 & 0xfffc)) { + x86gpf("loadcscall(): ex selector is NULL", 0); + return; + } + addr = seg2 & 0xfff8; + dt = (seg2 & 0x0004) ? &ldt : &gdt; + if ((addr + 7) > dt->limit) { + x86gpf("loadcscall(): ex Selector > DT limit", seg2 & 0xfff8); + return; + } + addr += dt->base; + read_descriptor(addr, segdat, segdat32, 1); + if (cpu_state.abrt) + return; x86seg_log("Code seg2 call - %04X - %04X %04X %04X\n", seg2, segdat[0], segdat[1], segdat[2]); - if (DPL > CPL) { - x86gpf("loadcscall(): ex DPL > CPL", seg2 & 0xfffc); - return; - } - if (!(segdat[2] & 0x8000)) { - x86seg_log("Call gate CS not present %04X\n", seg2); - x86np("Call gate CS not present", seg2 & 0xfffc); - return; - } + if (DPL > CPL) { + x86gpf("loadcscall(): ex DPL > CPL", seg2 & 0xfffc); + return; + } + if (!(segdat[2] & 0x8000)) { + x86seg_log("Call gate CS not present %04X\n", seg2); + x86np("Call gate CS not present", seg2 & 0xfffc); + return; + } - switch (segdat[2] & 0x1f00) { - case 0x1800: case 0x1900: case 0x1a00: case 0x1b00: /* Non-conforming code */ - if (DPL < CPL) { + switch (segdat[2] & 0x1f00) { + case 0x1800: case 0x1900: case 0x1a00: case 0x1b00: /* Non-conforming code */ + if (DPL < CPL) { #ifdef USE_NEW_DYNAREC - uint16_t oldcs = CS; + uint16_t oldcs = CS; #endif - oaddr = addr; - /* Load new stack */ - oldss = SS; - oldsp = oldsp2 = ESP; - cpl_override = 1; - if (tr.access & 8) { - addr = 4 + tr.base + (DPL << 3); - newss = readmemw(0, addr + 4); - if (cpu_16bitbus) { - newsp = readmemw(0, addr); - newsp |= (readmemw(0, addr + 2) << 16); - } else - newsp = readmeml(0, addr); - } else { - addr = 2 + tr.base + (DPL * 4); - newss = readmemw(0, addr + 2); + oaddr = addr; + /* Load new stack */ + oldss = SS; + oldsp = oldsp2 = ESP; + cpl_override = 1; + if (tr.access & 8) { + addr = 4 + tr.base + (DPL << 3); + newss = readmemw(0, addr + 4); + if (cpu_16bitbus) { newsp = readmemw(0, addr); - } - cpl_override = 0; - if (cpu_state.abrt) - return; - x86seg_log("New stack %04X:%08X\n", newss, newsp); - if (!(newss & 0xfffc)) { - x86ts(NULL, newss & 0xfffc); - return; - } - addr = newss & 0xfff8; - dt = (newss & 0x0004) ? &ldt : &gdt; - if ((addr + 7) > dt->limit) { - fatal("Bigger than DT limit %04X %08X %04X CSC SS\n", newss, addr, dt->limit); - x86ts(NULL, newss & ~3); - return; - } - addr += dt->base; - x86seg_log("Read stack seg\n"); - read_descriptor(addr, segdat2, segdat232, 1); - if (cpu_state.abrt) - return; - x86seg_log("Read stack seg done!\n"); - if (((newss & 0x0003) != DPL) || (DPL2 != DPL)) { - x86ts(NULL, newss & 0xfffc); - return; - } - if ((segdat2[2] & 0x1a00) != 0x1200) { - x86ts("Call gate loading SS unknown type", newss & 0xfffc); - return; - } - if (!(segdat2[2] & 0x8000)) { - x86ss("Call gate loading SS not present", newss & 0xfffc); - return; - } - if (!stack32) - oldsp &= 0xffff; - SS = newss; - set_stack32((segdat2[3] & 0x0040) ? 1 : 0); - if (stack32) - ESP = newsp; - else - SP = newsp; + newsp |= (readmemw(0, addr + 2) << 16); + } else + newsp = readmeml(0, addr); + } else { + addr = 2 + tr.base + (DPL * 4); + newss = readmemw(0, addr + 2); + newsp = readmemw(0, addr); + } + cpl_override = 0; + if (cpu_state.abrt) + return; + x86seg_log("New stack %04X:%08X\n", newss, newsp); + if (!(newss & 0xfffc)) { + x86ts(NULL, newss & 0xfffc); + return; + } + addr = newss & 0xfff8; + dt = (newss & 0x0004) ? &ldt : &gdt; + if ((addr + 7) > dt->limit) { + fatal("Bigger than DT limit %04X %08X %04X CSC SS\n", newss, addr, dt->limit); + x86ts(NULL, newss & ~3); + return; + } + addr += dt->base; + x86seg_log("Read stack seg\n"); + read_descriptor(addr, segdat2, segdat232, 1); + if (cpu_state.abrt) + return; + x86seg_log("Read stack seg done!\n"); + if (((newss & 0x0003) != DPL) || (DPL2 != DPL)) { + x86ts(NULL, newss & 0xfffc); + return; + } + if ((segdat2[2] & 0x1a00) != 0x1200) { + x86ts("Call gate loading SS unknown type", newss & 0xfffc); + return; + } + if (!(segdat2[2] & 0x8000)) { + x86ss("Call gate loading SS not present", newss & 0xfffc); + return; + } + if (!stack32) + oldsp &= 0xffff; + SS = newss; + set_stack32((segdat2[3] & 0x0040) ? 1 : 0); + if (stack32) + ESP = newsp; + else + SP = newsp; - do_seg_load(&cpu_state.seg_ss, segdat2); + do_seg_load(&cpu_state.seg_ss, segdat2); - x86seg_log("Set access 1\n"); - cpl_override = 1; - writememw(0, addr + 4, segdat2[2] | 0x100); /* Set accessed bit */ - cpl_override = 0; + x86seg_log("Set access 1\n"); + cpl_override = 1; + writememw(0, addr + 4, segdat2[2] | 0x100); /* Set accessed bit */ + cpl_override = 0; - CS = seg2; - do_seg_load(&cpu_state.seg_cs, segdat); - if ((CPL == 3) && (oldcpl != 3)) - flushmmucache_cr3(); + CS = seg2; + do_seg_load(&cpu_state.seg_cs, segdat); + if ((CPL == 3) && (oldcpl != 3)) + flushmmucache_cr3(); #ifdef USE_NEW_DYNAREC - oldcpl = CPL; + oldcpl = CPL; #endif - set_use32(segdat[3] & 0x0040); - cpu_state.pc = newpc; + set_use32(segdat[3] & 0x0040); + cpu_state.pc = newpc; - x86seg_log("Set access 2\n"); + x86seg_log("Set access 2\n"); - cpl_override = 1; - writememw(0, oaddr + 4, segdat[2] | 0x100); /* Set accessed bit */ - cpl_override = 0; + cpl_override = 1; + writememw(0, oaddr + 4, segdat[2] | 0x100); /* Set accessed bit */ + cpl_override = 0; - x86seg_log("Type %04X\n", type); - if (type == 0x0c00) { - PUSHL(oldss); - PUSHL(oldsp2); - if (cpu_state.abrt) { - SS = oldss; - ESP = oldsp2; + x86seg_log("Type %04X\n", type); + if (type == 0x0c00) { + PUSHL(oldss); + PUSHL(oldsp2); + if (cpu_state.abrt) { + SS = oldss; + ESP = oldsp2; #ifdef USE_NEW_DYNAREC - CS = oldcs; + CS = oldcs; #endif - return; + return; } if (count) { while (count--) { diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 81455f5a6..2969ca82d 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -57,8 +57,6 @@ #define STAT_IFULL 0x02 #define STAT_OFULL 0x01 -#define PS2_REFRESH_TIME (16 * TIMER_USEC) - #define RESET_DELAY_TIME (100 * 10) /* 600ms */ #define CCB_UNUSED 0x80 @@ -98,8 +96,7 @@ typedef struct { uint8_t command, status, old_status, out, old_out, secr_phase, mem_addr, input_port, output_port, old_output_port, key_command, output_locked, ami_stat, want60, - wantirq, key_wantdata, refresh, first_write, - ami_flags, pad[7]; + wantirq, key_wantdata, ami_flags, first_write; uint8_t mem[0x100]; @@ -109,7 +106,7 @@ typedef struct { uint32_t flags; - pc_timer_t refresh_time, pulse_cb; + pc_timer_t pulse_cb; uint8_t (*write60_ven)(void *p, uint8_t val); uint8_t (*write64_ven)(void *p, uint8_t val); @@ -1706,11 +1703,6 @@ kbd_write(uint16_t port, uint8_t val, void *priv) uint8_t mask, kbc_ven = 0x0; kbc_ven = dev->flags & KBC_VEN_MASK; - if ((kbc_ven == KBC_VEN_XI8088) && (port == 0x63)) - port = 0x61; - - kbd_log((port == 0x61) ? "" : "ATkbc: write(%04X, %02X)\n", port, val); - switch (port) { case 0x60: dev->status &= ~STAT_CD; @@ -1972,20 +1964,6 @@ kbd_write(uint16_t port, uint8_t val, void *priv) } break; - case 0x61: - ppi.pb = (ppi.pb & 0x10) | (val & 0x0f); - - speaker_update(); - speaker_gated = val & 1; - speaker_enable = val & 2; - if (speaker_enable) - was_speaker_enable = 1; - pit_ctr_set_gate(&pit->counters[2], val & 1); - - if (kbc_ven == KBC_VEN_XI8088) - xi8088_turbo_set(!!(val & 0x04)); - break; - case 0x64: /* Controller command. */ dev->want60 = 0; @@ -2135,9 +2113,6 @@ kbd_read(uint16_t port, void *priv) if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) cycles -= ISA_CYCLES(8); - if ((kbc_ven == KBC_VEN_XI8088) && (port == 0x63)) - port = 0x61; - switch (port) { case 0x60: ret = dev->out; @@ -2146,56 +2121,6 @@ kbd_read(uint16_t port, void *priv) dev->last_irq = 0; break; - case 0x61: - ret = ppi.pb & ~0xe0; - if (ppispeakon) - ret |= 0x20; - if ((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) { - if (dev->refresh) - ret |= 0x10; - else - ret &= ~0x10; - } - if (kbc_ven == KBC_VEN_XI8088) { - if (xi8088_turbo_get()) - ret |= 0x04; - else - ret &= ~0x04; - } - break; - - case 0x62: - ret = 0xff; - if (kbc_ven == KBC_VEN_OLIVETTI) { - /* SWA on Olivetti M240 mainboard (off=1) */ - ret = 0x00; - if (ppi.pb & 0x8) { - /* Switches 4, 5 - floppy drives (number) */ - int i, fdd_count = 0; - for (i = 0; i < FDD_NUM; i++) { - if (fdd_get_flags(i)) - fdd_count++; - } - if (!fdd_count) - ret |= 0x00; - else - ret |= ((fdd_count - 1) << 2); - /* Switches 6, 7 - monitor type */ - if (video_is_mda()) - ret |= 0x3; - else if (video_is_cga()) - ret |= 0x2; /* 0x10 would be 40x25 */ - else - ret |= 0x0; - } else { - /* bit 2 always on */ - ret |= 0x4; - /* Switch 8 - 8087 FPU. */ - if (hasfpu) - ret |= 0x02; - } - } - break; case 0x64: ret = (dev->status & 0xfb); if (dev->mem[0] & STAT_SYSFLAG) @@ -2219,16 +2144,6 @@ kbd_read(uint16_t port, void *priv) } -static void -kbd_refresh(void *priv) -{ - atkbd_t *dev = (atkbd_t *)priv; - - dev->refresh = !dev->refresh; - timer_advance_u64(&dev->refresh_time, PS2_REFRESH_TIME); -} - - static void kbd_reset(void *priv) { @@ -2273,7 +2188,7 @@ kbd_reset(void *priv) set_scancode_map(dev); - dev->ami_flags = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x01 : 0x00); + dev->ami_flags = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x01 : 0x00; } @@ -2295,7 +2210,6 @@ kbd_close(void *priv) /* Stop timers. */ timer_disable(&dev->send_delay_timer); - timer_disable(&dev->refresh_time); keyboard_scan = 0; keyboard_send = NULL; @@ -2321,15 +2235,11 @@ kbd_init(const device_t *info) video_reset(gfxcard); kbd_reset(dev); - io_sethandler(0x0060, 5, - kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); + io_sethandler(0x0060, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); + io_sethandler(0x0064, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); keyboard_send = add_data_kbd; timer_add(&dev->send_delay_timer, kbd_poll, dev, 1); - - if ((dev->flags & KBC_TYPE_MASK) > KBC_TYPE_PS2_NOREF) - timer_add(&dev->refresh_time, kbd_refresh, dev, 1); - timer_add(&dev->pulse_cb, pulse_poll, dev, 0); dev->write60_ven = NULL; diff --git a/src/win/win.c b/src/win/win.c index ee2fe4063..54aab11eb 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -139,6 +139,7 @@ win_log(const char *fmt, ...) #endif +void free_string(rc_str_t **str) { if (*str != NULL) { From 11431213eda6cc2a27c99b15162473a173f61c31 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 13 Nov 2021 23:25:07 +0100 Subject: [PATCH 95/96] Also reverted all the video changes. --- src/video/CMakeLists.txt | 4 +- src/video/vid_cl54xx.c | 22 --- src/video/vid_et3000.c | 308 -------------------------------------- src/video/vid_et4000.c | 162 ++++---------------- src/video/vid_et4000w32.c | 7 +- src/video/vid_oak_oti.c | 38 ++++- src/video/vid_s3.c | 32 +--- src/video/vid_svga.c | 152 +++---------------- src/video/vid_table.c | 2 - src/win/Makefile.mingw | 1 - 10 files changed, 92 insertions(+), 636 deletions(-) delete mode 100644 src/video/vid_et3000.c diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index edfab1864..c8cbdef62 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -20,8 +20,8 @@ add_library(vid OBJECT video.c vid_table.c vid_cga.c vid_cga_comp.c vid_svga_render.c vid_ddc.c vid_vga.c vid_ati_eeprom.c vid_ati18800.c vid_ati28800.c vid_ati_mach64.c vid_ati68860_ramdac.c vid_bt48x_ramdac.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 vid_rtg310x.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 vid_rtg310x.c vid_f82c425.c vid_ti_cf62011.c vid_tvga.c vid_tgui9440.c vid_tkd8001_ramdac.c vid_att20c49x_ramdac.c vid_s3.c vid_s3_virge.c vid_ibm_rgb528_ramdac.c vid_sdac_ramdac.c vid_ogc.c vid_nga.c vid_tvp3026_ramdac.c) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 21ddeca83..7ba2efb3c 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -1780,28 +1780,6 @@ gd54xx_recalctimings(svga_t *svga) } svga->vram_display_mask = (svga->crtc[0x1b] & 2) ? gd54xx->vram_mask : 0x3ffff; - - pclog("svga->crtc[0x1a] = %02X\n", svga->crtc[0x1a]); - pclog("svga->crtc[0x1b] = %02X\n", svga->crtc[0x1b]); - pclog("svga->crtc[0x1c] = %02X\n", svga->crtc[0x1c]); - - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430) - svga->htotal += ((svga->crtc[0x1c] >> 3) & 0x07); - - 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, - and the actual blanking comes from the display enable signal. */ - /* Start blanking at the first character clock after the last active one. */ - svga->hblankstart = svga->crtc[1] + 1; - svga->hblank_end_val = (svga->htotal + 6) & 0x3f; - /* 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; - /* Also make sure vertical blanking starts on display end. */ - svga->vblankstart = svga->dispend; - } } diff --git a/src/video/vid_et3000.c b/src/video/vid_et3000.c deleted file mode 100644 index 70a383bfa..000000000 --- a/src/video/vid_et3000.c +++ /dev/null @@ -1,308 +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. - * - * Emulation of the Tseng Labs ET3000. - * - * Authors: Miran Grca, - * - * Copyright 2016-2018 Miran Grca. - */ -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/io.h> -#include <86box/mca.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> - - -#define BIOS_ROM_PATH "roms/video/et3000/Tseng ET3000AX ISA VGA-VGA ULTRA.bin" - -typedef struct { - const char *name; - int type; - - svga_t svga; - - rom_t bios_rom; - - uint8_t banking; -} et3000_t; - - -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); - - -static uint8_t -et3000_in(uint16_t addr, void *priv) -{ - et3000_t *dev = (et3000_t *)priv; - svga_t *svga = &dev->svga; - - if (((addr & 0xfff0) == 0x3d0 || - (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; - - switch (addr) { - case 0x3cd: /*Banking*/ - return dev->banking; - - case 0x3d4: - return svga->crtcreg; - - case 0x3d5: - return svga->crtc[svga->crtcreg]; - } - - return svga_in(addr, svga); -} - -static void -et3000_out(uint16_t addr, uint8_t val, void *priv) -{ - et3000_t *dev = (et3000_t *)priv; - svga_t *svga = &dev->svga; - uint8_t old; - - if (((addr & 0xfff0) == 0x3d0 || - (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; - - switch (addr) { - case 0x3c0: - case 0x3c1: - 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); - } - break; - - case 0x3c5: - 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); - return; - } - break; - - case 0x3cf: - if ((svga->gdcaddr & 15) == 5) { - svga->chain4 &= ~0x10; - if (val & 0x40) - svga->chain4 |= (svga->attrregs[0x16] & 0x10); - } - break; - - case 0x3cd: /*Banking*/ - dev->banking = 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->read_bank = ((val >> 3) & 7) << 17; - break; - case 1: /*64K segments*/ - svga->write_bank = (val & 7) << 16; - svga->read_bank = ((val >> 3) & 7) << 16; - break; - } - } - return; - - case 0x3d4: - svga->crtcreg = val & 0x3f; - 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 < 0x0e || svga->crtcreg > 0x10) { - svga->fullchange = changeframecount; - svga_recalctimings(svga); - } - } - break; - } - - svga_out(addr, val, svga); -} - - -static void -et3000_recalctimings(svga_t *svga) -{ - svga->ma_latch |= (svga->crtc[0x23] & 2) << 15; - if (svga->crtc[0x25] & 1) svga->vblankstart |= 0x400; - if (svga->crtc[0x25] & 2) svga->vtotal |= 0x400; - if (svga->crtc[0x25] & 4) svga->dispend |= 0x400; - if (svga->crtc[0x25] & 8) svga->vsyncstart |= 0x400; - if (svga->crtc[0x25] & 0x10) svga->split |= 0x400; - - svga->interlace = !!(svga->crtc[0x25] & 0x80); - - if (svga->attrregs[0x16] & 0x10) { - svga->ma_latch <<= (1 << 0); - svga->rowoffset <<= (1 << 0); - switch (svga->gdcreg[5] & 0x60) { - case 0x00: - svga->render = svga_render_4bpp_highres; - svga->hdisp *= 2; - break; - case 0x20: - svga->render = svga_render_2bpp_highres; - break; - case 0x40: case 0x60: - svga->render = svga_render_8bpp_highres; - break; - } - } - - /* pclog("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: - case 1: - break; - case 3: - svga->clock = (cpuclock * (double)(1ull << 32)) / 40000000.0; - break; - case 5: - svga->clock = (cpuclock * (double)(1ull << 32)) / 65000000.0; - break; - default: - svga->clock = (cpuclock * (double)(1ull << 32)) / 36000000.0; - break; - } -} - - -static void * -et3000_init(const device_t *info) -{ - const char *fn; - et3000_t *dev; - - dev = (et3000_t *)malloc(sizeof(et3000_t)); - memset(dev, 0x00, sizeof(et3000_t)); - dev->name = info->name; - dev->type = info->local; - fn = BIOS_ROM_PATH; - - switch(dev->type) { - case 0: /* ISA ET3000AX */ - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et3000_isa); - svga_init(info, &dev->svga, dev, device_get_config_int("memory") << 10, - et3000_recalctimings, et3000_in, et3000_out, - NULL, NULL); - io_sethandler(0x03c0, 32, - et3000_in,NULL,NULL, et3000_out,NULL,NULL, dev); - break; - } - - rom_init(&dev->bios_rom, (char *) fn, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - - dev->svga.bpp = 8; - dev->svga.miscout = 1; - - return(dev); -} - - -static void -et3000_close(void *priv) -{ - et3000_t *dev = (et3000_t *)priv; - - svga_close(&dev->svga); - - free(dev); -} - - -static void -et3000_speed_changed(void *priv) -{ - et3000_t *dev = (et3000_t *)priv; - - svga_recalctimings(&dev->svga); -} - - -static void -et3000_force_redraw(void *priv) -{ - et3000_t *dev = (et3000_t *)priv; - - dev->svga.fullchange = changeframecount; -} - - -static int -et3000_available(void) -{ - return rom_present(BIOS_ROM_PATH); -} - -static const device_config_t et3000_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 512, "", { 0 }, - { - { - "256 KB", 256 - }, - { - "512 KB", 512 - }, - { - "1 MB", 1024 - }, - { - "" - } - } - }, - { - "", "", -1 - } -}; - -const device_t et3000_isa_device = { - "Tseng Labs ET3000AX (ISA)", - DEVICE_ISA, - 0, - et3000_init, et3000_close, NULL, - { et3000_available }, - et3000_speed_changed, - et3000_force_redraw, - et3000_config -}; diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index dd24a5b09..740be207e 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -55,7 +55,6 @@ #define BIOS_ROM_PATH "roms/video/et4000/et4000.bin" -#define TC6058AF_BIOS_ROM_PATH "roms/video/et4000/Tseng_Labs_VGA-4000_BIOS_V1.1.bin" #define KOREAN_BIOS_ROM_PATH "roms/video/et4000/tgkorvga.bin" #define KOREAN_FONT_ROM_PATH "roms/video/et4000/tg_ksc5601.rom" #define KASAN_BIOS_ROM_PATH "roms/video/et4000/et4000_kasan16.bin" @@ -110,14 +109,13 @@ et4000_in(uint16_t addr, void *priv) { et4000_t *dev = (et4000_t *)priv; svga_t *svga = &dev->svga; - uint8_t ret; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; switch (addr) { case 0x3c2: - if (dev->type == 2) { + if (dev->type == 1) { if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x4e) return 0; else @@ -134,9 +132,7 @@ et4000_in(uint16_t addr, void *priv) case 0x3c7: case 0x3c8: case 0x3c9: - if (dev->type >= 1) - return sc1502x_ramdac_in(addr, svga->ramdac, svga); - break; + return sc1502x_ramdac_in(addr, svga->ramdac, svga); case 0x3cd: /*Banking*/ return dev->banking; @@ -146,26 +142,6 @@ et4000_in(uint16_t addr, void *priv) case 0x3d5: return svga->crtc[svga->crtcreg]; - - 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; - - if (ret & 0x08) - ret &= 0x7f; - else - ret |= 0x80; - - return ret; } return svga_in(addr, svga); @@ -247,34 +223,12 @@ et4000_out(uint16_t addr, uint8_t val, void *priv) (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; switch (addr) { - case 0x3c5: - 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); - return; - } else if (svga->seqaddr == 0x0e) { - svga->seqregs[0x0e] = val; - svga->chain4 &= ~0x02; - if (svga->gdcreg[5] & 0x40) - svga->chain4 |= (svga->seqregs[0x0e] & 0x02); - svga_recalctimings(svga); - return; - } - break; - case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: - if (dev->type >= 1) { - sc1502x_ramdac_out(addr, val, svga->ramdac, svga); - return; - } - break; + sc1502x_ramdac_out(addr, val, svga->ramdac, svga); + return; case 0x3cd: /*Banking*/ if (!(svga->crtc[0x36] & 0x10) && !(svga->gdcreg[6] & 0x08)) { @@ -285,11 +239,7 @@ et4000_out(uint16_t addr, uint8_t val, void *priv) return; case 0x3cf: - if ((svga->gdcaddr & 15) == 5) { - svga->chain4 &= ~0x02; - if (val & 0x40) - svga->chain4 |= (svga->seqregs[0x0e] & 0x02); - } else if ((svga->gdcaddr & 15) == 6) { + if ((svga->gdcaddr & 15) == 6) { if (!(svga->crtc[0x36] & 0x10) && !(val & 0x08)) { svga->write_bank = (dev->banking & 0x0f) * 0x10000; svga->read_bank = ((dev->banking >> 4) & 0x0f) * 0x10000; @@ -470,8 +420,7 @@ et4000_kasan_out(uint16_t addr, uint8_t val, void *priv) break; case 1: case 2: - if ((et4000->kasan_cfg_index - 0xF0) <= 16) - et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val; + et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val; io_removehandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000); et4000->kasan_access_addr = (et4000->kasan_cfg_regs[2] << 8) | et4000->kasan_cfg_regs[1]; io_sethandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000); @@ -514,10 +463,8 @@ et4000_kasan_out(uint16_t addr, uint8_t val, void *priv) case 3: case 4: case 5: - if (et4000->kasan_cfg_regs[0] & 1) { - if ((addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)) <= 4) - et4000->kasan_font_data[addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)] = val; - } + if (et4000->kasan_cfg_regs[0] & 1) + et4000->kasan_font_data[addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)] = val; break; case 6: if ((et4000->kasan_cfg_regs[0] & 1) && (et4000->kasan_font_data[3] & !(val & 0x80)) && (et4000->get_korean_font_base & 0x7F) >= 0x20 && (et4000->get_korean_font_base & 0x7F) < 0x7F) { @@ -601,13 +548,13 @@ et4000_recalctimings(svga_t *svga) et4000_t *dev = (et4000_t *)svga->p; svga->ma_latch |= (svga->crtc[0x33] & 3) << 16; - if (svga->crtc[0x35] & 1) svga->vblankstart |= 0x400; - if (svga->crtc[0x35] & 2) svga->vtotal |= 0x400; - if (svga->crtc[0x35] & 4) svga->dispend |= 0x400; - if (svga->crtc[0x35] & 8) svga->vsyncstart |= 0x400; - if (svga->crtc[0x35] & 0x10) svga->split |= 0x400; + if (svga->crtc[0x35] & 1) svga->vblankstart += 0x400; + if (svga->crtc[0x35] & 2) svga->vtotal += 0x400; + if (svga->crtc[0x35] & 4) svga->dispend += 0x400; + if (svga->crtc[0x35] & 8) svga->vsyncstart += 0x400; + if (svga->crtc[0x35] & 0x10) svga->split += 0x400; if (!svga->rowoffset) svga->rowoffset = 0x100; - if (svga->crtc[0x3f] & 1) svga->htotal |= 0x100; + if (svga->crtc[0x3f] & 1) svga->htotal += 256; if (svga->attrregs[0x16] & 0x20) svga->hdisp <<= 1; switch (((svga->miscout >> 2) & 3) | ((svga->crtc[0x34] << 1) & 4)) { @@ -636,7 +583,7 @@ et4000_recalctimings(svga_t *svga) break; } - if (dev->type == 3 || dev->type == 4 || dev->type == 5) { + if (dev->type == 2 || dev->type == 3 || dev->type == 4) { if ((svga->render == svga_render_text_80) && ((svga->crtc[0x37] & 0x0A) == 0x0A)) { if (dev->port_32cb_val & 0x80) { svga->ma_latch -= 2; @@ -647,19 +594,6 @@ et4000_recalctimings(svga_t *svga) } } } - - if ((svga->seqregs[0x0e] & 0x02) && ((svga->gdcreg[5] & 0x60) >= 0x40)) { - svga->ma_latch <<= (1 << 0); - svga->rowoffset <<= (1 << 0); - svga->render = svga_render_8bpp_highres; - } - - if (dev->type == 0) { - if (svga->render == svga_render_8bpp_lowres) - svga->render = svga_render_8bpp_tseng_lowres; - else if (svga->render == svga_render_8bpp_highres) - svga->render = svga_render_8bpp_tseng_highres; - } } static void @@ -673,7 +607,6 @@ et4000_kasan_recalctimings(svga_t *svga) svga->ma_latch -= 3; svga->ca_adj = (et4000->kasan_cfg_regs[0] >> 6) - 3; svga->ksc5601_sbyte_mask = (et4000->kasan_cfg_regs[0] & 4) << 5; - /* TODO: Are we sure this doesn't use Attribute register 16h bit 6 (two-byte character code enable)? */ if((et4000->kasan_cfg_regs[0] & 0x23) == 0x20 && (et4000->kasan_cfg_regs[4] & 0x80) && ((svga->crtc[0x37] & 0x0B) == 0x0A)) svga->render = svga_render_text_80_ksc5601; } @@ -722,8 +655,7 @@ et4000_init(const device_t *info) fn = BIOS_ROM_PATH; switch(dev->type) { - case 0: /* ISA ET4000AX (TC6058AF) */ - case 1: /* ISA ET4000AX */ + case 0: /* ISA ET4000AX */ dev->vram_size = device_get_config_int("memory") << 10; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000_isa); svga_init(info, &dev->svga, dev, dev->vram_size, @@ -731,11 +663,9 @@ et4000_init(const device_t *info) NULL, NULL); io_sethandler(0x03c0, 32, et4000_in,NULL,NULL, et4000_out,NULL,NULL, dev); - if (dev->type == 0) - fn = TC6058AF_BIOS_ROM_PATH; break; - case 2: /* MCA ET4000AX */ + case 1: /* MCA ET4000AX */ dev->vram_size = 1024 << 10; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000_mca); svga_init(info, &dev->svga, dev, dev->vram_size, @@ -748,8 +678,8 @@ et4000_init(const device_t *info) mca_add(et4000_mca_read, et4000_mca_write, et4000_mca_feedb, NULL, dev); break; - case 3: /* Korean ET4000 */ - case 4: /* Trigem 286M ET4000 */ + case 2: /* Korean ET4000 */ + case 3: /* Trigem 286M ET4000 */ dev->vram_size = device_get_config_int("memory") << 10; dev->port_22cb_val = 0x60; dev->port_32cb_val = 0; @@ -773,7 +703,7 @@ et4000_init(const device_t *info) loadfont(KOREAN_FONT_ROM_PATH, 6); fn = KOREAN_BIOS_ROM_PATH; break; - case 5: /* Kasan ET4000 */ + case 4: /* Kasan ET4000 */ dev->vram_size = device_get_config_int("memory") << 10; dev->svga.ksc5601_sbyte_mask = 0; dev->svga.ksc5601_udc_area_msb[0] = 0xC9; @@ -809,8 +739,7 @@ et4000_init(const device_t *info) } - if (dev->type >= 1) - dev->svga.ramdac = device_add(&sc1502x_ramdac_device); + dev->svga.ramdac = device_add(&sc1502x_ramdac_device); dev->vram_mask = dev->vram_size - 1; @@ -854,13 +783,6 @@ et4000_force_redraw(void *priv) } -static int -et4000_tc6058af_available(void) -{ - return rom_present(TC6058AF_BIOS_ROM_PATH); -} - - static int et4000_available(void) { @@ -882,27 +804,6 @@ et4000_kasan_available(void) rom_present(KASAN_FONT_ROM_PATH); } -static const device_config_t et4000_tc6058af_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 1024, "", { 0 }, - { - { - "256 KB", 256 - }, - { - "512 KB", 512 - }, - { - "" - } - } - }, - { - "", "", -1 - } -}; - static const device_config_t et4000_config[] = { { @@ -927,21 +828,10 @@ static const device_config_t et4000_config[] = } }; -const device_t et4000_tc6058af_isa_device = { - "Tseng Labs ET4000AX (TC6058AF) (ISA)", - DEVICE_ISA, - 0, - et4000_init, et4000_close, NULL, - { et4000_tc6058af_available }, - et4000_speed_changed, - et4000_force_redraw, - et4000_tc6058af_config -}; - const device_t et4000_isa_device = { "Tseng Labs ET4000AX (ISA)", DEVICE_ISA, - 1, + 0, et4000_init, et4000_close, NULL, { et4000_available }, et4000_speed_changed, @@ -952,7 +842,7 @@ const device_t et4000_isa_device = { const device_t et4000_mca_device = { "Tseng Labs ET4000AX (MCA)", DEVICE_MCA, - 2, + 1, et4000_init, et4000_close, NULL, { et4000_available }, et4000_speed_changed, @@ -963,7 +853,7 @@ const device_t et4000_mca_device = { const device_t et4000k_isa_device = { "Trigem Korean VGA (Tseng Labs ET4000AX Korean)", DEVICE_ISA, - 3, + 2, et4000_init, et4000_close, NULL, { et4000k_available }, et4000_speed_changed, @@ -974,7 +864,7 @@ const device_t et4000k_isa_device = { const device_t et4000k_tg286_isa_device = { "Trigem Korean VGA (Trigem 286M)", DEVICE_ISA, - 4, + 3, et4000_init, et4000_close, NULL, { et4000k_available }, et4000_speed_changed, @@ -985,7 +875,7 @@ const device_t et4000k_tg286_isa_device = { const device_t et4000_kasan_isa_device = { "Kasan Hangulmadang-16 VGA (Tseng Labs ET4000AX Korean)", DEVICE_ISA, - 5, + 4, et4000_init, et4000_close, NULL, { et4000_kasan_available }, et4000_speed_changed, diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index f4384b459..65dced875 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -397,7 +397,6 @@ et4000w32p_recalctimings(svga_t *svga) svga->clock = (cpuclock * (double)(1ull << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen); -#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 */ @@ -414,10 +413,10 @@ et4000w32p_recalctimings(svga_t *svga) 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; } } -#endif if (et4000->type == ET4000W32) { if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { @@ -464,10 +463,8 @@ et4000w32p_recalctimings(svga_t *svga) else svga->render = svga_render_text_80; } else { -#if 0 if (svga->adv_flags & FLAG_NOSKEW) svga->ma_latch--; -#endif switch (svga->gdcreg[5] & 0x60) { case 0x00: diff --git a/src/video/vid_oak_oti.c b/src/video/vid_oak_oti.c index 31e49794a..941359987 100644 --- a/src/video/vid_oak_oti.c +++ b/src/video/vid_oak_oti.c @@ -31,7 +31,9 @@ #include <86box/vid_svga_render.h> #define BIOS_037C_PATH "roms/video/oti/bios.bin" -#define BIOS_067_AMA932J_PATH "roms/machines/ama932j/oti067.bin" +#define BIOS_067_AMA932J_PATH "roms/machines/ama932j/oti067.bin" +#define BIOS_067_M300_08_PATH "roms/machines/olivetti_m300_08/EVC_BIOS.ROM" +#define BIOS_067_M300_15_PATH "roms/machines/olivetti_m300_15/EVC_BIOS.ROM" #define BIOS_077_PATH "roms/video/oti/oti077.vbi" @@ -39,6 +41,7 @@ enum { OTI_037C, OTI_067 = 2, OTI_067_AMA932J, + OTI_067_M300 = 4, OTI_077 = 5 }; @@ -394,6 +397,16 @@ oti_init(const device_t *info) io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti); break; + case OTI_067_M300: + if (rom_present(BIOS_067_M300_15_PATH)) + romfn = BIOS_067_M300_15_PATH; + else + romfn = BIOS_067_M300_08_PATH; + oti->vram_size = device_get_config_int("memory"); + oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */ + io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti); + break; + case OTI_067: case OTI_077: romfn = BIOS_077_PATH; @@ -463,20 +476,27 @@ oti037c_available(void) return(rom_present(BIOS_037C_PATH)); } - static int oti067_ama932j_available(void) { return(rom_present(BIOS_067_AMA932J_PATH)); } - static int oti067_077_available(void) { return(rom_present(BIOS_077_PATH)); } +static int +oti067_m300_available(void) +{ + if (rom_present(BIOS_067_M300_15_PATH)) + return(rom_present(BIOS_067_M300_15_PATH)); + else + return(rom_present(BIOS_067_M300_08_PATH)); +} + static const device_config_t oti067_config[] = { @@ -569,6 +589,18 @@ const device_t oti067_device = oti067_config }; +const device_t oti067_m300_device = +{ + "Oak OTI-067 (Olivetti M300-08/15)", + DEVICE_ISA, + 4, + oti_init, oti_close, NULL, + { oti067_m300_available }, + oti_speed_changed, + oti_force_redraw, + oti067_config +}; + const device_t oti067_ama932j_device = { "Oak OTI-067 (AMA-932J)", diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index f64b30fd3..7dff04e4a 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -2801,8 +2801,6 @@ static void s3_recalctimings(svga_t *svga) s3_t *s3 = (s3_t *)svga->p; int clk_sel = (svga->miscout >> 2) & 3; - svga->hdisp = svga->hdisp_old; - if (!svga->scrblank && svga->attr_palette_enable) { if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { if (svga->crtc[0x3a] & 0x10) { /*256+ color register*/ @@ -2812,12 +2810,13 @@ static void s3_recalctimings(svga_t *svga) } svga->ma_latch |= (s3->ma_ext << 16); - if (s3->chip >= S3_86C928) { + svga->hdisp = svga->hdisp_old; + if (svga->crtc[0x5d] & 0x01) svga->htotal |= 0x100; if (svga->crtc[0x5d] & 0x02) { svga->hdisp_time |= 0x100; - svga->hdisp |= 0x100 * svga->dots_per_clock; + svga->hdisp |= 0x100 * ((svga->seqregs[1] & 8) ? 16 : 8); } if (svga->crtc[0x5e] & 0x01) svga->vtotal |= 0x400; if (svga->crtc[0x5e] & 0x02) svga->dispend |= 0x400; @@ -2826,7 +2825,7 @@ static void s3_recalctimings(svga_t *svga) if (svga->crtc[0x5e] & 0x40) svga->split |= 0x400; if (svga->crtc[0x51] & 0x30) svga->rowoffset |= (svga->crtc[0x51] & 0x30) << 4; else if (svga->crtc[0x43] & 0x04) svga->rowoffset |= 0x100; - } else if (svga->crtc[0x43] & 0x04) svga->rowoffset |= 0x100; + } if (!svga->rowoffset) svga->rowoffset = 256; if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { @@ -3066,28 +3065,6 @@ static void s3_recalctimings(svga_t *svga) } } } - - 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); - } - - 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. */ - // pclog("svga->crtc[0x5d] = %02X\n", svga->crtc[0x5d]); - if (svga->crtc[0x5d] & 0x08) - svga->hblank_ext = 0x40; - svga->hblank_end_len = 0x00000040; - } - } - - svga->hblank_overscan = !(svga->crtc[0x33] & 0x20); } static void s3_trio64v_recalctimings(svga_t *svga) @@ -8138,3 +8115,4 @@ const device_t s3_trio64v2_dx_onboard_pci_device = s3_force_redraw, s3_standard_config }; + diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 8ec5c978d..b1d446829 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -20,13 +20,11 @@ * Copyright 2016-2019 Miran Grca. */ #include -#include #include #include -#include #include +#include #include -#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/device.h> @@ -55,27 +53,6 @@ uint8_t svga_rotate[8][256]; static svga_t *svga_pri; -// #define ENABLE_SVGA_LOG 1 -#ifdef ENABLE_SVGA_LOG -int svga_do_log = ENABLE_SVGA_LOG; - - -static void -svga_log(const char *fmt, ...) -{ - va_list ap; - - if (svga_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -#define svga_log(fmt, ...) -#endif - - svga_t *svga_get_pri() { @@ -199,7 +176,7 @@ svga_out(uint16_t addr, uint8_t val, void *p) break; case 4: svga->chain2_write = !(val & 4); - svga->chain4 = (svga->chain4 & ~8) | (val & 8); + svga->chain4 = val & 8; svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && ((svga->chain4 && svga->packed_chain4) || svga->fb_only) && !(svga->adv_flags & FLAG_ADDR_BY8); break; @@ -260,7 +237,7 @@ svga_out(uint16_t addr, uint8_t val, void *p) break; case 6: if ((svga->gdcreg[6] & 0xc) != (val & 0xc)) { - switch (val & 0xc) { + switch (val&0xC) { case 0x0: /*128k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); svga->banked_mask = 0xffff; @@ -291,9 +268,6 @@ svga_out(uint16_t addr, uint8_t val, void *p) ((svga->gdcaddr & 15) == 6 && (val ^ o) & 1)) svga_recalctimings(svga); break; - case 0x3da: - svga->fcr = val; - break; } } @@ -361,9 +335,6 @@ svga_in(uint16_t addr, void *p) if (svga->adv_flags & FLAG_RAMDAC_SHIFT) ret >>= 2; break; - case 0x3ca: - ret = svga->fcr; - break; case 0x3cc: ret = svga->miscout; break; @@ -397,11 +368,7 @@ svga_in(uint16_t addr, void *p) svga->cgastat &= ~0x30; else svga->cgastat ^= 0x30; - ret = svga->cgastat; - - if ((svga->fcr & 0x08) && svga->dispon) - ret |= 0x08; break; } @@ -433,10 +400,6 @@ void svga_recalctimings(svga_t *svga) { double crtcconst, _dispontime, _dispofftime, disptime; -#ifdef ENABLE_SVGA_LOG - int vsyncend, vblankend; - int hdispstart, hdispend, hsyncstart, hsyncend; -#endif svga->vtotal = svga->crtc[6]; svga->dispend = svga->crtc[0x12]; @@ -474,9 +437,12 @@ svga_recalctimings(svga_t *svga) svga->vblankstart |= 0x200; svga->vblankstart++; - svga->hdisp = svga->crtc[1] - ((svga->crtc[3] & 0x60) >> 5); + svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5); svga->hdisp++; + svga->htotal = svga->crtc[0]; + svga->htotal += 6; /*+6 is required for Tyrian*/ + svga->rowoffset = svga->crtc[0x13]; svga->clock = (svga->vidclock) ? VGACONST2 : VGACONST1; @@ -493,19 +459,20 @@ svga_recalctimings(svga_t *svga) svga->hdisp_time = svga->hdisp; svga->render = svga_render_blank; 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->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)) { /*Text mode*/ - if (svga->seqregs[1] & 8) /*40 column*/ + if (svga->seqregs[1] & 8) /*40 column*/ { svga->render = svga_render_text_40; - else + svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; + /* Character clock is off by 1 now in 40-line modes, on all cards. */ + svga->ma_latch--; + svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18; + } else { svga->render = svga_render_text_80; + svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9; + } svga->hdisp_old = svga->hdisp; } else { + svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; svga->hdisp_old = svga->hdisp; switch (svga->gdcreg[5] & 0x60) { @@ -567,7 +534,7 @@ svga_recalctimings(svga_t *svga) } svga->linedbl = svga->crtc[9] & 0x80; - svga->char_width = (svga->seqregs[1] & 1) ? 8 : 9; + svga->char_width = (svga->seqregs[1] & 1) ? 8 : 9; if (enable_overscan) { overscan_y = (svga->rowcount + 1) << 1; @@ -584,41 +551,9 @@ svga_recalctimings(svga_t *svga) } else overscan_x = 16; - svga->htotal = svga->crtc[0]; - svga->hblankstart = svga->crtc[4] + 1; - svga->hblank_end_val = (svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00); - // pclog("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); - } else - svga->dots_per_clock = 1; - - /* Do svga->recalctimings_ex() here so that the above five variables can be - updated by said function. */ if (svga->recalctimings_ex) svga->recalctimings_ex(svga); - svga->htotal += 6; /*+6 is required for Tyrian*/ - 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; - - 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->y_add = (overscan_y >> 1) - (svga->crtc[8] & 0x1f); svga->x_add = (overscan_x >> 1); @@ -627,44 +562,6 @@ svga_recalctimings(svga_t *svga) crtcconst = svga->clock * svga->char_width; -#ifdef ENABLE_SVGA_LOG - vsyncend = (svga->vsyncstart & 0xfffffff0) | (svga->crtc[0x11] & 0x0f); - if (vsyncend <= svga->vsyncstart) - vsyncend += 0x00000010; - vblankend = (svga->vblankstart & 0xffffff80) | (svga->crtc[0x16] & 0x7f); - if (vblankend <= svga->vblankstart) - vblankend += 0x00000080; - - hdispstart = ((svga->crtc[3] >> 5) & 3); - hdispend = svga->crtc[1] + 1; - hsyncstart = svga->crtc[4] + ((svga->crtc[5] >> 5) & 3) + 1; - hsyncend = (hsyncstart & 0xffffffe0) | (svga->crtc[5] & 0x1f); - if (hsyncend <= hsyncstart) - hsyncend += 0x00000020; -#endif - - svga_log("Last scanline in the vertical period: %i\n" - "First scanline after the last of active display: %i\n" - "First scanline with vertical retrace asserted: %i\n" - "First scanline after the last with vertical retrace asserted: %i\n" - "First scanline of blanking: %i\n" - "First scanline after the last of blanking: %i\n" - "\n" - "Last character in the horizontal period: %i\n" - "First character of active display: %i\n" - "First character after the last of active display: %i\n" - "First character with horizontal retrace asserted: %i\n" - "First character after the last with horizontal retrace asserted: %i\n" - "First character of blanking: %i\n" - "First character after the last of blanking: %i\n" - "\n" - "\n", - svga->vtotal, svga->dispend, svga->vsyncstart, vsyncend, - svga->vblankstart, vblankend, - svga->htotal, hdispstart, hdispend, hsyncstart, hsyncend, - svga->hblankstart, svga->hblankend - ); - disptime = svga->htotal; _dispontime = svga->hdisp_time; @@ -750,8 +647,6 @@ svga_poll(void *p) uint32_t x, blink_delay; int wx, wy; int ret, old_ma; - // int lines_num = (svga->vtotal > svga->vsyncstart) ? svga->vtotal : svga->vsyncstart; - // int lines_num = svga->vsyncstart + 3 + 19; if (!svga->linepos) { if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena) { @@ -830,7 +725,7 @@ svga_poll(void *p) svga->displine++; if (svga->interlace) svga->displine++; - if ((svga->cgastat & 8) && ((svga->displine & 15) == (svga->crtc[0x11] & 15))) + if ((svga->cgastat & 8) && ((svga->displine & 15) == (svga->crtc[0x11] & 15)) && svga->vslines) svga->cgastat &= ~8; svga->vslines++; if (svga->displine > 1500) @@ -882,12 +777,11 @@ svga_poll(void *p) if (ret) { if (svga->interlace && svga->oddeven) - svga->ma = svga->maback = (svga->rowoffset << 1) + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub; + svga->ma = svga->maback = (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5); else - svga->ma = svga->maback = ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub; + svga->ma = svga->maback = ((svga->crtc[5] & 0x60) >> 5); svga->ma = (svga->ma << 2); svga->maback = (svga->maback << 2); - svga->sc = 0; if (svga->attrregs[0x10] & 0x20) { svga->scrollcache = 0; @@ -952,9 +846,9 @@ svga_poll(void *p) svga->vslines = 0; if (svga->interlace && svga->oddeven) - svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub; + svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5); else - svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub; + svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[5] & 0x60) >> 5); svga->ca = ((svga->crtc[0xe] << 8) | svga->crtc[0xf]) + ((svga->crtc[0xb] & 0x60) >> 5) + svga->ca_adj; svga->ma = (svga->ma << 2); @@ -964,7 +858,6 @@ svga_poll(void *p) if (svga->vsync_callback) svga->vsync_callback(svga); } - // if (svga->vc == lines_num) { if (svga->vc == svga->vtotal) { svga->vc = 0; svga->sc = 0; @@ -1084,7 +977,6 @@ svga_init(const device_t *info, svga_t *svga, void *p, 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; } diff --git a/src/video/vid_table.c b/src/video/vid_table.c index e5cd12f9a..32865df01 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -112,8 +112,6 @@ video_cards[] = { { "tvga9000b", &tvga9000b_device }, { "tgkorvga", &et4000k_isa_device }, { "et2000", &et2000_device }, - { "et3000ax", &et3000_isa_device }, - { "et4000ax_tc6058af", &et4000_tc6058af_isa_device }, { "et4000ax", &et4000_isa_device }, { "et4000w32", &et4000w32_device }, { "et4000w32i", &et4000w32i_isa_device }, diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 068562028..bdc3d1246 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -744,7 +744,6 @@ VIDOBJ := video.o \ vid_bt48x_ramdac.o \ vid_av9194.o vid_icd2061.o vid_ics2494.o vid_ics2595.o \ vid_cl54xx.o \ - vid_et3000.o \ vid_et4000.o vid_sc1148x_ramdac.o \ vid_sc1502x_ramdac.o \ vid_et4000w32.o vid_stg_ramdac.o \ From 3e70c7e98a2cceed896cdde62bab59651290664b Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 13 Nov 2021 17:33:43 -0500 Subject: [PATCH 96/96] Trivial fixes and cleanups for serial & parallel --- src/config.c | 10 +++++----- src/device/serial.c | 16 ++-------------- src/include/86box/config.h | 4 ++-- src/include/86box/serial.h | 4 +++- src/machine/m_pcjr.c | 2 +- src/machine/m_xt_zenith.c | 2 +- 6 files changed, 14 insertions(+), 24 deletions(-) diff --git a/src/config.c b/src/config.c index 0bd8dbfe3..872ed41a2 100644 --- a/src/config.c +++ b/src/config.c @@ -1042,12 +1042,12 @@ load_ports(void) char temp[512]; int c, d; - for (c = 0; c < 4; c++) { + for (c = 0; c < SERIAL_MAX; c++) { sprintf(temp, "serial%d_enabled", c + 1); serial_enabled[c] = !!config_get_int(cat, temp, (c >= 2) ? 0 : 1); } - for (c = 0; c < 3; c++) { + for (c = 0; c < PARALLEL_MAX; c++) { sprintf(temp, "lpt%d_enabled", c + 1); lpt_ports[c].enabled = !!config_get_int(cat, temp, (c == 0) ? 1 : 0); @@ -1059,7 +1059,7 @@ load_ports(void) /* Legacy config compatibility. */ d = config_get_int(cat, "lpt_enabled", 2); if (d < 2) { - for (c = 0; c < 3; c++) + for (c = 0; c < PARALLEL_MAX; c++) lpt_ports[c].enabled = d; } config_delete_var(cat, "lpt_enabled"); @@ -2512,7 +2512,7 @@ save_ports(void) char temp[512]; int c, d; - for (c = 0; c < 4; c++) { + for (c = 0; c < SERIAL_MAX; c++) { sprintf(temp, "serial%d_enabled", c + 1); if (((c < 2) && serial_enabled[c]) || ((c >= 2) && !serial_enabled[c])) config_delete_var(cat, temp); @@ -2520,7 +2520,7 @@ save_ports(void) config_set_int(cat, temp, serial_enabled[c]); } - for (c = 0; c < 3; c++) { + for (c = 0; c < PARALLEL_MAX; c++) { sprintf(temp, "lpt%d_enabled", c + 1); d = (c == 0) ? 1 : 0; if (lpt_ports[c].enabled == d) diff --git a/src/device/serial.c b/src/device/serial.c index 3de0c6826..15527fad4 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -717,20 +717,8 @@ serial_set_next_inst(int ni) void serial_standalone_init(void) { - if (next_inst == 0) { - device_add_inst(&i8250_device, 1); - device_add_inst(&i8250_device, 2); - device_add_inst(&i8250_device, 3); - device_add_inst(&i8250_device, 4); - } else if (next_inst == 1) { - device_add_inst(&i8250_device, 2); - device_add_inst(&i8250_device, 3); - device_add_inst(&i8250_device, 4); - } else if (next_inst == 2) { - device_add_inst(&i8250_device, 3); - device_add_inst(&i8250_device, 4); - } else - device_add_inst(&i8250_device, 4); + for ( ; next_inst < 4; ) + device_add_inst(&i8250_device, next_inst + 1); }; diff --git a/src/include/86box/config.h b/src/include/86box/config.h index 549306daa..b630d0c80 100644 --- a/src/include/86box/config.h +++ b/src/include/86box/config.h @@ -110,9 +110,9 @@ typedef struct { /* Ports category */ char parallel_devices[3][32]; /* LPT device names */ #ifdef USE_SERIAL_DEVICES - char serial_devices[2][32]; /* Serial device names */ + char serial_devices[4][32]; /* Serial device names */ #endif - int serial_enabled[2], /* Serial ports 1 and 2 enabled */ + int serial_enabled[4], /* Serial ports 1 and 2 enabled */ parallel_enabled[3]; /* LPT1, LPT2, LPT3 enabled */ /* Other peripherals category */ diff --git a/src/include/86box/serial.h b/src/include/86box/serial.h index 0b6b99aa5..f580f9f9f 100644 --- a/src/include/86box/serial.h +++ b/src/include/86box/serial.h @@ -27,6 +27,8 @@ #define SERIAL_NS16450 2 #define SERIAL_NS16550 3 +#define SERIAL_FIFO_SIZE 16 + /* Default settings for the standard ports. */ #define SERIAL1_ADDR 0x03f8 #define SERIAL1_IRQ 4 @@ -54,7 +56,7 @@ typedef struct serial_s uint8_t rcvr_fifo_pos, xmit_fifo_pos, pad0, pad1, - rcvr_fifo[16], xmit_fifo[16]; + rcvr_fifo[SERIAL_FIFO_SIZE], xmit_fifo[SERIAL_FIFO_SIZE]; pc_timer_t transmit_timer, timeout_timer; double clock_src, transmit_period; diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index 35ddfe6da..482c26ed6 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -867,7 +867,7 @@ machine_pcjr_init(const machine_t *model) device_add(&fdc_pcjr_device); device_add(&i8250_pcjr_device); - serial_set_next_inst(2); /* So that serial_standalone_init() won't do anything. */ + serial_set_next_inst(MAX_SERIAL); /* So that serial_standalone_init() won't do anything. */ return ret; } diff --git a/src/machine/m_xt_zenith.c b/src/machine/m_xt_zenith.c index 1ca553227..791ebdcd1 100644 --- a/src/machine/m_xt_zenith.c +++ b/src/machine/m_xt_zenith.c @@ -154,7 +154,7 @@ machine_xt_z184_init(const machine_t *model) lpt2_remove(); lpt1_init(0x278); device_add(&i8250_device); - serial_set_next_inst(2); /* So that serial_standalone_init() won't do anything. */ + serial_set_next_inst(MAX_SERIAL); /* So that serial_standalone_init() won't do anything. */ device_add(&cga_device);