pcem/src/acer386sx.c
SarahW 9dbedefc5f Improvements to Acermate 386SX25/N :
- Implemented serial & parallel port configuration
- Implemented shadow RAM
- OTI-067 now configured as on-board device rather than separate card
2017-08-20 21:49:33 +01:00

156 lines
5.5 KiB
C

#include "ibm.h"
#include "device.h"
#include "io.h"
#include "cpu.h"
#include "lpt.h"
#include "mem.h"
#include "serial.h"
#include "vid_oti067.h"
#include "acer386sx.h"
static int acer_index = 0;
static uint8_t acer_regs[256];
static uint8_t acer_last_write;
static int acer_locked;
static void *acer_oti067;
void acer386sx_set_oti067(void *oti067)
{
acer_oti067 = oti067;
}
void acer386sx_write(uint16_t addr, uint8_t val, void *priv)
{
if (addr & 1)
{
if (acer_locked)
{
if (acer_last_write == 0x14 && val == 0x09)
acer_locked = 0;
acer_last_write = val;
return;
}
if (acer_index == 0xff && val == 0xff)
acer_locked = 1;
else
{
pclog("Write ACER reg %02x %02x %08x\n", acer_index, val, cs);
acer_regs[acer_index] = val;
switch (acer_index)
{
case 0xa:
switch ((val >> 4) & 3)
{
case 0:
mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
break;
case 1:
mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
break;
case 2:
mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
break;
case 3:
mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
}
break;
case 0xb:
switch ((val >> 4) & 3)
{
case 0:
mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
break;
case 1:
mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
break;
case 2:
mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
break;
case 3:
mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
}
break;
}
}
}
else
acer_index = val;
}
uint8_t acer386sx_read(uint16_t addr, void *priv)
{
if (acer_locked)
return 0xff;
if (addr & 1)
{
if ((acer_index >= 0xc0 || acer_index == 0x20) && cpu_iscyrix)
return 0xff; /*Don't conflict with Cyrix config registers*/
return acer_regs[acer_index];
}
else
return acer_index;
}
static uint8_t acer386sx_37f = 0, acer386sx_io = 0;
void acer386sx_io_write(uint16_t addr, uint8_t val, void *priv)
{
switch (addr)
{
case 0x37f:
acer386sx_37f = val;
if (val & 4)
oti067_enable_disable(acer_oti067, 0);
else
oti067_enable_disable(acer_oti067, 1);
break;
case 0x3f3:
acer386sx_io = val;
serial1_remove();
serial2_remove();
lpt1_remove();
lpt2_remove();
switch (val & 3)
{
case 0: lpt1_init(0x378); break;
case 1: lpt1_init(0x3bc); break;
case 2: lpt1_init(0x278); break;
}
if (!(val & 0x04))
serial1_set(0x3f8, 4);
if (!(val & 0x08))
serial2_set(0x2f8, 3);
break;
}
}
uint8_t acer386sx_io_read(uint16_t addr, void *priv)
{
switch (addr)
{
case 0x37f:
return acer386sx_37f;
case 0x3f3:
return acer386sx_io;
}
return 0xff;
}
void acer386sx_init()
{
io_sethandler(0x0022, 0x0002, acer386sx_read, NULL, NULL, acer386sx_write, NULL, NULL, NULL);
io_sethandler(0x037f, 0x0001, acer386sx_io_read, NULL, NULL, acer386sx_io_write, NULL, NULL, NULL);
io_sethandler(0x03f3, 0x0001, acer386sx_io_read, NULL, NULL, acer386sx_io_write, NULL, NULL, NULL);
acer386sx_io = 0;
acer386sx_37f = 0;
}