diff --git a/src/mem.c b/src/mem.c index 9815ecc..6cd1231 100644 --- a/src/mem.c +++ b/src/mem.c @@ -36,7 +36,7 @@ static int _mem_state[0x40000]; static mem_mapping_t base_mapping; mem_mapping_t ram_low_mapping; -static mem_mapping_t ram_high_mapping; +mem_mapping_t ram_high_mapping; static mem_mapping_t ram_mid_mapping; static mem_mapping_t ram_remapped_mapping; mem_mapping_t bios_mapping[8]; diff --git a/src/mem.h b/src/mem.h index 689a66e..370be13 100644 --- a/src/mem.h +++ b/src/mem.h @@ -102,6 +102,7 @@ FILE *romfopen(char *fn, char *mode); mem_mapping_t bios_mapping[8]; mem_mapping_t bios_high_mapping[8]; +extern mem_mapping_t ram_high_mapping; typedef struct page_t { diff --git a/src/model.c b/src/model.c index 814ab2c..20f6f32 100644 --- a/src/model.c +++ b/src/model.c @@ -126,7 +126,7 @@ MODEL models[] = /* {"Phoenix 386 clone", ROM_PX386, { "Intel", cpus_i386SX, "AMD", cpus_Am386SX, "Cyrix", cpus_486SLC}, 0, MODEL_AT, 1, 16, 1, at_init, NULL},*/ {"Amstrad MegaPC", ROM_MEGAPC, "megapc", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, 1, MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 1, 16, 1, at_wd76c10_init, NULL}, {"AMI 386SX clone", ROM_AMI386SX, "ami386", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, 0, MODEL_AT|MODEL_HAS_IDE, 1, 256, 1, at_headland_init, NULL}, - {"IBM PS/2 Model 80", ROM_IBMPS2_M80, "ibmps2_m80", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, 1, MODEL_AT|MODEL_PS2|MODEL_MCA, 2, 4, 2, ps2_model_80_init, NULL}, + {"IBM PS/2 Model 80", ROM_IBMPS2_M80, "ibmps2_m80", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, 1, MODEL_AT|MODEL_PS2|MODEL_MCA, 1, 12, 1, ps2_model_80_init, NULL}, {"MR 386DX clone", ROM_MR386DX_OPTI495, "mr386dx", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, 0, MODEL_AT|MODEL_HAS_IDE, 1, 256, 1, at_opti495_init, NULL}, {"AMI 386DX clone", ROM_AMI386DX_OPTI495, "ami386dx", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, 0, MODEL_AT|MODEL_HAS_IDE, 1, 256, 1, at_opti495_init, NULL}, {"AMI 486 clone", ROM_AMI486, "ami486", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, 0, MODEL_AT|MODEL_HAS_IDE, 1, 256, 1, at_ali1429_init, NULL}, diff --git a/src/ps2_mca.c b/src/ps2_mca.c index e53cfd6..c482ab5 100644 --- a/src/ps2_mca.c +++ b/src/ps2_mca.c @@ -33,6 +33,8 @@ static struct uint8_t io_id; mem_mapping_t shadow_mapping; + mem_mapping_t split_mapping; + mem_mapping_t expansion_mapping; uint8_t (*planar_read)(uint16_t port); void (*planar_write)(uint16_t port, uint8_t val); @@ -40,40 +42,73 @@ static struct uint8_t mem_regs[3]; uint32_t split_addr; + + uint8_t mem_pos_regs[8]; } ps2; -uint8_t ps2_read_shadow_ram(uint32_t addr, void *priv) +static uint8_t ps2_read_shadow_ram(uint32_t addr, void *priv) { addr = (addr & 0x1ffff) + 0xe0000; return mem_read_ram(addr, priv); } -uint16_t ps2_read_shadow_ramw(uint32_t addr, void *priv) +static uint16_t ps2_read_shadow_ramw(uint32_t addr, void *priv) { addr = (addr & 0x1ffff) + 0xe0000; return mem_read_ramw(addr, priv); } -uint32_t ps2_read_shadow_raml(uint32_t addr, void *priv) +static uint32_t ps2_read_shadow_raml(uint32_t addr, void *priv) { addr = (addr & 0x1ffff) + 0xe0000; return mem_read_raml(addr, priv); } -void ps2_write_shadow_ram(uint32_t addr, uint8_t val, void *priv) +static void ps2_write_shadow_ram(uint32_t addr, uint8_t val, void *priv) { addr = (addr & 0x1ffff) + 0xe0000; mem_write_ram(addr, val, priv); } -void ps2_write_shadow_ramw(uint32_t addr, uint16_t val, void *priv) +static void ps2_write_shadow_ramw(uint32_t addr, uint16_t val, void *priv) { addr = (addr & 0x1ffff) + 0xe0000; mem_write_ramw(addr, val, priv); } -void ps2_write_shadow_raml(uint32_t addr, uint32_t val, void *priv) +static void ps2_write_shadow_raml(uint32_t addr, uint32_t val, void *priv) { addr = (addr & 0x1ffff) + 0xe0000; mem_write_raml(addr, val, priv); } +static uint8_t ps2_read_split_ram(uint32_t addr, void *priv) +{ + addr = (addr & 0x3ffff) + 0xa0000; + return mem_read_ram(addr, priv); +} +static uint16_t ps2_read_split_ramw(uint32_t addr, void *priv) +{ + addr = (addr & 0x3ffff) + 0xa0000; + return mem_read_ramw(addr, priv); +} +static uint32_t ps2_read_split_raml(uint32_t addr, void *priv) +{ + addr = (addr & 0x3ffff) + 0xa0000; + return mem_read_raml(addr, priv); +} +static void ps2_write_split_ram(uint32_t addr, uint8_t val, void *priv) +{ + addr = (addr & 0x3ffff) + 0xa0000; + mem_write_ram(addr, val, priv); +} +static void ps2_write_split_ramw(uint32_t addr, uint16_t val, void *priv) +{ + addr = (addr & 0x3ffff) + 0xa0000; + mem_write_ramw(addr, val, priv); +} +static void ps2_write_split_raml(uint32_t addr, uint32_t val, void *priv) +{ + addr = (addr & 0x3ffff) + 0xa0000; + mem_write_raml(addr, val, priv); +} + #define PS2_SETUP_IO 0x80 @@ -609,7 +644,7 @@ void ps2_mca_board_model_55sx_init() static void mem_encoding_update() { if (ps2.split_addr >= mem_size*1024) - mem_set_mem_state(ps2.split_addr, 256 * 1024, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + mem_mapping_disable(&ps2.split_mapping); ps2.split_addr = (ps2.mem_regs[0] & 0xf) << 20; @@ -621,7 +656,7 @@ static void mem_encoding_update() if (!(ps2.mem_regs[1] & 8)) { if (ps2.split_addr >= mem_size*1024) - mem_set_mem_state(ps2.split_addr, 256 * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_mapping_set_addr(&ps2.split_mapping, ps2.split_addr, 256*1024); } } @@ -650,6 +685,24 @@ static void mem_encoding_write(uint16_t addr, uint8_t val, void *p) mem_encoding_update(); } +static uint8_t ps2_mem_expansion_read(int port, void *p) +{ + return ps2.mem_pos_regs[port & 7]; +} + +static void ps2_mem_expansion_write(int port, uint8_t val, void *p) +{ + if (port < 0x102 || port == 0x104) + return; + + ps2.mem_pos_regs[port & 7] = val; + + if (ps2.mem_pos_regs[2] & 1) + mem_mapping_enable(&ps2.expansion_mapping); + else + mem_mapping_disable(&ps2.expansion_mapping); +} + void ps2_mca_board_model_80_type2_init() { ps2_mca_board_common_init(); @@ -667,8 +720,86 @@ void ps2_mca_board_model_80_type2_init() ps2.mem_regs[1] = 2; - if (mem_size == 2*1024) + switch (mem_size/1024) + { + case 1: + ps2.option[1] = 0x0c; + break; + case 2: ps2.option[1] = 0x0e; - else + break; + case 3: + ps2.option[1] = 0x02; + break; + case 4: + default: ps2.option[1] = 0x0a; + break; + } + + mem_mapping_add(&ps2.split_mapping, + (mem_size+256) * 1024, + 256*1024, + ps2_read_split_ram, + ps2_read_split_ramw, + ps2_read_split_raml, + ps2_write_split_ram, + ps2_write_split_ramw, + ps2_write_split_raml, + &ram[0xa0000], + MEM_MAPPING_INTERNAL, + NULL); + mem_mapping_disable(&ps2.split_mapping); + + if (mem_size > 4096) + { + /* Only 4 MB supported on planar, create a memory expansion card for the rest */ + mem_mapping_set_addr(&ram_high_mapping, 0x100000, 0x300000); + + ps2.mem_pos_regs[0] = 0xff; + ps2.mem_pos_regs[1] = 0xfc; + + switch (mem_size/1024) + { + case 5: + ps2.mem_pos_regs[4] = 0xfc; + break; + case 6: + ps2.mem_pos_regs[4] = 0xfe; + break; + case 7: + ps2.mem_pos_regs[4] = 0xf2; + break; + case 8: + ps2.mem_pos_regs[4] = 0xfa; + break; + case 9: + ps2.mem_pos_regs[4] = 0xca; + break; + case 10: + ps2.mem_pos_regs[4] = 0xea; + break; + case 11: + ps2.mem_pos_regs[4] = 0x2a; + break; + case 12: + ps2.mem_pos_regs[4] = 0xaa; + break; + } + + mca_add(ps2_mem_expansion_read, ps2_mem_expansion_write, NULL); + mem_mapping_add(&ps2.expansion_mapping, + 0x400000, + (mem_size - 4096)*1024, + mem_read_ram, + mem_read_ramw, + mem_read_raml, + mem_write_ram, + mem_write_ramw, + mem_write_raml, + &ram[0x400000], + MEM_MAPPING_INTERNAL, + NULL); + mem_mapping_disable(&ps2.expansion_mapping); + } }