diff --git a/src/chipset/opti5x7.c b/src/chipset/opti5x7.c new file mode 100644 index 000000000..4a83ed98d --- /dev/null +++ b/src/chipset/opti5x7.c @@ -0,0 +1,125 @@ +/*Based off the OPTI 82C546/82C547 datasheet. +The earlier 596/597 appears to be register compatible with the 546/547 from testing.*/ +#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/keyboard.h> +#include <86box/mem.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/port_92.h> +#include <86box/chipset.h> + + +typedef struct +{ + uint8_t cur_reg, + regs[64]; + port_92_t *port_92; +} opti5x7_t; + +static void +opti5x7_recalcmapping(opti5x7_t *dev) +{ + uint32_t shflags = 0; + + shadowbios = 0; + shadowbios_write = 0; + + + shadowbios |= !!(dev->regs[0x06] & 0x05); + shadowbios_write |= !!(dev->regs[0x06] & 0x0a); + + shflags = (dev->regs[0x06] & 0x01) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + shflags |= (dev->regs[0x06] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state(0xe0000, 0x10000, shflags); + + shflags = (dev->regs[0x06] & 0x04) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + shflags |= (dev->regs[0x06] & 0x08) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state(0xf0000, 0x10000, shflags); + + flushmmucache(); +} +static void +opti5x7_write(uint16_t addr, uint8_t val, void *priv) +{ + opti5x7_t *dev = (opti5x7_t *) priv; +// pclog("Write %02x to OPTi 5x7 address %02x\n", val, addr); + + switch (addr) { + case 0x22: + dev->cur_reg = val; + break; + case 0x24: + dev->regs[dev->cur_reg] = val; + if (dev->cur_reg == 0x02) { + cpu_cache_ext_enabled = val & 0x10; + } + if (dev->cur_reg == 0x06) { + opti5x7_recalcmapping(dev); + } + break; + } +} + + +static uint8_t +opti5x7_read(uint16_t addr, void *priv) +{ + uint8_t ret = 0xff; + opti5x7_t *dev = (opti5x7_t *) priv; + + switch (addr) { + case 0x24: +// pclog("Read from OPTI 5x7 register %02x\n", dev->cur_reg); + ret = dev->regs[dev->cur_reg]; + break; + } + + return ret; +} + + +static void +opti5x7_close(void *priv) +{ + opti5x7_t *dev = (opti5x7_t *) priv; + + free(dev); +} + + +static void * +opti5x7_init(const device_t *info) +{ + opti5x7_t *dev = (opti5x7_t *) malloc(sizeof(opti5x7_t)); + memset(dev, 0, sizeof(opti5x7_t)); + + io_sethandler(0x0022, 0x0001, opti5x7_read, NULL, NULL, opti5x7_write, NULL, NULL, dev); + io_sethandler(0x0024, 0x0001, opti5x7_read, NULL, NULL, opti5x7_write, NULL, NULL, dev); + + dev->port_92 = device_add(&port_92_device); +// pclog("OPTi 5x7 init\n"); + opti5x7_recalcmapping(dev); + + + return dev; +} + +const device_t opti5x7_device = { + "OPTi 82C5x6/82C5x7", + 0, + 0, + opti5x7_init, opti5x7_close, NULL, + NULL, NULL, NULL, + NULL +}; diff --git a/src/cpu_common/cpu.c b/src/cpu_common/cpu.c index 8a10948ac..c9b122dbe 100644 --- a/src/cpu_common/cpu.c +++ b/src/cpu_common/cpu.c @@ -141,7 +141,7 @@ CPU *cpu_s; int cpu_effective; int cpu_multi; double cpu_dmulti; -int cpu_16bitbus; +int cpu_16bitbus, cpu_64bitbus; int cpu_busspeed; int cpu_cyrix_alignment; int CPUID; @@ -309,7 +309,7 @@ cpu_set(void) isdx4 = (cpu_s->cpu_type >= CPU_iDX4) && (cpu_s->cpu_type < CPU_WINCHIP); is_am486 = (cpu_s->cpu_type == CPU_Am486SX) || (cpu_s->cpu_type == CPU_Am486SX2) || (cpu_s->cpu_type == CPU_Am486DX) || (cpu_s->cpu_type == CPU_Am486DX2) || (cpu_s->cpu_type == CPU_Am486DX4) || (cpu_s->cpu_type == CPU_Am5x86); - is_pentium = (cpu_s->cpu_type == CPU_PENTIUM) || (cpu_s->cpu_type == CPU_PENTIUMMMX); + is_pentium = (cpu_s->cpu_type == CPU_P24T) || (cpu_s->cpu_type == CPU_PENTIUM) || (cpu_s->cpu_type == CPU_PENTIUMMMX); /* Not Pentiums, but they share the same SMM save state table layout. */ is_pentium |= (cpu_s->cpu_type == CPU_i486DX2) || (cpu_s->cpu_type == CPU_iDX4); /* The WinChip datasheet claims these are Pentium-compatible. */ @@ -335,7 +335,8 @@ cpu_set(void) #endif cpu_16bitbus = (cpu_s->cpu_type == CPU_286 || cpu_s->cpu_type == CPU_386SX || cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_IBM386SLC || cpu_s->cpu_type == CPU_IBM486SLC ); - + cpu_64bitbus = (cpu_s->cpu_type >= CPU_WINCHIP); + if (cpu_s->multi) cpu_busspeed = cpu_s->rspeed / cpu_s->multi; else @@ -995,6 +996,7 @@ cpu_set(void) #endif break; + case CPU_P24T: case CPU_PENTIUM: #ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f); @@ -1787,7 +1789,8 @@ cpu_CPUID(void) break; } break; - + + case CPU_P24T: case CPU_PENTIUM: if (!EAX) { @@ -2697,6 +2700,7 @@ void cpu_RDMSR() } break; + case CPU_P24T: case CPU_PENTIUM: case CPU_PENTIUMMMX: EAX = EDX = 0; @@ -3175,7 +3179,8 @@ void cpu_WRMSR() break; } break; - + + case CPU_P24T: case CPU_PENTIUM: case CPU_PENTIUMMMX: switch (ECX) diff --git a/src/cpu_common/cpu.h b/src/cpu_common/cpu.h index e617f4e6d..3db00d1eb 100644 --- a/src/cpu_common/cpu.h +++ b/src/cpu_common/cpu.h @@ -52,6 +52,7 @@ enum { CPU_Cx486DX4, CPU_Am5x86, CPU_Cx5x86, + CPU_P24T, CPU_WINCHIP, /* 586 class CPUs */ CPU_WINCHIP2, CPU_PENTIUM, @@ -370,7 +371,7 @@ COMPILE_TIME_ASSERT(sizeof(cpu_state) <= 128) /* Global variables. */ extern int cpu_iscyrix; -extern int cpu_16bitbus; +extern int cpu_16bitbus, cpu_64bitbus; extern int cpu_busspeed, cpu_pci_speed; extern int cpu_multi; extern double cpu_dmulti; @@ -379,8 +380,8 @@ extern int cpu_cyrix_alignment; /*Cyrix 5x86/6x86 only has data misalignment extern int is8086, is286, is386, is486, is486sx, is486dx, is486sx2, is486dx2, isdx4; extern int is_am486, is_pentium, is_k5, is_k6, is_p6; -extern int hascache; -extern int isibm486; +extern int hascache; +extern int isibm486; extern int is_rapidcad; extern int hasfpu; #define CPU_FEATURE_RDTSC (1 << 0) diff --git a/src/cpu_common/cpu_table.c b/src/cpu_common/cpu_table.c index 5d8ec3457..41cea5233 100644 --- a/src/cpu_common/cpu_table.c +++ b/src/cpu_common/cpu_table.c @@ -288,8 +288,8 @@ CPU cpus_i486[] = { {"iDX4/100", CPU_iDX4, 100000000, 3.0, 0x483, 0x483, 0x0000, CPU_SUPPORTS_DYNAREC, 18,18, 9, 9, 12}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/ {"iDX4 OverDrive 75", CPU_iDX4, 75000000, 3.0, 0x1480, 0x1480, 0x0000, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9}, {"iDX4 OverDrive 100", CPU_iDX4, 100000000, 3.0, 0x1480, 0x1480, 0x0000, CPU_SUPPORTS_DYNAREC, 18,18, 9, 9, 12}, - {"Pentium OverDrive 63", CPU_PENTIUM, 62500000, 2.5, 0x1531, 0x1531, 0x0000, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, 15/2}, - {"Pentium OverDrive 83", CPU_PENTIUM, 83333333, 2.5, 0x1532, 0x1532, 0x0000, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8, 10}, + {"Pentium OverDrive 63", CPU_P24T, 62500000, 2.5, 0x1531, 0x1531, 0x0000, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, 15/2}, + {"Pentium OverDrive 83", CPU_P24T, 83333333, 2.5, 0x1532, 0x1532, 0x0000, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8, 10}, {"", -1, 0, 0, 0, 0, 0x0000, 0, 0, 0, 0, 0, 0} }; diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index 564203587..918f52287 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -48,6 +48,7 @@ extern const device_t i440zx_device; /* OPTi */ extern const device_t opti495_device; +extern const device_t opti5x7_device; /* C&T */ extern const device_t neat_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 86a6b294c..b61583abc 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -253,6 +253,8 @@ extern const device_t *at_cpqiii_get_device(void); #endif /* m_at_socket4_5.c */ +extern int machine_at_excalibur_init(const machine_t *); + extern int machine_at_batman_init(const machine_t *); extern int machine_at_ambradp60_init(const machine_t *); #if defined(DEV_BRANCH) && defined(USE_VPP60) diff --git a/src/machine/m_at_socket4_5.c b/src/machine/m_at_socket4_5.c index 59e237567..0567a5d1a 100644 --- a/src/machine/m_at_socket4_5.c +++ b/src/machine/m_at_socket4_5.c @@ -41,6 +41,26 @@ #include <86box/sio.h> #include <86box/video.h> #include <86box/machine.h> +int +machine_at_excalibur_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_inverted(L"roms/machines/excalibur/S75P.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&ide_vlb_device); + device_add(&opti5x7_device); + device_add(&fdc37c663_device); + device_add(&keyboard_at_ami_device); + + return ret; +} static void diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index e0b56c03a..e84f788d1 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -206,6 +206,9 @@ const machine_t machines[] = { { "[486 PCI] Zida Tomato 4DP", "4dps", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 255, 1, 127, machine_at_4dps_init, NULL }, /* Socket 4 machines */ + /* OPTi 596/597 */ + { "[Socket 4 OPTi] AMI Excalibur VLB", "excalibur", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_excalibur_init, NULL }, + /* 430LX */ { "[Socket 4 LX] IBM Ambra DP60 PCI", "ambradp60", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_ambradp60_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_VPP60) diff --git a/src/pit.c b/src/pit.c index 61d18e317..7c6c1923d 100644 --- a/src/pit.c +++ b/src/pit.c @@ -1029,8 +1029,10 @@ pit_set_clock(int clock) TIMER_USEC = (uint64_t)((cpuclock / 1000000.0) * (double)(1ull << 32)); isa_timing = (cpuclock / (double)8000000.0); - - bus_timing = (cpuclock / (double)cpu_busspeed); + if (cpu_64bitbus) + bus_timing = (cpuclock / ((double)cpu_busspeed) / 2); + else + bus_timing = (cpuclock / (double)cpu_busspeed); pci_timing = (cpuclock / (double)cpu_pci_speed); /* PCICLK in us for use with timer_on_auto(). */ diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index cf6d61fdc..1568eb008 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -1210,7 +1210,7 @@ uint8_t et4000w32p_pci_read(int func, int addr, void *p) case 0x09: return 0; /*Programming interface*/ case 0x0a: return 0x00; /*Supports VGA interface, XGA compatible*/ - case 0x0b: return is_pentium ? 0x03 : 0x00; /* This has to be done in order to make this card work with the two 486 PCI machines. */ + case 0x0b: return cpu_64bitbus ? 0x03 : 0x00; /* This has to be done in order to make this card work with the two 486 PCI machines. */ case 0x10: return 0x00; /*Linear frame buffer address*/ case 0x11: return 0x00; diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 9e2ad81d9..e761fc091 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -515,7 +515,7 @@ CPUOBJ := cpu.o cpu_table.o \ $(DYNARECOBJ) CHIPSETOBJ := acc2168.o acer_m3a.o cs8230.o ali1429.o headland.o \ - intel_4x0.o neat.o opti495.o scamp.o scat.o \ + intel_4x0.o neat.o opti495.o opti5x7.o scamp.o scat.o \ sis_85c471.o sis_85c496.o \ via_apollo.o via_vpx.o wd76c10.o diff --git a/src/win/Makefile_ndr.mingw b/src/win/Makefile_ndr.mingw index 29ff11093..03ae92185 100644 --- a/src/win/Makefile_ndr.mingw +++ b/src/win/Makefile_ndr.mingw @@ -519,7 +519,7 @@ CPUOBJ := cpu.o cpu_table.o \ $(DYNARECOBJ) CHIPSETOBJ := acc2168.o acer_m3a.o cs8230.o ali1429.o headland.o \ - intel_4x0.o neat.o opti495.o scamp.o scat.o \ + intel_4x0.o neat.o opti495.o opti5x7.o scamp.o scat.o \ sis_85c471.o sis_85c496.o \ via_apollo.o via_vpx.o wd76c10.o