Rewrote the VLSI 82C480 chipset emuluation and gave the PS/1 Model 2133 its Super I/O chip.
This commit is contained in:
@@ -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) {
|
|
||||||
case 0xec:
|
|
||||||
dev->cfg_index = val;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xed:
|
switch (addr) {
|
||||||
if (dev->cfg_index >= 0x01 && dev->cfg_index <= 0x24) {
|
case 0xec:
|
||||||
dev->cfg_regs[dev->cfg_index] = val;
|
dev->idx = val;
|
||||||
switch (dev->cfg_index) {
|
break;
|
||||||
case CFG_AAXS:
|
|
||||||
shadow_control(0xa0000, 0x4000, val & 3);
|
case 0xed:
|
||||||
shadow_control(0xa4000, 0x4000, (val >> 2) & 3);
|
if (dev->idx >= 0x01 && dev->idx <= 0x24) {
|
||||||
shadow_control(0xa8000, 0x4000, (val >> 4) & 3);
|
switch (dev->idx) {
|
||||||
shadow_control(0xac000, 0x4000, (val >> 6) & 3);
|
default:
|
||||||
|
dev->regs[dev->idx] = val;
|
||||||
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:
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
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;
|
|
||||||
|
|
||||||
io_sethandler(0x00ec, 0x0004, vl82c480_read, NULL, NULL, vl82c480_write, NULL, NULL, dev);
|
|
||||||
|
|
||||||
device_add(&port_92_device);
|
dev->regs[0x00] = 0x90;
|
||||||
|
dev->regs[0x01] = 0xff;
|
||||||
|
dev->regs[0x02] = 0x8a;
|
||||||
|
dev->regs[0x03] = 0x88;
|
||||||
|
dev->regs[0x06] = 0x1b;
|
||||||
|
dev->regs[0x08] = 0x38;
|
||||||
|
|
||||||
return dev;
|
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 = {
|
const device_t vl82c480_device = {
|
||||||
"VLSI VL82c480",
|
"VLSI VL82c480",
|
||||||
0,
|
0,
|
||||||
|
@@ -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)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user