2017-09-25 04:31:20 -04:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <wchar.h>
|
2017-10-17 01:59:09 -04:00
|
|
|
#include "../86box.h"
|
2017-09-02 20:39:57 +02:00
|
|
|
#include "../cpu/cpu.h"
|
|
|
|
|
#include "../cpu/x86.h"
|
|
|
|
|
#include "../io.h"
|
2017-09-04 01:52:29 -04:00
|
|
|
#include "../dma.h"
|
2017-09-02 20:39:57 +02:00
|
|
|
#include "../pic.h"
|
|
|
|
|
#include "../pit.h"
|
2017-09-04 01:52:29 -04:00
|
|
|
#include "../mca.h"
|
|
|
|
|
#include "../mem.h"
|
2017-12-10 15:16:24 +01:00
|
|
|
#include "../nmi.h"
|
2017-09-02 20:39:57 +02:00
|
|
|
#include "../rom.h"
|
2017-09-04 01:52:29 -04:00
|
|
|
#include "../device.h"
|
|
|
|
|
#include "../nvr.h"
|
|
|
|
|
#include "../nvr_ps2.h"
|
2017-11-05 01:57:04 -05:00
|
|
|
#include "../keyboard.h"
|
2017-09-04 01:52:29 -04:00
|
|
|
#include "../lpt.h"
|
|
|
|
|
#include "../mouse.h"
|
2017-09-02 20:39:57 +02:00
|
|
|
#include "../serial.h"
|
2017-12-04 20:35:05 +01:00
|
|
|
#include "../video/vid_vga.h"
|
2017-10-07 22:18:30 -04:00
|
|
|
#include "machine.h"
|
2017-05-06 17:48:33 +02:00
|
|
|
|
2017-05-05 01:49:42 +02:00
|
|
|
|
|
|
|
|
static struct
|
|
|
|
|
{
|
|
|
|
|
uint8_t adapter_setup;
|
|
|
|
|
uint8_t option[4];
|
|
|
|
|
uint8_t pos_vga;
|
|
|
|
|
uint8_t setup;
|
|
|
|
|
uint8_t sys_ctrl_port_a;
|
|
|
|
|
uint8_t subaddr_lo, subaddr_hi;
|
|
|
|
|
|
|
|
|
|
uint8_t memory_bank[8];
|
|
|
|
|
|
|
|
|
|
uint8_t io_id;
|
|
|
|
|
|
|
|
|
|
mem_mapping_t shadow_mapping;
|
|
|
|
|
mem_mapping_t expansion_mapping;
|
|
|
|
|
|
|
|
|
|
uint8_t (*planar_read)(uint16_t port);
|
|
|
|
|
void (*planar_write)(uint16_t port, uint8_t val);
|
|
|
|
|
|
|
|
|
|
uint8_t mem_regs[3];
|
|
|
|
|
|
2017-12-11 19:41:58 +01:00
|
|
|
uint32_t split_addr, split_size;
|
2017-05-05 01:49:42 +02:00
|
|
|
|
|
|
|
|
uint8_t mem_pos_regs[8];
|
|
|
|
|
} ps2;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static uint8_t ps2_read_shadow_ram(uint32_t addr, void *priv)
|
|
|
|
|
{
|
|
|
|
|
addr = (addr & 0x1ffff) + 0xe0000;
|
|
|
|
|
return mem_read_ram(addr, priv);
|
|
|
|
|
}
|
|
|
|
|
static uint16_t ps2_read_shadow_ramw(uint32_t addr, void *priv)
|
|
|
|
|
{
|
|
|
|
|
addr = (addr & 0x1ffff) + 0xe0000;
|
|
|
|
|
return mem_read_ramw(addr, priv);
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ps2_read_shadow_raml(uint32_t addr, void *priv)
|
|
|
|
|
{
|
|
|
|
|
addr = (addr & 0x1ffff) + 0xe0000;
|
|
|
|
|
return mem_read_raml(addr, 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);
|
|
|
|
|
}
|
|
|
|
|
static void ps2_write_shadow_ramw(uint32_t addr, uint16_t val, void *priv)
|
|
|
|
|
{
|
|
|
|
|
addr = (addr & 0x1ffff) + 0xe0000;
|
|
|
|
|
mem_write_ramw(addr, val, 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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define PS2_SETUP_IO 0x80
|
|
|
|
|
#define PS2_SETUP_VGA 0x20
|
|
|
|
|
|
|
|
|
|
#define PS2_ADAPTER_SETUP 0x08
|
|
|
|
|
|
|
|
|
|
static uint8_t model_50_read(uint16_t port)
|
|
|
|
|
{
|
|
|
|
|
switch (port)
|
|
|
|
|
{
|
|
|
|
|
case 0x100:
|
|
|
|
|
return 0xff;
|
|
|
|
|
case 0x101:
|
|
|
|
|
return 0xfb;
|
|
|
|
|
case 0x102:
|
|
|
|
|
return ps2.option[0];
|
|
|
|
|
case 0x103:
|
|
|
|
|
return ps2.option[1];
|
|
|
|
|
case 0x104:
|
|
|
|
|
return ps2.option[2];
|
|
|
|
|
case 0x105:
|
|
|
|
|
return ps2.option[3];
|
|
|
|
|
case 0x106:
|
|
|
|
|
return ps2.subaddr_lo;
|
|
|
|
|
case 0x107:
|
|
|
|
|
return ps2.subaddr_hi;
|
|
|
|
|
}
|
|
|
|
|
return 0xff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint8_t model_55sx_read(uint16_t port)
|
|
|
|
|
{
|
|
|
|
|
switch (port)
|
|
|
|
|
{
|
|
|
|
|
case 0x100:
|
|
|
|
|
return 0xff;
|
|
|
|
|
case 0x101:
|
|
|
|
|
return 0xfb;
|
|
|
|
|
case 0x102:
|
|
|
|
|
return ps2.option[0];
|
|
|
|
|
case 0x103:
|
|
|
|
|
return ps2.option[1];
|
|
|
|
|
case 0x104:
|
|
|
|
|
return ps2.memory_bank[ps2.option[3] & 7];
|
|
|
|
|
case 0x105:
|
|
|
|
|
return ps2.option[3];
|
|
|
|
|
case 0x106:
|
|
|
|
|
return ps2.subaddr_lo;
|
|
|
|
|
case 0x107:
|
|
|
|
|
return ps2.subaddr_hi;
|
|
|
|
|
}
|
|
|
|
|
return 0xff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint8_t model_80_read(uint16_t port)
|
|
|
|
|
{
|
|
|
|
|
switch (port)
|
|
|
|
|
{
|
|
|
|
|
case 0x100:
|
|
|
|
|
return 0xff;
|
|
|
|
|
case 0x101:
|
|
|
|
|
return 0xfd;
|
|
|
|
|
case 0x102:
|
|
|
|
|
return ps2.option[0];
|
|
|
|
|
case 0x103:
|
|
|
|
|
return ps2.option[1];
|
|
|
|
|
case 0x104:
|
|
|
|
|
return ps2.option[2];
|
|
|
|
|
case 0x105:
|
|
|
|
|
return ps2.option[3];
|
|
|
|
|
case 0x106:
|
|
|
|
|
return ps2.subaddr_lo;
|
|
|
|
|
case 0x107:
|
|
|
|
|
return ps2.subaddr_hi;
|
|
|
|
|
}
|
|
|
|
|
return 0xff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void model_50_write(uint16_t port, uint8_t val)
|
|
|
|
|
{
|
|
|
|
|
switch (port)
|
|
|
|
|
{
|
|
|
|
|
case 0x100:
|
|
|
|
|
ps2.io_id = val;
|
|
|
|
|
break;
|
|
|
|
|
case 0x101:
|
|
|
|
|
break;
|
|
|
|
|
case 0x102:
|
|
|
|
|
lpt1_remove();
|
2017-05-07 02:14:44 -04:00
|
|
|
serial_remove(1);
|
2017-05-05 01:49:42 +02:00
|
|
|
if (val & 0x04)
|
|
|
|
|
{
|
|
|
|
|
if (val & 0x08)
|
2017-05-07 02:14:44 -04:00
|
|
|
serial_setup(1, SERIAL1_ADDR, SERIAL1_IRQ);
|
2017-05-05 01:49:42 +02:00
|
|
|
else
|
2017-05-07 02:14:44 -04:00
|
|
|
serial_setup(1, SERIAL2_ADDR, SERIAL2_IRQ);
|
2017-05-05 01:49:42 +02:00
|
|
|
}
|
|
|
|
|
else
|
2017-05-07 02:14:44 -04:00
|
|
|
serial_remove(1);
|
2017-05-05 01:49:42 +02:00
|
|
|
if (val & 0x10)
|
|
|
|
|
{
|
|
|
|
|
switch ((val >> 5) & 3)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
lpt1_init(0x3bc);
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
lpt1_init(0x378);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
lpt1_init(0x278);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ps2.option[0] = val;
|
|
|
|
|
break;
|
|
|
|
|
case 0x103:
|
|
|
|
|
ps2.option[1] = val;
|
|
|
|
|
break;
|
|
|
|
|
case 0x104:
|
|
|
|
|
ps2.option[2] = val;
|
|
|
|
|
break;
|
|
|
|
|
case 0x105:
|
|
|
|
|
ps2.option[3] = val;
|
|
|
|
|
break;
|
|
|
|
|
case 0x106:
|
|
|
|
|
ps2.subaddr_lo = val;
|
|
|
|
|
break;
|
|
|
|
|
case 0x107:
|
|
|
|
|
ps2.subaddr_hi = val;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void model_55sx_write(uint16_t port, uint8_t val)
|
|
|
|
|
{
|
|
|
|
|
switch (port)
|
|
|
|
|
{
|
|
|
|
|
case 0x100:
|
|
|
|
|
ps2.io_id = val;
|
|
|
|
|
break;
|
|
|
|
|
case 0x101:
|
|
|
|
|
break;
|
|
|
|
|
case 0x102:
|
|
|
|
|
lpt1_remove();
|
2017-05-07 02:14:44 -04:00
|
|
|
serial_remove(1);
|
2017-05-05 01:49:42 +02:00
|
|
|
if (val & 0x04)
|
|
|
|
|
{
|
|
|
|
|
if (val & 0x08)
|
2017-05-07 02:14:44 -04:00
|
|
|
serial_setup(1, SERIAL1_ADDR, SERIAL1_IRQ);
|
2017-05-05 01:49:42 +02:00
|
|
|
else
|
2017-05-07 02:14:44 -04:00
|
|
|
serial_setup(1, SERIAL2_ADDR, SERIAL2_IRQ);
|
2017-05-05 01:49:42 +02:00
|
|
|
}
|
|
|
|
|
else
|
2017-05-07 02:14:44 -04:00
|
|
|
serial_remove(1);
|
2017-05-05 01:49:42 +02:00
|
|
|
if (val & 0x10)
|
|
|
|
|
{
|
|
|
|
|
switch ((val >> 5) & 3)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
lpt1_init(0x3bc);
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
lpt1_init(0x378);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
lpt1_init(0x278);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ps2.option[0] = val;
|
|
|
|
|
break;
|
|
|
|
|
case 0x103:
|
|
|
|
|
ps2.option[1] = val;
|
|
|
|
|
break;
|
|
|
|
|
case 0x104:
|
|
|
|
|
ps2.memory_bank[ps2.option[3] & 7] &= ~0xf;
|
|
|
|
|
ps2.memory_bank[ps2.option[3] & 7] |= (val & 0xf);
|
2018-01-04 07:44:33 +01:00
|
|
|
/* pclog("Write memory bank %i %02x\n", ps2.option[3] & 7, val); */
|
2017-05-05 01:49:42 +02:00
|
|
|
break;
|
|
|
|
|
case 0x105:
|
2018-01-04 07:44:33 +01:00
|
|
|
/* pclog("Write POS3 %02x\n", val); */
|
2017-05-05 01:49:42 +02:00
|
|
|
ps2.option[3] = val;
|
|
|
|
|
shadowbios = !(val & 0x10);
|
|
|
|
|
shadowbios_write = val & 0x10;
|
|
|
|
|
|
|
|
|
|
if (shadowbios)
|
|
|
|
|
{
|
|
|
|
|
mem_set_mem_state(0xe0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
|
|
|
|
|
mem_mapping_disable(&ps2.shadow_mapping);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
mem_set_mem_state(0xe0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
|
|
|
|
|
mem_mapping_enable(&ps2.shadow_mapping);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((ps2.option[1] & 1) && !(ps2.option[3] & 0x20))
|
|
|
|
|
mem_set_mem_state(mem_size * 1024, 256 * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
|
|
|
|
else
|
|
|
|
|
mem_set_mem_state(mem_size * 1024, 256 * 1024, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
|
|
|
|
|
break;
|
|
|
|
|
case 0x106:
|
|
|
|
|
ps2.subaddr_lo = val;
|
|
|
|
|
break;
|
|
|
|
|
case 0x107:
|
|
|
|
|
ps2.subaddr_hi = val;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void model_80_write(uint16_t port, uint8_t val)
|
|
|
|
|
{
|
|
|
|
|
switch (port)
|
|
|
|
|
{
|
|
|
|
|
case 0x100:
|
|
|
|
|
break;
|
|
|
|
|
case 0x101:
|
|
|
|
|
break;
|
|
|
|
|
case 0x102:
|
|
|
|
|
lpt1_remove();
|
2017-05-07 02:14:44 -04:00
|
|
|
serial_remove(1);
|
2017-05-05 01:49:42 +02:00
|
|
|
if (val & 0x04)
|
|
|
|
|
{
|
|
|
|
|
if (val & 0x08)
|
2017-05-07 02:14:44 -04:00
|
|
|
serial_setup(1, SERIAL1_ADDR, SERIAL1_IRQ);
|
2017-05-05 01:49:42 +02:00
|
|
|
else
|
2017-05-07 02:14:44 -04:00
|
|
|
serial_setup(1, SERIAL2_ADDR, SERIAL2_IRQ);
|
2017-05-05 01:49:42 +02:00
|
|
|
}
|
|
|
|
|
else
|
2017-05-07 02:14:44 -04:00
|
|
|
serial_remove(1);
|
2017-05-05 01:49:42 +02:00
|
|
|
if (val & 0x10)
|
|
|
|
|
{
|
|
|
|
|
switch ((val >> 5) & 3)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
lpt1_init(0x3bc);
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
lpt1_init(0x378);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
lpt1_init(0x278);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ps2.option[0] = val;
|
|
|
|
|
break;
|
|
|
|
|
case 0x103:
|
|
|
|
|
ps2.option[1] = (ps2.option[1] & 0x0f) | (val & 0xf0);
|
|
|
|
|
break;
|
|
|
|
|
case 0x104:
|
|
|
|
|
ps2.option[2] = val;
|
|
|
|
|
break;
|
|
|
|
|
case 0x105:
|
|
|
|
|
ps2.option[3] = val;
|
|
|
|
|
break;
|
|
|
|
|
case 0x106:
|
|
|
|
|
ps2.subaddr_lo = val;
|
|
|
|
|
break;
|
|
|
|
|
case 0x107:
|
|
|
|
|
ps2.subaddr_hi = val;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t ps2_mca_read(uint16_t port, void *p)
|
|
|
|
|
{
|
|
|
|
|
uint8_t temp;
|
|
|
|
|
|
|
|
|
|
switch (port)
|
|
|
|
|
{
|
|
|
|
|
case 0x91:
|
|
|
|
|
fatal("Read 91 setup=%02x adapter=%02x\n", ps2.setup, ps2.adapter_setup);
|
|
|
|
|
case 0x94:
|
|
|
|
|
temp = ps2.setup;
|
|
|
|
|
break;
|
|
|
|
|
case 0x96:
|
|
|
|
|
temp = ps2.adapter_setup | 0x70;
|
|
|
|
|
break;
|
|
|
|
|
case 0x100:
|
|
|
|
|
if (!(ps2.setup & PS2_SETUP_IO))
|
|
|
|
|
temp = ps2.planar_read(port);
|
|
|
|
|
else if (!(ps2.setup & PS2_SETUP_VGA))
|
|
|
|
|
temp = 0xfd;
|
|
|
|
|
else if (ps2.adapter_setup & PS2_ADAPTER_SETUP)
|
|
|
|
|
temp = mca_read(port);
|
|
|
|
|
else
|
|
|
|
|
temp = 0xff;
|
|
|
|
|
break;
|
|
|
|
|
case 0x101:
|
|
|
|
|
if (!(ps2.setup & PS2_SETUP_IO))
|
|
|
|
|
temp = ps2.planar_read(port);
|
|
|
|
|
else if (!(ps2.setup & PS2_SETUP_VGA))
|
|
|
|
|
temp = 0xef;
|
|
|
|
|
else if (ps2.adapter_setup & PS2_ADAPTER_SETUP)
|
|
|
|
|
temp = mca_read(port);
|
|
|
|
|
else
|
|
|
|
|
temp = 0xff;
|
|
|
|
|
break;
|
|
|
|
|
case 0x102:
|
|
|
|
|
if (!(ps2.setup & PS2_SETUP_IO))
|
|
|
|
|
temp = ps2.planar_read(port);
|
|
|
|
|
else if (!(ps2.setup & PS2_SETUP_VGA))
|
|
|
|
|
temp = ps2.pos_vga;
|
|
|
|
|
else if (ps2.adapter_setup & PS2_ADAPTER_SETUP)
|
|
|
|
|
temp = mca_read(port);
|
|
|
|
|
else
|
|
|
|
|
temp = 0xff;
|
|
|
|
|
break;
|
|
|
|
|
case 0x103:
|
|
|
|
|
if (!(ps2.setup & PS2_SETUP_IO))
|
|
|
|
|
temp = ps2.planar_read(port);
|
|
|
|
|
else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP))
|
|
|
|
|
temp = mca_read(port);
|
|
|
|
|
else
|
|
|
|
|
temp = 0xff;
|
|
|
|
|
break;
|
|
|
|
|
case 0x104:
|
|
|
|
|
if (!(ps2.setup & PS2_SETUP_IO))
|
|
|
|
|
temp = ps2.planar_read(port);
|
|
|
|
|
else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP))
|
|
|
|
|
temp = mca_read(port);
|
|
|
|
|
else
|
|
|
|
|
temp = 0xff;
|
|
|
|
|
break;
|
|
|
|
|
case 0x105:
|
|
|
|
|
if (!(ps2.setup & PS2_SETUP_IO))
|
|
|
|
|
temp = ps2.planar_read(port);
|
|
|
|
|
else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP))
|
|
|
|
|
temp = mca_read(port);
|
|
|
|
|
else
|
|
|
|
|
temp = 0xff;
|
|
|
|
|
break;
|
|
|
|
|
case 0x106:
|
|
|
|
|
if (!(ps2.setup & PS2_SETUP_IO))
|
|
|
|
|
temp = ps2.planar_read(port);
|
|
|
|
|
else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP))
|
|
|
|
|
temp = mca_read(port);
|
|
|
|
|
else
|
|
|
|
|
temp = 0xff;
|
|
|
|
|
break;
|
|
|
|
|
case 0x107:
|
|
|
|
|
if (!(ps2.setup & PS2_SETUP_IO))
|
|
|
|
|
temp = ps2.planar_read(port);
|
|
|
|
|
else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP))
|
|
|
|
|
temp = mca_read(port);
|
|
|
|
|
else
|
|
|
|
|
temp = 0xff;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
temp = 0xff;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2018-01-04 07:44:33 +01:00
|
|
|
|
|
|
|
|
/* pclog("ps2_read: port=%04x temp=%02x\n", port, temp); */
|
2017-05-05 01:49:42 +02:00
|
|
|
|
|
|
|
|
return temp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ps2_mca_write(uint16_t port, uint8_t val, void *p)
|
|
|
|
|
{
|
2018-01-04 07:44:33 +01:00
|
|
|
/* pclog("ps2_write: port=%04x val=%02x %04x:%04x\n", port, val, CS,cpu_state.pc); */
|
2017-05-05 01:49:42 +02:00
|
|
|
|
|
|
|
|
switch (port)
|
|
|
|
|
{
|
|
|
|
|
case 0x94:
|
|
|
|
|
ps2.setup = val;
|
|
|
|
|
break;
|
|
|
|
|
case 0x96:
|
|
|
|
|
ps2.adapter_setup = val;
|
|
|
|
|
mca_set_index(val & 7);
|
|
|
|
|
break;
|
|
|
|
|
case 0x100:
|
|
|
|
|
if (!(ps2.setup & PS2_SETUP_IO))
|
|
|
|
|
ps2.planar_write(port, val);
|
|
|
|
|
else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP))
|
|
|
|
|
mca_write(port, val);
|
|
|
|
|
break;
|
|
|
|
|
case 0x101:
|
|
|
|
|
if (!(ps2.setup & PS2_SETUP_IO))
|
|
|
|
|
ps2.planar_write(port, val);
|
|
|
|
|
else if ((ps2.setup & PS2_SETUP_VGA) && (ps2.setup & PS2_SETUP_VGA) && (ps2.adapter_setup & PS2_ADAPTER_SETUP))
|
|
|
|
|
mca_write(port, val);
|
|
|
|
|
break;
|
|
|
|
|
case 0x102:
|
|
|
|
|
if (!(ps2.setup & PS2_SETUP_IO))
|
|
|
|
|
ps2.planar_write(port, val);
|
|
|
|
|
else if (!(ps2.setup & PS2_SETUP_VGA))
|
|
|
|
|
ps2.pos_vga = val;
|
|
|
|
|
else if (ps2.adapter_setup & PS2_ADAPTER_SETUP)
|
|
|
|
|
mca_write(port, val);
|
|
|
|
|
break;
|
|
|
|
|
case 0x103:
|
|
|
|
|
if (!(ps2.setup & PS2_SETUP_IO))
|
|
|
|
|
ps2.planar_write(port, val);
|
|
|
|
|
else if (ps2.adapter_setup & PS2_ADAPTER_SETUP)
|
|
|
|
|
mca_write(port, val);
|
|
|
|
|
break;
|
|
|
|
|
case 0x104:
|
|
|
|
|
if (!(ps2.setup & PS2_SETUP_IO))
|
|
|
|
|
ps2.planar_write(port, val);
|
|
|
|
|
else if (ps2.adapter_setup & PS2_ADAPTER_SETUP)
|
|
|
|
|
mca_write(port, val);
|
|
|
|
|
break;
|
|
|
|
|
case 0x105:
|
|
|
|
|
if (!(ps2.setup & PS2_SETUP_IO))
|
|
|
|
|
ps2.planar_write(port, val);
|
|
|
|
|
else if (ps2.adapter_setup & PS2_ADAPTER_SETUP)
|
|
|
|
|
mca_write(port, val);
|
|
|
|
|
break;
|
|
|
|
|
case 0x106:
|
|
|
|
|
if (!(ps2.setup & PS2_SETUP_IO))
|
|
|
|
|
ps2.planar_write(port, val);
|
|
|
|
|
else if (ps2.adapter_setup & PS2_ADAPTER_SETUP)
|
|
|
|
|
mca_write(port, val);
|
|
|
|
|
break;
|
|
|
|
|
case 0x107:
|
|
|
|
|
if (!(ps2.setup & PS2_SETUP_IO))
|
|
|
|
|
ps2.planar_write(port, val);
|
|
|
|
|
else if (ps2.adapter_setup & PS2_ADAPTER_SETUP)
|
|
|
|
|
mca_write(port, val);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ps2_mca_board_common_init()
|
|
|
|
|
{
|
2018-01-07 20:36:30 +01:00
|
|
|
io_sethandler(0x0091, 0x0001, ps2_mca_read, NULL, NULL, ps2_mca_write, NULL, NULL, NULL);
|
2017-05-05 01:49:42 +02:00
|
|
|
io_sethandler(0x0094, 0x0001, ps2_mca_read, NULL, NULL, ps2_mca_write, NULL, NULL, NULL);
|
|
|
|
|
io_sethandler(0x0096, 0x0001, ps2_mca_read, NULL, NULL, ps2_mca_write, NULL, NULL, NULL);
|
|
|
|
|
io_sethandler(0x0100, 0x0008, ps2_mca_read, NULL, NULL, ps2_mca_write, NULL, NULL, NULL);
|
|
|
|
|
|
2018-01-07 20:36:30 +01:00
|
|
|
port_92_reset();
|
|
|
|
|
|
|
|
|
|
port_92_add();
|
|
|
|
|
|
2017-05-05 01:49:42 +02:00
|
|
|
ps2.setup = 0xff;
|
|
|
|
|
|
|
|
|
|
lpt1_init(0x3bc);
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-02 20:39:57 +02:00
|
|
|
static void ps2_mca_board_model_50_init()
|
2017-05-05 01:49:42 +02:00
|
|
|
{
|
|
|
|
|
ps2_mca_board_common_init();
|
|
|
|
|
|
|
|
|
|
mem_remap_top_384k();
|
|
|
|
|
mca_init(4);
|
|
|
|
|
|
|
|
|
|
ps2.planar_read = model_50_read;
|
|
|
|
|
ps2.planar_write = model_50_write;
|
2017-11-05 20:43:01 -05:00
|
|
|
|
2017-12-04 20:35:05 +01:00
|
|
|
device_add(&ps1vga_device);
|
2017-05-05 01:49:42 +02:00
|
|
|
}
|
|
|
|
|
|
2017-09-02 20:39:57 +02:00
|
|
|
static void ps2_mca_board_model_55sx_init()
|
2017-05-05 01:49:42 +02:00
|
|
|
{
|
|
|
|
|
ps2_mca_board_common_init();
|
|
|
|
|
|
|
|
|
|
mem_mapping_add(&ps2.shadow_mapping,
|
|
|
|
|
(mem_size+256) * 1024,
|
|
|
|
|
128*1024,
|
|
|
|
|
ps2_read_shadow_ram,
|
|
|
|
|
ps2_read_shadow_ramw,
|
|
|
|
|
ps2_read_shadow_raml,
|
|
|
|
|
ps2_write_shadow_ram,
|
|
|
|
|
ps2_write_shadow_ramw,
|
|
|
|
|
ps2_write_shadow_raml,
|
|
|
|
|
&ram[0xe0000],
|
|
|
|
|
MEM_MAPPING_INTERNAL,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mem_remap_top_256k();
|
|
|
|
|
ps2.option[3] = 0x10;
|
|
|
|
|
|
|
|
|
|
memset(ps2.memory_bank, 0xf0, 8);
|
|
|
|
|
switch (mem_size/1024)
|
|
|
|
|
{
|
|
|
|
|
case 1:
|
|
|
|
|
ps2.memory_bank[0] = 0x61;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
ps2.memory_bank[0] = 0x51;
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
ps2.memory_bank[0] = 0x51;
|
|
|
|
|
ps2.memory_bank[1] = 0x61;
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
ps2.memory_bank[0] = 0x51;
|
|
|
|
|
ps2.memory_bank[1] = 0x51;
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
ps2.memory_bank[0] = 0x01;
|
|
|
|
|
ps2.memory_bank[1] = 0x61;
|
|
|
|
|
break;
|
|
|
|
|
case 6:
|
|
|
|
|
ps2.memory_bank[0] = 0x01;
|
|
|
|
|
ps2.memory_bank[1] = 0x51;
|
|
|
|
|
break;
|
|
|
|
|
case 7: /*Not supported*/
|
|
|
|
|
ps2.memory_bank[0] = 0x01;
|
|
|
|
|
ps2.memory_bank[1] = 0x51;
|
|
|
|
|
break;
|
|
|
|
|
case 8:
|
|
|
|
|
ps2.memory_bank[0] = 0x01;
|
|
|
|
|
ps2.memory_bank[1] = 0x01;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mca_init(4);
|
|
|
|
|
|
|
|
|
|
ps2.planar_read = model_55sx_read;
|
|
|
|
|
ps2.planar_write = model_55sx_write;
|
2017-11-05 20:43:01 -05:00
|
|
|
|
2017-12-04 20:35:05 +01:00
|
|
|
device_add(&ps1vga_device);
|
2017-05-05 01:49:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void mem_encoding_update()
|
|
|
|
|
{
|
2017-12-11 19:41:58 +01:00
|
|
|
mem_split_disable(ps2.split_size, ps2.split_addr);
|
2017-05-05 01:49:42 +02:00
|
|
|
|
2017-12-10 15:16:24 +01:00
|
|
|
ps2.split_addr = ((uint32_t) (ps2.mem_regs[0] & 0xf)) << 20;
|
2017-05-05 01:49:42 +02:00
|
|
|
|
2017-12-10 15:16:24 +01:00
|
|
|
if (ps2.mem_regs[1] & 2) {
|
2017-05-05 01:49:42 +02:00
|
|
|
mem_set_mem_state(0xe0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
|
2018-01-04 07:44:33 +01:00
|
|
|
/* pclog("PS/2 Model 80-111: ROM space enabled\n"); */
|
2017-12-10 15:16:24 +01:00
|
|
|
} else {
|
2017-05-05 01:49:42 +02:00
|
|
|
mem_set_mem_state(0xe0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
|
2018-01-04 07:44:33 +01:00
|
|
|
/* pclog("PS/2 Model 80-111: ROM space disabled\n"); */
|
2017-12-10 15:16:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ps2.mem_regs[1] & 4) {
|
|
|
|
|
mem_mapping_set_addr(&ram_low_mapping, 0x00000, 0x80000);
|
2018-01-04 07:44:33 +01:00
|
|
|
/* pclog("PS/2 Model 80-111: 00080000- 0009FFFF disabled\n"); */
|
2017-12-10 15:16:24 +01:00
|
|
|
} else {
|
|
|
|
|
mem_mapping_set_addr(&ram_low_mapping, 0x00000, 0xa0000);
|
2018-01-04 07:44:33 +01:00
|
|
|
/* pclog("PS/2 Model 80-111: 00080000- 0009FFFF enabled\n"); */
|
2017-12-10 15:16:24 +01:00
|
|
|
}
|
2017-05-05 01:49:42 +02:00
|
|
|
|
|
|
|
|
if (!(ps2.mem_regs[1] & 8))
|
|
|
|
|
{
|
2017-12-11 19:41:58 +01:00
|
|
|
if (ps2.mem_regs[1] & 4)
|
|
|
|
|
ps2.split_size = 384;
|
|
|
|
|
else
|
|
|
|
|
ps2.split_size = 256;
|
|
|
|
|
|
|
|
|
|
mem_split_enable(ps2.split_size, ps2.split_addr);
|
2017-12-10 15:16:24 +01:00
|
|
|
|
2018-01-04 07:44:33 +01:00
|
|
|
/* pclog("PS/2 Model 80-111: Split memory block enabled at %08X\n", ps2.split_addr); */
|
|
|
|
|
} /* else {
|
2017-12-10 15:16:24 +01:00
|
|
|
pclog("PS/2 Model 80-111: Split memory block disabled\n");
|
2018-01-04 07:44:33 +01:00
|
|
|
} */
|
2017-05-05 01:49:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint8_t mem_encoding_read(uint16_t addr, void *p)
|
|
|
|
|
{
|
|
|
|
|
switch (addr)
|
|
|
|
|
{
|
|
|
|
|
case 0xe0:
|
|
|
|
|
return ps2.mem_regs[0];
|
|
|
|
|
case 0xe1:
|
|
|
|
|
return ps2.mem_regs[1];
|
|
|
|
|
}
|
|
|
|
|
return 0xff;
|
|
|
|
|
}
|
|
|
|
|
static void mem_encoding_write(uint16_t addr, uint8_t val, void *p)
|
|
|
|
|
{
|
|
|
|
|
switch (addr)
|
|
|
|
|
{
|
|
|
|
|
case 0xe0:
|
|
|
|
|
ps2.mem_regs[0] = val;
|
|
|
|
|
break;
|
|
|
|
|
case 0xe1:
|
|
|
|
|
ps2.mem_regs[1] = val;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-05 22:58:34 +01:00
|
|
|
static void ps2_mca_board_model_80_type2_init(int is486)
|
2017-05-05 01:49:42 +02:00
|
|
|
{
|
|
|
|
|
ps2_mca_board_common_init();
|
|
|
|
|
|
|
|
|
|
ps2.split_addr = mem_size * 1024;
|
2017-12-10 15:16:24 +01:00
|
|
|
mca_init(8);
|
2017-05-05 01:49:42 +02:00
|
|
|
|
|
|
|
|
ps2.planar_read = model_80_read;
|
|
|
|
|
ps2.planar_write = model_80_write;
|
|
|
|
|
|
|
|
|
|
device_add(&ps2_nvr_device);
|
|
|
|
|
|
|
|
|
|
io_sethandler(0x00e0, 0x0002, mem_encoding_read, NULL, NULL, mem_encoding_write, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
|
|
ps2.mem_regs[1] = 2;
|
2017-12-10 15:16:24 +01:00
|
|
|
|
|
|
|
|
/* Note by Kotori: I rewrote this because the original code was using
|
|
|
|
|
Model 80 Type 1-style 1 MB memory card settings, which are *NOT*
|
|
|
|
|
supported by Model 80 Type 2. */
|
2017-05-05 01:49:42 +02:00
|
|
|
switch (mem_size/1024)
|
|
|
|
|
{
|
|
|
|
|
case 1:
|
2017-12-10 15:16:24 +01:00
|
|
|
ps2.option[1] = 0x0e; /* 11 10 = 0 2 */
|
|
|
|
|
ps2.mem_regs[1] = 0xd2; /* 01 = 1 (first) */
|
|
|
|
|
ps2.mem_regs[0] = 0xf0; /* 11 = invalid */
|
2017-05-05 01:49:42 +02:00
|
|
|
break;
|
|
|
|
|
case 2:
|
2017-12-10 15:16:24 +01:00
|
|
|
ps2.option[1] = 0x0e; /* 11 10 = 0 2 */
|
|
|
|
|
ps2.mem_regs[1] = 0xc2; /* 00 = 2 */
|
|
|
|
|
ps2.mem_regs[0] = 0xf0; /* 11 = invalid */
|
2017-05-05 01:49:42 +02:00
|
|
|
break;
|
|
|
|
|
case 3:
|
2017-12-10 15:16:24 +01:00
|
|
|
ps2.option[1] = 0x0a; /* 10 10 = 2 2 */
|
|
|
|
|
ps2.mem_regs[1] = 0xc2; /* 00 = 2 */
|
|
|
|
|
ps2.mem_regs[0] = 0xd0; /* 01 = 1 (first) */
|
2017-05-05 01:49:42 +02:00
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
default:
|
2017-12-10 15:16:24 +01:00
|
|
|
ps2.option[1] = 0x0a; /* 10 10 = 2 2 */
|
|
|
|
|
ps2.mem_regs[1] = 0xc2; /* 00 = 2 */
|
|
|
|
|
ps2.mem_regs[0] = 0xc0; /* 00 = 2 */
|
2017-05-05 01:49:42 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-10 15:16:24 +01:00
|
|
|
ps2.mem_regs[0] |= ((mem_size/1024) & 0x0f);
|
|
|
|
|
|
2017-12-05 22:58:34 +01:00
|
|
|
if ((mem_size > 4096) && !is486)
|
2017-05-05 01:49:42 +02:00
|
|
|
{
|
|
|
|
|
/* Only 4 MB supported on planar, create a memory expansion card for the rest */
|
2017-12-10 15:16:24 +01:00
|
|
|
mem_mapping_set_addr(&ram_high_mapping, 0x100000, 0x300000);
|
2017-05-05 01:49:42 +02:00
|
|
|
|
|
|
|
|
ps2.mem_pos_regs[0] = 0xff;
|
|
|
|
|
ps2.mem_pos_regs[1] = 0xfc;
|
|
|
|
|
|
|
|
|
|
switch (mem_size/1024)
|
|
|
|
|
{
|
|
|
|
|
case 5:
|
2017-12-10 15:16:24 +01:00
|
|
|
ps2.mem_pos_regs[4] = 0xfc; /* 11 11 11 00 = 0 0 0 1 */
|
2017-05-05 01:49:42 +02:00
|
|
|
break;
|
|
|
|
|
case 6:
|
2017-12-10 15:16:24 +01:00
|
|
|
ps2.mem_pos_regs[4] = 0xfe; /* 11 11 11 10 = 0 0 0 2 */
|
2017-05-05 01:49:42 +02:00
|
|
|
break;
|
|
|
|
|
case 7:
|
2017-12-10 15:16:24 +01:00
|
|
|
ps2.mem_pos_regs[4] = 0xf2; /* 11 11 00 10 = 0 0 1 2 */
|
2017-05-05 01:49:42 +02:00
|
|
|
break;
|
|
|
|
|
case 8:
|
2017-12-10 15:16:24 +01:00
|
|
|
ps2.mem_pos_regs[4] = 0xfa; /* 11 11 10 10 = 0 0 2 2 */
|
2017-05-05 01:49:42 +02:00
|
|
|
break;
|
|
|
|
|
case 9:
|
2017-12-10 15:16:24 +01:00
|
|
|
ps2.mem_pos_regs[4] = 0xca; /* 11 00 10 10 = 0 1 2 2 */
|
2017-05-05 01:49:42 +02:00
|
|
|
break;
|
|
|
|
|
case 10:
|
2017-12-10 15:16:24 +01:00
|
|
|
ps2.mem_pos_regs[4] = 0xea; /* 11 10 10 10 = 0 2 2 2 */
|
2017-05-05 01:49:42 +02:00
|
|
|
break;
|
|
|
|
|
case 11:
|
2017-12-10 15:16:24 +01:00
|
|
|
ps2.mem_pos_regs[4] = 0x2a; /* 00 10 10 10 = 1 2 2 2 */
|
2017-05-05 01:49:42 +02:00
|
|
|
break;
|
|
|
|
|
case 12:
|
2017-12-10 15:16:24 +01:00
|
|
|
ps2.mem_pos_regs[4] = 0xaa; /* 10 10 10 10 = 2 2 2 2 */
|
2017-05-05 01:49:42 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 07:44:33 +01:00
|
|
|
/* pclog("ps2.mem_pos_regs[4] = %08X\n", ps2.mem_pos_regs[4]); */
|
2017-12-10 15:16:24 +01:00
|
|
|
|
2017-05-05 01:49:42 +02:00
|
|
|
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);
|
|
|
|
|
}
|
2017-11-05 20:43:01 -05:00
|
|
|
|
2017-12-04 20:35:05 +01:00
|
|
|
device_add(&ps1vga_device);
|
2017-05-05 01:49:42 +02:00
|
|
|
}
|
2017-09-02 20:39:57 +02:00
|
|
|
|
2017-10-07 22:18:30 -04:00
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
machine_ps2_common_init(machine_t *model)
|
2017-09-02 20:39:57 +02:00
|
|
|
{
|
2017-10-07 22:18:30 -04:00
|
|
|
machine_common_init(model);
|
|
|
|
|
|
2017-09-02 20:39:57 +02:00
|
|
|
dma16_init();
|
|
|
|
|
ps2_dma_init();
|
2018-01-04 07:44:33 +01:00
|
|
|
device_add(&keyboard_ps2_mca_device);
|
2017-10-03 16:26:55 -04:00
|
|
|
nvr_at_init(8);
|
2017-09-02 20:39:57 +02:00
|
|
|
pic2_init();
|
|
|
|
|
|
|
|
|
|
pit_ps2_init();
|
2017-12-10 15:16:24 +01:00
|
|
|
|
|
|
|
|
nmi_mask = 0x80;
|
2017-09-02 20:39:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-10-07 22:18:30 -04:00
|
|
|
void
|
|
|
|
|
machine_ps2_model_50_init(machine_t *model)
|
2017-09-02 20:39:57 +02:00
|
|
|
{
|
2017-10-07 22:18:30 -04:00
|
|
|
machine_ps2_common_init(model);
|
|
|
|
|
|
2017-09-02 20:39:57 +02:00
|
|
|
ps2_mca_board_model_50_init();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-10-07 22:18:30 -04:00
|
|
|
void
|
|
|
|
|
machine_ps2_model_55sx_init(machine_t *model)
|
2017-09-02 20:39:57 +02:00
|
|
|
{
|
2017-10-07 22:18:30 -04:00
|
|
|
machine_ps2_common_init(model);
|
|
|
|
|
|
2017-09-02 20:39:57 +02:00
|
|
|
ps2_mca_board_model_55sx_init();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-10-07 22:18:30 -04:00
|
|
|
void
|
|
|
|
|
machine_ps2_model_80_init(machine_t *model)
|
2017-09-02 20:39:57 +02:00
|
|
|
{
|
2017-10-07 22:18:30 -04:00
|
|
|
machine_ps2_common_init(model);
|
|
|
|
|
|
2017-12-05 22:58:34 +01:00
|
|
|
ps2_mca_board_model_80_type2_init(0);
|
2017-09-02 20:39:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-12-25 17:57:05 +01:00
|
|
|
#ifdef WALTJE
|
2017-10-07 22:18:30 -04:00
|
|
|
void
|
|
|
|
|
machine_ps2_model_80_486_init(machine_t *model)
|
2017-09-02 20:39:57 +02:00
|
|
|
{
|
2017-10-07 22:18:30 -04:00
|
|
|
machine_ps2_common_init(model);
|
|
|
|
|
|
2017-12-05 22:58:34 +01:00
|
|
|
ps2_mca_board_model_80_type2_init(1);
|
2017-09-02 20:39:57 +02:00
|
|
|
}
|
2017-12-25 17:57:05 +01:00
|
|
|
#endif
|