diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 0e3472957..c2ca3446f 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -25,8 +25,8 @@ If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. Windows 10]
- - Version [e.g. v2.06 build 2007]
- - Build type [i.e. regular, optimized, or dev]
+ - 86Box version: [e.g. v2.06 build 2007]
+ - Build type: [i.e. regular, optimized, or dev]
**Additional context**
Add any other context about the problem here. If you are using an Optimized build, make sure to try the regular build too before filing a bug report!
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index e301d68ce..4fe86d5ec 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -2,7 +2,7 @@
name: Feature request
about: Suggest an idea for this project
title: ''
-labels: feature request
+labels: feature
assignees: ''
---
diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml
new file mode 100644
index 000000000..e9c8d3013
--- /dev/null
+++ b/.github/workflows/c-cpp.yml
@@ -0,0 +1,38 @@
+name: C/C++ CI
+
+on:
+
+ push:
+ paths:
+ - src/**
+ - .github/workflows/**
+
+ pull_request:
+ paths:
+ - src/**
+ - .github/workflows/**
+
+jobs:
+ build:
+
+ runs-on: windows-latest
+
+ defaults:
+ run:
+ shell: msys2 {0}
+
+ strategy:
+ matrix:
+ dev-build: ['y', 'n']
+ new-dynarec: ['y', 'n']
+
+ steps:
+ - uses: msys2/setup-msys2@v1
+ with:
+ update: true
+ msystem: MINGW32
+ install: 'make mingw-w64-i686-toolchain mingw-w64-i686-openal mingw-w64-i686-freetype mingw-w64-i686-SDL2 mingw-w64-i686-zlib mingw-w64-i686-libpng mingw-w64-i686-libvncserver'
+ - uses: actions/checkout@v2
+ - name: make
+ run: make -fwin/makefile.mingw DEV_BUILD=${{ matrix.dev-build }} NEW_DYNAREC=${{ matrix.new-dynarec }} VNC=n
+ working-directory: ./src
diff --git a/src/Makefile.local b/src/Makefile.local
index 8b528ff28..095b60024 100644
--- a/src/Makefile.local
+++ b/src/Makefile.local
@@ -74,8 +74,11 @@ STUFF :=
# chipset/ logging:
# -DENABLE_I420EX_LOG=N sets logging level at N.
# -DENABLE_NEAT_LOG=N sets logging level at N.
+# -DENABLE_OPTI495_LOG=N sets logging level at N.
+# -DENABLE_OPTI895_LOG=N sets logging level at N.
# -DENABLE_PIIX_LOG=N sets logging level at N.
# -DENABLE_SIO_LOG=N sets logging level at N.
+# -DENABLE_SIS_85C496_LOG=N sets logging level at N.
# codegen/, codegen_new/, cpu/ logging:
# -DENABLE_X86SEG_LOG=N sets logging level at N.
# cpu/ logging:
diff --git a/src/chipset/acer_m3a.c b/src/chipset/acer_m3a.c
deleted file mode 100644
index fc7717a11..000000000
--- a/src/chipset/acer_m3a.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 86Box A hypervisor and IBM PC system emulator that specializes in
- * running old operating systems and software designed for IBM
- * PC systems and compatibles from 1981 through fairly recent
- * system designs based on the PCI bus.
- *
- * This file is part of the 86Box distribution.
- *
- * Implementation of the Acer M3A and V35N ports EAh and EBh.
- *
- *
- *
- * Authors: Sarah Walker,
- * Miran Grca,
- *
- * Copyright 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/keyboard.h>
-#include <86box/chipset.h>
-
-
-typedef struct
-{
- int index;
-} acerm3a_t;
-
-
-static void
-acerm3a_out(uint16_t port, uint8_t val, void *p)
-{
- acerm3a_t *dev = (acerm3a_t *) p;
-
- if (port == 0xea)
- dev->index = val;
-}
-
-
-static uint8_t
-acerm3a_in(uint16_t port, void *p)
-{
- acerm3a_t *dev = (acerm3a_t *) p;
-
- if (port == 0xeb) {
- switch (dev->index) {
- case 2:
- return 0xfd;
- }
- }
- return 0xff;
-}
-
-
-static void
-acerm3a_close(void *p)
-{
- acerm3a_t *dev = (acerm3a_t *)p;
-
- free(dev);
-}
-
-
-static void
-*acerm3a_init(const device_t *info)
-{
- acerm3a_t *acerm3a = (acerm3a_t *) malloc(sizeof(acerm3a_t));
- memset(acerm3a, 0, sizeof(acerm3a_t));
-
- io_sethandler(0x00ea, 0x0002, acerm3a_in, NULL, NULL, acerm3a_out, NULL, NULL, acerm3a);
-
- return acerm3a;
-}
-
-
-const device_t acerm3a_device =
-{
- "Acer M3A Register",
- 0,
- 0,
- acerm3a_init,
- acerm3a_close,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
-};
diff --git a/src/chipset/intel_420ex.c b/src/chipset/intel_420ex.c
index ca872599d..2c475c08b 100644
--- a/src/chipset/intel_420ex.c
+++ b/src/chipset/intel_420ex.c
@@ -32,6 +32,7 @@
#include <86box/hdc.h>
#include <86box/machine.h>
#include <86box/chipset.h>
+#include <86box/spd.h>
#define MEM_STATE_SHADOW_R 0x01
@@ -232,8 +233,6 @@ i420ex_write(int func, int addr, uint8_t val, void *priv)
break;
case 0x4c: case 0x51:
case 0x57:
- case 0x60: case 0x61: case 0x62: case 0x63:
- case 0x64:
case 0x68: case 0x69:
dev->regs[addr] = val;
if (addr == 0x4c) {
@@ -306,6 +305,9 @@ i420ex_write(int func, int addr, uint8_t val, void *priv)
i420ex_map(0xec000, 0x04000, val >> 4);
dev->regs[0x5f] = val;
break;
+ case 0x60: case 0x61: case 0x62: case 0x63: case 0x64:
+ spd_write_drbs(dev->regs, 0x60, 0x64, 1);
+ break;
case 0x66: case 0x67:
i420ex_log("Set IRQ routing: INT %c -> %02X\n", 0x41 + (addr & 0x01), val);
dev->regs[addr] = val & 0x8f;
diff --git a/src/chipset/intel_4x0.c b/src/chipset/intel_4x0.c
index f34ca0013..7d5c6f43c 100644
--- a/src/chipset/intel_4x0.c
+++ b/src/chipset/intel_4x0.c
@@ -6,7 +6,7 @@
*
* This file is part of the 86Box distribution.
*
- * Implementation of the Intel PCISet chips from 420TX to 440BX.
+ * Implementation of the Intel PCISet chips from 420TX to 440GX.
*
*
*
@@ -28,6 +28,7 @@
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/chipset.h>
+#include <86box/spd.h>
enum
@@ -52,12 +53,32 @@ typedef struct
{
uint8_t pm2_cntrl, max_func,
smram_locked, max_drb,
- drb_default;
+ drb_unit, drb_default;
uint8_t regs[2][256], regs_locked[2][256];
int type;
} i4x0_t;
+#ifdef ENABLE_I4X0_LOG
+int i4x0_do_log = ENABLE_I4X0_LOG;
+
+
+static void
+i4x0_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (i4x0_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+#define i4x0_log(fmt, ...)
+#endif
+
+
static void
i4x0_map(uint32_t addr, uint32_t size, int state)
{
@@ -491,6 +512,11 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
break;
case 0x55:
switch (dev->type) {
+ case INTEL_420TX: case INTEL_420ZX:
+ /* According to the FreeBSD 3.x source code, the 420TX/ZX chipset has
+ this register. The mask is unknown, so write all bits. */
+ regs[0x55] = val;
+ break;
case INTEL_430VX: case INTEL_430TX:
regs[0x55] = val & 0x01;
break;
@@ -502,6 +528,11 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
break;
case 0x56:
switch (dev->type) {
+ case INTEL_420TX: case INTEL_420ZX:
+ /* According to the FreeBSD 3.x source code, the 420TX/ZX chipset has
+ this register. The mask is unknown, so write all bits. */
+ regs[0x56] = val;
+ break;
case INTEL_430HX:
regs[0x56] = val & 0x1f;
break;
@@ -628,6 +659,10 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
regs[0x5f] = val & 0x77;
break;
case 0x60: case 0x61: case 0x62: case 0x63: case 0x64:
+ if ((addr & 0x7) <= dev->max_drb) {
+ spd_write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit);
+ break;
+ }
switch (dev->type) {
case INTEL_420TX: case INTEL_420ZX:
case INTEL_430LX: case INTEL_430NX:
@@ -647,6 +682,10 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
}
break;
case 0x65:
+ if ((addr & 0x7) <= dev->max_drb) {
+ spd_write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit);
+ break;
+ }
switch (dev->type) {
case INTEL_420TX: case INTEL_420ZX:
case INTEL_430LX: case INTEL_430NX:
@@ -666,6 +705,10 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
}
break;
case 0x66:
+ if ((addr & 0x7) <= dev->max_drb) {
+ spd_write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit);
+ break;
+ }
switch (dev->type) {
case INTEL_430NX: case INTEL_430HX:
case INTEL_440FX: case INTEL_440LX:
@@ -676,12 +719,16 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
}
break;
case 0x67:
+ if ((addr & 0x7) <= dev->max_drb) {
+ spd_write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit);
+ break;
+ }
switch (dev->type) {
case INTEL_430NX: case INTEL_430HX:
case INTEL_440FX: case INTEL_440LX:
case INTEL_440EX:
case INTEL_440BX: case INTEL_440GX:
- case INTEL_440ZX:
+ case INTEL_440ZX:
regs[addr] = val;
break;
case INTEL_430VX:
@@ -1284,28 +1331,33 @@ static void
regs[0x06] = 0x40;
regs[0x08] = (dev->type == INTEL_420ZX) ? 0x01 : 0x00;
regs[0x0d] = 0x20;
+ /* According to information from FreeBSD 3.x source code:
+ 0x00 = 486DX, 0x20 = 486SX, 0x40 = 486DX2 or 486DX4, 0x80 = Pentium OverDrive. */
if (is486sx)
regs[0x50] = 0x20;
else if (is486sx2)
regs[0x50] = 0x60; /* Guess based on the SX, DX, and DX2 values. */
- else if (is486dx || isdx4)
+ else if (is486dx)
regs[0x50] = 0x00;
- else if (is486dx2)
+ else if (is486dx2 || isdx4)
regs[0x50] = 0x40;
else
regs[0x50] = 0x80; /* Pentium OverDrive. */
- if (cpu_busspeed <= 25000000)
+ /* According to information from FreeBSD 3.x source code:
+ 00 = 25 MHz, 01 = 33 MHz. */
+ if (cpu_busspeed > 25000000)
regs[0x50] |= 0x01;
- else if ((cpu_busspeed > 25000000) && (cpu_busspeed <= 30000000))
- regs[0x50] |= 0x02;
- else if ((cpu_busspeed > 30000000) && (cpu_busspeed <= 33333333))
- regs[0x50] |= 0x03;
regs[0x51] = 0x80;
- regs[0x52] = 0xea; /* 512 kB burst cache, set to 0xaa for 256 kB */
+ /* According to information from FreeBSD 3.x source code:
+ 0x00 = None, 0x01 = 64 kB, 0x41 = 128 kB, 0x81 = 256 kB, 0xc1 = 512 kB,
+ If bit 0 is set, then if bit 2 is also set, the cache is write back,
+ otherwise it's write through. */
+ regs[0x52] = 0xc3; /* 512 kB writeback cache */
regs[0x57] = 0x31;
regs[0x59] = 0x0f;
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = 0x02;
dev->max_drb = 5;
+ dev->drb_unit = 4;
dev->drb_default = 0x02;
break;
case INTEL_430LX:
@@ -1324,6 +1376,7 @@ static void
regs[0x59] = 0x0f;
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = 0x02;
dev->max_drb = 5;
+ dev->drb_unit = 4;
dev->drb_default = 0x02;
break;
case INTEL_430NX:
@@ -1344,6 +1397,7 @@ static void
regs[0x59] = 0x0f;
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x02;
dev->max_drb = 7;
+ dev->drb_unit = 4;
dev->drb_default = 0x02;
break;
case INTEL_430FX:
@@ -1359,6 +1413,7 @@ static void
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = 0x02;
regs[0x72] = 0x02;
dev->max_drb = 4;
+ dev->drb_unit = 4;
dev->drb_default = 0x02;
break;
case INTEL_430HX:
@@ -1373,6 +1428,7 @@ static void
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x02;
regs[0x72] = 0x02;
dev->max_drb = 7;
+ dev->drb_unit = 4;
dev->drb_default = 0x02;
break;
case INTEL_430VX:
@@ -1394,6 +1450,7 @@ static void
regs[0x74] = 0x0e;
regs[0x78] = 0x23;
dev->max_drb = 4;
+ dev->drb_unit = 4;
dev->drb_default = 0x02;
break;
case INTEL_430TX:
@@ -1411,6 +1468,7 @@ static void
regs[0x70] = 0x20;
regs[0x72] = 0x02;
dev->max_drb = 5;
+ dev->drb_unit = 4;
dev->drb_default = 0x02;
break;
case INTEL_440FX:
@@ -1427,6 +1485,7 @@ static void
regs[0x71] = 0x10;
regs[0x72] = 0x02;
dev->max_drb = 7;
+ dev->drb_unit = 8;
dev->drb_default = 0x02;
break;
case INTEL_440LX:
@@ -1451,12 +1510,13 @@ static void
regs[0xa5] = 0x02;
regs[0xa7] = 0x1f;
dev->max_drb = 7;
+ dev->drb_unit = 8;
dev->drb_default = 0x01;
break;
case INTEL_440EX:
dev->max_func = 1;
- regs[0x02] = 0x80; regs[0x03] = 0x71; /* 82443EX. Same Vendor ID as 440LX*/
+ regs[0x02] = 0x80; regs[0x03] = 0x71; /* 82443EX. Same Vendor ID as 440LX */
regs[0x06] = 0x90;
regs[0x10] = 0x08;
regs[0x34] = 0xa0;
@@ -1475,6 +1535,7 @@ static void
regs[0xa5] = 0x02;
regs[0xa7] = 0x1f;
dev->max_drb = 7;
+ dev->drb_unit = 8;
dev->drb_default = 0x01;
break;
case INTEL_440BX: case INTEL_440ZX:
@@ -1503,6 +1564,7 @@ static void
regs[0xa5] = 0x02;
regs[0xa7] = 0x1f;
dev->max_drb = 7;
+ dev->drb_unit = 8;
dev->drb_default = 0x01;
break;
case INTEL_440GX:
@@ -1528,6 +1590,7 @@ static void
regs[0xa5] = 0x02;
regs[0xa7] = 0x1f;
dev->max_drb = 7;
+ dev->drb_unit = 8;
dev->drb_default = 0x01;
break;
}
diff --git a/src/chipset/opti283.c b/src/chipset/opti283.c
new file mode 100644
index 000000000..a4dad3d29
--- /dev/null
+++ b/src/chipset/opti283.c
@@ -0,0 +1,175 @@
+/*
+ * 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 82C283 chipset.
+ *
+ *
+ *
+ * Authors: Tiseno100
+ *
+ * Copyright 2020 Tiseno100
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#define HAVE_STDARG_H
+#include <86box/86box.h>
+#include "cpu.h"
+#include <86box/timer.h>
+#include <86box/io.h>
+#include <86box/device.h>
+#include <86box/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 index,
+ regs[256];
+} opti283_t;
+
+static void opti283_shadow_recalc(opti283_t *dev)
+{
+uint32_t base;
+uint32_t shflags, i = 0;
+
+shadowbios = 0;
+shadowbios_write = 0;
+
+ /* F0000 - FFFFF segmentation */
+if(!(dev->regs[0x11] & 0x80)){
+ shadowbios = 1;
+ shadowbios_write = 0;
+ mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
+} else {
+ shadowbios = 0;
+ shadowbios_write = 1;
+ mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
+}
+
+ /* C0000 - CFFFF segmentation */
+for(i = 4; i < 8; i++){
+ base = 0xc0000 + ((i-4) << 14);
+
+ if((dev->regs[0x13] & (1 << i)) & (dev->regs[0x11] & 0x10)){
+ shflags = MEM_READ_INTERNAL;
+ shflags |= (!(dev->regs[0x11] & 0x01)) ? MEM_WRITE_INTERNAL : MEM_WRITE_DISABLED;
+ mem_set_mem_state_both(base, 0x4000, shflags);
+ } else {
+ mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
+}
+}
+
+ /* D0000 - DFFFF segmentation */
+for(i = 0; i < 4; i++){
+ base = 0xd0000 + (i << 14);
+ if((dev->regs[0x12] & (1 << i)) & (dev->regs[0x11] & 0x20)){
+ shflags = MEM_READ_INTERNAL;
+ shflags |= (!(dev->regs[0x11] & 0x02)) ? MEM_WRITE_INTERNAL : MEM_WRITE_DISABLED;
+ mem_set_mem_state(base, 0x4000, shflags);
+ } else mem_set_mem_state(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
+}
+
+ /* E0000 - EFFFF segmentation */
+for(i = 4; i < 8; i++){
+ base = 0xe0000 + ((i-4) << 14);
+ if((dev->regs[0x12] & (1 << i)) & (dev->regs[0x11] & 0x40)){
+ shflags = MEM_READ_INTERNAL;
+ shflags |= (!(dev->regs[0x11] & 0x04)) ? MEM_WRITE_INTERNAL : MEM_WRITE_DISABLED;
+ mem_set_mem_state(base, 0x4000, shflags);
+ } else mem_set_mem_state(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
+}
+
+}
+
+static void
+opti283_write(uint16_t addr, uint8_t val, void *priv)
+{
+ opti283_t *dev = (opti283_t *) priv;
+
+ switch (addr) {
+ case 0x22:
+ dev->index = val;
+ break;
+ case 0x24:
+ /*pclog("OPTi 283: dev->regs[%02x] = %02x\n", dev->index, val);*/
+ dev->regs[dev->index] = val;
+
+ switch(dev->index){
+ case 0x10:
+ cpu_update_waitstates();
+
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ opti283_shadow_recalc(dev);
+ break;
+ }
+ break;
+ }
+}
+
+
+static uint8_t
+opti283_read(uint16_t addr, void *priv)
+{
+ uint8_t ret = 0xff;
+ opti283_t *dev = (opti283_t *) priv;
+
+ switch (addr) {
+ case 0x24:
+ ret = dev->regs[dev->index];
+ break;
+ }
+
+ return ret;
+}
+
+
+static void
+opti283_close(void *priv)
+{
+ opti283_t *dev = (opti283_t *) priv;
+
+ free(dev);
+}
+
+
+static void *
+opti283_init(const device_t *info)
+{
+ opti283_t *dev = (opti283_t *) malloc(sizeof(opti283_t));
+ memset(dev, 0, sizeof(opti283_t));
+
+ io_sethandler(0x022, 0x0001, opti283_read, NULL, NULL, opti283_write, NULL, NULL, dev);
+ io_sethandler(0x024, 0x0001, opti283_read, NULL, NULL, opti283_write, NULL, NULL, dev);
+
+ dev->regs[0x10] = 0x3f;
+ dev->regs[0x11] = 0xf0;
+ opti283_shadow_recalc(dev);
+
+ return dev;
+}
+
+
+const device_t opti283_device = {
+ "OPTi 82C283",
+ 0,
+ 0,
+ opti283_init, opti283_close, NULL,
+ NULL, NULL, NULL,
+ NULL
+};
diff --git a/src/chipset/opti495.c b/src/chipset/opti495.c
index 47ee25582..c3fa1bda4 100644
--- a/src/chipset/opti495.c
+++ b/src/chipset/opti495.c
@@ -1,256 +1,21 @@
-/*OPTi 82C495 emulation
- This is the chipset used in the AMI386 model
-
- Details for the chipset from Ralph Brown's interrupt list
- This describes the OPTi 82C493, the 82C495 seems similar except there is one
- more register (2C)
-
-----------P00220024--------------------------
-PORT 0022-0024 - OPTi 82C493 System Controller (SYSC) - CONFIGURATION REGISTERS
-Desc: The OPTi 486SXWB contains three chips and is designed for systems
- running at 20, 25 and 33MHz. The chipset includes an 82C493 System
- Controller (SYSC), the 82C392 Data Buffer Controller, and the
- 82C206 Integrated peripheral Controller (IPC).
-Note: every access to PORT 0024h must be preceded by a write to PORT 0022h,
- even if the same register is being accessed a second time
-SeeAlso: PORT 0022h"82C206"
-
-0022 ?W configuration register index (see #P0178)
-0024 RW configuration register data
-
-(Table P0178)
-Values for OPTi 82C493 System Controller configuration register index:
- 20h Control Register 1 (see #P0179)
- 21h Control Register 2 (see #P0180)
- 22h Shadow RAM Control Register 1 (see #P0181)
- 23h Shadow RAM Control Register 2 (see #P0182)
- 24h DRAM Control Register 1 (see #P0183)
- 25h DRAM Control Register 2 (see #P0184)
- 26h Shadow RAM Control Register 3 (see #P0185)
- 27h Control Register 3 (see #P0186)
- 28h Non-cachable Block 1 Register 1 (see #P0187)
- 29h Non-cachable Block 1 Register 2 (see #P0188)
- 2Ah Non-cachable Block 2 Register 1 (see #P0187)
- 2Bh Non-cachable Block 2 Register 2 (see #P0188)
-
-Bitfields for OPTi-82C493 Control Register 1:
-Bit(s) Description (Table P0179)
- 7-6 Revision of 82C493 (readonly) (default=01)
- 5 Burst wait state control
- 1 = Secondary cache read hit cycle is 3-2-2-2 or 2-2-2-2
- 0 = Secondary cache read hit cycle is 3-1-1-1 or 2-1-1-1 (default)
- (if bit 5 is set to 1, bit 4 must be set to 0)
- 4 Cache memory data buffer output enable control
- 0 = disable (default)
- 1 = enable
- (must be disabled for frequency <= 33Mhz)
- 3 Single Address Latch Enable (ALE)
- 0 = disable (default)
- 1 = enable
- (if enabled, SYSC will activate single ALE rather than multiples
- during bus conversion cycles)
- 2 enable Extra AT Cycle Wait State (default is 0 = disabled)
- 1 Emulation keyboard Reset Control
- 0 = disable (default)
- 1 = enable
- Note: This bit must be enabled in BIOS default value; enabling this
- bit requires HALT instruction to be executed before SYSC
- generates processor reset (CPURST)
- 0 enable Alternative Fast Reset (default is 0 = disabled)
-SeeAlso: #P0180,#P0186
-
-Bitfields for OPTi-82C493 Control Register 2:
-Bit(s) Description (Table P0180)
- 7 Master Mode Byte Swap Enable
- 0 = disable (default)
- 1 = enable
- 6 Emulation Keyboard Reset Delay Control
- 0 = Generate reset pulse 2us later (default)
- 1 = Generate reset pulse immediately
- 5 disable Parity Check (default is 0 = enabled)
- 4 Cache Enable
- 0 = Cache disabled and DRAM burst mode enabled (default)
- 1 = Cache enabled and DRAM burst mode disabled
- 3-2 Cache Size
- 00 64KB (default)
- 01 128KB
- 10 256KB
- 11 512KB
- 1 Secondary Cache Read Burst Cycles Control
- 0 = 3-1-1-1 cycle (default)
- 1 = 2-1-1-1 cycle
- 0 Cache Write Wait State Control
- 0 = 1 wait state (default)
- 1 = 0 wait state
-SeeAlso: #P0179,#P0186
-
-Bitfields for OPTi-82C493 Shadow RAM Control Register 1:
-Bit(s) Description (Table P0181)
- 7 ROM(F0000h - FFFFFh) Enable
- 0 = read/write on write-protected DRAM
- 1 = read from ROM, write to DRAM (default)
- 6 Shadow RAM at D0000h - EFFFFh Area
- 0 = disable (default)
- 1 = enable
- 5 Shadow RAM at E0000h - EFFFFh Area
- 0 = disable shadow RAM (default)
- E0000h - EFFFFh ROM is defaulted to reside on XD bus
- 1 = enable shadow RAM
- 4 enable write-protect for Shadow RAM at D0000h - DFFFFh Area
- 0 = disable (default)
- 1 = enable
- 3 enable write-protect for Shadow RAM at E0000h - EFFFFh Area
- 0 = disable (default)
- 1 = enable
- 2 Hidden refresh enable (with holding CPU)
- (Hidden refresh must be disabled if 4Mx1 or 1M x4 bit DRAM are used)
- 1 = disable (default)
- 0 = enable
- 1 unused
- 0 enable Slow Refresh (four times slower than normal refresh)
- (default is 0 = disable)
-SeeAlso: #P0182
-
-Bitfields for OPTi-82C493 Shadow RAM Control Register 2:
-Bit(s) Description (Table P0182)
- 7 enable Shadow RAM at EC000h - EFFFFh area
- 6 enable Shadow RAM at E8000h - EBFFFh area
- 5 enable Shadow RAM at E4000h - E7FFFh area
- 4 enable Shadow RAM at E0000h - E3FFFh area
- 3 enable Shadow RAM at DC000h - DFFFFh area
- 2 enable Shadow RAM at D8000h - DBFFFh area
- 1 enable Shadow RAM at D4000h - D7FFFh area
- 0 enable Shadow RAM at D0000h - D3FFFh area
-Note: the default is disabled (0) for all areas
-
-Bitfields for OPTi-82C493 DRAM Control Register 1:
-Bit(s) Description (Table P0183)
- 7 DRAM size
- 0 = 256K DRAM mode
- 1 = 1M and 4M DRAM mode
- 6-4 DRAM types used for bank0 and bank1
- bits 7-4 Bank0 Bank1
- 0000 256K x
- 0001 256K 256K
- 0010 256K 1M
- 0011 x x
- 01xx x x
- 1000 1M x (default)
- 1001 1M 1M
- 1010 1M 4M
- 1011 4M 1M
- 1100 4M x
- 1101 4M 4M
- 111x x x
- 3 unused
- 2-0 DRAM types used for bank2 and bank3
- bits 7,2-0 Bank2 Bank3
- x000 1M x
- x001 1M 1M
- x010 x x
- x011 4M 1M
- x100 4M x
- x101 4M 4M
- x11x x x (default)
-SeeAlso: #P0184
-
-Bitfields for OPTi-82C493 DRAM Control Register 2:
-Bit(s) Description (Table P0184)
- 7-6 Read cycle additional wait states
- 00 not used
- 01 = 0
- 10 = 1
- 11 = 2 (default)
- 5-4 Write cycle additional wait states
- 00 = 0
- 01 = 1
- 10 = 2
- 11 = 3 (default)
- 3 Fast decode enable
- 0 = disable fast decode. DRAM base wait states not changed (default)
- 1 = enable fast decode. DRAM base wait state is decreased by 1
- Note: This function may be enabled in 20/25Mhz operation to speed up
- DRAM access. If bit 4 of index register 21h (cache enable
- bit) is enabled, this bit is automatically disabled--even if
- set to 1
- 2 unused
- 1-0 ATCLK selection
- 00 ATCLK = CLKI/6 (default)
- 01 ATCLK = CLKI/4 (default)
- 10 ATCLK = CLKI/3
- 11 ATCLK = CLK2I/5 (CLKI * 2 /5)
- Note: bit 0 will reflect the BCLKS (pin 142) status and bit 1 will be
- set to 0 when 82C493 is reset.
-SeeAlso: #P0183,#P0185
-
-Bitfields for OPTi-82C493 Shadow RAM Control Register 3:
-Bit(s) Description (Table P0185)
- 7 unused
- 6 Shadow RAM copy enable for address C0000h - CFFFFh
- 0 = Read/write at AT bus (default)
- 1 = Read from AT bus and write into shadow RAM
- 5 Shadow write protect at address C0000h - CFFFFh
- 0 = Write protect disable (default)
- 1 = Write protect enable
- 4 enable Shadow RAM at C0000h - CFFFFh
- 3 enable Shadow RAM at CC000h - CFFFFh
- 2 enable Shadow RAM at C8000h - CBFFFh
- 1 enable Shadow RAM at C4000h - C7FFFh
- 0 enable Shadow RAM at C0000h - C3FFFh
-Note: the default is disabled (0) for bits 4-0
-SeeAlso: #P0183,#P0184
-
-Bitfields for OPTi-82C493 Control Register 3:
-Bit(s) Description (Table P0186)
- 7 enable NCA# pin to low state (default is 1 = enabled)
- 6-5 unused
- 4 Video BIOS at C0000h - C8000h non-cacheable
- 0 = cacheable
- 1 = non-cacheable (default)
- 3-0 Cacheable address range for local memory
- 0000 0 - 64MB
- 0001 0 - 4MB (default)
- 0010 0 - 8MB
- 0011 0 - 12MB
- 0100 0 - 16MB
- 0101 0 - 20MB
- 0110 0 - 24MB
- 0111 0 - 28MB
- 1000 0 - 32MB
- 1001 0 - 36MB
- 1010 0 - 40MB
- 1011 0 - 44MB
- 1100 0 - 48MB
- 1101 0 - 52MB
- 1110 0 - 56MB
- 1111 0 - 60MB
- Note: If total memory is 1MB or 2MB the cacheable range is 0-1 MB or
- 0-2 MB and independent of the value of bits 3-0
-SeeAlso: #P0179,#P0180
-
-Bitfields for OPTi-82C493 Non-cacheable Block Register 1:
-Bit(s) Description (Table P0187)
- 7-5 Size of non-cachable memory block
- 000 64K
- 001 128K
- 010 256K
- 011 512K
- 1xx disabled (default)
- 4-2 unused
- 1-0 Address bits 25 and 24 of non-cachable memory block (default = 00)
-Note: this register is used together with configuration register 29h
- (non-cacheable block 1) or register 2Bh (block 2) (see #P0188) to
- define a non-cacheable block. The starting address must be a
- multiple of the block size
-SeeAlso: #P0178,#P0188
-
-Bitfields for OPTi-82C493 Non-cacheable Block Register 2:
-Bit(s) Description (Table P0188)
- 7-0 Address bits 23-16 of non-cachable memory block (default = 0001xxxx)
-Note: the block address is forced to be a multiple of the block size by
- ignoring the appropriate number of the least-significant bits
-SeeAlso: #P0178,#P0187
-*/
+/*
+ * 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/82C495 chipset.
+ *
+ *
+ *
+ * Authors: Tiseno100,
+ * Miran Grca,
+ *
+ * Copyright 2008-2020 Tiseno100.
+ * Copyright 2016-2020 Miran Grca.
+ */
#include
#include
#include
@@ -267,17 +32,98 @@ SeeAlso: #P0178,#P0187
#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[16],
+ uint8_t idx,
+ regs[256],
scratch[2];
} opti495_t;
+#ifdef ENABLE_OPTI495_LOG
+int opti495_do_log = ENABLE_OPTI495_LOG;
+
+
+static void
+opti495_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (opti495_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+#define opti495_log(fmt, ...)
+#endif
+
+
+static void
+opti495_recalc(opti495_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[0x26] & 0x40) {
+ shflags = MEM_READ_EXTANY;
+ shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
+ } else
+ shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
+ }
+
+ 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) {
+ shflags = MEM_READ_EXTANY;
+ shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
+ } else
+ shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
+ }
+
+ mem_set_mem_state_both(base, 0x4000, shflags);
+ }
+
+ flushmmucache();
+}
+
+
static void
opti495_write(uint16_t addr, uint8_t val, void *priv)
{
@@ -285,26 +131,31 @@ opti495_write(uint16_t addr, uint8_t val, void *priv)
switch (addr) {
case 0x22:
- dev->cur_reg = val;
+ dev->idx = val;
break;
case 0x24:
- if ((dev->cur_reg >= 0x20) && (dev->cur_reg <= 0x2C)) {
- dev->regs[dev->cur_reg - 0x20] = val;
- if (dev->cur_reg == 0x21) {
- cpu_cache_ext_enabled = val & 0x10;
- cpu_update_waitstates();
- }
- if (dev->cur_reg == 0x22) {
- if (!(val & 0x80))
- mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
- else
- mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
+ if ((dev->idx >= 0x20) && (dev->idx <= 0x2c)) {
+ dev->regs[dev->idx] = val;
+ opti495_log("dev->regs[%04x] = %08x\n", dev->idx, val);
+
+ switch(dev->idx) {
+ case 0x21:
+ cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10);
+ cpu_update_waitstates();
+ break;
+
+ case 0x22:
+ case 0x23:
+ case 0x26:
+ opti495_recalc(dev);
+ break;
}
}
break;
+
case 0xe1:
case 0xe2:
- dev->scratch[addr - 0xe1] = val;
+ dev->scratch[addr] = val;
break;
}
}
@@ -318,12 +169,12 @@ opti495_read(uint16_t addr, void *priv)
switch (addr) {
case 0x24:
- if ((dev->cur_reg >= 0x20) && (dev->cur_reg <= 0x2C))
- ret = dev->regs[dev->cur_reg - 0x20];
+ if ((dev->idx >= 0x20) && (dev->idx <= 0x2c))
+ ret = dev->regs[dev->idx];
break;
case 0xe1:
case 0xe2:
- ret = dev->scratch[addr - 0xe1];
+ ret = dev->scratch[addr];
break;
}
@@ -351,19 +202,52 @@ opti495_init(const device_t *info)
dev->scratch[0] = dev->scratch[1] = 0xff;
- io_sethandler(0x00e1, 0x0002, opti495_read, NULL, NULL, opti495_write, NULL, NULL, dev);
+ if (info->local == 1) {
+ /* 85C495 */
+ dev->regs[0x20] = 0x02;
+ dev->regs[0x21] = 0x20;
+ dev->regs[0x22] = 0xe4;
+ dev->regs[0x25] = 0xf0;
+ dev->regs[0x26] = 0x80;
+ dev->regs[0x27] = 0xb1;
+ dev->regs[0x28] = 0x80;
+ dev->regs[0x29] = 0x10;
+ } else {
+ /* 85C493 */
+ dev->regs[0x20] = 0x40;
+ dev->regs[0x22] = 0x84;
+ dev->regs[0x24] = 0x87;
+ dev->regs[0x25] = 0xf1; /* Note: 0xf0 is also valid default. */
+ dev->regs[0x27] = 0x91;
+ dev->regs[0x28] = 0x80;
+ dev->regs[0x29] = 0x10;
+ dev->regs[0x2a] = 0x80;
+ dev->regs[0x2b] = 0x10;
+ }
- dev->regs[0x22 - 0x20] = 0x80;
+ opti495_recalc(dev);
+
+ io_sethandler(0x00e1, 0x0002, opti495_read, NULL, NULL, opti495_write, NULL, NULL, dev);
return dev;
}
-const device_t opti495_device = {
- "OPTi 82C495",
+const device_t opti493_device = {
+ "OPTi 82C493",
0,
0,
opti495_init, opti495_close, NULL,
NULL, NULL, NULL,
NULL
};
+
+
+const device_t opti495_device = {
+ "OPTi 82C495",
+ 0,
+ 1,
+ opti495_init, opti495_close, NULL,
+ NULL, NULL, NULL,
+ NULL
+};
diff --git a/src/chipset/opti5x7.c b/src/chipset/opti5x7.c
index 6f13edccf..ef43b5343 100644
--- a/src/chipset/opti5x7.c
+++ b/src/chipset/opti5x7.c
@@ -1,5 +1,19 @@
-/*Based off the OPTI 82C546/82C547 datasheet.
-The earlier 596/597 appears to be register compatible with the 546/547 from testing.*/
+/*
+ * 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 82C546/82C547 & 82C596/82C597 chipsets.
+
+ * Authors: plant/nerd73
+ * Miran Grca,
+ *
+ * Copyright 2020 plant/nerd73.
+ * Copyright 2020 Miran Grca.
+ */
#include
#include
#include
@@ -22,29 +36,40 @@ The earlier 596/597 appears to be register compatible with the 546/547 from test
typedef struct
{
- uint8_t cur_reg,
+ uint8_t idx,
regs[16];
- port_92_t *port_92;
+ port_92_t *port_92;
} opti5x7_t;
static void
-opti5x7_recalcmapping(opti5x7_t *dev)
+opti5x7_recalc(opti5x7_t *dev)
{
- uint32_t shflags = 0;
+ uint32_t base;
+ uint32_t i, j, shflags = 0;
+ uint32_t reg, lowest_bit;
+ uint32_t write = 0;
- shadowbios = 0;
- shadowbios_write = 0;
-
-
- shadowbios |= !!(dev->regs[0x06] & 0x05);
- shadowbios_write |= !!(dev->regs[0x06] & 0x0a);
+ for (i = 0; i < 8; i++) {
+ j = i / 2.01; /*Probably not a great way of doing this, but it does work*/
+ base = 0xc0000 + (j << 14);
+
+ lowest_bit = j * 2;
+ reg = 0x04 + ((base >> 16) & 0x01);
+
+ shflags = (dev->regs[reg] & (1 << lowest_bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
+ shflags |= (dev->regs[reg] & (1 << (lowest_bit + 1))) ? MEM_WRITE_INTERNAL : write;
+ write = (dev->regs[reg] & (1 << lowest_bit)) ? MEM_WRITE_DISABLED : MEM_WRITE_EXTANY;
+ mem_set_mem_state(base, 0x4000, shflags);
+ }
shflags = (dev->regs[0x06] & 0x01) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
- shflags |= (dev->regs[0x06] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
+ shflags |= (dev->regs[0x06] & 0x02) ? MEM_WRITE_INTERNAL : write;
+ write = (dev->regs[0x06] & 0x01) ? MEM_WRITE_DISABLED : 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;
+ shflags |= (dev->regs[0x06] & 0x08) ? MEM_WRITE_INTERNAL : write;
+ write = (dev->regs[0x06] & 0x04) ? MEM_WRITE_DISABLED : MEM_WRITE_EXTANY;
mem_set_mem_state(0xf0000, 0x10000, shflags);
flushmmucache();
@@ -53,18 +78,25 @@ 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);
+ pclog("Write %02x to OPTi 5x7 address %02x\n", val, addr);
switch (addr) {
case 0x22:
- dev->cur_reg = val;
+ dev->idx = val;
break;
case 0x24:
- dev->regs[dev->cur_reg] = val;
- if (dev->regs[0x02] & 0x0c)
- cpu_cache_ext_enabled = 1;
- if (dev->cur_reg == 0x06)
- opti5x7_recalcmapping(dev);
+ dev->regs[dev->idx] = val;
+ switch(dev->idx) {
+ case 0x02:
+ cpu_cache_ext_enabled = !!(dev->regs[0x02] & 0x04 & 0x08);
+ break;
+
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ opti5x7_recalc(dev);
+ break;
+ }
break;
}
}
@@ -78,8 +110,8 @@ opti5x7_read(uint16_t addr, void *priv)
switch (addr) {
case 0x24:
-// pclog("Read from OPTI 5x7 register %02x\n", dev->cur_reg);
- ret = dev->regs[dev->cur_reg];
+ pclog("Read from OPTi 5x7 register %02x\n", dev->idx);
+ ret = dev->regs[dev->idx];
break;
}
@@ -107,7 +139,7 @@ opti5x7_init(const device_t *info)
dev->port_92 = device_add(&port_92_device);
// pclog("OPTi 5x7 init\n");
- opti5x7_recalcmapping(dev);
+ opti5x7_recalc(dev);
return dev;
diff --git a/src/chipset/opti895.c b/src/chipset/opti895.c
new file mode 100644
index 000000000..8c1f050b4
--- /dev/null
+++ b/src/chipset/opti895.c
@@ -0,0 +1,296 @@
+/*
+ * 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 82C802G/82C895 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/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 idx, forced_green,
+ regs[256],
+ scratch[2];
+} opti895_t;
+
+
+#ifdef ENABLE_OPTI895_LOG
+int opti895_do_log = ENABLE_OPTI895_LOG;
+
+
+static void
+opti895_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (opti895_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+#define opti895_log(fmt, ...)
+#endif
+
+
+static void
+opti895_recalc(opti895_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[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[0x26] & 0x40) {
+ shflags = MEM_READ_EXTANY;
+ shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
+ } else
+ shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
+ }
+
+ mem_set_mem_state_both(base, 0x4000, shflags);
+ }
+
+ for (i = 0; i < 4; i++) {
+ base = 0xc0000 + (i << 14);
+
+ if (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) {
+ shflags = MEM_READ_EXTANY;
+ shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
+ } else
+ shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
+ }
+
+ mem_set_mem_state_both(base, 0x4000, shflags);
+ }
+
+ flushmmucache();
+}
+
+
+static void
+opti895_smram_map(int smm, uint32_t addr, uint32_t size, int is_smram)
+{
+ mem_set_mem_state_smram(smm, addr, size, is_smram);
+}
+
+
+static void
+opti895_write(uint16_t addr, uint8_t val, void *priv)
+{
+ opti895_t *dev = (opti895_t *) priv;
+
+ switch (addr) {
+ case 0x22:
+ dev->idx = val;
+ break;
+ case 0x23:
+ if (dev->idx == 0x01) {
+ dev->regs[dev->idx] = val;
+ opti895_log("dev->regs[%04x] = %08x\n", dev->idx, val);
+ }
+ break;
+ case 0x24:
+ if (((dev->idx >= 0x20) && (dev->idx <= 0x2c)) ||
+ ((dev->idx >= 0xe0) && (dev->idx <= 0xef))) {
+ dev->regs[dev->idx] = val;
+ opti895_log("dev->regs[%04x] = %08x\n", dev->idx, val);
+
+ switch(dev->idx) {
+ case 0x21:
+ cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10);
+ cpu_update_waitstates();
+ break;
+
+ case 0x22:
+ case 0x23:
+ case 0x26:
+ opti895_recalc(dev);
+ break;
+
+ case 0x24:
+ opti895_smram_map(0, smram[0].host_base, smram[0].size, !!(val & 0x80));
+ break;
+
+ case 0xe0:
+ if (!(val & 0x01))
+ dev->forced_green = 0;
+ break;
+
+ case 0xe1:
+ if ((val & 0x08) && (dev->regs[0xe0] & 0x01)) {
+ smi_line = 1;
+ dev->forced_green = 1;
+ break;
+ }
+ break;
+ }
+ }
+ break;
+
+ case 0xe1:
+ case 0xe2:
+ dev->scratch[addr] = val;
+ break;
+ }
+}
+
+
+static uint8_t
+opti895_read(uint16_t addr, void *priv)
+{
+ uint8_t ret = 0xff;
+ opti895_t *dev = (opti895_t *) priv;
+
+ switch (addr) {
+ case 0x23:
+ if (dev->idx == 0x01)
+ ret = dev->regs[dev->idx];
+ break;
+ case 0x24:
+ if (((dev->idx >= 0x20) && (dev->idx <= 0x2c)) ||
+ ((dev->idx >= 0xe0) && (dev->idx <= 0xef))) {
+ ret = dev->regs[dev->idx];
+ if (dev->idx == 0xe0)
+ ret = (ret & 0xf6) | (in_smm ? 0x00 : 0x08) | !!dev->forced_green;
+ }
+ break;
+ case 0xe1:
+ case 0xe2:
+ ret = dev->scratch[addr];
+ break;
+ }
+
+ return ret;
+}
+
+
+static void
+opti895_close(void *priv)
+{
+ opti895_t *dev = (opti895_t *) priv;
+
+ free(dev);
+}
+
+
+static void *
+opti895_init(const device_t *info)
+{
+ opti895_t *dev = (opti895_t *) malloc(sizeof(opti895_t));
+ memset(dev, 0, sizeof(opti895_t));
+
+ device_add(&port_92_device);
+
+ io_sethandler(0x0022, 0x0003, opti895_read, NULL, NULL, opti895_write, NULL, NULL, dev);
+
+ dev->scratch[0] = dev->scratch[1] = 0xff;
+
+ dev->regs[0x01] = 0xc0;
+
+ dev->regs[0x22] = 0xc4;
+ dev->regs[0x25] = 0x7c;
+ dev->regs[0x26] = 0x10;
+ dev->regs[0x27] = 0xde;
+ dev->regs[0x28] = 0xf8;
+ dev->regs[0x29] = 0x10;
+ dev->regs[0x2a] = 0xe0;
+ dev->regs[0x2b] = 0x10;
+ dev->regs[0x2d] = 0xc0;
+
+ dev->regs[0xe8] = 0x08;
+ dev->regs[0xe9] = 0x08;
+ dev->regs[0xeb] = 0xff;
+ dev->regs[0xef] = 0x40;
+
+ opti895_recalc(dev);
+
+ io_sethandler(0x00e1, 0x0002, opti895_read, NULL, NULL, opti895_write, NULL, NULL, dev);
+
+ smram[0].host_base = 0x00030000;
+ smram[0].ram_base = 0x000b0000;
+ smram[0].size = 0x00010000;
+
+ mem_mapping_set_addr(&ram_smram_mapping[0], smram[0].host_base, smram[0].size);
+ mem_mapping_set_exec(&ram_smram_mapping[0], ram + smram[0].ram_base);
+
+ opti895_smram_map(0, smram[0].host_base, smram[0].size, 0);
+ opti895_smram_map(1, smram[0].host_base, smram[0].size, 1);
+
+ return dev;
+}
+
+
+const device_t opti802g_device = {
+ "OPTi 82C802G",
+ 0,
+ 0,
+ opti895_init, opti895_close, NULL,
+ NULL, NULL, NULL,
+ NULL
+};
+
+
+const device_t opti895_device = {
+ "OPTi 82C895",
+ 0,
+ 0,
+ opti895_init, opti895_close, NULL,
+ NULL, NULL, NULL,
+ NULL
+};
diff --git a/src/chipset/sis_85c496.c b/src/chipset/sis_85c496.c
index 7fafa9607..0bec0232f 100644
--- a/src/chipset/sis_85c496.c
+++ b/src/chipset/sis_85c496.c
@@ -10,17 +10,17 @@
*
*
*
- * Authors: Sarah Walker,
- * Miran Grca,
+ * Authors: Miran Grca,
*
- * Copyright 2008-2019 Sarah Walker.
- * Copyright 2019 Miran Grca.
+ * Copyright 2019,2020 Miran Grca.
*/
+#include
#include
#include
#include
#include
#include
+#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/mem.h>
@@ -30,54 +30,93 @@
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/timer.h>
+#include <86box/dma.h>
+#include <86box/nvr.h>
+#include <86box/pic.h>
#include <86box/port_92.h>
#include <86box/hdc_ide.h>
#include <86box/machine.h>
#include <86box/chipset.h>
+#include <86box/spd.h>
typedef struct sis_85c496_t
{
- uint8_t cur_reg,
+ uint8_t cur_reg, rmsmiblk_count,
regs[127],
pci_conf[256];
+ pc_timer_t rmsmiblk_timer;
port_92_t * port_92;
+ nvr_t * nvr;
} sis_85c496_t;
+#ifdef ENABLE_SIS_85C496_LOG
+int sis_85c496_do_log = ENABLE_SIS_85C496_LOG;
+
+
+void
+sis_85c496_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (sis_85c496_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+#define sis_85c496_log(fmt, ...)
+#endif
+
+
static void
-sis_85c497_write(uint16_t port, uint8_t val, void *priv)
+sis_85c497_isa_write(uint16_t port, uint8_t val, void *priv)
{
sis_85c496_t *dev = (sis_85c496_t *) priv;
- uint8_t index = (port & 1) ? 0 : 1;
- if (index) {
- if ((val != 0x01) || ((val >= 0x70) && (val <= 0x76)))
- dev->cur_reg = val;
- } else {
- if (((dev->cur_reg < 0x70) && (dev->cur_reg != 0x01)) || (dev->cur_reg > 0x76))
- return;
- dev->regs[dev->cur_reg] = val;
- dev->cur_reg = 0;
+ sis_85c496_log("[%04X:%08X] ISA Write %02X to %04X\n", CS, cpu_state.pc, val, port);
+
+ if (port == 0x22)
+ dev->cur_reg = val;
+ else if (port == 0x23) switch (dev->cur_reg) {
+ case 0x01: /* Built-in 206 Timing Control */
+ dev->regs[dev->cur_reg] = val;
+ break;
+ case 0x70: /* ISA Bus Clock Selection */
+ dev->regs[dev->cur_reg] = val & 0xc0;
+ break;
+ case 0x71: /* ISA Bus Timing Control */
+ dev->regs[dev->cur_reg] = val & 0xf6;
+ break;
+ case 0x72: case 0x76: /* SMOUT */
+ case 0x74: /* BIOS Timer */
+ dev->regs[dev->cur_reg] = val;
+ break;
+ case 0x73: /* BIOS Timer */
+ dev->regs[dev->cur_reg] = val & 0xfd;
+ break;
+ case 0x75: /* DMA / Deturbo Control */
+ dev->regs[dev->cur_reg] = val & 0xfc;
+ dma_set_mask((val & 0x80) ? 0xffffffff : 0x00ffffff);
+ break;
}
}
static uint8_t
-sis_85c497_read(uint16_t port, void *priv)
+sis_85c497_isa_read(uint16_t port, void *priv)
{
sis_85c496_t *dev = (sis_85c496_t *) priv;
- uint8_t index = (port & 1) ? 0 : 1;
uint8_t ret = 0xff;
- if (index)
- ret = dev->cur_reg;
- else {
- if ((dev->cur_reg != 0x01) || ((dev->cur_reg >= 0x70) && (dev->cur_reg <= 0x76))) {
- ret = dev->regs[dev->cur_reg];
- dev->cur_reg = 0;
- }
- }
+ if (port == 0x23)
+ ret = dev->regs[dev->cur_reg];
+ else if (port == 0x33)
+ ret = 0x3c /*random_generate()*/;
+
+ sis_85c496_log("[%04X:%08X] ISA Read %02X from %04X\n", CS, cpu_state.pc, ret, port);
return ret;
}
@@ -100,170 +139,379 @@ sis_85c496_recalcmapping(sis_85c496_t *dev)
shadowbios_write |= (base >= 0xe0000) && !(dev->pci_conf[0x45] & 0x01);
shflags = (dev->pci_conf[0x45] & 0x02) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
shflags |= (dev->pci_conf[0x45] & 0x01) ? MEM_WRITE_EXTANY : MEM_WRITE_INTERNAL;
- mem_set_mem_state(base, 0x8000, shflags);
+ mem_set_mem_state_both(base, 0x8000, shflags);
} else
- mem_set_mem_state(base, 0x8000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
+ mem_set_mem_state_both(base, 0x8000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
}
+}
+
+static void
+sis_85c496_ide_handler(sis_85c496_t *dev)
+{
+ uint8_t ide_cfg[2];
+
+ ide_cfg[0] = dev->pci_conf[0x58];
+ ide_cfg[1] = dev->pci_conf[0x59];
+
+ ide_pri_disable();
+ ide_sec_disable();
+
+ if (ide_cfg[1] & 0x02) {
+ ide_set_base(0, 0x0170);
+ ide_set_side(0, 0x0376);
+ ide_set_base(1, 0x01f0);
+ ide_set_side(1, 0x03f6);
+
+ if (ide_cfg[1] & 0x01) {
+ if (!(ide_cfg[0] & 0x40))
+ ide_pri_enable();
+ if (!(ide_cfg[0] & 0x80))
+ ide_sec_enable();
+ }
+ } else {
+ ide_set_base(0, 0x01f0);
+ ide_set_side(0, 0x03f6);
+ ide_set_base(1, 0x0170);
+ ide_set_side(1, 0x0376);
+
+ if (ide_cfg[1] & 0x01) {
+ if (!(ide_cfg[0] & 0x40))
+ ide_sec_enable();
+ if (!(ide_cfg[0] & 0x80))
+ ide_pri_enable();
+ }
+ }
+}
+
+
+static void
+sis_85c496_smram_map(int smm, uint32_t addr, uint32_t size, int is_smram)
+{
+ mem_set_mem_state_smram(smm, addr, size, is_smram);
flushmmucache();
}
/* 00 - 3F = PCI Configuration, 40 - 7F = 85C496, 80 - FF = 85C497 */
static void
-sis_85c496_write(int func, int addr, uint8_t val, void *priv)
+sis_85c49x_pci_write(int func, int addr, uint8_t val, void *priv)
{
sis_85c496_t *dev = (sis_85c496_t *) priv;
- uint8_t old = dev->pci_conf[addr];
- uint8_t valxor;
+ uint8_t old, valxor;
+ uint8_t smm_irq[4] = { 10, 11, 12, 15 };
- if ((addr >= 4 && addr < 8) || addr >= 0x40)
- dev->pci_conf[addr] = val;
+ old = dev->pci_conf[addr];
+ valxor = (dev->pci_conf[addr]) ^ val;
- valxor = old ^ val;
+ sis_85c496_log("[%04X:%08X] PCI Write %02X to %02X:%02X\n", CS, cpu_state.pc, val, func, addr);
switch (addr) {
- case 0x42: /*Cache configure*/
+ /* PCI Configuration Header Registers (00h ~ 3Fh) */
+ case 0x04: /* PCI Device Command */
+ dev->pci_conf[addr] = val & 0x40;
+ break;
+ case 0x05: /* PCI Device Command */
+ dev->pci_conf[addr] = val & 0x03;
+ break;
+ case 0x07: /* Device Status */
+ dev->pci_conf[addr] &= ~(val & 0xf1);
+ break;
+
+ /* 86C496 Specific Registers (40h ~ 7Fh) */
+ case 0x40: /* CPU Configuration */
+ dev->pci_conf[addr] = val & 0x7f;
+ break;
+ case 0x41: /* DRAM Configuration */
+ dev->pci_conf[addr] = val;
+ break;
+ case 0x42: /* Cache Configure */
+ dev->pci_conf[addr] = val;
cpu_cache_ext_enabled = (val & 0x01);
cpu_update_waitstates();
break;
-
- case 0x44: /*Shadow configure*/
- if (valxor & 0xff)
- sis_85c496_recalcmapping(dev);
+ case 0x43: /* Cache Configure */
+ dev->pci_conf[addr] = val & 0x8f;
break;
- case 0x45: /*Shadow configure*/
- if (valxor & 0x03)
+ case 0x44: /* Shadow Configure */
+ dev->pci_conf[addr] = val;
+ if (valxor & 0xff) {
sis_85c496_recalcmapping(dev);
+ if (((old & 0xf0) == 0xf0) && ((val & 0xf0) == 0x30))
+ flushmmucache_nopc();
+ else
+ flushmmucache();
+ }
break;
-
- case 0x56:
+ case 0x45: /* Shadow Configure */
+ dev->pci_conf[addr] = val & 0x0f;
+ if (valxor & 0x03) {
+ sis_85c496_recalcmapping(dev);
+ flushmmucache();
+ }
+ break;
+ case 0x46: /* Cacheable Control */
+ dev->pci_conf[addr] = val;
+ break;
+ case 0x47: /* 85C496 Address Decoder */
+ dev->pci_conf[addr] = val & 0x1f;
+ break;
+ case 0x48: case 0x49: case 0x4a: case 0x4b: /* DRAM Boundary */
+ case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+ // dev->pci_conf[addr] = val;
+ spd_write_drbs(dev->pci_conf, 0x48, 0x4f, 1);
+ break;
+ case 0x50: case 0x51: /* Exclusive Area 0 Setup */
+ dev->pci_conf[addr] = val;
+ break;
+ case 0x52: case 0x53: /* Exclusive Area 1 Setup */
+ dev->pci_conf[addr] = val;
+ break;
+ case 0x54: /* Exclusive Area 2 Setup */
+ dev->pci_conf[addr] = val;
+ break;
+ case 0x55: /* Exclusive Area 3 Setup */
+ dev->pci_conf[addr] = val & 0xf0;
+ break;
+ case 0x56: /* PCI / Keyboard Configure */
+ dev->pci_conf[addr] = val;
if (valxor & 0x02) {
port_92_remove(dev->port_92);
if (val & 0x02)
port_92_add(dev->port_92);
}
break;
+ case 0x57: /* Output Pin Configuration */
+ dev->pci_conf[addr] = val;
+ break;
+ case 0x58: /* Build-in IDE Controller / VESA Bus Configuration */
+ dev->pci_conf[addr] = val & 0xd7;
+ if (valxor & 0xc0)
+ sis_85c496_ide_handler(dev);
+ break;
+ case 0x59: /* Build-in IDE Controller / VESA Bus Configuration */
+ dev->pci_conf[addr] = val;
+ if (valxor & 0x03)
+ sis_85c496_ide_handler(dev);
+ break;
+ case 0x5a: /* SMRAM Remapping Configuration */
+ dev->pci_conf[addr] = val & 0xbe;
+ if (valxor & 0x3e) {
+ unmask_a20_in_smm = !!(val & 0x20);
- case 0x59:
- if (valxor & 0x02) {
- if (val & 0x02) {
- ide_set_base(0, 0x0170);
- ide_set_side(0, 0x0376);
- ide_set_base(1, 0x01f0);
- ide_set_side(1, 0x03f6);
- } else {
- ide_set_base(0, 0x01f0);
- ide_set_side(0, 0x03f6);
- ide_set_base(1, 0x0170);
- ide_set_side(1, 0x0376);
+ if (smram[0].size != 0x00000000) {
+ sis_85c496_smram_map(0, smram[0].host_base, smram[0].size, 0);
+ sis_85c496_smram_map(1, smram[0].host_base, smram[0].size, 0);
+
+ memset(&smram[0], 0x00, sizeof(smram_t));
+ mem_mapping_disable(&ram_smram_mapping[0]);
+ }
+
+ if (val & 0x06) {
+ smram[0].size = 0x00010000;
+ switch ((val >> 3) & 0x03) {
+ case 0x00:
+ smram[0].host_base = 0x00060000;
+ smram[0].ram_base = 0x000a0000;
+ break;
+ case 0x01:
+ smram[0].host_base = 0x00060000;
+ smram[0].ram_base = 0x000b0000;
+ break;
+ case 0x02:
+ smram[0].host_base = 0x000e0000;
+ smram[0].ram_base = 0x000a0000;
+ break;
+ case 0x03:
+ smram[0].host_base = 0x000e0000;
+ smram[0].ram_base = 0x000b0000;
+ break;
+ }
+
+ mem_mapping_set_addr(&ram_smram_mapping[0], smram[0].host_base, 0x00010000);
+ mem_mapping_set_exec(&ram_smram_mapping[0], ram + smram[0].ram_base);
+
+ sis_85c496_smram_map(0, smram[0].host_base, smram[0].size, ((val & 0x06) == 0x06));
+ sis_85c496_smram_map(1, smram[0].host_base, smram[0].size, (val & 0x02));
}
}
break;
-
- case 0x58:
- if (valxor & 0x80) {
- if (dev->pci_conf[0x59] & 0x02) {
- ide_sec_disable();
- if (val & 0x80)
- ide_sec_enable();
- } else {
- ide_pri_disable();
- if (val & 0x80)
- ide_pri_enable();
- }
- }
- if (valxor & 0x40) {
- if (dev->pci_conf[0x59] & 0x02) {
- ide_pri_disable();
- if (val & 0x40)
- ide_pri_enable();
- } else {
- ide_sec_disable();
- if (val & 0x40)
- ide_sec_enable();
- }
- }
+ case 0x5b: /* Programmable I/O Traps Configure */
+ case 0x5c: case 0x5d: /* Programmable I/O Trap 0 Base */
+ case 0x5e: case 0x5f: /* Programmable I/O Trap 0 Base */
+ case 0x60: case 0x61: /* IDE Controller Channel 0 Configuration */
+ case 0x62: case 0x63: /* IDE Controller Channel 1 Configuration */
+ case 0x64: case 0x65: /* Exclusive Area 3 Setup */
+ case 0x66: /* EDO DRAM Configuration */
+ case 0x68: case 0x69: /* Asymmetry DRAM Configuration */
+ dev->pci_conf[addr] = val;
break;
-
- case 0x5a:
- if (valxor & 0x04) {
- if (val & 0x04)
- mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
- else
- mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
- }
- break;
-
- case 0x67:
+ case 0x67: /* Miscellaneous Control */
+ dev->pci_conf[addr] = val & 0xf9;
if (valxor & 0x60)
port_92_set_features(dev->port_92, !!(val & 0x20), !!(val & 0x40));
break;
- case 0x82:
- sis_85c497_write(0x22, val, priv);
+ /* 86C497 Specific Registers (80h ~ FFh) */
+ case 0x80: /* PMU Configuration */
+ case 0x85: /* STPCLK# Event Control */
+ case 0x86: case 0x87: /* STPCLK# Deassertion IRQ Selection */
+ case 0x89: /* Fast Timer Count */
+ case 0x8a: /* Generic Timer Count */
+ case 0x8b: /* Slow Timer Count */
+ case 0x8e: /* Clock Throttling On Timer Count */
+ case 0x8f: /* Clock Throttling Off Timer Count */
+ case 0x90: /* Clock Throttling On Timer Reload Condition */
+ case 0x92: /* Fast Timer Reload Condition */
+ case 0x94: /* Generic Timer Reload Condition */
+ case 0x96: /* Slow Timer Reload Condition */
+ case 0x98: case 0x99: /* Fast Timer Reload IRQ Selection */
+ case 0x9a: case 0x9b: /* Generic Timer Reload IRQ Selection */
+ case 0x9c: case 0x9d: /* Slow Timer Reload IRQ Selection */
+ case 0xa2: /* SMI Request Status Selection */
+ case 0xa4: case 0xa5: /* SMI Request IRQ Selection */
+ case 0xa6: case 0xa7: /* Clock Throttlign On Timer Reload IRQ Selection */
+ case 0xa8: /* GPIO Control */
+ case 0xaa: /* GPIO DeBounce Count */
+ case 0xd2: /* Exclusive Area 2 Base Address */
+ dev->pci_conf[addr] = val;
break;
-
- case 0xc0:
- if (val & 0x80)
- pci_set_irq_routing(PCI_INTA, val & 0xf);
- else
- pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED);
+ case 0x81: /* PMU CPU Type Configuration */
+ dev->pci_conf[addr] = val & 0x9f;
break;
- case 0xc1:
- if (val & 0x80)
- pci_set_irq_routing(PCI_INTB, val & 0xf);
- else
- pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED);
+ case 0x88: /* Timer Control */
+ dev->pci_conf[addr] = val & 0x3f;
break;
- case 0xc2:
- if (val & 0x80)
- pci_set_irq_routing(PCI_INTC, val & 0xf);
- else
- pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED);
+ case 0x8d: /* RMSMIBLK Timer Count */
+ dev->pci_conf[addr] = val;
+ dev->rmsmiblk_count = val;
+ timer_stop(&dev->rmsmiblk_timer);
+ if (val >= 0x02)
+ timer_on_auto(&dev->rmsmiblk_timer, 35.0);
break;
- case 0xc3:
+ case 0x91: /* Clock Throttling On Timer Reload Condition */
+ case 0x93: /* Fast Timer Reload Condition */
+ case 0x95: /* Generic Timer Reload Condition */
+ dev->pci_conf[addr] = val & 0x03;
+ break;
+ case 0x97: /* Slow Timer Reload Condition */
+ dev->pci_conf[addr] = val & 0xc3;
+ break;
+ case 0x9e: /* Soft-SMI Generation / RMSMIBLK Trigger */
+ if (!smi_block && (val & 0x01) && (dev->pci_conf[0x80] & 0x80) && (dev->pci_conf[0xa2] & 0x10)) {
+ if (dev->pci_conf[0x80] & 0x10)
+ picint(1 << smm_irq[dev->pci_conf[0x81] & 0x03]);
+ else
+ smi_line = 1;
+ smi_block = 1;
+ dev->pci_conf[0xa0] |= 0x10;
+ }
+ if (val & 0x02) {
+ timer_stop(&dev->rmsmiblk_timer);
+ if (dev->rmsmiblk_count >= 0x02)
+ timer_on_auto(&dev->rmsmiblk_timer, 35.0);
+ }
+ break;
+ case 0xa0: case 0xa1: /* SMI Request Status */
+ dev->pci_conf[addr] &= ~val;
+ break;
+ case 0xa3: /* SMI Request Status Selection */
+ dev->pci_conf[addr] = val & 0x7f;
+ break;
+ case 0xa9: /* GPIO SMI Request Status */
+ dev->pci_conf[addr] = ~(val & 0x03);
+ break;
+ case 0xc0: /* PCI INTA# -to-IRQ Link */
+ case 0xc1: /* PCI INTB# -to-IRQ Link */
+ case 0xc2: /* PCI INTC# -to-IRQ Link */
+ case 0xc3: /* PCI INTD# -to-IRQ Link */
+ dev->pci_conf[addr] = val & 0x8f;
if (val & 0x80)
- pci_set_irq_routing(PCI_INTD, val & 0xf);
+ pci_set_irq_routing(PCI_INTA + (addr & 0x03), val & 0xf);
else
- pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED);
+ pci_set_irq_routing(PCI_INTA + (addr & 0x03), PCI_IRQ_DISABLED);
+ break;
+ case 0xc6: /* 85C497 Post / INIT Configuration */
+ dev->pci_conf[addr] = val & 0x0f;
+ break;
+ case 0xc8: case 0xc9: case 0xca: case 0xcb: /* Mail Box */
+ dev->pci_conf[addr] = val;
+ break;
+ case 0xd0: /* ISA BIOS Configuration */
+ dev->pci_conf[addr] = val & 0xfb;
+ break;
+ case 0xd1: /* ISA Address Decoder */
+ if (dev->pci_conf[0xd0] & 0x01)
+ dev->pci_conf[addr] = val;
+ break;
+ case 0xd3: /* Exclusive Area 2 Base Address */
+ dev->pci_conf[addr] = val & 0xf0;
+ break;
+ case 0xd4: /* Miscellaneous Configuration */
+ dev->pci_conf[addr] = val & 0x6e;
+ nvr_bank_set(0, !!(val & 0x40), dev->nvr);
break;
}
}
static uint8_t
-sis_85c496_read(int func, int addr, void *priv)
+sis_85c49x_pci_read(int func, int addr, void *priv)
{
sis_85c496_t *dev = (sis_85c496_t *) priv;
uint8_t ret = dev->pci_conf[addr];
switch (addr) {
case 0x82: /*Port 22h Mirror*/
- ret = inb(0x22);
+ ret = dev->cur_reg;
break;
- case 0x70: /*Port 70h Mirror*/
+ case 0x83: /*Port 70h Mirror*/
ret = inb(0x70);
break;
}
+ sis_85c496_log("[%04X:%08X] PCI Read %02X from %02X:%02X\n", CS, cpu_state.pc, ret, func, addr);
+
return ret;
}
static void
-sis_85c497_reset(sis_85c496_t *dev)
+sis_85c496_rmsmiblk_count(void *priv)
+{
+ sis_85c496_t *dev = (sis_85c496_t *) priv;
+
+ dev->rmsmiblk_count--;
+
+ if (dev->rmsmiblk_count == 1) {
+ smi_block = 0;
+ dev->rmsmiblk_count = 0;
+ timer_stop(&dev->rmsmiblk_timer);
+ } else
+ timer_on_auto(&dev->rmsmiblk_timer, 35.0);
+}
+
+
+static void
+sis_85c497_isa_reset(sis_85c496_t *dev)
{
memset(dev->regs, 0, sizeof(dev->regs));
dev->regs[0x01] = 0xc0;
dev->regs[0x71] = 0x01;
dev->regs[0x72] = 0xff;
+ dev->regs[0x76] = 0xff;
+
+ dma_set_mask(0x00ffffff);
io_removehandler(0x0022, 0x0002,
- sis_85c497_read, NULL, NULL, sis_85c497_write, NULL, NULL, dev);
+ sis_85c497_isa_read, NULL, NULL, sis_85c497_isa_write, NULL, NULL, dev);
+ io_removehandler(0x0033, 0x0001,
+ sis_85c497_isa_read, NULL, NULL, sis_85c497_isa_write, NULL, NULL, dev);
io_sethandler(0x0022, 0x0002,
- sis_85c497_read, NULL, NULL, sis_85c497_write, NULL, NULL, dev);
+ sis_85c497_isa_read, NULL, NULL, sis_85c497_isa_write, NULL, NULL, dev);
+ io_sethandler(0x0033, 0x0001,
+ sis_85c497_isa_read, NULL, NULL, sis_85c497_isa_write, NULL, NULL, dev);
}
@@ -271,8 +519,43 @@ static void
sis_85c496_reset(void *priv)
{
sis_85c496_t *dev = (sis_85c496_t *) priv;
+ int i;
- sis_85c497_reset(dev);
+ sis_85c49x_pci_write(0, 0x44, 0x00, dev);
+ sis_85c49x_pci_write(0, 0x45, 0x00, dev);
+ sis_85c49x_pci_write(0, 0x58, 0x00, dev);
+ sis_85c49x_pci_write(0, 0x59, 0x00, dev);
+ sis_85c49x_pci_write(0, 0x5a, 0x00, dev);
+
+ for (i = 0; i < 8; i++)
+ sis_85c49x_pci_write(0, 0x48 + i, 0x00, dev);
+
+ sis_85c49x_pci_write(0, 0x80, 0x00, dev);
+ sis_85c49x_pci_write(0, 0x81, 0x00, dev);
+ sis_85c49x_pci_write(0, 0x9e, 0x00, dev);
+ sis_85c49x_pci_write(0, 0x8d, 0x00, dev);
+ sis_85c49x_pci_write(0, 0xa0, 0xff, dev);
+ sis_85c49x_pci_write(0, 0xa1, 0xff, dev);
+ sis_85c49x_pci_write(0, 0xc0, 0x00, dev);
+ sis_85c49x_pci_write(0, 0xc1, 0x00, dev);
+ sis_85c49x_pci_write(0, 0xc2, 0x00, dev);
+ sis_85c49x_pci_write(0, 0xc3, 0x00, dev);
+ sis_85c49x_pci_write(0, 0xc8, 0x00, dev);
+ sis_85c49x_pci_write(0, 0xc9, 0x00, dev);
+ sis_85c49x_pci_write(0, 0xca, 0x00, dev);
+ sis_85c49x_pci_write(0, 0xcb, 0x00, dev);
+
+ sis_85c49x_pci_write(0, 0xd0, 0x79, dev);
+ sis_85c49x_pci_write(0, 0xd1, 0xff, dev);
+ sis_85c49x_pci_write(0, 0xd0, 0x78, dev);
+ sis_85c49x_pci_write(0, 0xd4, 0x00, dev);
+
+ ide_pri_disable();
+ ide_sec_disable();
+
+ nvr_bank_set(0, 0, dev->nvr);
+
+ sis_85c497_isa_reset(dev);
}
@@ -289,33 +572,29 @@ static void
*sis_85c496_init(const device_t *info)
{
sis_85c496_t *dev = malloc(sizeof(sis_85c496_t));
- memset(dev, 0, sizeof(sis_85c496_t));
-
- dev->pci_conf[0x00] = 0x39; /*SiS*/
- dev->pci_conf[0x01] = 0x10;
- dev->pci_conf[0x02] = 0x96; /*496/497*/
- dev->pci_conf[0x03] = 0x04;
-
- dev->pci_conf[0x04] = 7;
- dev->pci_conf[0x05] = 0;
+ memset(dev, 0x00, sizeof(sis_85c496_t));
+ /* PCI Configuration Header Registers (00h ~ 3Fh) */
+ dev->pci_conf[0x00] = 0x39; /* SiS */
+ dev->pci_conf[0x01] = 0x10;
+ dev->pci_conf[0x02] = 0x96; /* 496/497 */
+ dev->pci_conf[0x03] = 0x04;
+ dev->pci_conf[0x04] = 0x07;
dev->pci_conf[0x06] = 0x80;
dev->pci_conf[0x07] = 0x02;
-
- dev->pci_conf[0x08] = 2; /*Device revision*/
-
- dev->pci_conf[0x09] = 0x00; /*Device class (PCI bridge)*/
- dev->pci_conf[0x0a] = 0x00;
+ dev->pci_conf[0x08] = 0x02; /* Device revision */
+ dev->pci_conf[0x09] = 0x00; /* Device class (PCI bridge) */
dev->pci_conf[0x0b] = 0x06;
- dev->pci_conf[0x0e] = 0x00; /*Single function device*/
+ /* 86C496 Specific Registers (40h ~ 7Fh) */
+ /* 86C497 Specific Registers (80h ~ FFh) */
dev->pci_conf[0xd0] = 0x78; /* ROM at E0000-FFFFF, Flash enable. */
dev->pci_conf[0xd1] = 0xff;
- pci_add_card(PCI_ADD_NORTHBRIDGE, sis_85c496_read, sis_85c496_write, dev);
+ pci_add_card(PCI_ADD_NORTHBRIDGE, sis_85c49x_pci_read, sis_85c49x_pci_write, dev);
- sis_85c497_reset(dev);
+ sis_85c497_isa_reset(dev);
dev->port_92 = device_add(&port_92_device);
port_92_set_period(dev->port_92, 2ULL * TIMER_USEC);
@@ -323,6 +602,18 @@ static void
sis_85c496_recalcmapping(dev);
+ ide_pri_disable();
+ ide_sec_disable();
+
+ if (info->local)
+ dev->nvr = device_add(&ls486e_nvr_device);
+ else
+ dev->nvr = device_add(&at_nvr_device);
+
+ dma_high_page_init();
+
+ timer_add(&dev->rmsmiblk_timer, sis_85c496_rmsmiblk_count, dev, 0);
+
return dev;
}
@@ -340,3 +631,18 @@ const device_t sis_85c496_device =
NULL,
NULL
};
+
+
+const device_t sis_85c496_ls486e_device =
+{
+ "SiS 85c496/85c497 (Lucky Star LS-486E)",
+ DEVICE_PCI,
+ 1,
+ sis_85c496_init,
+ sis_85c496_close,
+ sis_85c496_reset,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
diff --git a/src/chipset/via_apollo.c b/src/chipset/via_apollo.c
index a3200669a..929759fe0 100644
--- a/src/chipset/via_apollo.c
+++ b/src/chipset/via_apollo.c
@@ -32,6 +32,7 @@
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/chipset.h>
+#include <86box/spd.h>
typedef struct via_apollo_t
@@ -226,6 +227,13 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv)
dev->pci_conf[0][0x53] = (dev->pci_conf[0][0x53] & ~0xf0) | (val & 0xf0);
break;
+ case 0x56: case 0x57: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: /* DRAM Row Ending Address */
+ if (dev->id >= 0x0691)
+ spd_write_drbs(dev->pci_conf[0], 0x5a, 0x56, 8);
+ else if (addr >= 0x5a)
+ spd_write_drbs(dev->pci_conf[0], 0x5a, 0x5f, 8);
+ break;
+
case 0x58:
if (dev->id == 0x0597)
dev->pci_conf[0][0x58] = (dev->pci_conf[0][0x58] & ~0xee) | (val & 0xee);
diff --git a/src/chipset/via_vpx.c b/src/chipset/via_vpx.c
index c9798e319..87f7e94e6 100644
--- a/src/chipset/via_vpx.c
+++ b/src/chipset/via_vpx.c
@@ -35,6 +35,7 @@
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/chipset.h>
+#include <86box/spd.h>
typedef struct via_vpx_t
{
@@ -94,6 +95,10 @@ via_vpx_t *dev = (via_vpx_t *) priv;
dev->pci_conf[0x07] &= ~(val & 0xb0);
break;
+ case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: // Bank Ending
+ spd_write_drbs(dev->pci_conf, 0x5a, 0x5f, 4);
+ break;
+
case 0x61: // Shadow RAM control 1
if ((dev->pci_conf[0x61] ^ val) & 0x03)
vpx_map(0xc0000, 0x04000, val & 0x03);
@@ -201,6 +206,7 @@ via_vpx_init(const device_t *info)
dev->pci_conf[0x5e] = 1; // Bank 4 Ending
dev->pci_conf[0x5f] = 1; // Bank 5 Ending
+ dev->pci_conf[0x60] = 0x3f; // DRAM type
dev->pci_conf[0x64] = 0xab; // DRAM reference timing
return dev;
diff --git a/src/chipset/vl82c480.c b/src/chipset/vl82c480.c
index d20eb4ba6..a55cf846c 100644
--- a/src/chipset/vl82c480.c
+++ b/src/chipset/vl82c480.c
@@ -8,9 +8,9 @@
*
* Implementation of the VLSI VL82c480 chipset.
*
- * Authors: Sarah Walker,
+ * Authors: Miran Grca,
*
- * Copyright 2020 Sarah Walker.
+ * Copyright 2020 Miran Grca.
*/
#include
#include
@@ -28,153 +28,156 @@
#include <86box/chipset.h>
typedef struct {
- int cfg_index;
- uint8_t cfg_regs[256];
+ uint8_t idx,
+ regs[256];
} vl82c480_t;
-#define CFG_ID 0x00
-#define CFG_AAXS 0x0d
-#define CFG_BAXS 0x0e
-#define CFG_CAXS 0x0f
-#define CFG_DAXS 0x10
-#define CFG_EAXS 0x11
-#define CFG_FAXS 0x12
-#define ID_VL82C480 0x90
+static int
+vl82c480_shflags(uint8_t access)
+{
+ int ret = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
+
+ switch (access) {
+ case 0x00:
+ default:
+ ret = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
+ break;
+ case 0x01:
+ ret = MEM_READ_EXTANY | MEM_WRITE_INTERNAL;
+ break;
+ case 0x02:
+ ret = MEM_READ_INTERNAL | MEM_WRITE_EXTANY;
+ break;
+ case 0x03:
+ ret = MEM_READ_INTERNAL | MEM_WRITE_INTERNAL;
+ break;
+ }
+
+ return ret;
+}
+
static void
-shadow_control(uint32_t addr, uint32_t size, int state)
+vl82c480_recalc(vl82c480_t *dev)
{
-/* pclog("shadow_control: addr=%08x size=%04x state=%i\n", addr, size, state); */
- switch (state) {
- case 0:
- mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
- break;
- case 1:
- mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
- break;
- case 2:
- mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
- break;
- case 3:
- mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
- break;
+ int i, j;
+ uint32_t base;
+ uint8_t access;
+
+ shadowbios = 0;
+ shadowbios_write = 0;
+
+ for (i = 0; i < 8; i += 2) {
+ for (j = 0; j < 6; j++) {
+ base = 0x000a0000 + (i << 13) + (j << 16);
+ access = dev->regs[0x0d + j] & (3 << i);
+ mem_set_mem_state(base, 0x4000, vl82c480_shflags(access));
+ shadowbios |= ((base >= 0xe0000) && (access & 0x02));
+ shadowbios_write |= ((base >= 0xe0000) && (access & 0x01));
}
- flushmmucache_nopc();
+ }
+
+ flushmmucache();
}
+
static void
vl82c480_write(uint16_t addr, uint8_t val, void *p)
{
- vl82c480_t *dev = (vl82c480_t *)p;
-
- switch (addr) {
- case 0xec:
- dev->cfg_index = val;
- break;
+ vl82c480_t *dev = (vl82c480_t *)p;
- case 0xed:
- if (dev->cfg_index >= 0x01 && dev->cfg_index <= 0x24) {
- dev->cfg_regs[dev->cfg_index] = val;
- switch (dev->cfg_index) {
- case CFG_AAXS:
- shadow_control(0xa0000, 0x4000, val & 3);
- shadow_control(0xa4000, 0x4000, (val >> 2) & 3);
- shadow_control(0xa8000, 0x4000, (val >> 4) & 3);
- shadow_control(0xac000, 0x4000, (val >> 6) & 3);
+ switch (addr) {
+ case 0xec:
+ dev->idx = val;
+ break;
+
+ case 0xed:
+ if (dev->idx >= 0x01 && dev->idx <= 0x24) {
+ switch (dev->idx) {
+ default:
+ dev->regs[dev->idx] = val;
break;
- case CFG_BAXS:
- shadow_control(0xb0000, 0x4000, val & 3);
- shadow_control(0xb4000, 0x4000, (val >> 2) & 3);
- shadow_control(0xb8000, 0x4000, (val >> 4) & 3);
- shadow_control(0xbc000, 0x4000, (val >> 6) & 3);
+ case 0x05:
+ dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x10) | (val & 0xef);
break;
- case CFG_CAXS:
- shadow_control(0xc0000, 0x4000, val & 3);
- shadow_control(0xc4000, 0x4000, (val >> 2) & 3);
- shadow_control(0xc8000, 0x4000, (val >> 4) & 3);
- shadow_control(0xcc000, 0x4000, (val >> 6) & 3);
- break;
- case CFG_DAXS:
- shadow_control(0xd0000, 0x4000, val & 3);
- shadow_control(0xd4000, 0x4000, (val >> 2) & 3);
- shadow_control(0xd8000, 0x4000, (val >> 4) & 3);
- shadow_control(0xdc000, 0x4000, (val >> 6) & 3);
- break;
- case CFG_EAXS:
- shadow_control(0xe0000, 0x4000, val & 3);
- shadow_control(0xe4000, 0x4000, (val >> 2) & 3);
- shadow_control(0xe8000, 0x4000, (val >> 4) & 3);
- shadow_control(0xec000, 0x4000, (val >> 6) & 3);
- break;
- case CFG_FAXS:
- shadow_control(0xf0000, 0x4000, val & 3);
- shadow_control(0xf4000, 0x4000, (val >> 2) & 3);
- shadow_control(0xf8000, 0x4000, (val >> 4) & 3);
- shadow_control(0xfc000, 0x4000, (val >> 6) & 3);
+ case 0x0d: case 0x0e: case 0x0f: case 0x10:
+ case 0x11: case 0x12:
+ dev->regs[dev->idx] = val;
+ vl82c480_recalc(dev);
break;
}
}
break;
- case 0xee:
- if (mem_a20_alt)
- outb(0x92, inb(0x92) & ~2);
- break;
- }
+ case 0xee:
+ if (mem_a20_alt)
+ outb(0x92, inb(0x92) & ~2);
+ break;
+ }
}
+
static uint8_t
vl82c480_read(uint16_t addr, void *p)
{
- vl82c480_t *dev = (vl82c480_t *)p;
- uint8_t ret = 0xff;
+ vl82c480_t *dev = (vl82c480_t *)p;
+ uint8_t ret = 0xff;
- switch (addr) {
- case 0xec:
- ret = dev->cfg_index;
- break;
-
- case 0xed:
- ret = dev->cfg_regs[dev->cfg_index];
- break;
-
- case 0xee:
- if (!mem_a20_alt)
- outb(0x92, inb(0x92) | 2);
- break;
-
- case 0xef:
- softresetx86();
- cpu_set_edx();
- break;
- }
+ switch (addr) {
+ case 0xec:
+ ret = dev->idx;
+ break;
- return ret;
+ case 0xed:
+ ret = dev->regs[dev->idx];
+ break;
+
+ case 0xee:
+ if (!mem_a20_alt)
+ outb(0x92, inb(0x92) | 2);
+ break;
+
+ case 0xef:
+ softresetx86();
+ cpu_set_edx();
+ break;
+ }
+
+ return ret;
}
+
static void
vl82c480_close(void *p)
{
- vl82c480_t *dev = (vl82c480_t *)p;
+ vl82c480_t *dev = (vl82c480_t *)p;
- free(dev);
+ free(dev);
}
static void *
vl82c480_init(const device_t *info)
{
- vl82c480_t *dev = (vl82c480_t *)malloc(sizeof(vl82c480_t));
- memset(dev, 0, sizeof(vl82c480_t));
-
- dev->cfg_regs[CFG_ID] = ID_VL82C480;
-
- io_sethandler(0x00ec, 0x0004, vl82c480_read, NULL, NULL, vl82c480_write, NULL, NULL, dev);
-
- return dev;
+ vl82c480_t *dev = (vl82c480_t *)malloc(sizeof(vl82c480_t));
+ memset(dev, 0, sizeof(vl82c480_t));
+
+ dev->regs[0x00] = 0x90;
+ dev->regs[0x01] = 0xff;
+ dev->regs[0x02] = 0x8a;
+ dev->regs[0x03] = 0x88;
+ dev->regs[0x06] = 0x1b;
+ dev->regs[0x08] = 0x38;
+
+ io_sethandler(0x00ec, 0x0004, vl82c480_read, NULL, NULL, vl82c480_write, NULL, NULL, dev);
+
+ device_add(&port_92_device);
+
+ return dev;
}
+
const device_t vl82c480_device = {
"VLSI VL82c480",
0,
diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c
index 1bda39a95..3bfc3ccbc 100644
--- a/src/cpu/386_common.c
+++ b/src/cpu/386_common.c
@@ -61,7 +61,8 @@ extern int optype;
extern uint32_t pccache;
-int in_sys = 0;
+int in_sys = 0, unmask_a20_in_smm = 0;
+uint32_t old_rammask = 0xffffffff;
smram_t temp_smram[2];
@@ -1100,6 +1101,13 @@ enter_smm(int in_hlt)
smm_in_hlt = in_hlt;
+ if (unmask_a20_in_smm) {
+ old_rammask = rammask;
+ rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF;
+
+ flushmmucache();
+ }
+
CPU_BLOCK_END();
}
@@ -1151,6 +1159,12 @@ leave_smm(void)
x386_common_log("Reading %08X from memory at %08X to array element %i\n", saved_state[n], smram_state, n);
}
+ if (unmask_a20_in_smm) {
+ rammask = old_rammask;
+
+ flushmmucache();
+ }
+
x386_common_log("New SMBASE: %08X (%08X)\n", saved_state[SMRAM_FIELD_P5_SMBASE_OFFSET], saved_state[66]);
if (is_pentium) /* Intel P5 (Pentium) */
smram_restore_state_p5(saved_state);
diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h
index 674186337..439c70acb 100644
--- a/src/cpu/386_ops.h
+++ b/src/cpu/386_ops.h
@@ -527,6 +527,96 @@ const OpFn OP_TABLE(486_0f)[1024] =
/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32,
/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32,
+/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
+/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+};
+const OpFn OP_TABLE(ibm486_0f)[1024] =
+{
+ /*16-bit data, 16-bit addr*/
+/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
+/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, ILLEGAL, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
+/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
+/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16,
+/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL,
+
+/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
+/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+ /*32-bit data, 16-bit addr*/
+/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
+/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, ILLEGAL, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
+/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
+/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16,
+/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16,
+
+/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
+/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+ /*16-bit data, 32-bit addr*/
+/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
+/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, ILLEGAL, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
+/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
+/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32,
+/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL,
+
+/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
+/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+ /*32-bit data, 32-bit addr*/
+/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
+/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, ILLEGAL, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
+/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
+/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32,
+/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32,
+
/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
diff --git a/src/cpu/808x.c b/src/cpu/808x.c
index a712e6830..2cde6d9c5 100644
--- a/src/cpu/808x.c
+++ b/src/cpu/808x.c
@@ -977,6 +977,7 @@ reset_common(int hard)
in_smm = smi_latched = 0;
smi_line = smm_in_hlt = 0;
+ smi_block = 0;
if (hard) {
smbase = 0x00030000;
diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c
index c958158fc..7cdd36ed4 100644
--- a/src/cpu/cpu.c
+++ b/src/cpu/cpu.c
@@ -137,6 +137,7 @@ const OpFn *x86_opcodes_REPNE;
const OpFn *x86_opcodes_3DNOW;
int in_smm = 0, smi_line = 0, smi_latched = 0, smm_in_hlt = 0;
+int smi_block = 0;
uint32_t smbase = 0x30000;
CPU *cpu_s;
@@ -189,6 +190,10 @@ uint64_t mtrr_fix16k_a000_msr = 0;
uint64_t mtrr_fix4k_msr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint64_t mtrr_deftype_msr = 0;
+uint64_t ibm_por_msr = 0; /*Processor Operation Register*/
+uint64_t ibm_crcr_msr = 0; /*Cache Region Control Register*/
+uint64_t ibm_por2_msr = 0; /*Processor Operation Register*/
+
uint16_t cs_msr = 0;
uint32_t esp_msr = 0;
uint32_t eip_msr = 0;
@@ -358,13 +363,14 @@ cpu_set(void)
cpu_s = &machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective];
cpu_alt_reset = 0;
+ unmask_a20_in_smm = 0;
CPUID = cpu_s->cpuid_model;
is8086 = (cpu_s->cpu_type > CPU_8088);
is286 = (cpu_s->cpu_type >= CPU_286);
is386 = (cpu_s->cpu_type >= CPU_386SX);
- israpidcad = (cpu_s->cpu_type == CPU_RAPIDCAD);
- isibm486 = (cpu_s->cpu_type == CPU_IBM486SLC) || (cpu_s->cpu_type == CPU_IBM486BL);
+ israpidcad = (cpu_s->cpu_type == CPU_RAPIDCAD);
+ isibm486 = (cpu_s->cpu_type == CPU_IBM386SLC) || (cpu_s->cpu_type == CPU_IBM486SLC) || (cpu_s->cpu_type == CPU_IBM486BL);
is486 = (cpu_s->cpu_type >= CPU_i486SX) || (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_RAPIDCAD);
is486sx = (cpu_s->cpu_type >= CPU_i486SX) && (cpu_s->cpu_type < CPU_i486SX2);
is486sx2 = (cpu_s->cpu_type >= CPU_i486SX2) && (cpu_s->cpu_type < CPU_i486DX);
@@ -616,12 +622,13 @@ cpu_set(void)
break;
case CPU_IBM486SLC:
+ case CPU_IBM386SLC:
#ifdef USE_DYNAREC
- x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f);
+ x86_setopcodes(ops_386, ops_ibm486_0f, dynarec_ops_386, dynarec_ops_ibm486_0f);
#else
- x86_setopcodes(ops_386, ops_486_0f);
+ x86_setopcodes(ops_386, ops_ibm486_0f);
#endif
- case CPU_IBM386SLC:
+ cpu_features = CPU_FEATURE_MSR;
case CPU_386SX:
timing_rr = 2; /*register dest - register src*/
timing_rm = 6; /*register dest - memory src*/
@@ -655,10 +662,11 @@ cpu_set(void)
case CPU_IBM486BL:
#ifdef USE_DYNAREC
- x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f);
+ x86_setopcodes(ops_386, ops_ibm486_0f, dynarec_ops_386, dynarec_ops_ibm486_0f);
#else
- x86_setopcodes(ops_386, ops_486_0f);
+ x86_setopcodes(ops_386, ops_ibm486_0f);
#endif
+ cpu_features = CPU_FEATURE_MSR;
case CPU_386DX:
if (fpu_type == FPU_287) /*In case we get Deskpro 386 emulation*/
{
@@ -722,7 +730,7 @@ cpu_set(void)
timing_jmp_pm = 27;
timing_jmp_pm_gate = 45;
break;
-
+
case CPU_RAPIDCAD:
#ifdef USE_DYNAREC
@@ -2494,6 +2502,36 @@ void cpu_RDMSR()
{
switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type)
{
+ case CPU_IBM386SLC:
+ EAX = EDX = 0;
+ switch (ECX)
+ {
+ case 0x1000:
+ EAX = ibm_por_msr & 0xfeff;
+
+ case 0x1001:
+ EAX = ibm_crcr_msr & 0xffffffffff;
+ }
+ break;
+
+ case CPU_IBM486SLC:
+ case CPU_IBM486BL:
+ EAX = EDX = 0;
+ switch (ECX)
+ {
+ case 0x1000:
+ EAX = ibm_por_msr & 0xffeff;
+
+ case 0x1001:
+ EAX = ibm_crcr_msr & 0xffffffffff;
+
+ if (cpu_s->multi) {
+ case 0x1002:
+ EAX = ibm_por2_msr & 0x3f000000;
+ }
+ }
+ break;
+
case CPU_WINCHIP:
case CPU_WINCHIP2:
EAX = EDX = 0;
@@ -3044,6 +3082,44 @@ void cpu_WRMSR()
cpu_log("WRMSR %08X %08X%08X\n", ECX, EDX, EAX);
switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type)
{
+ case CPU_IBM386SLC:
+ switch (ECX)
+ {
+ case 0x1000:
+ ibm_por_msr = EAX & 0xfeff;
+ if (EAX & (1 << 7))
+ cpu_cache_int_enabled = 1;
+ else
+ cpu_cache_int_enabled = 0;
+ break;
+ case 0x1001:
+ ibm_crcr_msr = EAX & 0xffffffffff;
+ break;
+ }
+ break;
+
+ case CPU_IBM486BL:
+ case CPU_IBM486SLC:
+ switch (ECX)
+ {
+ case 0x1000:
+ ibm_por_msr = EAX & 0xffeff;
+ if (EAX & (1 << 7))
+ cpu_cache_int_enabled = 1;
+ else
+ cpu_cache_int_enabled = 0;
+ break;
+ case 0x1001:
+ ibm_crcr_msr = EAX & 0xffffffffff;
+ break;
+ if (cpu_s->multi) {
+ case 0x1002:
+ ibm_por2_msr = EAX & 0x3f000000;
+ }
+ break;
+ }
+ break;
+
case CPU_WINCHIP:
case CPU_WINCHIP2:
switch (ECX)
diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h
index 567b40fc0..cf99c0ae1 100644
--- a/src/cpu/cpu.h
+++ b/src/cpu/cpu.h
@@ -412,6 +412,7 @@ extern int hasfpu;
extern uint32_t cpu_features;
extern int in_smm, smi_line, smi_latched, smm_in_hlt;
+extern int smi_block;
extern uint32_t smbase;
#ifdef USE_NEW_DYNAREC
@@ -497,7 +498,8 @@ extern int timing_retf_rm, timing_retf_pm, timing_retf_pm_outer;
extern int timing_jmp_rm, timing_jmp_pm, timing_jmp_pm_gate;
extern int timing_misaligned;
-extern int in_sys;
+extern int in_sys, unmask_a20_in_smm;
+extern uint32_t old_rammask;
extern uint16_t cpu_fast_off_count, cpu_fast_off_val;
extern uint32_t cpu_fast_off_flags;
diff --git a/src/cpu/x86_ops.h b/src/cpu/x86_ops.h
index f66e2392d..6ee001b0b 100644
--- a/src/cpu/x86_ops.h
+++ b/src/cpu/x86_ops.h
@@ -79,6 +79,7 @@ extern const OpFn dynarec_ops_386[1024];
extern const OpFn dynarec_ops_386_0f[1024];
extern const OpFn dynarec_ops_486_0f[1024];
+extern const OpFn dynarec_ops_ibm486_0f[1024];
extern const OpFn dynarec_ops_winchip_0f[1024];
extern const OpFn dynarec_ops_winchip2_0f[1024];
@@ -174,6 +175,7 @@ extern const OpFn ops_386[1024];
extern const OpFn ops_386_0f[1024];
extern const OpFn ops_486_0f[1024];
+extern const OpFn ops_ibm486_0f[1024];
extern const OpFn ops_winchip_0f[1024];
extern const OpFn ops_winchip2_0f[1024];
diff --git a/src/device/hwm_gl518sm.c b/src/device/hwm_gl518sm.c
new file mode 100644
index 000000000..e09c29443
--- /dev/null
+++ b/src/device/hwm_gl518sm.c
@@ -0,0 +1,278 @@
+/*
+ * 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 Genesys Logic GL518SM hardware monitoring chip.
+ *
+ *
+ *
+ * Author: RichardG,
+ *
+ * Copyright 2020 RichardG.
+ */
+#include
+#include
+#include
+#include
+#include
+#define HAVE_STDARG_H
+#include
+#include <86box/86box.h>
+#include <86box/device.h>
+#include <86box/io.h>
+#include "cpu.h"
+#include <86box/smbus.h>
+#include <86box/hwm.h>
+
+
+#define CLAMP(a, min, max) (((a)< (min)) ? (min) : (((a) > (max)) ? (max) : (a)))
+#define GL518SM_RPM_TO_REG(r, d) ((r) ? CLAMP(480000 / (r * d), 1, 255) : 0)
+#define GL518SM_VOLTAGE_TO_REG(v) (((v) / 19) & 0xff)
+#define GL518SM_VDD_TO_REG(v) ((((v) * 4) / 95) & 0xff)
+
+
+typedef struct {
+ uint32_t local;
+ hwm_values_t *values;
+
+ uint16_t regs[32];
+ uint8_t addr_register;
+
+ uint8_t smbus_addr;
+} gl518sm_t;
+
+
+static uint8_t gl518sm_smbus_read_byte(uint8_t addr, void *priv);
+static uint8_t gl518sm_smbus_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv);
+static uint16_t gl518sm_smbus_read_word_cmd(uint8_t addr, uint8_t cmd, void *priv);
+static uint16_t gl518sm_read(gl518sm_t *dev, uint8_t reg);
+static void gl518sm_smbus_write_byte(uint8_t addr, uint8_t val, void *priv);
+static void gl518sm_smbus_write_byte_cmd(uint8_t addr, uint8_t cmd, uint8_t val, void *priv);
+static void gl518sm_smbus_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_t val, void *priv);
+static uint8_t gl518sm_write(gl518sm_t *dev, uint8_t reg, uint16_t val);
+static void gl518sm_reset(gl518sm_t *dev);
+
+
+#ifdef ENABLE_GL518SM_LOG
+int gl518sm_do_log = ENABLE_GL518SM_LOG;
+
+
+static void
+gl518sm_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (gl518sm_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+#define gl518sm_log(fmt, ...)
+#endif
+
+
+static void
+gl518sm_remap(gl518sm_t *dev, uint8_t addr)
+{
+ gl518sm_log("GL518SM: remapping to SMBus %02Xh\n", addr);
+
+ smbus_removehandler(dev->smbus_addr, 1,
+ gl518sm_smbus_read_byte, gl518sm_smbus_read_byte_cmd, gl518sm_smbus_read_word_cmd, NULL,
+ gl518sm_smbus_write_byte, gl518sm_smbus_write_byte_cmd, gl518sm_smbus_write_word_cmd, NULL,
+ dev);
+
+ if (addr < 0x80) smbus_sethandler(addr, 1,
+ gl518sm_smbus_read_byte, gl518sm_smbus_read_byte_cmd, gl518sm_smbus_read_word_cmd, NULL,
+ gl518sm_smbus_write_byte, gl518sm_smbus_write_byte_cmd, gl518sm_smbus_write_word_cmd, NULL,
+ dev);
+
+ dev->smbus_addr = addr;
+}
+
+
+static uint8_t
+gl518sm_smbus_read_byte(uint8_t addr, void *priv)
+{
+ gl518sm_t *dev = (gl518sm_t *) priv;
+ return gl518sm_read(dev, dev->addr_register);
+}
+
+
+static uint8_t
+gl518sm_smbus_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv)
+{
+ gl518sm_t *dev = (gl518sm_t *) priv;
+ return gl518sm_read(dev, cmd);
+}
+
+
+static uint16_t
+gl518sm_smbus_read_word_cmd(uint8_t addr, uint8_t cmd, void *priv)
+{
+ gl518sm_t *dev = (gl518sm_t *) priv;
+ return gl518sm_read(dev, cmd);
+}
+
+
+static uint16_t
+gl518sm_read(gl518sm_t *dev, uint8_t reg)
+{
+ uint16_t ret = dev->regs[reg & 0x1f];
+
+ switch (reg) {
+ case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c:
+ /* two-byte registers: leave as-is */
+ break;
+ default:
+ /* single-byte registers: duplicate low byte to high byte (real hardware behavior unknown) */
+ ret |= (ret << 8);
+ break;
+ }
+
+ gl518sm_log("GL518SM: read(%02X) = %04X\n", reg, ret);
+
+ return ret;
+}
+
+
+static void
+gl518sm_smbus_write_byte(uint8_t addr, uint8_t val, void *priv)
+{
+ gl518sm_t *dev = (gl518sm_t *) priv;
+ dev->addr_register = val;
+}
+
+
+static void
+gl518sm_smbus_write_byte_cmd(uint8_t addr, uint8_t cmd, uint8_t val, void *priv)
+{
+ gl518sm_t *dev = (gl518sm_t *) priv;
+ gl518sm_write(dev, cmd, val);
+}
+
+
+static void
+gl518sm_smbus_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_t val, void *priv)
+{
+ gl518sm_t *dev = (gl518sm_t *) priv;
+ gl518sm_write(dev, cmd, val);
+}
+
+
+static uint8_t
+gl518sm_write(gl518sm_t *dev, uint8_t reg, uint16_t val)
+{
+ gl518sm_log("GL518SM: write(%02X, %04X)\n", reg, val);
+
+ switch (reg) {
+ case 0x00: case 0x01: case 0x04: case 0x07: case 0x0d: case 0x12: case 0x13: case 0x14: case 0x15:
+ /* read-only registers */
+ return 0;
+
+ case 0x0a:
+ dev->regs[0x13] = (val & 0xff);
+ break;
+
+ case 0x03:
+ dev->regs[reg] = (val & 0xfc);
+
+ if (val & 0x80) /* Init */
+ gl518sm_reset(dev);
+ break;
+
+ case 0x0f:
+ dev->regs[reg] = (val & 0xf8);
+
+ /* update fan values to match the new divisor */
+ dev->regs[0x07] = (GL518SM_RPM_TO_REG(dev->values->fans[0], 1 << ((dev->regs[0x0f] >> 6) & 0x3)) << 8);
+ dev->regs[0x07] |= GL518SM_RPM_TO_REG(dev->values->fans[1], 1 << ((dev->regs[0x0f] >> 4) & 0x3));
+ break;
+
+ case 0x11:
+ dev->regs[reg] = (val & 0x7f);
+ break;
+
+ default:
+ dev->regs[reg] = val;
+ break;
+ }
+
+ return 1;
+}
+
+
+static void
+gl518sm_reset(gl518sm_t *dev)
+{
+ memset(dev->regs, 0, sizeof(dev->regs));
+
+ dev->regs[0x00] = 0x80;
+ dev->regs[0x01] = 0x80; /* revision 0x80 can read all voltages */
+ dev->regs[0x04] = ((dev->values->temperatures[0] + 119) & 0xff);
+ dev->regs[0x05] = 0xc7;
+ dev->regs[0x06] = 0xc2;
+ dev->regs[0x07] = ((GL518SM_RPM_TO_REG(dev->values->fans[0], 8) << 8) | GL518SM_RPM_TO_REG(dev->values->fans[1], 8));
+ dev->regs[0x08] = 0x6464;
+ dev->regs[0x09] = 0xdac5;
+ dev->regs[0x0a] = 0xdac5;
+ dev->regs[0x0b] = 0xdac5;
+ dev->regs[0x0c] = 0xdac5;
+ /* AOpen System Monitor requires an approximate voltage offset of 13 at least on 3.3V (voltages[2]) */
+ dev->regs[0x0d] = 13 + GL518SM_VOLTAGE_TO_REG(dev->values->voltages[2]);
+ dev->regs[0x0f] = 0xf8;
+ dev->regs[0x13] = 13 + GL518SM_VOLTAGE_TO_REG(dev->values->voltages[1]);
+ dev->regs[0x14] = 13 + GL518SM_VOLTAGE_TO_REG(dev->values->voltages[0]);
+ dev->regs[0x15] = 13 + GL518SM_VDD_TO_REG(5000);
+}
+
+
+static void
+gl518sm_close(void *priv)
+{
+ gl518sm_t *dev = (gl518sm_t *) priv;
+
+ gl518sm_remap(dev, 0);
+
+ free(dev);
+}
+
+
+static void *
+gl518sm_init(const device_t *info)
+{
+ gl518sm_t *dev = (gl518sm_t *) malloc(sizeof(gl518sm_t));
+ memset(dev, 0, sizeof(gl518sm_t));
+
+ dev->local = info->local;
+ dev->values = hwm_get_values();
+
+ gl518sm_reset(dev);
+ gl518sm_remap(dev, dev->local & 0x7f);
+
+ return dev;
+}
+
+
+const device_t gl518sm_2c_device = {
+ "Genesys Logic GL518SM Hardware Monitor",
+ DEVICE_ISA,
+ 0x2c,
+ gl518sm_init, gl518sm_close, NULL,
+ NULL, NULL, NULL,
+ NULL
+};
+
+const device_t gl518sm_2d_device = {
+ "Genesys Logic GL518SM Hardware Monitor",
+ DEVICE_ISA,
+ 0x2d,
+ gl518sm_init, gl518sm_close, NULL,
+ NULL, NULL, NULL,
+ NULL
+};
diff --git a/src/device/hwm_lm75.c b/src/device/hwm_lm75.c
index 097b62e8e..c7a057ff4 100644
--- a/src/device/hwm_lm75.c
+++ b/src/device/hwm_lm75.c
@@ -60,19 +60,21 @@ lm75_log(const char *fmt, ...)
void
-lm75_remap(lm75_t *dev)
+lm75_remap(lm75_t *dev, uint8_t addr)
{
- lm75_log("LM75: remapping to SMBus %02Xh\n", dev->smbus_addr);
+ lm75_log("LM75: remapping to SMBus %02Xh\n", addr);
smbus_removehandler(dev->smbus_addr, 1,
lm75_smbus_read_byte, lm75_smbus_read_byte_cmd, lm75_smbus_read_word_cmd, NULL,
lm75_smbus_write_byte, lm75_smbus_write_byte_cmd, lm75_smbus_write_word_cmd, NULL,
dev);
- if (dev->smbus_addr) smbus_sethandler(dev->smbus_addr, 1,
+ if (addr < 0x80) smbus_sethandler(addr, 1,
lm75_smbus_read_byte, lm75_smbus_read_byte_cmd, lm75_smbus_read_word_cmd, NULL,
lm75_smbus_write_byte, lm75_smbus_write_byte_cmd, lm75_smbus_write_word_cmd, NULL,
dev);
+
+ dev->smbus_addr = addr;
}
@@ -128,7 +130,7 @@ lm75_read(lm75_t *dev, uint8_t reg)
/* The AS99127F hardware monitor uses the addresses of its LM75 devices
to access some of its proprietary registers. Pass this operation on to
the main monitor address through an internal SMBus call, if necessary. */
- if ((reg > 0x7) && ((reg & 0xf8) != 0x50) && (dev->as99127f_smbus_addr))
+ if ((reg > 0x7) && ((reg & 0xf8) != 0x50) && (dev->as99127f_smbus_addr < 0x80))
ret = smbus_read_byte_cmd(dev->as99127f_smbus_addr, reg);
else
ret = dev->regs[reg & 0x7];
@@ -191,7 +193,7 @@ lm75_write(lm75_t *dev, uint8_t reg, uint8_t val)
/* The AS99127F hardware monitor uses the addresses of its LM75 devices
to access some of its proprietary registers. Pass this operation on to
the main monitor address through an internal SMBus call, if necessary. */
- if ((reg > 0x7) && ((reg & 0xf8) != 0x50) && (dev->as99127f_smbus_addr)) {
+ if ((reg > 0x7) && ((reg & 0xf8) != 0x50) && (dev->as99127f_smbus_addr < 0x80)) {
smbus_write_byte_cmd(dev->as99127f_smbus_addr, reg, val);
return 1;
}
@@ -216,7 +218,7 @@ lm75_reset(lm75_t *dev)
dev->regs[0x3] = 0x4b;
dev->regs[0x5] = 0x50;
- lm75_remap(dev);
+ lm75_remap(dev, dev->local & 0x7f);
}
@@ -224,6 +226,9 @@ static void
lm75_close(void *priv)
{
lm75_t *dev = (lm75_t *) priv;
+
+ lm75_remap(dev, 0);
+
free(dev);
}
@@ -237,8 +242,7 @@ lm75_init(const device_t *info)
dev->local = info->local;
dev->values = hwm_get_values();
- dev->smbus_addr = dev->local;
- dev->as99127f_smbus_addr = 0x00;
+ dev->as99127f_smbus_addr = 0x80;
lm75_reset(dev);
diff --git a/src/device/hwm_lm78.c b/src/device/hwm_lm78.c
index bf474db9e..829e323ce 100644
--- a/src/device/hwm_lm78.c
+++ b/src/device/hwm_lm78.c
@@ -91,24 +91,26 @@ lm78_log(const char *fmt, ...)
static void
-lm78_remap(lm78_t *dev)
+lm78_remap(lm78_t *dev, uint8_t addr)
{
lm75_t *lm75;
if (!(dev->local & LM78_SMBUS)) return;
- lm78_log("LM78: remapping to SMBus %02Xh\n", dev->smbus_addr);
+ lm78_log("LM78: remapping to SMBus %02Xh\n", addr);
smbus_removehandler(dev->smbus_addr, 1,
lm78_smbus_read_byte, lm78_smbus_read_byte_cmd, lm78_smbus_read_word_cmd, NULL,
lm78_smbus_write_byte, lm78_smbus_write_byte_cmd, lm78_smbus_write_word_cmd, NULL,
dev);
- if (dev->smbus_addr) smbus_sethandler(dev->smbus_addr, 1,
+ if (addr < 0x80) smbus_sethandler(addr, 1,
lm78_smbus_read_byte, lm78_smbus_read_byte_cmd, lm78_smbus_read_word_cmd, NULL,
lm78_smbus_write_byte, lm78_smbus_write_byte_cmd, lm78_smbus_write_word_cmd, NULL,
dev);
+ dev->smbus_addr = addr;
+
if (dev->local & LM78_AS99127F) {
/* Store the main SMBus address on the LM75 devices to ensure reads/writes
to the AS99127F's proprietary registers are passed through to this side. */
@@ -291,10 +293,8 @@ lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank)
switch (reg) {
case 0x40:
- if (val & 0x80) {
- /* INITIALIZATION bit resets all registers except main SMBus address */
+ if (val & 0x80) /* INITIALIZATION bit resets all registers except main SMBus address */
lm78_reset(dev, 1);
- }
break;
case 0x47:
/* update FAN1/FAN2 values to match the new divisor */
@@ -303,19 +303,15 @@ lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank)
break;
case 0x48:
/* set main SMBus address */
- if (dev->local & LM78_SMBUS) {
- dev->smbus_addr = (dev->regs[0x48] & 0x7f);
- lm78_remap(dev);
- }
+ if (dev->local & LM78_SMBUS)
+ lm78_remap(dev, dev->regs[0x48] & 0x7f);
break;
case 0x49:
if (!(dev->local & LM78_WINBOND)) {
- if (val & 0x20) {
- /* Chip Reset bit (LM78 only) resets all registers */
+ if (val & 0x20) /* Chip Reset bit (LM78 only) resets all registers */
lm78_reset(dev, 0);
- } else {
+ else
dev->regs[0x49] = 0x40;
- }
} else {
dev->regs[0x49] &= 0x01;
}
@@ -328,10 +324,9 @@ lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank)
if (!lm75)
continue;
if (dev->regs[0x4a] & (0x08 * (0x10 * i))) /* DIS_T2 and DIS_T3 bit disable those interfaces */
- lm75->smbus_addr = 0x00;
+ lm75_remap(lm75, 0x80);
else
- lm75->smbus_addr = (0x48 + ((dev->regs[0x4a] >> (i * 4)) & 0x7));
- lm75_remap(lm75);
+ lm75_remap(lm75, 0x48 + ((dev->regs[0x4a] >> (i * 4)) & 0x7));
}
}
break;
@@ -428,7 +423,7 @@ lm78_reset(lm78_t *dev, uint8_t initialization)
dev->regs[0x49] = 0x40;
}
- lm78_remap(dev);
+ lm78_remap(dev, dev->smbus_addr);
}
diff --git a/src/device/smbus_piix4.c b/src/device/smbus_piix4.c
index ad8ff64d0..947a536de 100644
--- a/src/device/smbus_piix4.c
+++ b/src/device/smbus_piix4.c
@@ -102,9 +102,9 @@ smbus_piix4_write(uint16_t addr, uint8_t val, void *priv)
switch (addr - dev->io_base) {
case 0x00:
/* some status bits are reset by writing 1 to them */
- for (smbus_addr = 0x02; smbus_addr <= 0x10; smbus_addr = smbus_addr << 1) {
+ for (smbus_addr = 0x02; smbus_addr <= 0x10; smbus_addr <<= 1) {
if (val & smbus_addr)
- dev->stat = dev->stat & ~smbus_addr;
+ dev->stat &= ~smbus_addr;
}
break;
case 0x02:
@@ -150,7 +150,7 @@ smbus_piix4_write(uint16_t addr, uint8_t val, void *priv)
dev->data0 = (temp & 0xFF);
dev->data1 = (temp >> 8);
} else {
- temp = (dev->data1 << 8) | dev->data0;
+ temp = ((dev->data1 << 8) | dev->data0);
smbus_write_word_cmd(smbus_addr, dev->cmd, temp);
}
dev->next_stat = 0x2;
@@ -216,7 +216,7 @@ smbus_piix4_remap(smbus_piix4_t *dev, uint16_t new_io_base, uint8_t enable)
dev->io_base = new_io_base;
smbus_piix4_log("SMBus PIIX4: remap to %04Xh\n", dev->io_base);
- if (enable && (dev->io_base != 0x0000))
+ if ((enable) && (dev->io_base != 0x0000))
io_sethandler(dev->io_base, 0x10, smbus_piix4_read, NULL, NULL, smbus_piix4_write, NULL, NULL, dev);
}
diff --git a/src/dma.c b/src/dma.c
index bbfdf2118..3e7ac0152 100644
--- a/src/dma.c
+++ b/src/dma.c
@@ -485,9 +485,9 @@ dma_write(uint16_t addr, uint8_t val, void *priv)
case 6: /*Address registers*/
dma_wp[0] ^= 1;
if (dma_wp[0])
- dma[channel].ab = (dma[channel].ab & 0xffff00) | val;
+ dma[channel].ab = (dma[channel].ab & 0xffffff00 & dma_mask) | val;
else
- dma[channel].ab = (dma[channel].ab & 0xff00ff) | (val << 8);
+ dma[channel].ab = (dma[channel].ab & 0xffff00ff & dma_mask) | (val << 8);
dma[channel].ac = dma[channel].ab;
return;
@@ -778,14 +778,14 @@ dma16_write(uint16_t addr, uint8_t val, void *priv)
dma_wp[1] ^= 1;
if (dma_ps2.is_ps2) {
if (dma_wp[1])
- dma[channel].ab = (dma[channel].ab & 0xffff00) | val;
+ dma[channel].ab = (dma[channel].ab & 0xffffff00 & dma_mask) | val;
else
- dma[channel].ab = (dma[channel].ab & 0xff00ff) | (val << 8);
+ dma[channel].ab = (dma[channel].ab & 0xffff00ff & dma_mask) | (val << 8);
} else {
if (dma_wp[1])
- dma[channel].ab = (dma[channel].ab & 0xfffe00) | (val << 1);
+ dma[channel].ab = (dma[channel].ab & 0xfffffe00 & dma_mask) | (val << 1);
else
- dma[channel].ab = (dma[channel].ab & 0xfe01ff) | (val << 9);
+ dma[channel].ab = (dma[channel].ab & 0xfffe01ff & dma_mask) | (val << 9);
}
dma[channel].ac = dma[channel].ab;
return;
@@ -878,12 +878,12 @@ dma_page_write(uint16_t addr, uint8_t val, void *priv)
if (addr > 4) {
dma[addr].page = val & 0xfe;
- dma[addr].ab = (dma[addr].ab & 0x1ffff) | (dma[addr].page << 16);
- dma[addr].ac = (dma[addr].ac & 0x1ffff) | (dma[addr].page << 16);
+ dma[addr].ab = (dma[addr].ab & 0xff01ffff & dma_mask) | (dma[addr].page << 16);
+ dma[addr].ac = (dma[addr].ac & 0xff01ffff & dma_mask) | (dma[addr].page << 16);
} else {
dma[addr].page = (AT) ? val : val & 0xf;
- dma[addr].ab = (dma[addr].ab & 0xffff) | (dma[addr].page << 16);
- dma[addr].ac = (dma[addr].ac & 0xffff) | (dma[addr].page << 16);
+ dma[addr].ab = (dma[addr].ab & 0xff00ffff & dma_mask) | (dma[addr].page << 16);
+ dma[addr].ac = (dma[addr].ac & 0xff00ffff & dma_mask) | (dma[addr].page << 16);
}
}
}
@@ -959,6 +959,20 @@ dma_set_params(uint8_t advanced, uint32_t mask)
}
+void
+dma_set_mask(uint32_t mask)
+{
+ int i;
+
+ dma_mask = mask;
+
+ for (i = 0; i < 8; i++) {
+ dma[i].ab &= mask;
+ dma[i].ac &= mask;
+ }
+}
+
+
void
dma_reset(void)
{
@@ -1355,14 +1369,14 @@ dma_channel_read(int channel)
else if (dma_advanced)
dma_retreat(dma_c);
else
- dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac - 1) & 0xffff);
+ dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac - 1) & 0xffff);
} else {
if (dma_ps2.is_ps2)
dma_c->ac++;
else if (dma_advanced)
dma_advance(dma_c);
else
- dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac + 1) & 0xffff);
+ dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac + 1) & 0xffff);
}
} else {
temp = _dma_readw(dma_c->ac, dma_c);
@@ -1373,14 +1387,14 @@ dma_channel_read(int channel)
else if (dma_advanced)
dma_retreat(dma_c);
else
- dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac - 2) & 0x1ffff);
+ dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac - 2) & 0x1ffff);
} else {
if (dma_ps2.is_ps2)
dma_c->ac += 2;
else if (dma_advanced)
dma_advance(dma_c);
else
- dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac + 2) & 0x1ffff);
+ dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac + 2) & 0x1ffff);
}
}
@@ -1443,14 +1457,14 @@ dma_channel_write(int channel, uint16_t val)
else if (dma_advanced)
dma_retreat(dma_c);
else
- dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac - 1) & 0xffff);
+ dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac - 1) & 0xffff);
} else {
if (dma_ps2.is_ps2)
dma_c->ac++;
else if (dma_advanced)
dma_advance(dma_c);
else
- dma_c->ac = (dma_c->ac & 0xff0000) | ((dma_c->ac + 1) & 0xffff);
+ dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac + 1) & 0xffff);
}
} else {
_dma_writew(dma_c->ac, val, dma_c);
@@ -1461,15 +1475,15 @@ dma_channel_write(int channel, uint16_t val)
else if (dma_advanced)
dma_retreat(dma_c);
else
- dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac - 2) & 0x1ffff);
- dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac - 2) & 0x1ffff);
+ dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac - 2) & 0x1ffff);
+ dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac - 2) & 0x1ffff);
} else {
if (dma_ps2.is_ps2)
dma_c->ac += 2;
else if (dma_advanced)
dma_advance(dma_c);
else
- dma_c->ac = (dma_c->ac & 0xfe0000) | ((dma_c->ac + 2) & 0x1ffff);
+ dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac + 2) & 0x1ffff);
}
}
diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c
index 5184bbe5f..3be66cf0f 100644
--- a/src/floppy/fdc.c
+++ b/src/floppy/fdc.c
@@ -1468,6 +1468,9 @@ fdc_poll_common_finish(fdc_t *fdc, int compare, int st5)
static void
fdc_poll_readwrite_finish(fdc_t *fdc, int compare)
{
+ if ((fdc->interrupt == 5) || (fdc->interrupt == 9))
+ fdd_do_writeback(real_drive(fdc, fdc->drive));
+
fdc->inread = 0;
fdc->interrupt = -2;
@@ -1902,7 +1905,8 @@ void
fdc_sector_finishcompare(fdc_t *fdc, int satisfying)
{
fdc->stat = 0x10;
- fdc->satisfying_sectors++;
+ if (satisfying)
+ fdc->satisfying_sectors++;
fdc->inread = 0;
fdc_callback(fdc);
}
diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c
index 791c82abd..7e1b21452 100644
--- a/src/floppy/fdd.c
+++ b/src/floppy/fdd.c
@@ -719,3 +719,10 @@ fdd_init(void)
fdd_load(2, floppyfns[2]);
fdd_load(3, floppyfns[3]);
}
+
+
+void
+fdd_do_writeback(int drive)
+{
+ d86f_handler[drive].writeback(drive);
+}
diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c
index 26463da34..9939a037a 100644
--- a/src/floppy/fdd_86f.c
+++ b/src/floppy/fdd_86f.c
@@ -103,10 +103,6 @@ enum {
/* 1 11 01 ??? */
STATE_0D_SPIN_TO_INDEX = 0xE8, /* FORMAT TRACK */
STATE_0D_FORMAT_TRACK,
-
- /* 1 11 11 ??? */
- STATE_0D_NOP_SPIN_TO_INDEX = 0xF8, /* FORMAT TRACK */
- STATE_0D_NOP_FORMAT_TRACK
};
enum {
@@ -138,9 +134,9 @@ typedef struct {
} sliding_buffer_t;
typedef struct {
- uint32_t sync_marks;
uint32_t bits_obtained;
- uint32_t bytes_obtained;
+ uint16_t bytes_obtained;
+ uint16_t sync_marks;
uint32_t sync_pos;
} find_t;
@@ -181,47 +177,35 @@ typedef struct {
*/
typedef struct {
FILE *f;
- uint16_t version;
- uint16_t disk_flags;
- int32_t extra_bit_cells[2];
+ uint8_t state, fill, sector_count, format_state,
+ error_condition, id_found;
+ uint16_t version, disk_flags, satisfying_bytes, turbo_pos;
+ uint16_t cur_track;
uint16_t track_encoded_data[2][53048];
uint16_t *track_surface_data[2];
uint16_t thin_track_encoded_data[2][2][53048];
uint16_t *thin_track_surface_data[2][2];
uint16_t side_flags[2];
+ uint16_t preceding_bit[2];
+ uint16_t current_byte[2];
+ uint16_t current_bit[2];
+ uint16_t last_word[2];
+#ifdef D86F_COMPRESS
+ int is_compressed;
+#endif
+ int32_t extra_bit_cells[2];
+ uint32_t file_size, index_count, track_pos, datac,
+ id_pos, dma_over;
uint32_t index_hole_pos[2];
uint32_t track_offset[512];
- uint32_t file_size;
sector_id_t last_sector;
sector_id_t req_sector;
- uint32_t index_count;
- uint8_t state;
- uint8_t fill;
- uint32_t track_pos;
- uint32_t datac;
- uint32_t id_pos;
- uint16_t last_word[2];
find_t id_find;
find_t data_find;
crc_t calc_crc;
crc_t track_crc;
- uint8_t sector_count;
- uint8_t format_state;
- uint16_t satisfying_bytes;
- uint16_t preceding_bit[2];
- uint16_t current_byte[2];
- uint16_t current_bit[2];
- int cur_track;
- uint32_t error_condition;
-#ifdef D86F_COMPRESS
- int is_compressed;
-#endif
- int id_found;
wchar_t original_file_name[2048];
- uint8_t *filebuf;
- uint8_t *outbuf;
- uint32_t dma_over;
- int turbo_pos;
+ uint8_t *filebuf, *outbuf;
sector_t *last_side_sector[2];
} d86f_t;
@@ -833,16 +817,14 @@ uint32_t
d86f_get_data_len(int drive)
{
d86f_t *dev = d86f[drive];
+ uint32_t i, ret = 128;
- if (dev->req_sector.id.n) {
- if (dev->req_sector.id.n == 8) return 32768;
- return (128 << ((uint32_t) dev->req_sector.id.n));
- } else {
- if (fdc_get_dtl(d86f_fdc) < 128)
- return fdc_get_dtl(d86f_fdc);
- else
- return (128 << ((uint32_t) dev->req_sector.id.n));
- }
+ if (dev->req_sector.id.n)
+ ret = (uint32_t)128 << dev->req_sector.id.n;
+ else if ((i = fdc_get_dtl(d86f_fdc)) < 128)
+ ret = i;
+
+ return ret;
}
@@ -973,7 +955,8 @@ d86f_encode_byte(int drive, int sync, decoded_t b, decoded_t prev_b)
uint8_t bits3210 = b.nibbles.nibble0;
uint16_t encoded_7654, encoded_3210, result;
- if (encoding > 1) return 0xff;
+ if (encoding > 1)
+ return 0xffff;
if (sync) {
result = d86f_encode_get_data(b.byte);
@@ -1475,7 +1458,7 @@ d86f_read_sector_id(int drive, int side, int match)
} else {
/* CRC is valid. */
dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = 0;
- dev->id_found++;
+ dev->id_found |= 1;
if ((dev->last_sector.dword == dev->req_sector.dword) || !match) {
d86f_handler[drive].set_sector(drive, side, dev->last_sector.id.c, dev->last_sector.id.h, dev->last_sector.id.r, dev->last_sector.id.n);
if (dev->state == STATE_02_READ_ID) {
@@ -1729,7 +1712,6 @@ d86f_write_sector_data(int drive, int side, int mfm, uint16_t am)
dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0;
dev->error_condition = 0;
dev->state = STATE_IDLE;
- d86f_handler[drive].writeback(drive);
fdc_sector_finishread(d86f_fdc);
return;
}
@@ -1780,7 +1762,7 @@ d86f_spin_to_index(int drive, int side)
d86f_advance_bit(drive, side);
if (dev->track_pos == d86f_handler[drive].index_hole_pos(drive, side)) {
- if ((dev->state == STATE_0D_SPIN_TO_INDEX) || (dev->state == STATE_0D_NOP_SPIN_TO_INDEX)) {
+ if (dev->state == STATE_0D_SPIN_TO_INDEX) {
/* When starting format, reset format state to the beginning. */
dev->preceding_bit[side] = 1;
dev->format_state = FMT_PRETRK_GAP0;
@@ -2100,22 +2082,6 @@ d86f_format_track(int drive, int side, int do_write)
}
-void
-d86f_format_track_normal(int drive, int side)
-{
- d86f_t *dev = d86f[drive];
-
- d86f_format_track(drive, side, (dev->version == D86FVER));
-}
-
-
-void
-d86f_format_track_nop(int drive, int side)
-{
- d86f_format_track(drive, side, 0);
-}
-
-
void
d86f_initialize_last_sector_id(int drive, int c, int h, int r, int n)
{
@@ -2317,7 +2283,6 @@ d86f_turbo_poll(int drive, int side)
switch(dev->state) {
case STATE_0D_SPIN_TO_INDEX:
- case STATE_0D_NOP_SPIN_TO_INDEX:
dev->sector_count = 0;
dev->datac = 5;
/*FALLTHROUGH*/
@@ -2412,11 +2377,7 @@ d86f_turbo_poll(int drive, int side)
break;
case STATE_0D_FORMAT_TRACK:
- d86f_turbo_format(drive, side, 0);
- return;
-
- case STATE_0D_NOP_FORMAT_TRACK:
- d86f_turbo_format(drive, side, 1);
+ d86f_turbo_format(drive, side, (side && (d86f_get_sides(drive) != 2)));
return;
case STATE_IDLE:
@@ -2460,7 +2421,6 @@ d86f_poll(int drive)
switch(dev->state) {
case STATE_02_SPIN_TO_INDEX:
case STATE_0D_SPIN_TO_INDEX:
- case STATE_0D_NOP_SPIN_TO_INDEX:
d86f_spin_to_index(drive, side);
return;
@@ -2547,12 +2507,7 @@ d86f_poll(int drive)
case STATE_0D_FORMAT_TRACK:
if (! (dev->track_pos & 15))
- d86f_format_track_normal(drive, side);
- return;
-
- case STATE_0D_NOP_FORMAT_TRACK:
- if (! (dev->track_pos & 15))
- d86f_format_track_nop(drive, side);
+ d86f_format_track(drive, side, (!side || (d86f_get_sides(drive) == 2)) && (dev->version == D86FVER));
return;
case STATE_IDLE:
@@ -2962,9 +2917,9 @@ d86f_read_track(int drive, int track, int thin_track, int side, uint16_t *da, ui
} else
fseek(dev->f, dev->track_offset[logical_track] + d86f_track_header_size(drive), SEEK_SET);
array_size = d86f_get_array_size(drive, side, 0);
+ fread(da, 1, array_size, dev->f);
if (d86f_has_surface_desc(drive))
fread(sa, 1, array_size, dev->f);
- fread(da, 1, array_size, dev->f);
} else {
if (! thin_track) {
switch((dev->disk_flags >> 1) & 3) {
@@ -3059,10 +3014,10 @@ d86f_write_track(int drive, FILE **f, int side, uint16_t *da0, uint16_t *sa0)
fwrite(&index_hole_pos, 1, 4, *f);
+ fwrite(da0, 1, array_size, *f);
+
if (d86f_has_surface_desc(drive))
fwrite(sa0, 1, array_size, *f);
-
- fwrite(da0, 1, array_size, *f);
}
@@ -3099,7 +3054,7 @@ d86f_write_tracks(int drive, FILE **f, uint32_t *track_table)
fdd_side = fdd_get_head(drive);
sides = d86f_get_sides(drive);
- if (track_table)
+ if (track_table != NULL)
tbl = track_table;
if (!fdd_doublestep_40(drive)) {
@@ -3432,10 +3387,7 @@ d86f_common_format(int drive, int side, int rate, uint8_t fill, int proxy)
dev->index_count = dev->error_condition = dev->satisfying_bytes = dev->sector_count = 0;
dev->dma_over = 0;
- if (!side || (d86f_get_sides(drive) == 2))
- dev->state = STATE_0D_SPIN_TO_INDEX;
- else
- dev->state = STATE_0D_NOP_SPIN_TO_INDEX;
+ dev->state = STATE_0D_SPIN_TO_INDEX;
}
diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h
index 276da03c8..c2e4b8fe0 100644
--- a/src/include/86box/chipset.h
+++ b/src/include/86box/chipset.h
@@ -21,9 +21,6 @@
/* ACC */
extern const device_t acc2168_device;
-/* Acer M3A and V35N */
-extern const device_t acerm3a_device;
-
/* ALi */
extern const device_t ali1429_device;
@@ -63,7 +60,11 @@ extern const device_t slc90e66_device;
extern const device_t ioapic_device;
/* OPTi */
+extern const device_t opti283_device;
+extern const device_t opti493_device;
extern const device_t opti495_device;
+extern const device_t opti802g_device;
+extern const device_t opti895_device;
extern const device_t opti5x7_device;
/* C&T */
@@ -77,6 +78,7 @@ extern const device_t cs8230_device;
extern const device_t rabbit_device;
extern const device_t sis_85c471_device;
extern const device_t sis_85c496_device;
+extern const device_t sis_85c496_ls486e_device;
#if defined(DEV_BRANCH) && defined(USE_SIS_85C50X)
extern const device_t sis_85c50x_device;
#endif
diff --git a/src/include/86box/dma.h b/src/include/86box/dma.h
index d5ee9fcb3..bc09bac97 100644
--- a/src/include/86box/dma.h
+++ b/src/include/86box/dma.h
@@ -96,8 +96,9 @@ extern void dma_bm_read(uint32_t PhysAddress, uint8_t *DataRead, uint32_t TotalS
extern void dma_bm_write(uint32_t PhysAddress, const uint8_t *DataWrite, uint32_t TotalSize, int TransferSize);
void dma_set_params(uint8_t advanced, uint32_t mask);
-void dma_ext_mode_init(void);
+void dma_set_mask(uint32_t mask);
+void dma_ext_mode_init(void);
void dma_high_page_init(void);
void dma_remove_sg(void);
diff --git a/src/include/86box/fdd.h b/src/include/86box/fdd.h
index b486b617d..4a7de7c21 100644
--- a/src/include/86box/fdd.h
+++ b/src/include/86box/fdd.h
@@ -112,6 +112,7 @@ extern void fdd_readaddress(int drive, int side, int density);
extern void fdd_format(int drive, int side, int density, uint8_t fill);
extern int fdd_hole(int drive);
extern void fdd_stop(int drive);
+extern void fdd_do_writeback(int drive);
extern int motorspin;
extern uint64_t motoron[FDD_NUM];
diff --git a/src/include/86box/hwm.h b/src/include/86box/hwm.h
index 0cae77dbb..53d69500b 100644
--- a/src/include/86box/hwm.h
+++ b/src/include/86box/hwm.h
@@ -43,7 +43,7 @@ typedef struct {
extern void hwm_set_values(hwm_values_t new_values);
extern hwm_values_t* hwm_get_values();
-extern void lm75_remap(lm75_t *dev);
+extern void lm75_remap(lm75_t *dev, uint8_t addr);
extern uint8_t lm75_read(lm75_t *dev, uint8_t reg);
extern uint8_t lm75_write(lm75_t *dev, uint8_t reg, uint8_t val);
@@ -56,5 +56,8 @@ extern const device_t w83781d_device;
extern const device_t as99127f_device;
extern const device_t as99127f_rev2_device;
+extern const device_t gl518sm_2c_device;
+extern const device_t gl518sm_2d_device;
+
#endif /*EMU_HWM_H*/
diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h
index b0b4fa054..055679bac 100644
--- a/src/include/86box/machine.h
+++ b/src/include/86box/machine.h
@@ -252,6 +252,8 @@ extern int machine_at_asus386_init(const machine_t *);
extern int machine_at_ecs386_init(const machine_t *);
extern int machine_at_micronics386_init(const machine_t *);
+extern int machine_at_rycleopardlx_init(const machine_t *);
+
extern int machine_at_pb410a_init(const machine_t *);
extern int machine_at_acera1g_init(const machine_t *);
@@ -262,6 +264,8 @@ extern int machine_at_opti495_init(const machine_t *);
extern int machine_at_opti495_ami_init(const machine_t *);
extern int machine_at_opti495_mr_init(const machine_t *);
+extern int machine_at_403tg_init(const machine_t *);
+
extern int machine_at_vli486sv2g_init(const machine_t *);
extern int machine_at_ami471_init(const machine_t *);
extern int machine_at_dtk486_init(const machine_t *);
@@ -300,6 +304,10 @@ extern int machine_at_ambradp60_init(const machine_t *);
#if defined(DEV_BRANCH) && defined(USE_VPP60)
extern int machine_at_valuepointp60_init(const machine_t *);
#endif
+extern int machine_at_opti560l_init(const machine_t *);
+#if defined(DEV_BRANCH) && defined(USE_DELLXP60)
+extern int machine_at_dellxp60_init(const machine_t *);
+#endif
extern int machine_at_p5mp3_init(const machine_t *);
extern int machine_at_586mc1_init(const machine_t *);
diff --git a/src/include/86box/mem.h b/src/include/86box/mem.h
index 4104c4fa0..e0ff655ba 100644
--- a/src/include/86box/mem.h
+++ b/src/include/86box/mem.h
@@ -39,10 +39,10 @@
Bits 24 -31: SMM read
*/
-#define MEM_READ_ANY 0x0000
+#define MEM_READ_DISABLED 0x0000
#define MEM_READ_INTERNAL 0x0100
#define MEM_READ_EXTERNAL 0x0200
-#define MEM_READ_DISABLED 0x0300
+#define MEM_READ_ANY 0x0300
#define MEM_READ_NORMAL 0x0400 /* SMM only - means use the non-SMM state */
#define MEM_READ_EXTERNAL_EX 0x0500 /* External but with internal exec - needed by the VIA Apollo Pro */
#define MEM_READ_ROMCS 0x0600 /* EXTERNAL type + ROMC flag */
@@ -52,10 +52,10 @@
#define MEM_READ_DISABLED_EX 0x4000
#define MEM_READ_MASK 0xff00
-#define MEM_WRITE_ANY 0x0000
+#define MEM_WRITE_DISABLED 0x0000
#define MEM_WRITE_INTERNAL 0x0001
#define MEM_WRITE_EXTERNAL 0x0002
-#define MEM_WRITE_DISABLED 0x0003
+#define MEM_WRITE_ANY 0x0003
#define MEM_WRITE_NORMAL 0x0004 /* SMM only - means use the non-SMM state */
#define MEM_WRITE_EXTERNAL_EX 0x0005
#define MEM_WRITE_ROMCS 0x0006 /* EXTERNAL type + ROMC flag */
diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h
index c2bc5aeae..cb38a9e53 100644
--- a/src/include/86box/sio.h
+++ b/src/include/86box/sio.h
@@ -29,6 +29,7 @@ extern const device_t pc87306_device;
extern const device_t pc87307_device;
extern const device_t pc87309_device;
extern const device_t pc87332_device;
+extern const device_t pc87332_ps1_device;
extern const device_t pc97307_device;
extern const device_t ps1_m2133_sio;
extern const device_t sio_detect_device;
diff --git a/src/include/86box/spd.h b/src/include/86box/spd.h
index 098fb3ed7..4acce679d 100644
--- a/src/include/86box/spd.h
+++ b/src/include/86box/spd.h
@@ -100,10 +100,8 @@ typedef struct _spd_sdram_ {
} spd_sdram_t;
-extern spd_t *spd_devices[SPD_MAX_SLOTS];
-
-
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);
#endif /*EMU_SPD_H*/
diff --git a/src/io.c b/src/io.c
index b09624064..f78dc268e 100644
--- a/src/io.c
+++ b/src/io.c
@@ -367,7 +367,7 @@ inw(uint16_t port)
ret8[0] = ret & 0xff;
ret8[1] = (ret >> 8) & 0xff;
for (i = 0; i < 2; i++) {
- p = io[port + i];
+ p = io[(port + i) & 0xffff];
while(p) {
if (p->inb && !p->inw) {
ret8[i] &= p->inb(port + i, p->priv);
@@ -414,7 +414,7 @@ outw(uint16_t port, uint16_t val)
}
for (i = 0; i < 2; i++) {
- p = io[port + i];
+ p = io[(port + i) & 0xffff];
while(p) {
if (p->outb && !p->outw) {
p->outb(port + i, val >> (i << 3), p->priv);
@@ -463,7 +463,7 @@ inl(uint16_t port)
ret16[0] = ret & 0xffff;
ret16[1] = (ret >> 16) & 0xffff;
for (i = 0; i < 4; i += 2) {
- p = io[port + i];
+ p = io[(port + i) & 0xffff];
while(p) {
if (p->inw && !p->inl) {
ret16[i >> 1] &= p->inw(port + i, p->priv);
@@ -480,7 +480,7 @@ inl(uint16_t port)
ret8[2] = (ret >> 16) & 0xff;
ret8[3] = (ret >> 24) & 0xff;
for (i = 0; i < 4; i++) {
- p = io[port + i];
+ p = io[(port + i) & 0xffff];
while(p) {
if (p->inb && !p->inw && !p->inl) {
ret8[i] &= p->inb(port + i, p->priv);
@@ -523,14 +523,13 @@ outl(uint16_t port, uint32_t val)
p->outl(port, val, p->priv);
found |= 4;
qfound++;
- // return;
}
p = p->next;
}
}
for (i = 0; i < 4; i += 2) {
- p = io[port + i];
+ p = io[(port + i) & 0xffff];
while(p) {
if (p->outw && !p->outl) {
p->outw(port + i, val >> (i << 3), p->priv);
@@ -542,7 +541,7 @@ outl(uint16_t port, uint32_t val)
}
for (i = 0; i < 4; i++) {
- p = io[port + i];
+ p = io[(port + i) & 0xffff];
while(p) {
if (p->outb && !p->outw && !p->outl) {
p->outb(port + i, val >> (i << 3), p->priv);
diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c
index cdf86fee8..9876fd498 100644
--- a/src/machine/m_at_386dx_486.c
+++ b/src/machine/m_at_386dx_486.c
@@ -102,6 +102,25 @@ machine_at_ecs386_init(const machine_t *model)
return ret;
}
+int
+machine_at_rycleopardlx_init(const machine_t *model)
+{
+ int ret;
+
+ ret = bios_load_linear(L"roms/machines/rycleopardlx/486-RYC-Leopard-LX.BIN",
+ 0x000f0000, 65536, 0);
+
+ if (bios_only || !ret)
+ return ret;
+
+ machine_at_common_init(model);
+
+ device_add(&opti283_device);
+ device_add(&keyboard_at_ami_device);
+ device_add(&fdc_at_device);
+
+ return ret;
+}
int
machine_at_pb410a_init(const machine_t *model)
@@ -272,6 +291,26 @@ machine_at_opti495_mr_init(const machine_t *model)
return ret;
}
+int
+machine_at_403tg_init(const machine_t *model)
+{
+ int ret;
+
+ ret = bios_load_linear(L"roms/machines/403tg/403TG.BIN",
+ 0x000f0000, 65536, 0);
+
+ if (bios_only || !ret)
+ return ret;
+
+ machine_at_common_ide_init(model);
+
+ device_add(&opti895_device);
+
+ device_add(&keyboard_at_device);
+ device_add(&fdc_at_device);
+
+ return ret;
+}
static void
machine_at_sis_85c471_common_init(const machine_t *model)
@@ -385,16 +424,11 @@ machine_at_sis_85c496_common_init(const machine_t *model)
pci_init(PCI_CONFIG_TYPE_1);
pci_register_slot(0x05, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
- 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_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);
-
- device_add(&sis_85c496_device);
}
@@ -409,9 +443,13 @@ machine_at_r418_init(const machine_t *model)
if (bios_only || !ret)
return ret;
- machine_at_common_init(model);
+ machine_at_common_init_ex(model, 2);
machine_at_sis_85c496_common_init(model);
+ device_add(&sis_85c496_device);
+ 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(0x07, PCI_CARD_NORMAL, 4, 1, 2, 3);
device_add(&fdc37c665_device);
@@ -433,9 +471,12 @@ machine_at_ls486e_init(const machine_t *model)
return ret;
machine_at_common_init_ex(model, 2);
- device_add(&ls486e_nvr_device);
machine_at_sis_85c496_common_init(model);
+ device_add(&sis_85c496_ls486e_device);
+ 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(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3);
device_add(&fdc37c665_device);
@@ -456,14 +497,21 @@ machine_at_4dps_init(const machine_t *model)
if (bios_only || !ret)
return ret;
- machine_at_common_init(model);
+ machine_at_common_init_ex(model, 2);
machine_at_sis_85c496_common_init(model);
+ device_add(&sis_85c496_device);
+ 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(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2);
pci_register_slot(0x07, PCI_CARD_NORMAL, 4, 1, 2, 3);
device_add(&w83787f_device);
device_add(&keyboard_ps2_pci_device);
+ // device_add(&sst_flash_29ee010_device);
+ device_add(&intel_flash_bxt_device);
+
return ret;
}
diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c
index 3ddc77186..9236b459e 100644
--- a/src/machine/m_at_slot1.c
+++ b/src/machine/m_at_slot1.c
@@ -365,13 +365,30 @@ machine_at_ax6bc_init(const machine_t *model)
pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3);
pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3);
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4);
- pci_register_slot(0x01, PCI_CARD_NORMAL, 1, 2, 3, 4);
+ pci_register_slot(0x01, PCI_CARD_NORMAL, 1, 2, 3, 4);
device_add(&i440bx_device);
device_add(&piix4e_device);
device_add(&keyboard_ps2_pci_device);
device_add(&w83977tf_device);
device_add(&sst_flash_29ee020_device);
- spd_register(SPD_TYPE_SDRAM, 0x7, 256);
+ spd_register(SPD_TYPE_SDRAM, 0x7, 256);
+
+ hwm_values_t machine_hwm = {
+ { /* fan speeds */
+ 3000, /* System */
+ 3000 /* CPU */
+ }, { /* temperatures */
+ 30 /* CPU */
+ }, { /* voltages */
+ 2050, /* VCORE (2.05V by default) */
+ RESISTOR_DIVIDER(12000, 150, 47), /* +12V (15K/4.7K divider suggested in the GL518SM datasheet) */
+ 3300 /* +3.3V */
+ }
+ };
+ if (model->cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type == CPU_PENTIUM2)
+ machine_hwm.voltages[0] = 2800; /* set higher VCORE (2.8V) for Klamath */
+ hwm_set_values(machine_hwm);
+ device_add(&gl518sm_2d_device);
return ret;
}
diff --git a/src/machine/m_at_socket4_5.c b/src/machine/m_at_socket4_5.c
index 0f21ca67a..5fa8c341c 100644
--- a/src/machine/m_at_socket4_5.c
+++ b/src/machine/m_at_socket4_5.c
@@ -39,6 +39,7 @@
#include <86box/sio.h>
#include <86box/video.h>
#include <86box/machine.h>
+
int
machine_at_excalibur_init(const machine_t *model)
{
@@ -159,6 +160,67 @@ machine_at_valuepointp60_init(const machine_t *model)
}
#endif
+int
+machine_at_opti560l_init(const machine_t *model)
+{
+ int ret;
+
+ ret = bios_load_linear(L"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_NO_IRQ_STEERING);
+ pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
+ pci_register_slot(0x01, PCI_CARD_SPECIAL, 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(&i430lx_device);
+ device_add(&keyboard_ps2_intel_ami_pci_device);
+ device_add(&sio_device);
+ device_add(&fdc37c665_device);
+ device_add(&intel_flash_bxt_ami_device);
+
+ return ret;
+}
+
+#if defined(DEV_BRANCH) && defined(USE_DELLXP60)
+int
+machine_at_dellxp60_init(const machine_t *model) // Doesn't like the regular SMC 665
+{
+ int ret;
+
+ ret = bios_load_linear(L"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_NO_IRQ_STEERING);
+ pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
+ pci_register_slot(0x01, PCI_CARD_SPECIAL, 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(&i430lx_device);
+ device_add(&keyboard_ps2_intel_ami_pci_device);
+ device_add(&sio_device);
+ device_add(&fdc37c665_device);
+ device_add(&intel_flash_bxt_ami_device);
+
+ return ret;
+}
+#endif
int
machine_at_p5mp3_init(const machine_t *model)
@@ -190,7 +252,6 @@ machine_at_p5mp3_init(const machine_t *model)
return ret;
}
-
int
machine_at_586mc1_init(const machine_t *model)
{
diff --git a/src/machine/m_at_socket7_s7.c b/src/machine/m_at_socket7_s7.c
index a2fa0cceb..a029b717c 100644
--- a/src/machine/m_at_socket7_s7.c
+++ b/src/machine/m_at_socket7_s7.c
@@ -238,7 +238,6 @@ machine_at_acerm3a_init(const machine_t *model)
device_add(&piix3_device);
device_add(&keyboard_ps2_pci_device);
device_add(&fdc37c932fr_device);
- device_add(&acerm3a_device);
device_add(&sst_flash_29ee010_device);
@@ -271,7 +270,6 @@ machine_at_acerv35n_init(const machine_t *model)
device_add(&piix3_device);
device_add(&keyboard_ps2_pci_device);
device_add(&fdc37c932fr_device);
- device_add(&acerm3a_device);
device_add(&sst_flash_29ee010_device);
@@ -983,6 +981,7 @@ machine_at_ficva502_init(const machine_t *model)
device_add(&keyboard_ps2_pci_device);
device_add(&fdc37c669_device);
device_add(&sst_flash_29ee010_device);
+ spd_register(SPD_TYPE_SDRAM, 0x3, 256);
return ret;
}
@@ -1013,6 +1012,7 @@ machine_at_ficpa2012_init(const machine_t *model)
device_add(&keyboard_ps2_pci_device);
device_add(&w83877f_device);
device_add(&sst_flash_39sf010_device);
+ spd_register(SPD_TYPE_SDRAM, 0x7, 512);
return ret;
}
diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c
index 04fcffd1f..41904d191 100644
--- a/src/machine/m_at_socket8.c
+++ b/src/machine/m_at_socket8.c
@@ -121,7 +121,6 @@ machine_at_v60n_init(const machine_t *model)
device_add(&piix3_device);
device_add(&keyboard_ps2_pci_device);
device_add(&fdc37c935_device);
- device_add(&acerm3a_device);
device_add(&sst_flash_29ee010_device);
return ret;
diff --git a/src/machine/m_at_sockets7.c b/src/machine/m_at_sockets7.c
index f66a29353..e2687986b 100644
--- a/src/machine/m_at_sockets7.c
+++ b/src/machine/m_at_sockets7.c
@@ -67,7 +67,7 @@ machine_at_ax59pro_init(const machine_t *model)
device_add(&keyboard_ps2_pci_device);
device_add(&w83877tf_device);
device_add(&sst_flash_39sf020_device);
- spd_register(SPD_TYPE_SDRAM, 0xF, 256);
+ spd_register(SPD_TYPE_SDRAM, 0x7, 512);
return ret;
}
@@ -90,7 +90,7 @@ machine_at_mvp3_init(const machine_t *model)
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(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2);
pci_register_slot(0x01, PCI_CARD_NORMAL, 1, 2, 3, 4);
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4);
device_add(&via_mvp3_device);
@@ -98,6 +98,7 @@ machine_at_mvp3_init(const machine_t *model)
device_add(&keyboard_ps2_pci_device);
device_add(&w83877tf_device);
device_add(&sst_flash_39sf010_device);
+ spd_register(SPD_TYPE_SDRAM, 0x3, 512);
return ret;
}
diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c
index 52ac3a523..651ef1d25 100644
--- a/src/machine/m_ps1.c
+++ b/src/machine/m_ps1.c
@@ -495,7 +495,7 @@ ps1_setup(int model)
/* Enable the PS/1 VGA controller. */
if (model == 2011)
device_add(&ps1vga_device);
- else
+ else if (model == 2021)
device_add(&ibm_ps1_2121_device);
}
@@ -558,6 +558,7 @@ machine_ps1_m2121_init(const machine_t *model)
return ret;
}
+
int
machine_ps1_m2133_init(const machine_t *model)
{
@@ -570,9 +571,9 @@ machine_ps1_m2133_init(const machine_t *model)
return ret;
ps1_common_init(model);
- device_add(&fdc_at_device);
device_add(&ide_isa_device);
device_add(&vl82c480_device);
+ device_add(&pc87332_ps1_device);
nmi_mask = 0x80;
@@ -582,6 +583,7 @@ machine_ps1_m2133_init(const machine_t *model)
return ret;
}
+
const device_t *
ps1_m2133_get_device(void)
{
diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c
index 5a1bf3fd5..3295fc884 100644
--- a/src/machine/m_ps2_mca.c
+++ b/src/machine/m_ps2_mca.c
@@ -964,6 +964,11 @@ static void ps2_mca_board_model_55sx_init()
static void mem_encoding_update()
{
mem_mapping_disable(&ps2.split_mapping);
+
+ if (ps2.split_size > 0)
+ mem_set_mem_state(ps2.split_addr, ps2.split_size << 10, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
+ if (((mem_size << 10) - (1 << 20)) > 0)
+ mem_set_mem_state(1 << 20, (mem_size << 10) - (1 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
ps2.split_addr = ((uint32_t) (ps2.mem_regs[0] & 0xf)) << 20;
@@ -993,12 +998,15 @@ static void mem_encoding_update()
ps2.split_phys = 0xa0000;
}
+ mem_set_mem_state(ps2.split_addr, ps2.split_size << 10, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
mem_mapping_set_exec(&ps2.split_mapping, &ram[ps2.split_phys]);
mem_mapping_set_addr(&ps2.split_mapping, ps2.split_addr, ps2.split_size << 10);
ps2_mca_log("PS/2 Model 80-111: Split memory block enabled at %08X\n", ps2.split_addr);
- } else
+ } else {
+ ps2.split_size = 0;
ps2_mca_log("PS/2 Model 80-111: Split memory block disabled\n");
+ }
}
static uint8_t mem_encoding_read(uint16_t addr, void *p)
@@ -1242,6 +1250,8 @@ static void ps2_mca_board_model_80_type2_init(int is486)
if (gfxcard == VID_INTERNAL)
device_add(&ps1vga_mca_device);
+
+ ps2.split_size = 0;
}
diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c
index 063612dad..80828826d 100644
--- a/src/machine/machine_table.c
+++ b/src/machine/machine_table.c
@@ -197,9 +197,11 @@ const machine_t machines[] = {
{ "[ACC 2168] Packard Bell PB410A", "pb410a", MACHINE_TYPE_486, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 4, 36, 1, 127, machine_at_pb410a_init, NULL },
/* 486 machines */
+ { "[OPTi 283] RYC Leopard LX", "rycleopardlx", MACHINE_TYPE_486, {{"IBM", cpus_IBM486SLC}, {"", NULL}, {"", NULL},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 16, 1, 127, machine_at_rycleopardlx_init, NULL },
{ "[OPTi 495] Award 486 clone", "award486", MACHINE_TYPE_486, {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_init, NULL },
{ "[OPTi 495] MR 486 clone", "mr486", MACHINE_TYPE_486, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_mr_init, NULL },
{ "[OPTi 495] Dataexpert SX495 (486)", "ami486", MACHINE_TYPE_486, {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL },
+ { "[OPTi 895] Jetway J-403TG", "403tg", MACHINE_TYPE_486, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT, 1, 64, 1, 127, machine_at_403tg_init, NULL },
{ "[SiS 471] ASUS VL/I-486SV2G (GX4)", "vli486sv2g", MACHINE_TYPE_486, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_vli486sv2g_init, NULL },
{ "[SiS 471] AMI 486 Clone", "ami471", MACHINE_TYPE_486, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_ami471_init, NULL },
#if defined(DEV_BRANCH) && defined(USE_WIN471)
@@ -221,9 +223,9 @@ const machine_t machines[] = {
{ "[i420EX] ASUS PVI-486AP4", "486ap4", MACHINE_TYPE_486, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 128, 1, 127, machine_at_486ap4_init, NULL },
{ "[i420ZX] ASUS PCI/I-486SP3G", "486sp3g", MACHINE_TYPE_486, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 128, 1, 127, machine_at_486sp3g_init, NULL },
{ "[i420TX] Intel Classic/PCI", "alfredo", MACHINE_TYPE_486, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_alfredo_init, NULL },
- { "[SiS 496] Lucky Star LS-486E", "ls486e", MACHINE_TYPE_486, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 128, 1, 127, machine_at_ls486e_init, NULL },
- { "[SiS 496] Rise Computer R418", "r418", MACHINE_TYPE_486, {{"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_r418_init, NULL },
- { "[SiS 496] Zida Tomato 4DP", "4dps", MACHINE_TYPE_486, {{"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 },
+ { "[SiS 496] Lucky Star LS-486E", "ls486e", MACHINE_TYPE_486, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 128, 1, 255, machine_at_ls486e_init, NULL },
+ { "[SiS 496] Rise Computer R418", "r418", MACHINE_TYPE_486, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 255, 1, 255, machine_at_r418_init, NULL },
+ { "[SiS 496] Zida Tomato 4DP", "4dps", MACHINE_TYPE_486, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 255, 1, 255, machine_at_4dps_init, NULL },
/* Socket 4 machines */
/* OPTi 596/597 */
@@ -235,7 +237,11 @@ const machine_t machines[] = {
{ "[i430LX] IBM PS/ValuePoint P60", "valuepointp60", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_valuepointp60_init, NULL },
#endif
{ "[i430LX] Intel Premiere/PCI", "revenge", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_batman_init, NULL },
- { "[i430LX] ASUS P/I-P5MP3", "p5mp3", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 192, 2, 127, machine_at_p5mp3_init, NULL },
+ { "[i430LX] Dell OptiPlex 560L", "opti560l", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_opti560l_init, NULL },
+#if defined(DEV_BRANCH) && defined(USE_VPP60)
+ { "[i430LX] Dell Dimension XPS P60", "dellxp60", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_dellxp60_init, NULL },
+#endif
+ { "[i430LX] ASUS P/I-P5MP3", "p5mp3", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 192, 2, 127, machine_at_p5mp3_init, NULL },
{ "[i430LX] Micro Star 586MC1", "586mc1", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_586mc1_init, NULL },
/* Socket 5 machines */
@@ -297,12 +303,12 @@ const machine_t machines[] = {
{ "[VIA VPX] FIC VA-502", "ficva502", MACHINE_TYPE_SOCKET7, MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_ficva502_init, NULL },
/* Apollo VP3 */
- { "[VIA VP3] FIC PA-2012", "ficpa2012", MACHINE_TYPE_SOCKET7, MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_ficpa2012_init, NULL },
+ { "[VIA VP3] FIC PA-2012", "ficpa2012", MACHINE_TYPE_SOCKET7, MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_ficpa2012_init, NULL },
/* Super Socket 7 machines */
/* Apollo MVP3 */
- { "[VIA MVP3] AOpen AX59 Pro", "ax59pro", MACHINE_TYPE_SOCKETS7, MACHINE_CPUS_PENTIUM_SS7, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 255, machine_at_ax59pro_init, NULL },
- { "[VIA MVP3] FIC VA-503+", "ficva503p", MACHINE_TYPE_SOCKETS7, MACHINE_CPUS_PENTIUM_SS7, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 255, machine_at_mvp3_init, NULL },
+ { "[VIA MVP3] AOpen AX59 Pro", "ax59pro", MACHINE_TYPE_SOCKETS7, MACHINE_CPUS_PENTIUM_SS7, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 255, machine_at_ax59pro_init, NULL },
+ { "[VIA MVP3] FIC VA-503+", "ficva503p", MACHINE_TYPE_SOCKETS7, MACHINE_CPUS_PENTIUM_SS7, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 255, machine_at_mvp3_init, NULL },
/* Socket 8 machines */
/* 440FX */
@@ -348,13 +354,13 @@ const machine_t machines[] = {
/* 440BX */
{ "[i440BX] ASUS CUBX", "cubx", MACHINE_TYPE_SOCKET370, {{"Intel", cpus_Celeron}, {"VIA", cpus_Cyrix3}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 255, machine_at_cubx_init, NULL },
{ "[i440BX] A-Trend ATC7020BXII", "atc7020bxii", MACHINE_TYPE_SOCKET370, {{"Intel", cpus_Celeron}, {"VIA", cpus_Cyrix3}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 255, machine_at_atc7020bxii_init, NULL },
- { "[i440BX] AmazePC AM-BX133", "ambx133", MACHINE_TYPE_SOCKET370, {{"Intel", cpus_Celeron}, {"VIA", cpus_Cyrix3}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 255, machine_at_ambx133_init, NULL },
+ { "[i440BX] AmazePC AM-BX133", "ambx133", MACHINE_TYPE_SOCKET370, {{"Intel", cpus_Celeron}, {"VIA", cpus_Cyrix3}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 255, machine_at_ambx133_init, NULL },
/* 440ZX */
{ "[i440ZX] Soltek SL-63A1", "63a", MACHINE_TYPE_SOCKET370, {{"Intel", cpus_Celeron}, {"VIA", cpus_Cyrix3}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 255, machine_at_63a_init, NULL },
/* VIA Apollo Pro */
- { "[VIA Apollo Pro] PC Partner APAS3", "apas3", MACHINE_TYPE_SOCKET370, {{"Intel", cpus_Celeron}, {"VIA", cpus_Cyrix3}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 255, machine_at_apas3_init, NULL },
+ { "[VIA Apollo Pro] PC Partner APAS3", "apas3", MACHINE_TYPE_SOCKET370, {{"Intel", cpus_Celeron}, {"VIA", cpus_Cyrix3}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 255, machine_at_apas3_init, NULL },
{ NULL, NULL, MACHINE_TYPE_NONE, {{"", 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 572c5878a..29d67d1a1 100644
--- a/src/mem/mem.c
+++ b/src/mem/mem.c
@@ -2520,6 +2520,11 @@ mem_reset(void)
{
uint32_t c, m, m2;
+#if FIXME
+ memset(ff_array, 0xff, sizeof(ff_array));
+#endif
+ memset(page_ff, 0xff, sizeof(page_ff));
+
m = 1024UL * mem_size;
if (ram != NULL) {
free(ram);
@@ -2654,6 +2659,9 @@ mem_log("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz);
#endif
}
+ memset(read_mapping, 0x00, sizeof(read_mapping));
+ memset(write_mapping, 0x00, sizeof(write_mapping));
+
memset(_mem_exec, 0x00, sizeof(_mem_exec));
memset(&base_mapping, 0x00, sizeof(base_mapping));
@@ -2664,6 +2672,8 @@ mem_log("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz);
MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
mem_set_mem_state_both(0x0a0000, 0x60000,
MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ mem_set_mem_state_both((mem_size << 10), (uint32_t) (0x100000000ULL - (mem_size << 10)),
+ MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
mem_mapping_add(&ram_low_mapping, 0x00000,
(mem_size > 640) ? 0xa0000 : mem_size * 1024,
@@ -2765,11 +2775,6 @@ mem_init(void)
writelookup2 = malloc((1<<20)*sizeof(uintptr_t));
#endif
-#if FIXME
- memset(ff_array, 0xff, sizeof(ff_array));
-#endif
- memset(page_ff, 0xff, sizeof(page_ff));
-
/* Reset the memory state. */
mem_reset();
}
diff --git a/src/mem/spd.c b/src/mem/spd.c
index c0f288793..f65417f9f 100644
--- a/src/mem/spd.c
+++ b/src/mem/spd.c
@@ -26,12 +26,14 @@
#include <86box/smbus.h>
#include <86box/spd.h>
#include <86box/version.h>
+#include <86box/machine.h>
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define SPD_ROLLUP(x) ((x) >= 16 ? ((x) - 15) : (x))
+int spd_present = 0;
spd_t *spd_devices[SPD_MAX_SLOTS];
uint8_t spd_data[SPD_MAX_SLOTS][SPD_DATA_SIZE];
@@ -117,6 +119,8 @@ spd_close(void *priv)
spd_write_byte, NULL, NULL, NULL,
dev);
+ spd_present = 0;
+
free(dev);
}
@@ -133,6 +137,8 @@ spd_init(const device_t *info)
spd_write_byte, NULL, NULL, NULL,
dev);
+ spd_present = 1;
+
return dev;
}
@@ -157,41 +163,13 @@ comp_ui16_rev(const void *elem1, const void *elem2)
void
-spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size)
+spd_populate(uint16_t *vslots, uint8_t slot_count, uint16_t total_size, uint16_t min_module_size, uint16_t max_module_size, uint8_t enable_asym)
{
- uint8_t slot, slot_count, vslot, next_empty_vslot, i, split;
- uint16_t min_module_size, total_size, vslots[SPD_MAX_SLOTS], asym;
- device_t *info;
- spd_edo_t *edo_data;
- spd_sdram_t *sdram_data;
-
- /* determine the minimum module size for this RAM type */
- switch (ram_type) {
- case SPD_TYPE_FPM:
- case SPD_TYPE_EDO:
- min_module_size = SPD_MIN_SIZE_EDO;
- break;
-
- case SPD_TYPE_SDRAM:
- min_module_size = SPD_MIN_SIZE_SDRAM;
- break;
-
- default:
- spd_log("SPD: unknown RAM type 0x%02X\n", ram_type);
- return;
- }
-
- /* count how many (real) slots are enabled */
- slot_count = 0;
- for (slot = 0; slot < SPD_MAX_SLOTS; slot++) {
- vslots[slot] = 0;
- if (slot_mask & (1 << slot)) {
- slot_count++;
- }
- }
+ uint8_t vslot, next_empty_vslot, split, i;
+ uint16_t asym;
/* populate vslots with modules in power-of-2 capacities */
- total_size = (mem_size >> 10);
+ memset(vslots, 0x00, SPD_MAX_SLOTS << 1);
for (vslot = 0; vslot < slot_count && total_size; vslot++) {
/* populate slot */
vslots[vslot] = (1 << log2_ui16(MIN(total_size, max_module_size)));
@@ -206,15 +184,17 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size)
/* did we populate all the RAM? */
if (total_size) {
- /* work backwards to add the missing RAM as asymmetric modules */
- vslot = slot_count - 1;
- do {
- asym = (1 << log2_ui16(MIN(total_size, vslots[vslot])));
- if (vslots[vslot] + asym <= max_module_size) {
- vslots[vslot] += asym;
- total_size -= asym;
- }
- } while (vslot-- > 0 && total_size);
+ /* work backwards to add the missing RAM as asymmetric modules if possible */
+ if (enable_asym) {
+ vslot = slot_count - 1;
+ do {
+ asym = (1 << log2_ui16(MIN(total_size, vslots[vslot])));
+ if (vslots[vslot] + asym <= max_module_size) {
+ vslots[vslot] += asym;
+ total_size -= asym;
+ }
+ } while ((vslot-- > 0) && total_size);
+ }
if (total_size) /* still not enough */
spd_log("SPD: not enough RAM slots (%d) to cover memory (%d MB short)\n", slot_count, total_size);
@@ -242,12 +222,52 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size)
spd_log("SPD: splitting vslot %d (%d MB) into %d and %d (%d MB each)\n", vslot, vslots[vslot], vslot, next_empty_vslot, (vslots[vslot] >> 1));
vslots[vslot] = vslots[next_empty_vslot] = (vslots[vslot] >> 1);
split = 1;
+ break;
}
- /* re-sort vslots by descending capacity if any modules were split */
+ /* sort vslots by descending capacity if any were split */
if (split)
qsort(vslots, slot_count, sizeof(uint16_t), comp_ui16_rev);
}
+}
+
+
+void
+spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size)
+{
+ uint8_t slot, slot_count, vslot, i;
+ uint16_t min_module_size, vslots[SPD_MAX_SLOTS], asym;
+ device_t *info;
+ spd_edo_t *edo_data;
+ spd_sdram_t *sdram_data;
+
+ /* determine the minimum module size for this RAM type */
+ switch (ram_type) {
+ case SPD_TYPE_FPM:
+ case SPD_TYPE_EDO:
+ min_module_size = SPD_MIN_SIZE_EDO;
+ break;
+
+ case SPD_TYPE_SDRAM:
+ min_module_size = SPD_MIN_SIZE_SDRAM;
+ break;
+
+ default:
+ spd_log("SPD: unknown RAM type 0x%02X\n", ram_type);
+ return;
+ }
+
+ /* count how many (real) slots are enabled */
+ slot_count = 0;
+ for (slot = 0; slot < SPD_MAX_SLOTS; slot++) {
+ vslots[slot] = 0;
+ if (slot_mask & (1 << slot)) {
+ slot_count++;
+ }
+ }
+
+ /* populate vslots */
+ spd_populate(vslots, slot_count, (mem_size >> 10), min_module_size, max_module_size, 1);
/* register SPD devices and populate their data according to the vslots */
vslot = 0;
@@ -382,3 +402,59 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size)
vslot++;
}
}
+
+
+void
+spd_write_drbs(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, vslots[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) >> 1; /* amount of "DIMM"s, also used to determine the maximum "DIMM" size */
+ spd_populate(vslots, dimm, (mem_size >> 10), drb_unit, 1 << (log2_ui16(machines[machine].max_ram / dimm)), 0);
+ }
+
+ /* Write DRBs for each row. */
+ spd_log("Writing DRBs... regs=[%02X:%02X] unit=%d\n", reg_min, reg_max, drb_unit);
+ for (row = 0; row <= (reg_max - reg_min); row++) {
+ dimm = (row >> 1);
+ size = 0;
+
+ if (spd_present) {
+ /* SPD enabled: use SPD info for this slot, if present. */
+ if (spd_devices[dimm]) {
+ if (spd_devices[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) ? 0 : drb_unit);
+ else
+ size = ((row & 1) ? spd_devices[dimm]->row2 : spd_devices[dimm]->row1);
+ }
+ } else {
+ /* No SPD: use the values calculated above. */
+ size = (vslots[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("DRB[%d] = %d MB (%02Xh raw)\n", row, size, regs[drb]);
+ }
+}
diff --git a/src/pit.c b/src/pit.c
index b33adbc1a..fec976d79 100644
--- a/src/pit.c
+++ b/src/pit.c
@@ -1030,9 +1030,9 @@ pit_set_clock(int clock)
isa_timing = (cpuclock / (double)8000000.0);
if (cpu_64bitbus)
- bus_timing = (cpuclock / ((double)cpu_busspeed / 2));
+ bus_timing = (cpuclock / ((double)cpu_busspeed / 2));
else
- bus_timing = (cpuclock / (double)cpu_busspeed);
+ 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/sio/sio_fdc37c93x.c b/src/sio/sio_fdc37c93x.c
index 7e08ab373..2f6a4a61b 100644
--- a/src/sio/sio_fdc37c93x.c
+++ b/src/sio/sio_fdc37c93x.c
@@ -108,8 +108,11 @@ static uint8_t
fdc37c93x_gpio_read(uint16_t port, void *priv)
{
fdc37c93x_t *dev = (fdc37c93x_t *) priv;
+ uint8_t ret = 0xff;
- return dev->gpio_regs[port & 1];
+ ret = dev->gpio_regs[port & 1];
+
+ return ret;
}
@@ -118,7 +121,8 @@ fdc37c93x_gpio_write(uint16_t port, uint8_t val, void *priv)
{
fdc37c93x_t *dev = (fdc37c93x_t *) priv;
- dev->gpio_regs[port & 1] = val;
+ if (!(port & 1))
+ dev->gpio_regs[0] = (dev->gpio_regs[0] & 0xfc) | (val & 0x03);
}
@@ -756,8 +760,8 @@ fdc37c93x_init(const device_t *info)
dev->chip_id = info->local;
- dev->gpio_regs[0] = 0xFD;
- dev->gpio_regs[1] = 0xFF;
+ dev->gpio_regs[0] = 0xff;
+ dev->gpio_regs[1] = 0xfd;
if (dev->chip_id == 0x30) {
dev->nvr = device_add(&at_nvr_device);
diff --git a/src/sio/sio_pc87332.c b/src/sio/sio_pc87332.c
index 3a9b04785..03cbcf823 100644
--- a/src/sio/sio_pc87332.c
+++ b/src/sio/sio_pc87332.c
@@ -41,7 +41,6 @@ typedef struct {
int cur_reg;
fdc_t *fdc;
serial_t *uart[2];
- nvr_t *nvr;
} pc87332_t;
@@ -292,12 +291,15 @@ pc87332_init(const device_t *info)
dev->uart[0] = device_add_inst(&ns16550_device, 1);
dev->uart[1] = device_add_inst(&ns16550_device, 2);
- // dev->nvr = device_add(&piix4_nvr_device);
-
pc87332_reset(dev);
- io_sethandler(0x02e, 0x0002,
- pc87332_read, NULL, NULL, pc87332_write, NULL, NULL, dev);
+ if (info->local == 1) {
+ io_sethandler(0x398, 0x0002,
+ pc87332_read, NULL, NULL, pc87332_write, NULL, NULL, dev);
+ } else {
+ io_sethandler(0x02e, 0x0002,
+ pc87332_read, NULL, NULL, pc87332_write, NULL, NULL, dev);
+ }
return dev;
}
@@ -311,3 +313,13 @@ const device_t pc87332_device = {
NULL, NULL, NULL,
NULL
};
+
+
+const device_t pc87332_ps1_device = {
+ "National Semiconductor PC87332 Super I/O (IBM PS/1 Model 2133 EMEA 451)",
+ 0,
+ 1,
+ pc87332_init, pc87332_close, NULL,
+ NULL, NULL, NULL,
+ NULL
+};
diff --git a/src/sio/sio_ps1_m2133.c b/src/sio/sio_ps1_m2133.c
deleted file mode 100644
index 264dd78c7..000000000
--- a/src/sio/sio_ps1_m2133.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * 86Box A hypervisor and IBM PC system emulator that specializes in
- * running old operating systems and software designed for IBM
- * PC systems and compatibles from 1981 through fairly recent
- * system designs based on the PCI bus.
- *
- * This file is part of the 86Box distribution.
- *
- * Implementation of the chipset used by the IBM PS/1 Model 2133 EMEA 451
- * whose name is currently unknown.
- *
- * Authors: Sarah Walker,
- *
- * Copyright 2020 Sarah Walker.
- */
-#include
-#include
-#include
-#include
-#include
-#include <86box/86box.h>
-#include <86box/io.h>
-#include <86box/timer.h>
-#include <86box/device.h>
-#include <86box/lpt.h>
-#include <86box/serial.h>
-#include <86box/sio.h>
-
-
-typedef struct ps1_m2133_sio_t
-{
- int idx;
- uint8_t regs[3];
- serial_t *uart[2];
-} ps1_m2133_sio_t;
-
-static uint16_t ps1_lpt_io[4] = {0x378, 0x3bc, 0x278, 0x378};
-static uint16_t ps1_com_io[4] = {0x3f8, 0x2f8, 0x3e8, 0x2e8};
-
-static uint8_t
-ps1_m2133_read(uint16_t port, void *p)
-{
- ps1_m2133_sio_t *dev = (ps1_m2133_sio_t *)p;
- uint8_t ret = 0xff;
-
- switch (port) {
- case 0x398:
- ret = dev->idx;
- break;
-
- case 0x399:
- if (dev->idx < 3)
- ret = dev->regs[dev->idx];
- break;
- }
- return ret;
-}
-
-static void
-ps1_m2133_write(uint16_t port, uint8_t val, void *p)
-{
- ps1_m2133_sio_t *dev = (ps1_m2133_sio_t *)p;
- uint16_t lpt_addr;
-
- switch (port) {
- case 0x398:
- dev->idx = val;
- break;
-
- case 0x399:
- if (dev->idx < 3) {
- dev->regs[dev->idx] = val;
-
- lpt1_remove();
- lpt2_remove();
- serial_remove(dev->uart[0]);
- serial_remove(dev->uart[1]);
-
- if (dev->regs[0] & 1) {
- lpt_addr = ps1_lpt_io[dev->regs[1] & 3];
-
- lpt1_init(lpt_addr);
- if ((lpt_addr == 0x378) || (lpt_addr == 0x3bc)) {
- if (((dev->regs[1] & 3) == 3) && (lpt_addr == 0x378)) {
- lpt1_irq(5);
- } else {
- lpt1_irq(7);
- }
- } else if (lpt_addr == 0x278) {
- lpt1_irq(5);
- }
- }
-
- if (dev->regs[0] & 2)
- serial_setup(dev->uart[0], ps1_com_io[(dev->regs[1] >> 2) & 3], 4);
- if (dev->regs[0] & 4)
- serial_setup(dev->uart[1], ps1_com_io[(dev->regs[1] >> 4) & 3], 3);
- }
- break;
- }
-}
-
-static void
-ps1_m2133_reset(ps1_m2133_sio_t *dev)
-{
- serial_remove(dev->uart[0]);
- serial_setup(dev->uart[0], SERIAL1_ADDR, SERIAL1_IRQ);
-
- serial_remove(dev->uart[1]);
- serial_setup(dev->uart[1], SERIAL2_ADDR, SERIAL2_IRQ);
-
- lpt1_remove();
- lpt1_init(0x378);
- lpt1_irq(7);
-}
-
-static void *
-ps1_m2133_init(const device_t *info)
-{
- ps1_m2133_sio_t *dev = (ps1_m2133_sio_t *) malloc(sizeof(ps1_m2133_sio_t));
- memset(dev, 0, sizeof(ps1_m2133_sio_t));
-
- dev->uart[0] = device_add_inst(&ns16450_device, 1);
- dev->uart[1] = device_add_inst(&ns16450_device, 2);
-
- io_sethandler(0x0398, 0x0002, ps1_m2133_read, NULL, NULL, ps1_m2133_write, NULL, NULL, dev);
-
- ps1_m2133_reset(dev);
-
- return dev;
-}
-
-static void
-ps1_m2133_close(void *p)
-{
- ps1_m2133_sio_t *dev = (ps1_m2133_sio_t *)p;
-
- free(dev);
-}
-
-const device_t ps1_m2133_sio = {
- "IBM PS/1 Model 2133 EMEA 451 Super I/O",
- 0,
- 0,
- ps1_m2133_init, ps1_m2133_close, NULL,
- NULL, NULL, NULL,
- NULL
-};
diff --git a/src/sio/sio_w83787f.c b/src/sio/sio_w83787f.c
index bc1a4792c..8fe4f4bf7 100644
--- a/src/sio/sio_w83787f.c
+++ b/src/sio/sio_w83787f.c
@@ -145,27 +145,24 @@ w83787f_serial_handler(w83787f_t *dev, int uart)
static void
w83787f_lpt_handler(w83787f_t *dev)
{
- int ptrs0 = !!(dev->regs[1] & 4);
- int ptrs1 = !!(dev->regs[1] & 5);
- int ptrs, irq = 7;
+ int ptras = (dev->regs[1] >> 4) & 0x03;
+ int irq = 7;
uint16_t addr = 0x378, enable = 1;
- ptrs = (ptrs1 << 1) | ptrs0;
-
- switch (ptrs) {
- case 0:
+ switch (ptras) {
+ case 0x00:
addr = 0x3bc;
irq = 7;
break;
- case 1:
+ case 0x01:
addr = 0x278;
irq = 5;
break;
- case 2:
+ case 0x02:
addr = 0x378;
irq = 7;
break;
- case 3:
+ case 0x03:
default:
enable = 0;
break;
@@ -186,7 +183,7 @@ static void
w83787f_fdc_handler(w83787f_t *dev)
{
fdc_remove(dev->fdc);
- if (!(dev->regs[0] & 0x20))
+ if (!(dev->regs[0] & 0x20) && !(dev->regs[6] & 0x08))
fdc_set_base(dev->fdc, (dev->regs[0] & 0x10) ? 0x03f0 : 0x0370);
}
@@ -254,11 +251,8 @@ w83787f_write(uint16_t port, uint8_t val, void *priv)
w83787f_lpt_handler(dev);
break;
case 6:
- if (valxor & 0x08) {
- fdc_remove(dev->fdc);
- if (!(dev->regs[6] & 0x08))
- fdc_set_base(dev->fdc, 0x03f0);
- }
+ if (valxor & 0x08)
+ w83787f_fdc_handler(dev);
break;
case 7:
if (valxor & 0x03)
@@ -286,6 +280,9 @@ w83787f_write(uint16_t port, uint8_t val, void *priv)
if (valxor & 0x80)
w83787f_lpt_handler(dev);
break;
+ case 0xB:
+ pclog("Writing %02X to CRB\n", val);
+ break;
case 0xC:
if (valxor & 0x20)
w83787f_remap(dev);
diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c
index c169253b0..478edd8f4 100644
--- a/src/video/vid_cl54xx.c
+++ b/src/video/vid_cl54xx.c
@@ -702,7 +702,7 @@ gd54xx_in(uint16_t addr, void *p)
case 0x17:
ret = svga->gdcreg[0x17] & ~(7 << 3);
if (svga->crtc[0x27] <= CIRRUS_ID_CLGD5429) {
- if (svga->crtc[0x27] == CIRRUS_ID_CLGD5428) {
+ if ((svga->crtc[0x27] == CIRRUS_ID_CLGD5428) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5426)) {
if (gd54xx->vlb)
ret |= (CL_GD5428_SYSTEM_BUS_VESA << 3);
else if (gd54xx->mca)
@@ -3023,9 +3023,9 @@ static void
#endif
case CIRRUS_ID_CLGD5426:
- if (info->local & 0x200) {
+ if (info->local & 0x200)
romfn = NULL;
- } else
+ else
romfn = BIOS_GD5426_PATH;
break;
@@ -3082,15 +3082,18 @@ static void
vram = 1;
gd54xx->vram_size = 1 << 20;
} else {
- if (id >= CIRRUS_ID_CLGD5420)
- vram = device_get_config_int("memory");
- else
- vram = 0;
-
+ if (id >= CIRRUS_ID_CLGD5420) {
+ if ((id == CIRRUS_ID_CLGD5426) && (info->local & 0x200))
+ vram = 1;
+ else
+ vram = device_get_config_int("memory");
+ } else
+ vram = 0;
+
if (vram)
- gd54xx->vram_size = vram << 20;
+ gd54xx->vram_size = vram << 20;
else
- gd54xx->vram_size = 1 << 19;
+ gd54xx->vram_size = 1 << 19;
}
gd54xx->vram_mask = gd54xx->vram_size - 1;
@@ -3556,7 +3559,7 @@ const device_t gd5426_onboard_device =
NULL,
gd54xx_speed_changed,
gd54xx_force_redraw,
- gd5428_config
+ NULL
};
const device_t gd5428_isa_device =
diff --git a/src/win/86Box.rc b/src/win/86Box.rc
index 9b0d829eb..1265799cf 100644
--- a/src/win/86Box.rc
+++ b/src/win/86Box.rc
@@ -8,8 +8,6 @@
*
* Application resource script for Windows.
*
- *
- *
* Authors: Miran Grca,
* Fred N. van Kempen,
* David Hrdlička,
@@ -164,7 +162,7 @@ BEGIN
#endif
POPUP "&Help"
BEGIN
- MENUITEM "&About " EMU_NAME "...", IDM_ABOUT
+ MENUITEM "&About 86Box...", IDM_ABOUT
END
END
@@ -319,7 +317,7 @@ END
DLG_CONFIG DIALOG DISCARDABLE 0, 0, 366, 251
STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
-CAPTION EMU_NAME " Settings"
+CAPTION "86Box Settings"
FONT 9, "Segoe UI"
BEGIN
DEFPUSHBUTTON "OK",IDOK,246,230,50,14
@@ -878,7 +876,7 @@ END
STRINGTABLE DISCARDABLE
BEGIN
- 2048 EMU_NAME
+ 2048 "86Box"
IDS_2049 "Error"
IDS_2050 "Fatal error"
IDS_2051 "Are you sure you want to save the settings?"
@@ -886,7 +884,7 @@ BEGIN
IDS_2053 "Speed"
IDS_2054 "ZIP %03i %i (%s): %ls"
IDS_2055 "ZIP images (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0"
- IDS_2056 EMU_NAME " could not find any usable ROM images.\n\nPlease download a ROM set from " EMU_ROMS_URL " and extract it into the ""roms"" directory."
+ IDS_2056 "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the ""roms"" directory."
IDS_2057 "(empty)"
IDS_2058 "ZIP images (*.IM?;*.ZDI)\0*.IM?;*.ZDI\0All files (*.*)\0*.*\0"
IDS_2059 "Turbo"
@@ -951,19 +949,19 @@ BEGIN
IDS_2110 "Unable to initialize FreeType"
IDS_2111 "Unable to initialize SDL, SDL2.dll is required"
IDS_2112 "Are you sure you want to hard reset the emulated machine?"
- IDS_2113 "Are you sure you want to exit " EMU_NAME "?"
+ IDS_2113 "Are you sure you want to exit 86Box?"
IDS_2114 "Unable to initialize Ghostscript"
IDS_2115 "MO %i (%03i): %ls"
IDS_2116 "MO images (*.IM?)\0*.IM?\0All files (*.*)\0*.*\0"
- IDS_2117 "Welcome to " EMU_NAME "!"
+ IDS_2117 "Welcome to 86Box!"
IDS_2118 "Internal controller"
IDS_2119 "Exit"
IDS_2120 "No ROMs found"
IDS_2121 "Save changes\nThis will hard reset the emulated machine."
IDS_2122 "Discard changes\nAll changes made to the settings will be lost."
IDS_2123 "Cancel\nGo back to the Settings window."
- IDS_2124 "About " EMU_NAME
- IDS_2125 EMU_NAME " v" EMU_VERSION
+ IDS_2124 "About 86Box"
+ IDS_2125 "86Box v2.10"
IDS_2126 "An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, MoochMcGee, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2. See LICENSE for more information."
IDS_2127 "OK"
IDS_2128 "Hardware not available"
@@ -1104,9 +1102,9 @@ BEGIN
VALUE "FileDescription", EMU_NAME "\0"
VALUE "FileVersion", EMU_VERSION "\0"
VALUE "InternalName", EMU_NAME "\0"
- VALUE "LegalCopyright", "Copyright © 2007-" COPYRIGHT_YEAR " " EMU_NAME " contributors\0"
- VALUE "OriginalFilename", EMU_NAME ".exe\0"
- VALUE "ProductName", EMU_NAME " Emulator\0"
+ VALUE "LegalCopyright", "Copyright © 2007-2020 " EMU_NAME " contributors\0"
+ VALUE "OriginalFilename", "86box.exe\0"
+ VALUE "ProductName", EMU_NAME "\0"
VALUE "ProductVersion", EMU_VERSION "\0"
END
END
diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw
index 2334fa603..69983be69 100644
--- a/src/win/Makefile.mingw
+++ b/src/win/Makefile.mingw
@@ -87,6 +87,9 @@ ifeq ($(DEV_BUILD), y)
ifndef GUSMAX
GUSMAX := y
endif
+ ifndef DELLXP60
+ DELLXP60 := y
+ endif
else
ifndef DEBUG
DEBUG := n
@@ -148,6 +151,9 @@ else
ifndef GUSMAX
GUSMAX := n
endif
+ ifndef DELLXP60
+ DELLXP60 := n
+ endif
endif
# Defaults for several build options (possibly defined in a chained file.)
@@ -530,6 +536,10 @@ ifeq ($(GUSMAX), y)
OPTS += -DUSE_GUSMAX
endif
+ifeq ($(DELLXP60), y)
+OPTS += -DUSE_DELLXP60
+endif
+
endif
@@ -559,10 +569,10 @@ CPUOBJ := cpu.o cpu_table.o \
x86seg.o x87.o x87_timings.o \
$(DYNARECOBJ)
-CHIPSETOBJ := acc2168.o acer_m3a.o cs8230.o ali1429.o headland.o i82335.o \
+CHIPSETOBJ := acc2168.o cs8230.o ali1429.o headland.o i82335.o \
intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \
- neat.o opti495.o opti5x7.o scamp.o scat.o \
- sis_85c310.o sis_85c471.o sis_85c496.o \
+ neat.o opti495.o opti895.o opti5x7.o scamp.o scat.o \
+ sis_85c310.o sis_85c471.o sis_85c496.o opti283.o \
via_apollo.o via_vpx.o via_vt82c586b.o via_vt82c596b.o wd76c10.o vl82c480.o \
amd640.o
@@ -582,7 +592,7 @@ MCHOBJ := machine.o machine_table.o \
m_at_socket4_5.o m_at_socket7_s7.o m_at_sockets7.o \
m_at_socket8.o m_at_slot1.o m_at_slot2.o m_at_socket370.o
-DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o ibm_5161.o isamem.o isartc.o lpt.o postcard.o serial.o \
+DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o ibm_5161.o isamem.o isartc.o lpt.o postcard.o serial.o \
smbus.o smbus_piix4.o \
keyboard.o \
keyboard_xt.o keyboard_at.o \
@@ -595,7 +605,6 @@ SIOOBJ := sio_acc3221.o \
sio_fdc37c661.o sio_fdc37c66x.o sio_fdc37c669.o \
sio_fdc37c93x.o \
sio_pc87306.o sio_pc87307.o sio_pc87309.o sio_pc87332.o \
- sio_ps1_m2133.o \
sio_w83787f.o \
sio_w83877f.o sio_w83977f.o \
sio_um8669f.o