Add IBM PS/1 Model 2133 (EMEA 451) emulation. Currently displays a cache error
on boot, but otherwise seems to work fine.
This commit is contained in:
parent
adf4a2de93
commit
8870334114
14 changed files with 319 additions and 12 deletions
169
src/vl82c480.c
Normal file
169
src/vl82c480.c
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
#include "ibm.h"
|
||||
#include "io.h"
|
||||
#include "mem.h"
|
||||
#include "vl82c480.h"
|
||||
|
||||
static struct
|
||||
{
|
||||
int cfg_index;
|
||||
uint8_t cfg_regs[256];
|
||||
|
||||
uint8_t port_92;
|
||||
} vl82c480;
|
||||
|
||||
#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 void shadow_control(uint32_t addr, uint32_t size, int state)
|
||||
{
|
||||
// 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_EXTERNAL | MEM_WRITE_EXTERNAL);
|
||||
break;
|
||||
case 1:
|
||||
mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
|
||||
break;
|
||||
case 2:
|
||||
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
|
||||
break;
|
||||
case 3:
|
||||
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
break;
|
||||
}
|
||||
flushmmucache_nopc();
|
||||
}
|
||||
|
||||
void vl82c480_write(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
// if (addr != 0x92) pclog("vl82c480_write: addr=%04x val=%02x\n", addr, val);
|
||||
switch (addr)
|
||||
{
|
||||
case 0x92:
|
||||
if ((mem_a20_alt ^ val) & 2)
|
||||
{
|
||||
mem_a20_alt = val & 2;
|
||||
mem_a20_recalc();
|
||||
}
|
||||
if ((~vl82c480.port_92 & val) & 1)
|
||||
{
|
||||
softresetx86();
|
||||
cpu_set_edx();
|
||||
}
|
||||
vl82c480.port_92 = val;
|
||||
break;
|
||||
|
||||
case 0xec:
|
||||
vl82c480.cfg_index = val;
|
||||
break;
|
||||
|
||||
case 0xed:
|
||||
if (vl82c480.cfg_index >= 0x01 && vl82c480.cfg_index <= 0x24)
|
||||
{
|
||||
vl82c480.cfg_regs[vl82c480.cfg_index] = val;
|
||||
switch (vl82c480.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);
|
||||
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);
|
||||
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);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xee:
|
||||
if (mem_a20_alt)
|
||||
{
|
||||
vl82c480.port_92 &= ~2;
|
||||
mem_a20_alt = 0;
|
||||
mem_a20_recalc();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t vl82c480_read(uint16_t addr, void *p)
|
||||
{
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x92:
|
||||
ret = vl82c480.port_92;
|
||||
break;
|
||||
|
||||
case 0xec:
|
||||
ret = vl82c480.cfg_index;
|
||||
break;
|
||||
|
||||
case 0xed:
|
||||
ret = vl82c480.cfg_regs[vl82c480.cfg_index];
|
||||
break;
|
||||
|
||||
case 0xee:
|
||||
if (!mem_a20_alt)
|
||||
{
|
||||
vl82c480.port_92 |= 2;
|
||||
mem_a20_alt = 1;
|
||||
mem_a20_recalc();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xef:
|
||||
softresetx86();
|
||||
cpu_set_edx();
|
||||
break;
|
||||
}
|
||||
|
||||
// pclog("vl82c480_read: addr=%04x ret=%02x\n", addr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void vl82c480_init(void)
|
||||
{
|
||||
memset(&vl82c480, 0, sizeof(vl82c480));
|
||||
vl82c480.cfg_regs[CFG_ID] = ID_VL82C480;
|
||||
|
||||
io_sethandler(0x0092, 0x0001, vl82c480_read, NULL, NULL, vl82c480_write, NULL, NULL, NULL);
|
||||
io_sethandler(0x00ec, 0x0004, vl82c480_read, NULL, NULL, vl82c480_write, NULL, NULL, NULL);
|
||||
}
|
||||
Loading…
Reference in a new issue