diff --git a/src/include/86box/nvr.h b/src/include/86box/nvr.h index 511b88643..f923200e7 100644 --- a/src/include/86box/nvr.h +++ b/src/include/86box/nvr.h @@ -50,7 +50,7 @@ # define EMU_NVR_H -#define NVR_MAXSIZE 256 /* max size of NVR data */ +#define NVR_MAXSIZE 512 /* max size of NVR data */ /* Conversion from BCD to Binary and vice versa. */ #define RTC_BCD(x) (((x) % 10) | (((x) / 10) << 4)) @@ -113,7 +113,10 @@ extern void nvr_time_get(struct tm *); extern void nvr_time_set(struct tm *); extern void nvr_at_handler(int set, uint16_t base, nvr_t *nvr); +extern void nvr_at_sec_handler(int set, uint16_t base, nvr_t *nvr); extern void nvr_wp_set(int set, int h, nvr_t *nvr); +extern void nvr_bank_set(int base, uint8_t bank, nvr_t *nvr); +extern void nvr_lock_set(int base, int size, int lock, nvr_t *nvr); #endif /*EMU_NVR_H*/ diff --git a/src/machine/m_at_socket4_5.c b/src/machine/m_at_socket4_5.c index 02e4074e2..590508002 100644 --- a/src/machine/m_at_socket4_5.c +++ b/src/machine/m_at_socket4_5.c @@ -427,7 +427,7 @@ machine_at_vectra54_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 219399bb4..05df872bf 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -198,7 +198,7 @@ const machine_t machines[] = { { "[Socket 5 FX] AMI Apollo", "apollo", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_apollo_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_VECTRA54) - { "[Socket 5 FX] HP Vectra VL 5 Series 4", "vectra54", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 767, machine_at_vectra54_init, NULL }, + { "[Socket 5 FX] HP Vectra VL 5 Series 4", "vectra54", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 511, machine_at_vectra54_init, NULL }, #endif { "[Socket 5 FX] Intel Advanced/ZP", "zappa", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_zappa_init, NULL }, { "[Socket 5 FX] PC Partner MB500N", "mb500n", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_mb500n_init, NULL }, diff --git a/src/nvr_at.c b/src/nvr_at.c index 0ed657760..4e19e6b96 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -296,7 +296,8 @@ typedef struct { uint8_t cent; uint8_t def, flags; - uint8_t addr[8], wp[2]; + uint8_t addr[8], wp[2], + bank[8], *lock; int16_t count, state; @@ -566,6 +567,8 @@ nvr_write(uint16_t addr, uint8_t val, void *priv) sub_cycles(ISA_CYCLES(8)); if (addr & 1) { + if (local->bank[addr_id] == 0xff) + return; old = nvr->regs[local->addr[addr_id]]; switch(local->addr[addr_id]) { case RTC_REGA: @@ -603,6 +606,8 @@ nvr_write(uint16_t addr, uint8_t val, void *priv) break; if ((local->addr[addr_id] >= 0xb8) && (local->addr[addr_id] <= 0xbf) && local->wp[1]) break; + if (local->lock[local->addr[addr_id]]) + break; if (nvr->regs[local->addr[addr_id]] != val) { nvr->regs[local->addr[addr_id]] = val; nvr_dosave = 1; @@ -627,6 +632,8 @@ nvr_write(uint16_t addr, uint8_t val, void *priv) local->addr[addr_id] &= 0x7f; else if ((addr_id == 0x1) && (local->flags & FLAG_PIIX4)) local->addr[addr_id] = (local->addr[addr_id] & 0x7f) | 0x80; + if (local->bank[addr_id] > 0) + local->addr[addr_id] = (local->addr[addr_id] & 0x7f) | (0x80 * local->bank[addr_id]); if (!(machines[machine].flags & MACHINE_MCA) && !(machines[machine].flags & MACHINE_NONMI)) nmi_mask = (~val & 0x80); @@ -646,6 +653,9 @@ nvr_read(uint16_t addr, void *priv) sub_cycles(ISA_CYCLES(8)); + if ((addr & 1) && (local->bank[addr_id] == 0xff)) + return 0xff; + if (addr & 1) switch(local->addr[addr_id]) { case RTC_REGA: ret = (nvr->regs[RTC_REGA] & 0x7f) | local->stat; @@ -693,6 +703,22 @@ nvr_read(uint16_t addr, void *priv) } +/* Secondary NVR write - used by SMC. */ +static void +nvr_sec_write(uint16_t addr, uint8_t val, void *priv) +{ + nvr_write(0x72 + (addr & 1), val, priv); +} + + +/* Secondary NVR read - used by SMC. */ +static uint8_t +nvr_sec_read(uint16_t addr, void *priv) +{ + return nvr_read(0x72 + (addr & 1), priv); +} + + /* Reset the RTC state to 1980/01/01 00:00. */ static void nvr_reset(nvr_t *nvr) @@ -771,6 +797,14 @@ nvr_at_handler(int set, uint16_t base, nvr_t *nvr) } +void +nvr_at_sec_handler(int set, uint16_t base, nvr_t *nvr) +{ + io_handler(set, base, 2, + nvr_sec_read,NULL,NULL, nvr_sec_write,NULL,NULL, nvr); +} + + void nvr_wp_set(int set, int h, nvr_t *nvr) { @@ -780,6 +814,26 @@ nvr_wp_set(int set, int h, nvr_t *nvr) } +void +nvr_bank_set(int base, uint8_t bank, nvr_t *nvr) +{ + local_t *local = (local_t *) nvr->data; + + local->bank[base] = bank; +} + + +void +nvr_lock_set(int base, int size, int lock, nvr_t *nvr) +{ + local_t *local = (local_t *) nvr->data; + int i; + + for (i = 0; i < size; i++) + local->lock[base + i] = lock; +} + + static void * nvr_at_init(const device_t *info) { @@ -797,6 +851,8 @@ nvr_at_init(const device_t *info) /* This is machine specific. */ nvr->size = machines[machine].nvrmask + 1; + local->lock = (uint8_t *) malloc(nvr->size); + memset(local->lock, 0x00, nvr->size); local->def = 0x00; local->flags = 0x00; switch(info->local & 7) { diff --git a/src/sio_fdc37c93x.c b/src/sio_fdc37c93x.c index f28cf7e81..e5ed9e164 100644 --- a/src/sio_fdc37c93x.c +++ b/src/sio_fdc37c93x.c @@ -30,6 +30,7 @@ #include <86box/hdc_ide.h> #include <86box/fdd.h> #include <86box/fdc.h> +#include <86box/nvr.h> #include <86box/sio.h> @@ -51,12 +52,13 @@ typedef struct { regs[48], ld_regs[10][256]; uint16_t gpio_base, /* Set to EA */ - auxio_base; + auxio_base, nvr_sec_base; int locked, cur_reg; fdc_t *fdc; serial_t *uart[2]; access_bus_t *access_bus; + nvr_t *nvr; } fdc37c93x_t; @@ -72,6 +74,18 @@ make_port(fdc37c93x_t *dev, uint8_t ld) } +static uint16_t +make_port_sec(fdc37c93x_t *dev, uint8_t ld) +{ + uint16_t r0 = dev->ld_regs[ld][0x62]; + uint16_t r1 = dev->ld_regs[ld][0x63]; + + uint16_t p = (r0 << 8) + r1; + + return p; +} + + static uint8_t fdc37c93x_auxio_read(uint16_t port, void *priv) { @@ -162,7 +176,34 @@ fdc37c93x_serial_handler(fdc37c93x_t *dev, int uart) } -static void fdc37c93x_auxio_handler(fdc37c93x_t *dev) +static void +fdc37c93x_nvr_pri_handler(fdc37c93x_t *dev) +{ + uint8_t local_enable = !!dev->ld_regs[6][0x30]; + + nvr_at_handler(0, 0x70, dev->nvr); + if (local_enable) + nvr_at_handler(1, 0x70, dev->nvr); +} + + +static void +fdc37c93x_nvr_sec_handler(fdc37c93x_t *dev) +{ + uint16_t ld_port = 0; + uint8_t local_enable = !!dev->ld_regs[6][0x30]; + + nvr_at_sec_handler(0, dev->nvr_sec_base, dev->nvr); + if (local_enable) { + dev->nvr_sec_base = ld_port = make_port_sec(dev, 6); + if ((ld_port >= 0x0100) && (ld_port <= 0x0FFE)) + nvr_at_sec_handler(1, ld_port, dev->nvr); + } +} + + +static void +fdc37c93x_auxio_handler(fdc37c93x_t *dev) { uint16_t ld_port = 0; uint8_t local_enable = !!dev->ld_regs[8][0x30]; @@ -321,7 +362,6 @@ fdc37c93x_write(uint16_t port, uint8_t val, void *priv) else switch (dev->regs[7]) { case 1: case 2: - case 6: case 7: return; case 9: @@ -443,6 +483,60 @@ fdc37c93x_write(uint16_t port, uint8_t val, void *priv) break; } break; + case 6: + /* RTC/NVR */ + if (dev->chip_id != 0x30) + break; + switch(dev->cur_reg) { + case 0x30: + if (valxor) + fdc37c93x_nvr_pri_handler(dev); + /* FALLTHROUGH */ + case 0x60: + case 0x61: + if (valxor) + fdc37c93x_nvr_sec_handler(dev); + break; + case 0xf0: + if (valxor) { + nvr_lock_set(0x80, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x01), dev->nvr); + nvr_lock_set(0xa0, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x02), dev->nvr); + nvr_lock_set(0xc0, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x04), dev->nvr); + nvr_lock_set(0xe0, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x08), dev->nvr); + if (dev->ld_regs[6][dev->cur_reg] & 0x80) switch ((dev->ld_regs[6][dev->cur_reg] >> 4) & 0x07) { + case 0x00: + default: + nvr_bank_set(0, 0xff, dev->nvr); + nvr_bank_set(1, 1, dev->nvr); + break; + case 0x01: + nvr_bank_set(0, 0, dev->nvr); + nvr_bank_set(1, 1, dev->nvr); + break; + case 0x02: case 0x04: + nvr_bank_set(0, 0xff, dev->nvr); + nvr_bank_set(1, 0xff, dev->nvr); + break; + case 0x03: case 0x05: + nvr_bank_set(0, 0, dev->nvr); + nvr_bank_set(1, 0xff, dev->nvr); + break; + case 0x06: + nvr_bank_set(0, 0xff, dev->nvr); + nvr_bank_set(1, 2, dev->nvr); + break; + case 0x07: + nvr_bank_set(0, 0, dev->nvr); + nvr_bank_set(1, 2, dev->nvr); + break; + } else { + nvr_bank_set(0, 0, dev->nvr); + nvr_bank_set(1, 0xff, dev->nvr); + } + } + break; + } + break; case 8: /* Auxiliary I/O */ switch(dev->cur_reg) { @@ -508,8 +602,8 @@ fdc37c93x_reset(fdc37c93x_t *dev) memset(dev->regs, 0, 48); dev->regs[0x03] = 0x03; - dev->regs[0x21] = 0x01; dev->regs[0x20] = dev->chip_id; + dev->regs[0x21] = 0x01; dev->regs[0x22] = 0x39; dev->regs[0x24] = 0x04; dev->regs[0x26] = 0xF0; @@ -571,7 +665,8 @@ fdc37c93x_reset(fdc37c93x_t *dev) serial_setup(dev->uart[1], 0x2f8, dev->ld_regs[5][0x70]); /* Logical device 6: RTC */ - dev->ld_regs[6][0x63] = 0x70; + dev->ld_regs[5][0x30] = 1; + dev->ld_regs[6][0x63] = 0x00; dev->ld_regs[6][0xF4] = 3; /* Logical device 7: Keyboard */ @@ -652,6 +747,13 @@ fdc37c93x_init(const device_t *info) dev->gpio_regs[0] = 0xFD; dev->gpio_regs[1] = 0xFF; + if (dev->chip_id == 0x30) { + dev->nvr = device_add(&at_nvr_device); + + nvr_bank_set(0, 0, dev->nvr); + nvr_bank_set(1, 0xff, dev->nvr); + } + if (dev->chip_id == 0x03) dev->access_bus = device_add(&access_bus_device); @@ -676,7 +778,7 @@ const device_t fdc37c932fr_device = { const device_t fdc37c932qf_device = { "SMC FDC37C932QF Super I/O", 0, - 0x02, /* Share the same ID with the 935. */ + 0x30, /* Share the same ID with the 935. */ fdc37c93x_init, fdc37c93x_close, NULL, NULL, NULL, NULL, NULL