diff --git a/src/86box.c b/src/86box.c index eca8544a5..e965f84c5 100644 --- a/src/86box.c +++ b/src/86box.c @@ -724,6 +724,26 @@ pc_init_modules(void) wchar_t temp[512]; char tempc[512]; + c = m = 0; + while (machine_get_internal_name_ex(c) != NULL) { + m = machine_available(c); + if (!m) + pclog("Missing machine: %s\n", machine_getname_ex(c)); + c++; + } + + c = m = 0; + while (video_get_internal_name(c) != NULL) { + memset(tempc, 0, sizeof(tempc)); + device_get_name(video_card_getdevice(c), 0, tempc); + if ((c > 1) && !(tempc[0])) + break; + m = video_card_available(c); + if (!m) + pclog("Missing video card: %s\n", tempc); + c++; + } + pc_log("Scanning for ROM images:\n"); c = m = 0; while (machine_get_internal_name_ex(m) != NULL) { diff --git a/src/chipset/ims8848.c b/src/chipset/ims8848.c new file mode 100644 index 000000000..da758ad5e --- /dev/null +++ b/src/chipset/ims8848.c @@ -0,0 +1,411 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the IMS 8848/8849 chipset. + * + * + * + * Authors: Miran Grca, + * Tiseno100, + * + * Copyright 2021 Miran Grca. + * Copyright 2021 Tiseno100. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/io.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/smram.h> +#include <86box/pci.h> +#include <86box/port_92.h> +#include <86box/chipset.h> + + +/* + IMS 884x Configuration Registers + + Note: IMS 884x are rebadged ATMEL AT 40411/40412 chipsets + + By: Tiseno100, Miran Grca(OBattler) + + Register 00h: + Bit 3: F0000-FFFFF Shadow Enable + Bit 2: E0000-EFFFF Shadow Enable + Bit 0: ???? + + Register 04h: + Bit 3: Cache Write Hit Wait State + Bit 2: Cache Read Hit Wait State + + Register 06h: + Bit 3: System BIOS Cacheable (1: Yes / 0: No) + Bit 1: Power Management Mode (1: IRQ / 0: SMI#) + + Register 08h: + Bit 2: System BIOS Shadow Write (1: Enable / 0: Disable) + Bit 1: System BIOS Shadow Read? + + Register 0Dh: + Bit 0: IO 100H-3FFH Idle Detect (1: Enable / 0: Disable) + + Register 0Eh: + Bit 7: DMA & Local Bus Idle Detect (1: Enable / 0: Disable) + Bit 6: Floppy Disk Idle Detect (1: Enable / 0: Disable) + Bit 5: IDE Idle Detect (1: Enable / 0: Disable) + Bit 4: Serial Port Idle Detect (1: Enable / 0: Disable) + Bit 3: Parallel Port Idle Detect (1: Enable / 0: Disable) + Bit 2: Keyboard Idle Detect (1: Enable / 0: Disable) + Bit 1: Video Idle Detect (1: Enable / 0: Disable) + + Register 12h: + Bits 3-2: Power Saving Timer (00 = 1 MIN, 01 = 3 MIN, 10 = 5 MIN, 11 = 8 MIN) + Bit 1: Base Memory (1: 512KB / 0: 640KB) + + Register 1Ah: + Bit 3: Cache Write Hit W/S For PCI (1: Enabled / 0: Disable) + Bit 2: Cache Read Hit W/S For PCI (1: Enabled / 0: Disable) + Bit 1: VESA Clock Skew (1: 4ns/6ns, 0: No Delay/2ns) + + Register 1Bh: + Bit 6: Enable SMRAM (always at 30000-4FFFF) in SMM + Bit 5: ???? + Bit 4: Software SMI# + Bit 3: DC000-DFFFF Shadow Enable + Bit 2: D8000-DBFFF Shadow Enable + Bit 1: D4000-D7FFF Shadow Enable + Bit 0: D0000-D3FFF Shadow Enable + + Register 1Ch: + Bits 7-4: INTA IRQ routing (0 = disabled, 1 to F = IRQ) + Bit 3: CC000-CFFFF Shadow Enable + Bit 2: C8000-CBFFF Shadow Enable + Bit 1: C4000-C7FFF Shadow Enable + Bit 0: C0000-C3FFF Shadow Enable + + Register 1Dh: + Bits 7-4: INTB IRQ routing (0 = disabled, 1 to F = IRQ) + + Register 1Eh: + Bits 7-4: INTC IRQ routing (0 = disabled, 1 to F = IRQ) + Bit 1: C4000-C7FFF Cacheable + Bit 0: C0000-C3FFF Cacheable + + Register 21h: + Bits 7-4: INTD IRQ routing (0 = disabled, 1 to F = IRQ) + + Register 22h: + Bit 5: Local Bus Master #2 select (0 = VESA, 1 = PCI) + Bit 4: Local Bus Master #1 select (0 = VESA, 1 = PCI) + Bits 1-0: Internal HADS# Delay Always (00 = No Delay, 01 = 1 Clk, 10 = 2 Clks) + + Register 23h: + Bit 7: Seven Bits Tag (1: Enabled / 0: Disable) + Bit 3: Extend LBRDY#(VL Master) (1: Enabled / 0: Disable) + Bit 2: Sync LRDY#(VL Slave) (1: Enabled / 0: Disable) + Bit 0: HADS# Delay After LB. Cycle (1: Enabled / 0: Disable) +*/ + +typedef struct +{ + uint8_t idx, access_data, + regs[256], pci_conf[256]; + + smram_t *smram; +} ims8848_t; + + +#ifdef ENABLE_IMS8848_LOG +int ims8848_do_log = ENABLE_IMS8848_LOG; + + +static void +ims8848_log(const char *fmt, ...) +{ + va_list ap; + + if (ims8848_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define ims8848_log(fmt, ...) +#endif + + +/* Shadow write always enabled, 1B and 1C control C000-DFFF read. */ +static void +ims8848_recalc(ims8848_t *dev) +{ + int i, state_on; + uint32_t base; + ims8848_log("SHADOW: 00 = %02X, 08 = %02X, 1B = %02X, 1C = %02X\n", + dev->regs[0x00], dev->regs[0x08], dev->regs[0x1b], dev->regs[0x1c]); + + state_on = MEM_READ_INTERNAL; + state_on |= (dev->regs[0x08] & 0x04) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + + for (i = 0; i < 2; i++) { + base = 0xe0000 + (i << 16); + if (dev->regs[0x00] & (1 << (i + 2))) + mem_set_mem_state_both(base, 0x10000, state_on); + else + mem_set_mem_state_both(base, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + } + + for (i = 0; i < 4; i++) { + base = 0xc0000 + (i << 14); + if (dev->regs[0x1c] & (1 << i)) + mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + else + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + + base = 0xd0000 + (i << 14); + if (dev->regs[0x1b] & (1 << i)) + mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + else + mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + } + + flushmmucache_nopc(); +} + + +static void +ims8848_base_memory(ims8848_t *dev) +{ + /* We can use the proper mem_set_access to handle that. */ + mem_set_mem_state_both(0x80000, 0x20000, (dev->regs[0x12] & 2) ? + (MEM_READ_DISABLED | MEM_WRITE_DISABLED) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)); +} + + +static void +ims8848_smram(ims8848_t *dev) +{ + smram_disable_all(); + + smram_enable(dev->smram, 0x00030000, 0x00030000, 0x20000, dev->regs[0x1b] & 0x40, 1); +} + + +static void +ims8848_write(uint16_t addr, uint8_t val, void *priv) +{ + ims8848_t *dev = (ims8848_t *) priv; + uint8_t old = dev->regs[dev->idx]; + + switch (addr) { + case 0x22: + ims8848_log("[W] IDX = %02X\n", val); + dev->idx = val; + break; + case 0x23: + ims8848_log("[W] IDX IN = %02X\n", val); + if (((val & 0x0f) == ((dev->idx >> 4) & 0x0f)) && ((val & 0xf0) == ((dev->idx << 4) & 0xf0))) + dev->access_data = 1; + break; + case 0x24: + ims8848_log("[W] [%i] REG %02X = %02X\n", dev->access_data, dev->idx, val); + if (dev->access_data) { + dev->regs[dev->idx] = val; + switch (dev->idx) { + case 0x00: case 0x08: case 0x1b: case 0x1c: + /* Shadow RAM */ + ims8848_recalc(dev); + if (dev->idx == 0x1b) { + ims8848_smram(dev); + if (!(old & 0x10) && (val & 0x10)) + smi_line = 1; + } else if (dev->idx == 0x1c) + pci_set_irq_routing(PCI_INTA, (val >> 4) ? (val >> 4) : PCI_IRQ_DISABLED); + break; + + case 0x1d: case 0x1e: + pci_set_irq_routing(PCI_INTB + (dev->idx - 0x1d), (val >> 4) ? (val >> 4) : PCI_IRQ_DISABLED); + break; + case 0x21: + pci_set_irq_routing(PCI_INTD, (val >> 4) ? (val >> 4) : PCI_IRQ_DISABLED); + break; + + case 0x12: + /* Base Memory */ + ims8848_base_memory(dev); + break; + } + dev->access_data = 0; + } + break; + } +} + + +static uint8_t +ims8848_read(uint16_t addr, void *priv) +{ + uint8_t ret = 0xff; + ims8848_t *dev = (ims8848_t *) priv; +#ifdef ENABLE_IMS8848_LOG + uint8_t old_ad = dev->access_data; +#endif + + switch (addr) { + case 0x22: + ims8848_log("[R] IDX = %02X\n", ret); + ret = dev->idx; + break; + case 0x23: + ims8848_log("[R] IDX IN = %02X\n", ret); + ret = (dev->idx >> 4) | (dev->idx << 4); + break; + case 0x24: + if (dev->access_data) { + ret = dev->regs[dev->idx]; + dev->access_data = 0; + } + ims8848_log("[R] [%i] REG %02X = %02X\n", old_ad, dev->idx, ret); + break; + } + + return ret; +} + + +static void +ims8849_pci_write(int func, int addr, uint8_t val, void *priv) +{ + ims8848_t *dev = (ims8848_t *)priv; + + ims8848_log("IMS 884x-PCI: dev->regs[%02x] = %02x POST: %02x\n", addr, val, inb(0x80)); + + if (func == 0) switch (addr) { + case 0x04: + dev->pci_conf[addr] = val; + break; + + case 0x05: + dev->pci_conf[addr] = val & 3; + break; + + case 0x07: + dev->pci_conf[addr] &= val & 0xf7; + break; + + case 0x0c ... 0x0d: + dev->pci_conf[addr] = val; + break; + + case 0x52 ... 0x55: + dev->pci_conf[addr] = val; + break; + } +} + + +static uint8_t +ims8849_pci_read(int func, int addr, void *priv) +{ + ims8848_t *dev = (ims8848_t *)priv; + uint8_t ret = 0xff; + + if (func == 0) + ret = dev->pci_conf[addr]; + + return ret; +} + + +static void +ims8848_reset(void *priv) +{ + ims8848_t *dev = (ims8848_t *)priv; + + memset(dev->regs, 0x00, sizeof(dev->regs)); + memset(dev->pci_conf, 0x00, sizeof(dev->pci_conf)); + + dev->pci_conf[0x00] = 0xe0; /* Integrated Micro Solutions (IMS) */ + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x49; /* 8849 */ + dev->pci_conf[0x03] = 0x88; + + dev->pci_conf[0x04] = 0x07; + dev->pci_conf[0x07] = 0x02; + + dev->pci_conf[0x0b] = 0x06; + + ims8848_recalc(dev); /* Shadow RAM Setup */ + ims8848_base_memory(dev); /* Base Memory Setup */ + + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + + ims8848_smram(dev); +} + + +static void +ims8848_close(void *priv) +{ + ims8848_t *dev = (ims8848_t *) priv; + + smram_del(dev->smram); + + free(dev); +} + + +static void * +ims8848_init(const device_t *info) +{ + ims8848_t *dev = (ims8848_t *) malloc(sizeof(ims8848_t)); + memset(dev, 0, sizeof(ims8848_t)); + + device_add(&port_92_device); + + /* IMS 8848: + 22h Index + 23h Data Unlock + 24h Data + + IMS 8849: + PCI Device 0: IMS 8849 Dummy for compatibility reasons + */ + io_sethandler(0x0022, 0x0003, ims8848_read, NULL, NULL, ims8848_write, NULL, NULL, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, ims8849_pci_read, ims8849_pci_write, dev); + + dev->smram = smram_add(); + smram_set_separate_smram(1); + + cpu_cache_ext_enabled = 1; + cpu_update_waitstates(); + + ims8848_reset(dev); + + return dev; +} + + +const device_t ims8848_device = { + "IMS 8848/8849", + 0, + 0, + ims8848_init, ims8848_close, ims8848_reset, + { NULL }, NULL, NULL, + NULL +}; diff --git a/src/chipset/intel_4x0.c b/src/chipset/intel_4x0.c index 6da41c24f..bf64bd00f 100644 --- a/src/chipset/intel_4x0.c +++ b/src/chipset/intel_4x0.c @@ -55,6 +55,7 @@ typedef struct smram_locked, max_drb, drb_unit, drb_default; uint8_t regs[256], regs_locked[256]; + uint8_t mem_state[256]; int type; smram_t *smram_low, *smram_high; } i4x0_t; @@ -81,23 +82,18 @@ i4x0_log(const char *fmt, ...) static void -i4x0_map(uint32_t addr, uint32_t size, int state) +i4x0_map(i4x0_t *dev, uint32_t addr, uint32_t size, int state) { - switch (state & 3) { - case 0: - mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - break; - case 1: - mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); - break; - case 2: - mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); - break; - case 3: - mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; + uint32_t base = addr >> 12; + int states[4] = { MEM_READ_EXTANY | MEM_WRITE_EXTANY, MEM_READ_INTERNAL | MEM_WRITE_EXTANY, + MEM_READ_EXTANY | MEM_WRITE_INTERNAL, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL }; + + state &= 3; + if (dev->mem_state[base] != state) { + mem_set_mem_state_both(addr, size, states[state]); + dev->mem_state[base] = state; + flushmmucache_nopc(); } - flushmmucache_nopc(); } @@ -584,10 +580,10 @@ i4x0_write(int func, int addr, uint8_t val, void *priv) case 0x59: /* PAM0 */ if (dev->type <= INTEL_430NX) { if ((regs[0x59] ^ val) & 0x0f) - i4x0_map(0x80000, 0x20000, val & 0x0f); + i4x0_map(dev, 0x80000, 0x20000, val & 0x0f); } if ((regs[0x59] ^ val) & 0xf0) { - i4x0_map(0xf0000, 0x10000, val >> 4); + i4x0_map(dev, 0xf0000, 0x10000, val >> 4); shadowbios = (val & 0x10); } if (dev->type > INTEL_430NX) @@ -597,44 +593,44 @@ i4x0_write(int func, int addr, uint8_t val, void *priv) break; case 0x5a: /* PAM1 */ if ((regs[0x5a] ^ val) & 0x0f) - i4x0_map(0xc0000, 0x04000, val & 0xf); + i4x0_map(dev, 0xc0000, 0x04000, val & 0xf); if ((regs[0x5a] ^ val) & 0xf0) - i4x0_map(0xc4000, 0x04000, val >> 4); + i4x0_map(dev, 0xc4000, 0x04000, val >> 4); regs[0x5a] = val & 0x77; break; case 0x5b: /*PAM2 */ if ((regs[0x5b] ^ val) & 0x0f) - i4x0_map(0xc8000, 0x04000, val & 0xf); + i4x0_map(dev, 0xc8000, 0x04000, val & 0xf); if ((regs[0x5b] ^ val) & 0xf0) - i4x0_map(0xcc000, 0x04000, val >> 4); + i4x0_map(dev, 0xcc000, 0x04000, val >> 4); regs[0x5b] = val & 0x77; break; case 0x5c: /*PAM3 */ if ((regs[0x5c] ^ val) & 0x0f) - i4x0_map(0xd0000, 0x04000, val & 0xf); + i4x0_map(dev, 0xd0000, 0x04000, val & 0xf); if ((regs[0x5c] ^ val) & 0xf0) - i4x0_map(0xd4000, 0x04000, val >> 4); + i4x0_map(dev, 0xd4000, 0x04000, val >> 4); regs[0x5c] = val & 0x77; break; case 0x5d: /* PAM4 */ if ((regs[0x5d] ^ val) & 0x0f) - i4x0_map(0xd8000, 0x04000, val & 0xf); + i4x0_map(dev, 0xd8000, 0x04000, val & 0xf); if ((regs[0x5d] ^ val) & 0xf0) - i4x0_map(0xdc000, 0x04000, val >> 4); + i4x0_map(dev, 0xdc000, 0x04000, val >> 4); regs[0x5d] = val & 0x77; break; case 0x5e: /* PAM5 */ if ((regs[0x5e] ^ val) & 0x0f) - i4x0_map(0xe0000, 0x04000, val & 0xf); + i4x0_map(dev, 0xe0000, 0x04000, val & 0xf); if ((regs[0x5e] ^ val) & 0xf0) - i4x0_map(0xe4000, 0x04000, val >> 4); + i4x0_map(dev, 0xe4000, 0x04000, val >> 4); regs[0x5e] = val & 0x77; break; case 0x5f: /* PAM6 */ if ((regs[0x5f] ^ val) & 0x0f) - i4x0_map(0xe8000, 0x04000, val & 0xf); + i4x0_map(dev, 0xe8000, 0x04000, val & 0xf); if ((regs[0x5f] ^ val) & 0xf0) - i4x0_map(0xec000, 0x04000, val >> 4); + i4x0_map(dev, 0xec000, 0x04000, val >> 4); regs[0x5f] = val & 0x77; break; case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: diff --git a/src/chipset/opti499.c b/src/chipset/opti499.c new file mode 100644 index 000000000..87bc39c8d --- /dev/null +++ b/src/chipset/opti499.c @@ -0,0 +1,264 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the OPTi 82C493/82C499 chipset. + * + * + * + * Authors: Tiseno100, + * Miran Grca, + * + * Copyright 2008-2020 Tiseno100. + * Copyright 2016-2020 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/io.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/port_92.h> +#include <86box/chipset.h> + + +typedef struct +{ + uint8_t idx, + regs[256], scratch[2]; +} opti499_t; + + +#ifdef ENABLE_OPTI499_LOG +int opti499_do_log = ENABLE_OPTI499_LOG; + + +static void +opti499_log(const char *fmt, ...) +{ + va_list ap; + + if (opti499_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define opti499_log(fmt, ...) +#endif + + +static void +opti499_recalc(opti499_t *dev) +{ + uint32_t base; + uint32_t i, shflags = 0; + + shadowbios = 0; + shadowbios_write = 0; + + if (dev->regs[0x22] & 0x80) { + shadowbios = 1; + shadowbios_write = 0; + shflags = MEM_READ_EXTANY | MEM_WRITE_INTERNAL; + } else { + shadowbios = 0; + shadowbios_write = 1; + shflags = MEM_READ_INTERNAL | MEM_WRITE_DISABLED; + } + + mem_set_mem_state_both(0xf0000, 0x10000, shflags); + + for (i = 0; i < 8; i++) { + base = 0xd0000 + (i << 14); + + if ((dev->regs[0x22] & ((base >= 0xe0000) ? 0x20 : 0x40)) && + (dev->regs[0x23] & (1 << i))) { + shflags = MEM_READ_INTERNAL; + shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; + } else { + if (dev->regs[0x2d] && (1 << ((i >> 1) + 2))) + shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY; + else + shflags = MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL; + } + + mem_set_mem_state_both(base, 0x4000, shflags); + } + + for (i = 0; i < 4; i++) { + base = 0xc0000 + (i << 14); + + if ((dev->regs[0x26] & 0x10) && (dev->regs[0x26] & (1 << i))) { + shflags = MEM_READ_INTERNAL; + shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; + } else { + if (dev->regs[0x26] & 0x40) { + if (dev->regs[0x2d] && (1 << (i >> 1))) + shflags = MEM_READ_EXTANY; + else + shflags = MEM_READ_EXTERNAL; + shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; + } else { + if (dev->regs[0x2d] && (1 << (i >> 1))) + shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY; + else + shflags = MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL; + } + } + + mem_set_mem_state_both(base, 0x4000, shflags); + } + + flushmmucache_nopc(); +} + + +static void +opti499_write(uint16_t addr, uint8_t val, void *priv) +{ + opti499_t *dev = (opti499_t *) priv; + + switch (addr) { + case 0x22: + opti499_log("[%04X:%08X] [W] dev->idx = %02X\n", CS, cpu_state.pc, val); + dev->idx = val; + break; + case 0x24: + if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) { + if (dev->idx == 0x20) + dev->regs[dev->idx] = (dev->regs[dev->idx] & 0xc0) | (val & 0x3f); + else + dev->regs[dev->idx] = val; + opti499_log("[%04X:%08X] [W] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, val); + + switch(dev->idx) { + case 0x20: + reset_on_hlt = !(val & 0x02); + break; + + case 0x21: + cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10); + cpu_update_waitstates(); + break; + + case 0x22: case 0x23: + case 0x26: case 0x2d: + opti499_recalc(dev); + break; + } + } + break; + + case 0xe1: case 0xe2: + dev->scratch[addr] = val; + break; + } +} + + +static uint8_t +opti499_read(uint16_t addr, void *priv) +{ + uint8_t ret = 0xff; + opti499_t *dev = (opti499_t *) priv; + + switch (addr) { + case 0x22: + opti499_log("[%04X:%08X] [R] dev->idx = %02X\n", CS, cpu_state.pc, ret); + break; + case 0x24: + if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) { + if (dev->idx == 0x2d) + ret = dev->regs[dev->idx] & 0xbf; + else + ret = dev->regs[dev->idx]; + opti499_log("[%04X:%08X] [R] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, ret); + } + break; + case 0xe1: + case 0xe2: + ret = dev->scratch[addr]; + break; + } + + return ret; +} + + +static void +opti499_reset(void *priv) +{ + opti499_t *dev = (opti499_t *) priv; + + memset(dev->regs, 0xff, sizeof(dev->regs)); + memset(&(dev->regs[0x20]), 0x00, 14 * sizeof(uint8_t)); + + dev->scratch[0] = dev->scratch[1] = 0xff; + + dev->regs[0x22] = 0x84; + dev->regs[0x24] = 0x87; + dev->regs[0x25] = 0xf0; + dev->regs[0x27] = 0xd1; + dev->regs[0x28] = dev->regs[0x2a] = 0x80; + dev->regs[0x29] = dev->regs[0x2b] = 0x10; + dev->regs[0x2d] = 0x40; + + reset_on_hlt = 1; + + cpu_cache_ext_enabled = 0; + cpu_update_waitstates(); + + opti499_recalc(dev); + + free(dev); +} + + +static void +opti499_close(void *priv) +{ + opti499_t *dev = (opti499_t *) priv; + + free(dev); +} + + +static void * +opti499_init(const device_t *info) +{ + opti499_t *dev = (opti499_t *) malloc(sizeof(opti499_t)); + memset(dev, 0, sizeof(opti499_t)); + + device_add(&port_92_device); + + io_sethandler(0x0022, 0x0001, opti499_read, NULL, NULL, opti499_write, NULL, NULL, dev); + io_sethandler(0x0024, 0x0001, opti499_read, NULL, NULL, opti499_write, NULL, NULL, dev); + + opti499_reset(dev); + + io_sethandler(0x00e1, 0x0002, opti499_read, NULL, NULL, opti499_write, NULL, NULL, dev); + + return dev; +} + + +const device_t opti499_device = { + "OPTi 82C499", + 0, + 1, + opti499_init, opti499_close, opti499_reset, + { NULL }, NULL, NULL, + NULL +}; diff --git a/src/chipset/sis_5511.c b/src/chipset/sis_5511.c index 673d37ebe..f85b021b5 100644 --- a/src/chipset/sis_5511.c +++ b/src/chipset/sis_5511.c @@ -79,40 +79,56 @@ typedef struct sis_5511_t } sis_5511_t; static void -sis_5511_shadow_recalc(int cur_reg, sis_5511_t *dev) +sis_5511_shadow_recalc(sis_5511_t *dev) { - if (cur_reg == 0x86) - mem_set_mem_state_both(0xf0000, 0x10000, ((dev->pci_conf[cur_reg] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->pci_conf[cur_reg] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); - else - { - mem_set_mem_state_both(0xc0000 + ((cur_reg & 7) << 15), 0x4000, ((dev->pci_conf[cur_reg] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->pci_conf[cur_reg] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); - mem_set_mem_state_both(0xc4000 + ((cur_reg & 7) << 15), 0x4000, ((dev->pci_conf[cur_reg] & 8) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->pci_conf[cur_reg] & 2) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); - } + int i, state; + uint32_t base; - flushmmucache_nopc(); + for (i = 0x80; i <= 0x86; i++) { + if (i == 0x86) { + state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_both(0xf0000, 0x10000, state); + pclog("000F0000-000FFFFF\n"); + } else { + base = ((i & 0x07) << 15) + 0xc0000; + + state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_both(base, 0x4000, state); + pclog("%08X-%08X\n", base, base + 0x3fff); + + state = (dev->pci_conf[i] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + state |= (dev->pci_conf[i] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_both(base + 0x4000, 0x4000, state); + pclog("%08X-%08X\n", base + 0x4000, base + 0x7fff); + } + } + + flushmmucache_nopc(); } static void sis_5511_smram_recalc(sis_5511_t *dev) { - smram_disable_all(); + smram_disable_all(); - switch (dev->pci_conf[0x65] >> 6) - { - case 0: - smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1); - break; - case 1: - smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1); - break; - case 2: - smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1); - break; - } + switch (dev->pci_conf[0x65] >> 6) { + case 0: + smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1); + break; + case 1: + smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1); + break; + case 2: + smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1); + break; + } flushmmucache(); } + void sis_5513_ide_handler(sis_5511_t *dev) { ide_pri_disable(); @@ -140,31 +156,19 @@ void sis_5513_bm_handler(sis_5511_t *dev) sff_bus_master_handler(dev->ide_drive[1], dev->pci_conf_sb[1][4] & 4, BUS_MASTER_BASE + 8); } + static void sis_5511_write(int func, int addr, uint8_t val, void *priv) { - sis_5511_t *dev = (sis_5511_t *)priv; + sis_5511_t *dev = (sis_5511_t *)priv; - switch (addr) - { - case 0x04: /* Command - low byte */ - dev->pci_conf[addr] = val; - break; - - case 0x05: /* Command - high byte */ - dev->pci_conf[addr] = val; - break; - - case 0x06: /* Status - Low Byte */ - dev->pci_conf[addr] &= val; - break; - - case 0x07: /* Status - High Byte */ - dev->pci_conf[addr] &= 0x16; + switch (addr) { + case 0x07: /* Status - High Byte */ + dev->pci_conf[addr] &= 0xb0; break; case 0x50: - dev->pci_conf[addr] = (val & 0xf9) | 4; + dev->pci_conf[addr] = val; cpu_cache_ext_enabled = !!(val & 0x40); cpu_update_waitstates(); break; @@ -177,8 +181,7 @@ sis_5511_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf[addr] = val & 0x3f; break; - case 0x53: - case 0x54: + case 0x53: case 0x54: dev->pci_conf[addr] = val; break; @@ -186,15 +189,17 @@ sis_5511_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf[addr] = val & 0xf8; break; - case 0x57: - case 0x58: - case 0x59: + case 0x56 ... 0x59: dev->pci_conf[addr] = val; break; case 0x5a: + /* TODO: Fast Gate A20 Emulation and Fast Reset Emulation on the KBC. + The former (bit 7) means the chipset intercepts D1h to 64h and 00h to 60h. + The latter (bit 6) means the chipset intercepts all odd FXh to 64h. + Bit 5 sets fast reset latency. This should be fixed on the other SiS + chipsets as well. */ dev->pci_conf[addr] = val; - port_92_set_features(dev->port_92, !!(val & 0x40), !!(val & 0x80)); break; case 0x5b: @@ -214,22 +219,18 @@ sis_5511_write(int func, int addr, uint8_t val, void *priv) break; case 0x5f: - dev->pci_conf[addr] = val; + dev->pci_conf[addr] = val & 0xfe; break; case 0x60: dev->pci_conf[addr] = val & 0x3e; - if (!!(val & 2) && (dev->pci_conf[0x68] & 1)) - { + if ((dev->pci_conf[0x68] & 1) && (val & 2)) { smi_line = 1; dev->pci_conf[0x69] |= 1; } break; - case 0x61: /* STPCLK# Assertion Timer */ - case 0x62: /* STPCLK# De-assertion Timer */ - case 0x63: /* System Standby Timer */ - case 0x64: + case 0x61 ... 0x64: dev->pci_conf[addr] = val; break; @@ -242,8 +243,7 @@ sis_5511_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf[addr] = val & 0x7f; break; - case 0x67: - case 0x68: + case 0x67: case 0x68: dev->pci_conf[addr] = val; break; @@ -251,11 +251,7 @@ sis_5511_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf[addr] &= val; break; - case 0x6a: - case 0x6b: - case 0x6c: - case 0x6d: - case 0x6e: + case 0x6a ... 0x6e: dev->pci_conf[addr] = val; break; @@ -329,8 +325,7 @@ sis_5511_write(int func, int addr, uint8_t val, void *priv) case 0x85: case 0x86: dev->pci_conf[addr] = val & ((addr == 0x86) ? 0xe8 : 0xee); - sis_5511_shadow_recalc(addr, dev); - sis_5511_smram_recalc(dev); + sis_5511_shadow_recalc(dev); break; case 0x90: /* 5512 General Purpose Register Index */ @@ -620,24 +615,45 @@ sis_5513_isa_read(uint16_t addr, void *priv) return 0xff; } + static void sis_5511_reset(void *priv) { - sis_5511_t *dev = (sis_5511_t *)priv; + sis_5511_t *dev = (sis_5511_t *)priv; + + /* SiS 5511 */ + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x11; + dev->pci_conf[0x03] = 0x55; + dev->pci_conf[0x04] = 0x07; + dev->pci_conf[0x05] = dev->pci_conf[0x06] = 0x00; + dev->pci_conf[0x07] = 0x02; + dev->pci_conf[0x08] = 0x00; + dev->pci_conf[0x09] = dev->pci_conf[0x0a] = 0x00; + dev->pci_conf[0x0b] = 0x06; + dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x00; + dev->pci_conf[0x52] = 0x20; + dev->pci_conf[0x53] = dev->pci_conf[0x54] = 0x00; + dev->pci_conf[0x55] = dev->pci_conf[0x56] = 0x00; + dev->pci_conf[0x57] = dev->pci_conf[0x58] = 0x00; + dev->pci_conf[0x59] = dev->pci_conf[0x5a] = 0x00; + dev->pci_conf[0x5b] = dev->pci_conf[0x5c] = 0x00; + dev->pci_conf[0x5d] = dev->pci_conf[0x5e] = 0x00; + dev->pci_conf[0x5f] = dev->pci_conf[0x60] = 0x00; + dev->pci_conf[0x61] = dev->pci_conf[0x62] = 0xff; + dev->pci_conf[0x63] = 0xff; + dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00; + dev->pci_conf[0x66] = 0x00; + dev->pci_conf[0x67] = 0xff; + dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00; + dev->pci_conf[0x6a] = dev->pci_conf[0x6b] = 0x00; + dev->pci_conf[0x6c] = dev->pci_conf[0x6d] = 0x00; + dev->pci_conf[0x6e] = dev->pci_conf[0x6f] = 0x00; + + cpu_cache_ext_enabled = 0; + cpu_update_waitstates(); - /* SiS 5511 */ - dev->pci_conf[0x00] = 0x39; - dev->pci_conf[0x01] = 0x10; - dev->pci_conf[0x02] = 0x11; - dev->pci_conf[0x03] = 0x55; - dev->pci_conf[0x04] = 7; - dev->pci_conf[0x07] = 2; - dev->pci_conf[0x0b] = 6; - dev->pci_conf[0x52] = 0x20; - dev->pci_conf[0x61] = 0xff; - dev->pci_conf[0x62] = 0xff; - dev->pci_conf[0x63] = 0xff; - dev->pci_conf[0x67] = 0xff; dev->pci_conf[0x6b] = 0xff; dev->pci_conf[0x6c] = 0xff; dev->pci_conf[0x70] = 4; @@ -652,6 +668,15 @@ sis_5511_reset(void *priv) dev->pci_conf[0x7c] = 4; dev->pci_conf[0x7e] = 4; dev->pci_conf[0x7f] = 0x80; + dev->pci_conf[0x80] = 0x00; + dev->pci_conf[0x81] = 0x00; + dev->pci_conf[0x82] = 0x00; + dev->pci_conf[0x83] = 0x00; + dev->pci_conf[0x84] = 0x00; + dev->pci_conf[0x85] = 0x00; + dev->pci_conf[0x86] = 0x00; + sis_5511_smram_recalc(dev); + sis_5511_shadow_recalc(dev); /* SiS 5513 */ dev->pci_conf_sb[0][0x00] = 0x39; diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 1664576fb..14d7a9b63 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -124,6 +124,10 @@ int isa_cycles, cpu_inited, timing_jmp_rm, timing_jmp_pm, timing_jmp_pm_gate, timing_misaligned; uint32_t cpu_features, cpu_fast_off_flags; +uint32_t _tr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +uint32_t cache_index = 0; +uint8_t _cache[2048]; + uint64_t cpu_CR4_mask, tsc = 0; uint64_t pmc[2] = {0, 0}; @@ -2290,6 +2294,7 @@ amd_k_invalid_rdmsr: EDX = tsc >> 32; break; } + pclog("RDMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX); break; case CPU_PENTIUMPRO: @@ -2695,6 +2700,7 @@ amd_k_invalid_wrmsr: case CPU_CxGX1: case CPU_Cx6x86MX: #endif + pclog("WRMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX); switch (ECX) { case 0x10: tsc = EAX | ((uint64_t)EDX << 32); diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 68a053b6f..9beac3fab 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -542,6 +542,9 @@ extern uint64_t amd_efer, star; #define msw cpu_state.CR0.w extern uint32_t cr2, cr3, cr4; extern uint32_t dr[8]; +extern uint32_t _tr[8]; +extern uint32_t cache_index; +extern uint8_t _cache[2048]; /*Segments - diff --git a/src/cpu/x86.c b/src/cpu/x86.c index 725d674e8..55ef45000 100644 --- a/src/cpu/x86.c +++ b/src/cpu/x86.c @@ -282,13 +282,13 @@ reset_common(int hard) if (is386 || hard) EAX = EBX = ECX = EDX = ESI = EDI = EBP = ESP = 0; - /* if (hard) { + if (hard) { makeznptable(); resetreadlookup(); makemod1table(); cpu_set_edx(); mmu_perm = 4; - } */ + } x86seg_reset(); #ifdef USE_DYNAREC if (hard) @@ -308,15 +308,19 @@ reset_common(int hard) if (hard) { if (is486) smbase = is_am486dxl ? 0x00060000 : 0x00030000; - // ppi_reset(); + ppi_reset(); } in_sys = 0; shadowbios = shadowbios_write = 0; alt_access = cpu_end_block_after_ins = 0; - if (hard) + if (hard) { reset_on_hlt = hlt_reset_pending = 0; + cache_index = 0; + memset(_tr, 0x00, sizeof(_tr)); + memset(_cache, 0x00, sizeof(_cache)); + } if (!is286) reset_808x(hard); @@ -328,15 +332,6 @@ void resetx86(void) { reset_common(1); -/* ---- */ - makeznptable(); - resetreadlookup(); - makemod1table(); - cpu_set_edx(); - mmu_perm = 4; - - ppi_reset(); -/* ---- */ soft_reset_mask = 0; } diff --git a/src/cpu/x86_ops_misc.h b/src/cpu/x86_ops_misc.h index a6e7e9193..e630c685b 100644 --- a/src/cpu/x86_ops_misc.h +++ b/src/cpu/x86_ops_misc.h @@ -607,6 +607,8 @@ static int opF7_l_a32(uint32_t fetchdat) static int opHLT(uint32_t fetchdat) { + pclog("HLT: CS = %04X, DS = %04X, ES = %04X, SS = %04X, IP = %04X\n", CS, DS, ES, SS, cpu_state.pc); + if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) { x86gpf(NULL,0); diff --git a/src/cpu/x86_ops_mov_ctrl.h b/src/cpu/x86_ops_mov_ctrl.h index 17f51b971..28504890c 100644 --- a/src/cpu/x86_ops_mov_ctrl.h +++ b/src/cpu/x86_ops_mov_ctrl.h @@ -256,54 +256,113 @@ static int opMOV_DRx_r_a32(uint32_t fetchdat) return 0; } +static void opMOV_r_TRx(void) +{ + uint32_t base; + + base = _tr[4] & 0xfffff800; + switch (cpu_reg) { + case 3: + pclog("[R] %08X cache = %08X\n", base + cache_index, _tr[3]); + _tr[3] = *(uint32_t *) &(_cache[cache_index]); + cache_index = (cache_index + 4) & 0xf; + break; + } + cpu_state.regs[cpu_rm].l = _tr[cpu_reg]; + CLOCK_CYCLES(6); +} static int opMOV_r_TRx_a16(uint32_t fetchdat) { - if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) + if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))) { x86gpf(NULL, 0); return 1; } fetch_ea_16(fetchdat); - cpu_state.regs[cpu_rm].l = 0; - CLOCK_CYCLES(6); + opMOV_r_TRx(); PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0); return 0; } static int opMOV_r_TRx_a32(uint32_t fetchdat) { - if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) + if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))) { x86gpf(NULL, 0); return 1; } fetch_ea_32(fetchdat); - cpu_state.regs[cpu_rm].l = 0; - CLOCK_CYCLES(6); + opMOV_r_TRx(); PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1); return 0; } +static void opMOV_TRx_r(void) +{ + uint32_t base; + int i, ctl; + + _tr[cpu_reg] = cpu_state.regs[cpu_rm].l; + base = _tr[4] & 0xfffff800; + ctl = _tr[5] & 3; + switch (cpu_reg) { + case 3: + pclog("[W] %08X cache = %08X\n", base + cache_index, _tr[3]); + *(uint32_t *) &(_cache[cache_index]) = _tr[3]; + cache_index = (cache_index + 4) & 0xf; + break; + case 4: + if (!(cr0 & 1) && !(_tr[5] & (1 << 19))) + pclog("TAG = %08X, DEST = %08X\n", base, base + cache_index - 16); + break; + case 5: + pclog("[16] EXT = %i (%i), SET = %04X\n", !!(_tr[5] & (1 << 19)), _tr[5] & 0x03, _tr[5] & 0x7f0); + if (!(_tr[5] & (1 << 19))) { + switch(ctl) { + case 0: + pclog(" Cache fill or read...\n", base); + break; + case 1: + base += (_tr[5] & 0x7f0); + pclog(" Writing 16 bytes to %08X...\n", base); + for (i = 0; i < 16; i += 4) + mem_writel_phys(base + i, *(uint32_t *) &(_cache[i])); + break; + case 2: + base += (_tr[5] & 0x7f0); + pclog(" Reading 16 bytes from %08X...\n", base); + for (i = 0; i < 16; i += 4) + *(uint32_t *) &(_cache[i]) = mem_readl_phys(base + i); + break; + case 3: + pclog(" Cache invalidate/flush...\n", base); + break; + } + } + break; + } + CLOCK_CYCLES(6); +} static int opMOV_TRx_r_a16(uint32_t fetchdat) { - if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) + if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))) { x86gpf(NULL, 0); return 1; } fetch_ea_16(fetchdat); - CLOCK_CYCLES(6); + opMOV_TRx_r(); PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0); return 0; } static int opMOV_TRx_r_a32(uint32_t fetchdat) { - if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) + if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))) { x86gpf(NULL, 0); return 1; } - fetch_ea_16(fetchdat); - CLOCK_CYCLES(6); + fetch_ea_32(fetchdat); + opMOV_TRx_r(); PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1); return 0; } diff --git a/src/device/phoenix_486_jumper.c b/src/device/phoenix_486_jumper.c index 5a07362d2..53fea5d92 100644 --- a/src/device/phoenix_486_jumper.c +++ b/src/device/phoenix_486_jumper.c @@ -39,11 +39,14 @@ typedef struct { - uint8_t jumper; + uint8_t type, jumper; } phoenix_486_jumper_t; + #ifdef ENABLE_PHOENIX_486_JUMPER_LOG int phoenix_486_jumper_do_log = ENABLE_PHOENIX_486_JUMPER_LOG; + + static void phoenix_486_jumper_log(const char *fmt, ...) { @@ -59,14 +62,19 @@ phoenix_486_jumper_log(const char *fmt, ...) #define phoenix_486_jumper_log(fmt, ...) #endif + static void phoenix_486_jumper_write(uint16_t addr, uint8_t val, void *priv) { phoenix_486_jumper_t *dev = (phoenix_486_jumper_t *) priv; phoenix_486_jumper_log("Phoenix 486 Jumper: Write %02x\n", val); - dev->jumper = val; + if (dev->type == 1) + dev->jumper = val & 0xbf; + else + dev->jumper = val; } + static uint8_t phoenix_486_jumper_read(uint16_t addr, void *priv) { @@ -76,6 +84,21 @@ phoenix_486_jumper_read(uint16_t addr, void *priv) } +static void +phoenix_486_jumper_reset(void *priv) +{ + phoenix_486_jumper_t *dev = (phoenix_486_jumper_t *) priv; + + if (dev->type == 1) + dev->jumper = 0x00; + else { + dev->jumper = 0x9f; + if (gfxcard != 0x01) + dev->jumper |= 0x40; + } +} + + static void phoenix_486_jumper_close(void *priv) { @@ -84,26 +107,38 @@ phoenix_486_jumper_close(void *priv) free(dev); } + static void * phoenix_486_jumper_init(const device_t *info) { phoenix_486_jumper_t *dev = (phoenix_486_jumper_t *) malloc(sizeof(phoenix_486_jumper_t)); memset(dev, 0, sizeof(phoenix_486_jumper_t)); - dev->jumper = 0x9f; - if (gfxcard != 0x01) - dev->jumper |= 0x40; + dev->type = info->local; + + phoenix_486_jumper_reset(dev); io_sethandler(0x0078, 0x0001, phoenix_486_jumper_read, NULL, NULL, phoenix_486_jumper_write, NULL, NULL, dev); return dev; } + const device_t phoenix_486_jumper_device = { "Phoenix 486 Jumper Readout", 0, 0, - phoenix_486_jumper_init, phoenix_486_jumper_close, NULL, + phoenix_486_jumper_init, phoenix_486_jumper_close, phoenix_486_jumper_reset, + { NULL }, NULL, NULL, + NULL +}; + + +const device_t phoenix_486_jumper_pci_device = { + "Phoenix 486 Jumper Readout (PCI machines)", + 0, + 1, + phoenix_486_jumper_init, phoenix_486_jumper_close, phoenix_486_jumper_reset, { NULL }, NULL, NULL, NULL }; diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index c12aec7e8..988717406 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -59,6 +59,9 @@ extern const device_t headland_ht18a_device; extern const device_t headland_ht18b_device; extern const device_t headland_ht18c_device; +/* IMS */ +extern const device_t ims8848_device; + /* Intel */ extern const device_t intel_82335_device; extern const device_t i420ex_device; @@ -162,7 +165,7 @@ extern const device_t wd76c10_device; /* Miscellaneous Hardware */ extern const device_t phoenix_486_jumper_device; -extern const device_t vpc2007_device; +extern const device_t phoenix_486_jumper_pci_device; #if defined(DEV_BRANCH) && defined(USE_OLIVETTI) extern const device_t olivetti_eva_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index b3c875925..8fa2b2f12 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -366,6 +366,9 @@ extern int machine_at_ms4145_init(const machine_t *); extern int machine_at_sbc_490_init(const machine_t *); extern int machine_at_tf_486_init(const machine_t *); +extern int machine_at_pci400c_b_init(const machine_t *); +extern int machine_at_g486ip_init(const machine_t *); + extern int machine_at_itoxstar_init(const machine_t *); extern int machine_at_arb1423c_init(const machine_t *); extern int machine_at_arb1479_init(const machine_t *); diff --git a/src/include/86box/mem.h b/src/include/86box/mem.h index 2bd76eb30..dfcbef242 100644 --- a/src/include/86box/mem.h +++ b/src/include/86box/mem.h @@ -89,6 +89,7 @@ /* Internal execute access, external read access. */ #define MEM_READ_EXTERNAL_EX 0 #define MEM_READ_SMRAM (ACCESS_X_SMRAM | ACCESS_R_SMRAM) +#define MEM_READ_CACHE (ACCESS_X_CACHE | ACCESS_R_CACHE) #define MEM_READ_SMRAM_EX (ACCESS_X_SMRAM) #define MEM_EXEC_SMRAM MEM_READ_SMRAM_EX #define MEM_READ_SMRAM_2 (ACCESS_R_SMRAM) @@ -104,6 +105,7 @@ #define MEM_WRITE_ROMCS (ACCESS_W_ROMCS) #define MEM_WRITE_EXTANY (ACCESS_W_ROMCS) #define MEM_WRITE_SMRAM (ACCESS_W_SMRAM) +#define MEM_WRITE_CACHE (ACCESS_W_CACHE) /* Theese two are going to be identical. */ #define MEM_WRITE_DISABLED_EX MEM_READ_DISABLED #define MEM_WRITE_MASK 0x03e0 diff --git a/src/include/86box/smram.h b/src/include/86box/smram.h index 3d91c1e96..6fc89971e 100644 --- a/src/include/86box/smram.h +++ b/src/include/86box/smram.h @@ -52,6 +52,8 @@ extern void smram_enable(smram_t *smr, uint32_t host_base, uint32_t ram_base, ui extern int smram_enabled(smram_t *smr); /* Changes the SMRAM state. */ extern void smram_state_change(smram_t *smr, int smm, int flags); +/* Enables or disables the use of a separate SMRAM for addresses below A0000. */ +extern void smram_set_separate_smram(uint8_t set); #endif /*EMU_SMRAM_H*/ diff --git a/src/io.c b/src/io.c index 742e601c4..21ea02f1b 100644 --- a/src/io.c +++ b/src/io.c @@ -319,6 +319,9 @@ inb(uint16_t port) if (port == 0x1ed) ret = 0xfe; + if (port == 0x2b60) + ret = 0x00; + io_log("[%04X:%08X] (%i, %i, %04i) in b(%04X) = %02X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); return(ret); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 2068b3c88..50718475b 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -66,7 +66,7 @@ machine_at_acc386_init(const machine_t *model) device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_device); return ret; } @@ -1147,6 +1147,68 @@ machine_at_486sp3_init(const machine_t *model) } +int +machine_at_pci400c_b_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/pci400c-b/032295.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&ide_isa_device); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 4, 3, 2, 1); /* 0F = Slot 1 */ + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 0E = Slot 2 */ + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 0D = Slot 3 */ + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 0C = Slot 4 */ + device_add(&keyboard_ps2_ami_pci_device); /* Assume AMI Megakey 1993 stanalone ('P') + because of the Tekram machine below. */ + + device_add(&ims8848_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + + +int +machine_at_g486ip_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/g486ip/G486IP.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&ide_isa_device); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 03 = Slot 1 */ + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 04 = Slot 2 */ + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 05 = Slot 3 */ + device_add(&keyboard_ps2_ami_pci_device); /* AMI Megakey 1993 stanalone ('P') */ + + device_add(&ims8848_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + + int machine_at_486sp3g_init(const machine_t *model) { @@ -1623,8 +1685,10 @@ machine_at_hot433_init(const machine_t *model) device_add(&umc_hb4_device); device_add(&umc_8886af_device); device_add(&um8669f_device); - device_add(&intel_flash_bxt_device); - device_add(&keyboard_at_ami_device); + // device_add(&intel_flash_bxt_device); + device_add(&sst_flash_29ee010_device); + // device_add(&keyboard_at_ami_device); + device_add(&keyboard_ps2_ami_device); return ret; } @@ -1652,6 +1716,7 @@ machine_at_atc1415_init(const machine_t *model) device_add(&umc_hb4_device); device_add(&umc_8886af_device); + device_add(&intel_flash_bxt_device); device_add(&keyboard_at_ami_device); if (fdc_type == FDC_INTERNAL) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 6910a5274..3a57cf0c6 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -432,6 +432,10 @@ const machine_t machines[] = { { "[i420TX] ASUS PCI/I-486SP3", "486sp3", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_IDE_DUAL | MACHINE_SCSI, 1024, 131072, 1024, 127, machine_at_486sp3_init, NULL }, /* This has the Phoenix MultiKey KBC firmware. */ { "[i420TX] Intel Classic/PCI", "alfredo", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_alfredo_init, NULL }, + /* This most likely has a standalone AMI Megakey 1993, which is type 'P', like the below Tekram board. */ + { "[IMS 8848] J-Bond PCI400C-B", "pci400c_b", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_pci400c_b_init, NULL }, + /* This has a standalone AMI Megakey 1993, which is type 'P'. */ + { "[IMS 8848] Tekram G486IP", "g486ip", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2048, 131072, 2048, 127, machine_at_g486ip_init, NULL }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ { "[SiS 496] ASUS PVI-486SP3C", "486sp3c", MACHINE_TYPE_486_S3, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_PCIV | MACHINE_IDE_DUAL, 1024, 261120, 1024, 255, machine_at_486sp3c_init, NULL }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ diff --git a/src/mem/smram.c b/src/mem/smram.c index 1173d716a..8e405af8a 100644 --- a/src/mem/smram.c +++ b/src/mem/smram.c @@ -32,6 +32,9 @@ static smram_t *base_smram, *last_smram; +static uint8_t use_separate_smram = 0; +static uint8_t smram[0x40000]; + #ifdef ENABLE_SMRAM_LOG int smram_do_log = ENABLE_SMRAM_LOG; @@ -61,8 +64,10 @@ smram_read(uint32_t addr, void *priv) if (new_addr >= (1 << 30)) return mem_read_ram_2gb(new_addr, priv); - else + else if (!use_separate_smram || (new_addr >= 0xa0000)) return mem_read_ram(new_addr, priv); + else + return dev->mapping.exec[addr - dev->host_base]; } @@ -74,8 +79,10 @@ smram_readw(uint32_t addr, void *priv) if (new_addr >= (1 << 30)) return mem_read_ram_2gbw(new_addr, priv); - else + else if (!use_separate_smram || (new_addr >= 0xa0000)) return mem_read_ramw(new_addr, priv); + else + return *(uint16_t *) &(dev->mapping.exec[addr - dev->host_base]); } @@ -87,8 +94,10 @@ smram_readl(uint32_t addr, void *priv) if (new_addr >= (1 << 30)) return mem_read_ram_2gbl(new_addr, priv); - else + else if (!use_separate_smram || (new_addr >= 0xa0000)) return mem_read_raml(new_addr, priv); + else + return *(uint32_t *) &(dev->mapping.exec[addr - dev->host_base]); } @@ -98,7 +107,10 @@ smram_write(uint32_t addr, uint8_t val, void *priv) smram_t *dev = (smram_t *) priv; uint32_t new_addr = addr - dev->host_base + dev->ram_base; - mem_write_ram(new_addr, val, priv); + if (!use_separate_smram || (new_addr >= 0xa0000)) + mem_write_ram(new_addr, val, priv); + else + dev->mapping.exec[addr - dev->host_base] = val; } @@ -108,7 +120,10 @@ smram_writew(uint32_t addr, uint16_t val, void *priv) smram_t *dev = (smram_t *) priv; uint32_t new_addr = addr - dev->host_base + dev->ram_base; - mem_write_ramw(new_addr, val, priv); + if (!use_separate_smram || (new_addr >= 0xa0000)) + mem_write_ramw(new_addr, val, priv); + else + *(uint16_t *) &(dev->mapping.exec[addr - dev->host_base]) = val; } @@ -118,7 +133,10 @@ smram_writel(uint32_t addr, uint32_t val, void *priv) smram_t *dev = (smram_t *) priv; uint32_t new_addr = addr - dev->host_base + dev->ram_base; - mem_write_raml(new_addr, val, priv); + if (!use_separate_smram || (new_addr >= 0xa0000)) + mem_write_raml(new_addr, val, priv); + else + *(uint32_t *) &(dev->mapping.exec[addr - dev->host_base]) = val; } @@ -263,6 +281,8 @@ smram_add(void) smram_write,smram_writew,smram_writel, ram, MEM_MAPPING_SMRAM, temp_smram); + smram_set_separate_smram(0); + return temp_smram; } @@ -326,10 +346,21 @@ smram_enable(smram_t *smr, uint32_t host_base, uint32_t ram_base, uint32_t size, smr->size = size; mem_mapping_set_addr(&(smr->mapping), smr->host_base, smr->size); - if (smr->ram_base < (1 << 30)) - mem_mapping_set_exec(&(smr->mapping), ram + smr->ram_base); - else - mem_mapping_set_exec(&(smr->mapping), ram2 + smr->ram_base - (1 << 30)); + if (!use_separate_smram || (smr->ram_base >= 0x000a0000)) { + if (smr->ram_base < (1 << 30)) + mem_mapping_set_exec(&(smr->mapping), ram + smr->ram_base); + else + mem_mapping_set_exec(&(smr->mapping), ram2 + smr->ram_base - (1 << 30)); + } else { + if (smr->ram_base == 0x00030000) + mem_mapping_set_exec(&(smr->mapping), smram); + else if (smr->ram_base == 0x00040000) + mem_mapping_set_exec(&(smr->mapping), smram + 0x10000); + else if (smr->ram_base == 0x00060000) + mem_mapping_set_exec(&(smr->mapping), smram + 0x20000); + else if (smr->ram_base == 0x00070000) + mem_mapping_set_exec(&(smr->mapping), smram + 0x30000); + } smram_map(0, host_base, size, flags_normal); smram_map(1, host_base, size, flags_smm); @@ -364,3 +395,10 @@ smram_state_change(smram_t *smr, int smm, int flags) smram_map(smm, smr->host_base, smr->size, flags); } + + +void +smram_set_separate_smram(uint8_t set) +{ + use_separate_smram = set; +} diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index f06c3d77a..b7680640f 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -593,7 +593,7 @@ CHIPSETOBJ := 82c100.o acc2168.o \ cs4031.o cs8230.o \ ali1429.o ali1489.o ali1531.o ali1541.o ali1543.o ali1621.o ali6117.o \ gc100.o headland.o \ - intel_82335.o intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \ + ims8848.o intel_82335.o intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \ neat.o \ opti283.o opti291.o opti391.o opti495.o opti822.o opti895.o opti5x7.o \ scamp.o scat.o \