Rewrote the VLSI 82C480 chipset emuluation and gave the PS/1 Model 2133 its Super I/O chip.

This commit is contained in:
OBattler
2020-06-30 15:37:07 +02:00
parent 13e8d9c923
commit 81d178e9f6
2 changed files with 112 additions and 108 deletions

View File

@@ -8,9 +8,9 @@
* *
* Implementation of the VLSI VL82c480 chipset. * Implementation of the VLSI VL82c480 chipset.
* *
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/> * Authors: Miran Grca, <mgrca8@gmail.com>
* *
* Copyright 2020 Sarah Walker. * Copyright 2020 Miran Grca.
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
@@ -28,155 +28,156 @@
#include <86box/chipset.h> #include <86box/chipset.h>
typedef struct { typedef struct {
int cfg_index; uint8_t idx,
uint8_t cfg_regs[256]; regs[256];
} vl82c480_t; } 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 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); */ int i, j;
switch (state) { uint32_t base;
case 0: uint8_t access;
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break; shadowbios = 0;
case 1: shadowbios_write = 0;
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
break; for (i = 0; i < 8; i += 2) {
case 2: for (j = 0; j < 6; j++) {
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); base = 0x000a0000 + (i << 13) + (j << 16);
break; access = dev->regs[0x0d + j] & (3 << i);
case 3: mem_set_mem_state(base, 0x4000, vl82c480_shflags(access));
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); shadowbios |= ((base >= 0xe0000) && (access & 0x02));
break; shadowbios_write |= ((base >= 0xe0000) && (access & 0x01));
} }
flushmmucache_nopc(); }
flushmmucache();
} }
static void static void
vl82c480_write(uint16_t addr, uint8_t val, void *p) vl82c480_write(uint16_t addr, uint8_t val, void *p)
{ {
vl82c480_t *dev = (vl82c480_t *)p; vl82c480_t *dev = (vl82c480_t *)p;
switch (addr) { switch (addr) {
case 0xec: case 0xec:
dev->cfg_index = val; dev->idx = val;
break; break;
case 0xed: case 0xed:
if (dev->cfg_index >= 0x01 && dev->cfg_index <= 0x24) { if (dev->idx >= 0x01 && dev->idx <= 0x24) {
dev->cfg_regs[dev->cfg_index] = val; switch (dev->idx) {
switch (dev->cfg_index) { default:
case CFG_AAXS: dev->regs[dev->idx] = val;
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);
break; break;
case CFG_BAXS: case 0x05:
shadow_control(0xb0000, 0x4000, val & 3); dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x10) | (val & 0xef);
shadow_control(0xb4000, 0x4000, (val >> 2) & 3);
shadow_control(0xb8000, 0x4000, (val >> 4) & 3);
shadow_control(0xbc000, 0x4000, (val >> 6) & 3);
break; break;
case CFG_CAXS: case 0x0d: case 0x0e: case 0x0f: case 0x10:
shadow_control(0xc0000, 0x4000, val & 3); case 0x11: case 0x12:
shadow_control(0xc4000, 0x4000, (val >> 2) & 3); dev->regs[dev->idx] = val;
shadow_control(0xc8000, 0x4000, (val >> 4) & 3); vl82c480_recalc(dev);
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);
break; break;
} }
} }
break; break;
case 0xee: case 0xee:
if (mem_a20_alt) if (mem_a20_alt)
outb(0x92, inb(0x92) & ~2); outb(0x92, inb(0x92) & ~2);
break; break;
} }
} }
static uint8_t static uint8_t
vl82c480_read(uint16_t addr, void *p) vl82c480_read(uint16_t addr, void *p)
{ {
vl82c480_t *dev = (vl82c480_t *)p; vl82c480_t *dev = (vl82c480_t *)p;
uint8_t ret = 0xff; uint8_t ret = 0xff;
switch (addr) { switch (addr) {
case 0xec: case 0xec:
ret = dev->cfg_index; ret = dev->idx;
break; break;
case 0xed: case 0xed:
ret = dev->cfg_regs[dev->cfg_index]; ret = dev->regs[dev->idx];
break; break;
case 0xee: case 0xee:
if (!mem_a20_alt) if (!mem_a20_alt)
outb(0x92, inb(0x92) | 2); outb(0x92, inb(0x92) | 2);
break; break;
case 0xef: case 0xef:
softresetx86(); softresetx86();
cpu_set_edx(); cpu_set_edx();
break; break;
} }
return ret; return ret;
} }
static void static void
vl82c480_close(void *p) vl82c480_close(void *p)
{ {
vl82c480_t *dev = (vl82c480_t *)p; vl82c480_t *dev = (vl82c480_t *)p;
free(dev); free(dev);
} }
static void * static void *
vl82c480_init(const device_t *info) vl82c480_init(const device_t *info)
{ {
vl82c480_t *dev = (vl82c480_t *)malloc(sizeof(vl82c480_t)); vl82c480_t *dev = (vl82c480_t *)malloc(sizeof(vl82c480_t));
memset(dev, 0, sizeof(vl82c480_t)); memset(dev, 0, sizeof(vl82c480_t));
dev->cfg_regs[CFG_ID] = ID_VL82C480; 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); io_sethandler(0x00ec, 0x0004, vl82c480_read, NULL, NULL, vl82c480_write, NULL, NULL, dev);
device_add(&port_92_device); device_add(&port_92_device);
return dev; return dev;
} }
const device_t vl82c480_device = { const device_t vl82c480_device = {
"VLSI VL82c480", "VLSI VL82c480",
0, 0,

View File

@@ -558,6 +558,7 @@ machine_ps1_m2121_init(const machine_t *model)
return ret; return ret;
} }
int int
machine_ps1_m2133_init(const machine_t *model) machine_ps1_m2133_init(const machine_t *model)
{ {
@@ -573,6 +574,7 @@ machine_ps1_m2133_init(const machine_t *model)
device_add(&fdc_at_device); device_add(&fdc_at_device);
device_add(&ide_isa_device); device_add(&ide_isa_device);
device_add(&vl82c480_device); device_add(&vl82c480_device);
device_add(&ps1_m2133_sio);
nmi_mask = 0x80; nmi_mask = 0x80;
@@ -582,6 +584,7 @@ machine_ps1_m2133_init(const machine_t *model)
return ret; return ret;
} }
const device_t * const device_t *
ps1_m2133_get_device(void) ps1_m2133_get_device(void)
{ {