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..6a4001962 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,26 @@ 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; + } else if (dev->vendor == VEN_SMC) { + if (do_smi) + smi_line = 1; + } } } @@ -740,7 +748,7 @@ acpi_reg_write_ali(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); } } } @@ -816,7 +824,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 +981,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 +1004,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 +1092,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 +1484,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,21 +1506,43 @@ 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) { acpi_t *dev = (acpi_t *) p; + uint16_t old_port = port; acpi_log("[%04X:%08X] APM write: %04X = %02X (AX = %04X, BX = %04X, CX = %04X)\n", CS, cpu_state.pc, port, val, AX, BX, CX); port &= 0x0001; - if (port == 0x0000) { + if ((old_port == 0x00b1) && (dev->vendor == VEN_ALI)) { + pclog("ALi SOFT SMI# status set\n"); dev->apm->cmd = val; - if (dev->apm->do_smi) { - if ((dev->vendor == VEN_INTEL) || (dev->vendor == VEN_ALI)) + dev->regs.ali_soft_smi = 1; + // acpi_raise_smi(dev, dev->apm->do_smi); + if (dev->apm->do_smi) + smi_line = 1; + } else if (port == 0x0000) { + dev->apm->cmd = val; + if (dev->vendor != VEN_ALI) { + if (dev->vendor == VEN_INTEL) dev->regs.glbsts |= 0x20; - acpi_raise_smi(dev); + acpi_raise_smi(dev, dev->apm->do_smi); } } else dev->apm->stat = val; @@ -1517,10 +1554,13 @@ acpi_apm_in(uint16_t port, void *p) { acpi_t *dev = (acpi_t *) p; uint8_t ret = 0xff; + uint16_t old_port = port; port &= 0x0001; - if (port == 0x0000) + if ((old_port == 0x00b1) && (dev->vendor == VEN_ALI)) + ret = dev->apm->cmd; + else if (port == 0x0000) ret = dev->apm->cmd; else ret = dev->apm->stat; @@ -1616,8 +1656,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) { + pclog("Setting I/O handler at port B1\n"); + io_sethandler(0x00b1, 0x0001, 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..25b2c3779 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 acc2168.c cs8230.c ali1217.c ali1429.c ali1489.c et6000.c headland.c +add_library(chipset OBJECT acc2168.c cs8230.c ali1217.c ali1429.c ali1489.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 + 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) diff --git a/src/chipset/ali1531.c b/src/chipset/ali1531.c index c29d831fc..5068b69c1 100644 --- a/src/chipset/ali1531.c +++ b/src/chipset/ali1531.c @@ -41,201 +41,265 @@ typedef struct ali1531_t smram_t *smram; } ali1531_t; -void ali1531_shadow_recalc(int cur_reg, ali1531_t *dev) + +static void +ali1531_smm_recalc(uint8_t val, 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(); -} - -void ali1531_smm_recalc(uint8_t smm_state, 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: + 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: + 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: + 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; + } + + pclog("%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_smm_recalc((val >> 1) & 7, 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 +331,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 +354,7 @@ ali1531_close(void *priv) free(dev); } + static void * ali1531_init(const device_t *info) { @@ -296,6 +370,7 @@ ali1531_init(const device_t *info) return dev; } + const device_t ali1531_device = { "ALi M1531 CPU-to-PCI Bridge", DEVICE_PCI, @@ -306,4 +381,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..e9c604be0 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,7 @@ #include <86box/chipset.h> + #ifdef ENABLE_ALI1543_LOG int ali1543_do_log = ENABLE_ALI1543_LOG; static void @@ -65,27 +68,28 @@ ali1543_log(const char *fmt, ...) #define ali1543_log(fmt, ...) #endif + typedef struct ali1543_t { - uint8_t pci_conf[256], pmu_conf[256], usb_conf[256], ide_conf[256], - sio_regs[256], device_regs[8][256], sio_index, in_configuration_mode, - pci_slot, ide_slot, usb_slot, pmu_slot; + 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; + 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 @@ -93,188 +97,411 @@ typedef struct ali1543_t - 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}; +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 }; -void ali1533_ddma_handler(ali1543_t *dev) + +static 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; + 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 0x40: - dev->pci_conf[addr] = val & 0x7f; - break; + case 0x07: /* Status Byte */ + dev->pci_conf[addr] &= ~(val & 0x30); + 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 0x2c: /* Subsystem Vendor ID */ + case 0x2d: + case 0x2e: + case 0x2f: + if (!(dev->pci_conf[0x74] & 0x40)) + dev->pci_conf[addr] = val; + break; - break; + case 0x40: + dev->pci_conf[addr] = val & 0x7f; + 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 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 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 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 0x45: /* DDMA Enable */ - dev->pci_conf[addr] = 0xcf; - ali1533_ddma_handler(dev); - 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 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; + /* 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)); + pclog("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 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; + /* 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 0x54: /* USB Control ? */ - dev->pci_conf[addr] = val & 0xdf; - 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 0x57: - dev->pci_conf[addr] = val & 0xc7; - break; + /* PCI IRQ Routing */ + case 0x48: case 0x49: case 0x4a: case 0x4b: + dev->pci_conf[addr] = val; - case 0x58: /* IDE Enable */ - dev->pci_conf[addr] = val & 0x7f; - ali5229_ide_handler(dev); - 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 0x59: - case 0x5a: - dev->pci_conf[addr] = val & 0x0e; - break; + case 0x4c: /* PCI INT to ISA Level to Edge transfer */ + dev->pci_conf[addr] = val; - case 0x5b: - dev->pci_conf[addr] = val & 0x02; - break; + for (irq = 1; irq < 9; irq++) + pci_set_irq_level(irq, !(val & (1 << (irq - 1)))); + break; - case 0x5c: - dev->pci_conf[addr] = val & 0x7f; - break; + case 0x4d: /* MBIRQ0(SIRQI#), MBIRQ1(SIRQII#) Interrupt to ISA IRQ routing table */ + dev->pci_conf[addr] = val; - case 0x5d: - dev->pci_conf[addr] = val & 0x02; - break; + pclog("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 0x5e: - dev->pci_conf[addr] = val & 0xe0; - 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 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 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 0x6d: - dev->pci_conf[addr] = val & 0xbf; - break; + /* Hardware setting status bits, read-only (register 0x54) */ - case 0x71: - case 0x72: - dev->pci_conf[addr] = val & 0xef; - 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 0x73: /* DDMA Base Address */ - dev->pci_conf[addr] = val; - ali1533_ddma_handler(dev); - break; + /* IDE interface control + TODO: What is IDSEL address? */ + case 0x58: + dev->pci_conf[addr] = val & 0x7f; + 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; + } + pclog("IDE slot = %02X (A%0i)\n", dev->ide_slot, dev->ide_slot + 11 - 5); + // ali5229_ide_handler(dev); + ali5229_ide_irq_handler(dev); + break; - case 0x74: /* USB IRQ Routing */ - dev->pci_conf[addr] = val & 0xdf; - break; + /* General Purpose input multiplexed pin(GPI) select */ + case 0x59: + dev->pci_conf[addr] = val & 0x0e; + 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 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 0x76: /* PMU IRQ Routing */ - dev->pci_conf[addr] = val & 0x1f; - acpi_set_irq_line(dev->acpi, val & 0x0f); - break; + case 0x5c: + dev->pci_conf[addr] = val & 0x7f; + break; + case 0x5d: + dev->pci_conf[addr] = val & 0x02; + break; - case 0x77: /* SMBus IRQ Routing */ - dev->pci_conf[addr] = val & 0x1f; - break; + case 0x5e: + dev->pci_conf[addr] = val & 0xe0; + break; - default: - dev->pci_conf[addr] = val; - 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; + } + pclog("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; + } + pclog("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)); + pclog("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]; + ret = 0x00; + else { + ret = dev->pci_conf[addr]; + if (addr == 0x41) + ret |= (keyboard_at_get_mouse_scan() << 2); + } + + 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. */ + pclog("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 */ + pclog("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 */ + pclog("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 */ + pclog("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 */ + pclog("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. */ + pclog("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 */ + pclog("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 */ + pclog("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 */ + pclog("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 */ + pclog("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 +515,84 @@ 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; } + if (dev->ide_conf[0x52] & 0x10) + ch ^= 8; + +#if 0 /* 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] & 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] & 0x20) { + current_sec_base = current_pri_base; + current_sec_side = current_pri_side; } +#endif + pclog("ali5229_ide_handler(): Disabling primary IDE...\n"); ide_pri_disable(); + pclog("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) && (dev->ide_conf[0x50] & 0x01)) { + /* Primary Channel Setup */ + if (dev->ide_conf[0x09] & 0x20) { + pclog("ali5229_ide_handler(): Primary IDE base now %04X...\n", current_pri_base); + ide_set_base(0, current_pri_base); + pclog("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); + pclog("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) { + pclog("ali5229_ide_handler(): Secondary IDE base now %04X...\n", current_sec_base); + ide_set_base(1, current_sec_base); + pclog("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); + pclog("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 +600,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 +611,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 +623,757 @@ ali1543_reset(void *priv) dev->ide_conf[0x67] = 0x01; dev->ide_conf[0x78] = 0x21; + ali5229_write(0, 0x04, 0x00, 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); + ali5229_write(0, 0x09, 0xfa, dev); + ali5229_write(0, 0x50, 0x00, dev); + ali5229_write(0, 0x52, 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 (!dev->ide_dev_enable) + return; + + switch (addr) { + case 0x04: /* COM - Command Register */ + dev->ide_conf[addr] = val; + ali5229_ide_handler(dev); + break; + + case 0x09: /* Control */ +#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 */ + dev->ide_conf[addr] = val & 0x2b; + 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) { + ret = dev->ide_conf[addr]; + if ((addr == 0x09) && !(dev->ide_conf[0x50] & 0x02)) + ret &= 0x0f; + 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 (!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) + 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 (!dev->pmu_dev_enable) + return; + + switch (addr) { + case 0x04: /* Enable PMU */ + 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; + pclog("PMU41: %02X\n", val); + // apm_set_do_smi(dev->acpi->apm, (dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x41] & 0x10)); + apm_set_do_smi(dev->acpi->apm, 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)); + pclog("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) { + /* 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) { + pclog("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; + + /* 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); + + /* 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 +1387,51 @@ 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); /* 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; @@ -889,6 +1466,7 @@ ali1543_reset(void *priv) ali1533_sio_lpt_handler(dev); } + static void ali1543_close(void *priv) { @@ -897,6 +1475,7 @@ ali1543_close(void *priv) free(dev); } + static void * ali1543_init(const device_t *info) { @@ -912,7 +1491,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 +1499,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 +1533,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 +1559,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_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/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/device/postcard.c b/src/device/postcard.c index b9f409589..a79590fb5 100644 --- a/src/device/postcard.c +++ b/src/device/postcard.c @@ -40,6 +40,7 @@ static char postcard_str[UISTR_LEN]; /* UI output string */ extern void ui_sb_bugui(char *__str); +#define ENABLE_POSTCARD_LOG 1 #ifdef ENABLE_POSTCARD_LOG int postcard_do_log = ENABLE_POSTCARD_LOG; 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..2ecda49ca 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. */ + pclog("[%08X] Setting channel %i to legacy IRQ %i\n", dev, channel, 14 + channel); + break; + case 1: + /* Native PCI IRQ mode with interrupt pin. */ + pclog("[%08X] Setting channel %i to native PCI INT%c\n", dev, channel, '@' + dev->irq_pin); + break; + case 2: + case 5: + /* MIRQ 0 or 1. */ + pclog("[%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. */ + pclog("[%08X] Setting channel %i to native PCI IRQ %i\n", dev, channel, dev->irq_line); + break; + case 4: + /* ALi Aladdin Native PCI INTAJ mode. */ + pclog("[%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..65f34127d 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -44,9 +44,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 +57,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 +112,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 +121,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 +141,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..2737ce077 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,92 +381,115 @@ 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_ficva502_init(const machine_t *); + +extern int machine_at_ficpa2012_init(const machine_t *); + extern int machine_at_r534f_init(const machine_t *); extern int machine_at_ms5146_init(const machine_t *); @@ -475,19 +498,7 @@ 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 *); - -#ifdef EMU_DEVICE_H -extern const device_t *at_thor_get_device(void); -extern const device_t *at_pb640_get_device(void); -#endif - -/* 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 +537,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 +568,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 +656,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 187bd86fc..290d9636d 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/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 1e7ec471a..4c3a4c70e 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) { @@ -703,6 +728,7 @@ machine_at_pja511m_init(const machine_t *model) return ret; } + #endif /* @@ -730,6 +756,7 @@ machine_at_pc8_init(const machine_t *model) return ret; } + /* * Current bugs: * - ctrl-alt-del produces an 8042 error @@ -763,6 +790,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 @@ -790,6 +818,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) @@ -802,9 +831,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); @@ -813,58 +843,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..1679a8185 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,74 @@ 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; +} + + +#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) @@ -1328,22 +915,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 +948,22 @@ 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; } +#endif 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 39dbe0539..54df9b68d 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,695 @@ 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, 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/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 6b1eafa02..53714bcae 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..9c7154257 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -99,6 +99,9 @@ ifeq ($(DEV_BUILD), y) ifndef OLIVETTI OLIVETTI := y endif + ifndef NEW_KBC + NEW_KBC := n + endif else ifndef DEBUG DEBUG := n @@ -172,6 +175,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.) @@ -598,8 +604,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 +616,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 \ + 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 +643,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 +667,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 +776,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) {