Rewrote the V86P's I/O chip and fixed its UART IRQ assignments, fixes serial mouse, closes #1678.
This commit is contained in:
@@ -43,306 +43,318 @@
|
|||||||
#include <86box/nvr.h>
|
#include <86box/nvr.h>
|
||||||
#include <86box/sio.h>
|
#include <86box/sio.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct upc_t
|
typedef struct upc_t
|
||||||
{
|
{
|
||||||
uint32_t local;
|
uint32_t local;
|
||||||
int configuration_state; /* state of algorithm to enter configuration mode */
|
int configuration_state; /* state of algorithm to enter configuration mode */
|
||||||
int configuration_mode;
|
int configuration_mode;
|
||||||
uint16_t cri_addr; /* cri = configuration index register, addr is even */
|
uint16_t cri_addr; /* cri = configuration index register, addr is even */
|
||||||
uint16_t cap_addr; /* cap = configuration access port, addr is odd and is cri_addr + 1 */
|
uint16_t cap_addr; /* cap = configuration access port, addr is odd and is cri_addr + 1 */
|
||||||
uint8_t cri; /* currently indexed register */
|
uint8_t cri; /* currently indexed register */
|
||||||
|
uint8_t last_write;
|
||||||
|
|
||||||
/* these regs are not affected by reset */
|
/* these regs are not affected by reset */
|
||||||
uint8_t regs[15]; /* there are 16 indexes, but there is no need to store the last one which is: R = cri_addr / 4, W = exit config mode */
|
uint8_t regs[15]; /* there are 16 indexes, but there is no need to store the last one which is: R = cri_addr / 4, W = exit config mode */
|
||||||
fdc_t *fdc;
|
fdc_t * fdc;
|
||||||
nvr_t *nvr;
|
nvr_t * nvr;
|
||||||
void *gameport;
|
void * gameport;
|
||||||
serial_t *uart[2];
|
serial_t * uart[2];
|
||||||
} upc_t;
|
} upc_t;
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
f82c710_update_ports(upc_t *upc)
|
f82c710_update_ports(upc_t *dev, int set)
|
||||||
{
|
{
|
||||||
uint16_t com_addr = 0;
|
uint16_t com_addr = 0;
|
||||||
uint16_t lpt_addr = 0;
|
uint16_t lpt_addr = 0;
|
||||||
|
|
||||||
serial_remove(upc->uart[0]);
|
|
||||||
serial_remove(upc->uart[1]);
|
|
||||||
lpt1_remove();
|
|
||||||
lpt2_remove();
|
|
||||||
fdc_remove(upc->fdc);
|
|
||||||
ide_pri_disable();
|
|
||||||
|
|
||||||
if (upc->regs[0] & 4) {
|
serial_remove(dev->uart[0]);
|
||||||
com_addr = upc->regs[4] * 4;
|
serial_remove(dev->uart[1]);
|
||||||
if (com_addr == SERIAL1_ADDR) {
|
lpt1_remove();
|
||||||
serial_setup(upc->uart[0], com_addr, 4);
|
lpt2_remove();
|
||||||
} else if (com_addr == SERIAL2_ADDR) {
|
fdc_remove(dev->fdc);
|
||||||
serial_setup(upc->uart[1], com_addr, 3);
|
ide_pri_disable();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (upc->regs[0] & 8) {
|
if (!set)
|
||||||
lpt_addr = upc->regs[6] * 4;
|
return;
|
||||||
lpt1_init(lpt_addr);
|
|
||||||
if ((lpt_addr == 0x378) || (lpt_addr == 0x3bc)) {
|
|
||||||
lpt1_irq(7);
|
|
||||||
} else if (lpt_addr == 0x278) {
|
|
||||||
lpt1_irq(5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (upc->regs[12] & 0x80) {
|
if (dev->regs[0] & 4) {
|
||||||
ide_pri_enable();
|
com_addr = dev->regs[4] * 4;
|
||||||
}
|
if (com_addr == SERIAL1_ADDR)
|
||||||
|
serial_setup(dev->uart[0], com_addr, 4);
|
||||||
|
else if (com_addr == SERIAL2_ADDR)
|
||||||
|
serial_setup(dev->uart[1], com_addr, 3);
|
||||||
|
}
|
||||||
|
|
||||||
if (upc->regs[12] & 0x20) {
|
if (dev->regs[0] & 8) {
|
||||||
fdc_set_base(upc->fdc, 0x03f0);
|
lpt_addr = dev->regs[6] * 4;
|
||||||
}
|
lpt1_init(lpt_addr);
|
||||||
|
if ((lpt_addr == 0x378) || (lpt_addr == 0x3bc))
|
||||||
|
lpt1_irq(7);
|
||||||
|
else if (lpt_addr == 0x278)
|
||||||
|
lpt1_irq(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev->regs[12] & 0x80)
|
||||||
|
ide_pri_enable();
|
||||||
|
|
||||||
|
if (dev->regs[12] & 0x20)
|
||||||
|
fdc_set_base(dev->fdc, 0x03f0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
f82c606_update_ports(upc_t *upc)
|
f82c606_update_ports(upc_t *dev, int set)
|
||||||
{
|
{
|
||||||
uint8_t uart1_int = 0xff;
|
uint8_t uart1_int = 0xff;
|
||||||
uint8_t uart2_int = 0xff;
|
uint8_t uart2_int = 0xff;
|
||||||
uint8_t lpt1_int = 0xff;
|
uint8_t lpt1_int = 0xff;
|
||||||
int nvr_int = -1;
|
int nvr_int = -1;
|
||||||
|
|
||||||
serial_remove(upc->uart[0]);
|
serial_remove(dev->uart[0]);
|
||||||
serial_remove(upc->uart[1]);
|
serial_remove(dev->uart[1]);
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
lpt2_remove();
|
lpt2_remove();
|
||||||
|
|
||||||
nvr_at_handler(0, upc->regs[3] * 4, upc->nvr);
|
nvr_at_handler(0, ((uint16_t) dev->regs[3]) << 2, dev->nvr);
|
||||||
nvr_at_handler(0, 0x70, upc->nvr);
|
nvr_at_handler(0, 0x70, dev->nvr);
|
||||||
|
|
||||||
switch (upc->regs[8] & 0xc0) {
|
gameport_remap(dev->gameport, 0);
|
||||||
case 0x40: nvr_int = 4; break;
|
|
||||||
case 0x80: uart1_int = 4; break;
|
|
||||||
case 0xc0: uart2_int = 4; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (upc->regs[8] & 0x30) {
|
if (!set)
|
||||||
case 0x10: nvr_int = 3; break;
|
return;
|
||||||
case 0x20: uart1_int = 3; break;
|
|
||||||
case 0x30: uart2_int = 3; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (upc->regs[8] & 0x0c) {
|
switch (dev->regs[8] & 0xc0) {
|
||||||
|
case 0x40: nvr_int = 3; break;
|
||||||
|
case 0x80: uart1_int = 3; break;
|
||||||
|
case 0xc0: uart2_int = 3; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (dev->regs[8] & 0x30) {
|
||||||
|
case 0x10: nvr_int = 4; break;
|
||||||
|
case 0x20: uart1_int = 4; break;
|
||||||
|
case 0x30: uart2_int = 4; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (dev->regs[8] & 0x0c) {
|
||||||
case 0x04: nvr_int = 5; break;
|
case 0x04: nvr_int = 5; break;
|
||||||
case 0x08: uart1_int = 5; break;
|
case 0x08: uart1_int = 5; break;
|
||||||
case 0x0c: lpt1_int = 5; break;
|
case 0x0c: lpt1_int = 5; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (upc->regs[8] & 0x03) {
|
switch (dev->regs[8] & 0x03) {
|
||||||
case 0x01: nvr_int = 7; break;
|
case 0x01: nvr_int = 7; break;
|
||||||
case 0x02: uart2_int = 7; break;
|
case 0x02: uart2_int = 7; break;
|
||||||
case 0x03: lpt1_int = 7; break;
|
case 0x03: lpt1_int = 7; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (upc->regs[0] & 1)
|
if (dev->regs[0] & 1) {
|
||||||
gameport_remap(upc->gameport, upc->regs[7] * 4);
|
gameport_remap(dev->gameport, ((uint16_t) dev->regs[7]) << 2);
|
||||||
else
|
pclog("Game port at %04X\n", ((uint16_t) dev->regs[7]) << 2);
|
||||||
gameport_remap(upc->gameport, 0);
|
}
|
||||||
|
|
||||||
if (upc->regs[0] & 2)
|
if (dev->regs[0] & 2) {
|
||||||
serial_setup(upc->uart[0], upc->regs[4] * 4, uart1_int);
|
serial_setup(dev->uart[0], ((uint16_t) dev->regs[4]) << 2, uart1_int);
|
||||||
|
pclog("UART 1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[4]) << 2, uart1_int);
|
||||||
|
}
|
||||||
|
|
||||||
if (upc->regs[0] & 4)
|
if (dev->regs[0] & 4) {
|
||||||
serial_setup(upc->uart[1], upc->regs[5] * 4, uart2_int);
|
serial_setup(dev->uart[1], ((uint16_t) dev->regs[5]) << 2, uart2_int);
|
||||||
|
pclog("UART 2 at %04X, IRQ %i\n", ((uint16_t) dev->regs[5]) << 2, uart2_int);
|
||||||
|
}
|
||||||
|
|
||||||
if (upc->regs[0] & 8) {
|
if (dev->regs[0] & 8) {
|
||||||
lpt1_init(upc->regs[6] * 4);
|
lpt1_init(((uint16_t) dev->regs[6]) << 2);
|
||||||
lpt1_irq(lpt1_int);
|
lpt1_irq(lpt1_int);
|
||||||
}
|
pclog("LPT1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[6]) << 2, lpt1_int);
|
||||||
|
}
|
||||||
|
|
||||||
nvr_at_handler(1, upc->regs[3] * 4, upc->nvr);
|
nvr_at_handler(1, ((uint16_t) dev->regs[3]) << 2, dev->nvr);
|
||||||
nvr_irq_set(nvr_int, upc->nvr);
|
nvr_irq_set(nvr_int, dev->nvr);
|
||||||
|
pclog("RTC at %04X, IRQ %i\n", ((uint16_t) dev->regs[3]) << 2, nvr_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
f82c710_config_read(uint16_t port, void *priv)
|
f82c710_config_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
upc_t *upc = (upc_t *)priv;
|
upc_t *dev = (upc_t *) priv;
|
||||||
uint8_t temp = 0xff;
|
uint8_t temp = 0xff;
|
||||||
|
|
||||||
if (upc->configuration_mode) {
|
if (dev->configuration_mode) {
|
||||||
if (port == upc->cri_addr) {
|
if (port == dev->cri_addr) {
|
||||||
temp = upc->cri;
|
temp = dev->cri;
|
||||||
} else if (port == upc->cap_addr) {
|
} else if (port == dev->cap_addr) {
|
||||||
if (upc->cri == 0xf)
|
if (dev->cri == 0xf)
|
||||||
temp = upc->cri_addr / 4;
|
temp = dev->cri_addr / 4;
|
||||||
else
|
else
|
||||||
temp = upc->regs[upc->cri];
|
temp = dev->regs[dev->cri];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
f82c710_config_write(uint16_t port, uint8_t val, void *priv)
|
f82c710_config_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
upc_t *upc = (upc_t *)priv;
|
upc_t *dev = (upc_t *) priv;
|
||||||
int configuration_state_event = 0;
|
int configuration_state_event = 0;
|
||||||
|
|
||||||
switch(port) {
|
switch (port) {
|
||||||
case 0x2fa:
|
case 0x2fa:
|
||||||
if (upc->configuration_state == 0 && val == 0x55)
|
if ((dev->configuration_state == 0) && (val != 0x00) && (val != 0xff) && (dev->local == 606)) {
|
||||||
configuration_state_event = 1;
|
configuration_state_event = 1;
|
||||||
else if (upc->configuration_state == 4) {
|
dev->last_write = val;
|
||||||
uint8_t addr_verify = upc->cri_addr / 4;
|
} else if ((dev->configuration_state == 0) && (val == 0x55) && (dev->local == 710))
|
||||||
addr_verify += val;
|
configuration_state_event = 1;
|
||||||
if (addr_verify == 0xff) {
|
else if (dev->configuration_state == 4) {
|
||||||
upc->configuration_mode = 1;
|
if ((val | dev->last_write) == 0xff) {
|
||||||
/* TODO: is the value of cri reset here or when exiting configuration mode? */
|
dev->cri_addr = ((uint16_t) dev->last_write) << 2;
|
||||||
io_sethandler(upc->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, upc);
|
dev->cap_addr = dev->cri_addr + 1;
|
||||||
} else {
|
dev->configuration_mode = 1;
|
||||||
upc->configuration_mode = 0;
|
if (dev->local == 606)
|
||||||
}
|
f82c606_update_ports(dev, 0);
|
||||||
}
|
else if (dev->local == 710)
|
||||||
break;
|
f82c710_update_ports(dev, 0);
|
||||||
case 0x3fa:
|
/* TODO: is the value of cri reset here or when exiting configuration mode? */
|
||||||
if (upc->configuration_state == 1 && val == 0xaa)
|
io_sethandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev);
|
||||||
configuration_state_event = 1;
|
} else
|
||||||
else if (upc->configuration_state == 2 && val == 0x36)
|
dev->configuration_mode = 0;
|
||||||
configuration_state_event = 1;
|
}
|
||||||
else if (upc->configuration_state == 3) {
|
break;
|
||||||
upc->cri_addr = val * 4;
|
case 0x3fa:
|
||||||
upc->cap_addr = upc->cri_addr + 1;
|
if ((dev->configuration_state == 1) && ((val | dev->last_write) == 0xff) && (dev->local == 606))
|
||||||
configuration_state_event = 1;
|
configuration_state_event = 1;
|
||||||
}
|
else if ((dev->configuration_state == 1) && (val == 0xaa) && (dev->local == 710))
|
||||||
break;
|
configuration_state_event = 1;
|
||||||
default:
|
else if ((dev->configuration_state == 2) && (val == 0x36))
|
||||||
break;
|
configuration_state_event = 1;
|
||||||
}
|
else if (dev->configuration_state == 3) {
|
||||||
|
dev->last_write = val;
|
||||||
if (upc->configuration_mode) {
|
configuration_state_event = 1;
|
||||||
if (port == upc->cri_addr) {
|
}
|
||||||
upc->cri = val & 0xf;
|
break;
|
||||||
} else if (port == upc->cap_addr) {
|
default:
|
||||||
if (upc->cri == 0xf) {
|
break;
|
||||||
upc->configuration_mode = 0;
|
}
|
||||||
io_removehandler(upc->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, upc);
|
|
||||||
/* TODO: any benefit in updating at each register write instead of when exiting config mode? */
|
|
||||||
if (upc->local == 710)
|
|
||||||
f82c710_update_ports(upc);
|
|
||||||
if (upc->local == 606)
|
|
||||||
f82c606_update_ports(upc);
|
|
||||||
} else {
|
|
||||||
upc->regs[upc->cri] = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: is the state only reset when accessing 0x2fa and 0x3fa wrongly? */
|
if (dev->configuration_mode) {
|
||||||
if ((port == 0x2fa || port == 0x3fa) && configuration_state_event)
|
if (port == dev->cri_addr) {
|
||||||
upc->configuration_state++;
|
dev->cri = val & 0xf;
|
||||||
else
|
} else if (port == dev->cap_addr) {
|
||||||
upc->configuration_state = 0;
|
if (dev->cri == 0xf) {
|
||||||
|
dev->configuration_mode = 0;
|
||||||
|
io_removehandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev);
|
||||||
|
/* TODO: any benefit in updating at each register write instead of when exiting config mode? */
|
||||||
|
if (dev->local == 606)
|
||||||
|
f82c606_update_ports(dev, 1);
|
||||||
|
else if (dev->local == 710)
|
||||||
|
f82c710_update_ports(dev, 1);
|
||||||
|
} else
|
||||||
|
dev->regs[dev->cri] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: is the state only reset when accessing 0x2fa and 0x3fa wrongly? */
|
||||||
|
if ((port == 0x2fa || port == 0x3fa) && configuration_state_event)
|
||||||
|
dev->configuration_state++;
|
||||||
|
else
|
||||||
|
dev->configuration_state = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
f82c710_reset(upc_t *upc)
|
f82c710_reset(void *priv)
|
||||||
{
|
{
|
||||||
serial_remove(upc->uart[0]);
|
upc_t *dev = (upc_t *) priv;
|
||||||
serial_setup(upc->uart[0], SERIAL1_ADDR, SERIAL1_IRQ);
|
|
||||||
|
|
||||||
serial_remove(upc->uart[1]);
|
/* Set power-on defaults. */
|
||||||
serial_setup(upc->uart[1], SERIAL2_ADDR, SERIAL2_IRQ);
|
if (dev->local == 606) {
|
||||||
|
dev->regs[0] = 0x00; /* Enable */
|
||||||
lpt1_remove();
|
dev->regs[1] = 0x00; /* Configuration Register */
|
||||||
lpt1_init(0x378);
|
dev->regs[2] = 0x00; /* Ext Baud Rate Select */
|
||||||
lpt1_irq(7);
|
dev->regs[3] = 0xb0; /* RTC Base */
|
||||||
|
dev->regs[4] = 0xfe; /* UART1 Base */
|
||||||
|
dev->regs[5] = 0xbe; /* UART2 Base */
|
||||||
|
dev->regs[6] = 0x9e; /* Parallel Base */
|
||||||
|
dev->regs[7] = 0x80; /* Game Base */
|
||||||
|
dev->regs[8] = 0xec; /* Interrupt Select */
|
||||||
|
} else if (dev->local == 710) {
|
||||||
|
dev->regs[0] = 0x0c;
|
||||||
|
dev->regs[1] = 0x00;
|
||||||
|
dev->regs[2] = 0x00;
|
||||||
|
dev->regs[3] = 0x00;
|
||||||
|
dev->regs[4] = 0xfe;
|
||||||
|
dev->regs[5] = 0x00;
|
||||||
|
dev->regs[6] = 0x9e;
|
||||||
|
dev->regs[7] = 0x00;
|
||||||
|
dev->regs[8] = 0x00;
|
||||||
|
dev->regs[9] = 0xb0;
|
||||||
|
dev->regs[10] = 0x00;
|
||||||
|
dev->regs[11] = 0x00;
|
||||||
|
dev->regs[12] = 0xa0;
|
||||||
|
dev->regs[13] = 0x00;
|
||||||
|
dev->regs[14] = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
if (upc->local == 710)
|
if (dev->local == 606)
|
||||||
fdc_reset(upc->fdc);
|
f82c606_update_ports(dev, 1);
|
||||||
|
else if (dev->local == 710)
|
||||||
|
f82c710_update_ports(dev, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *
|
|
||||||
f82c710_init(const device_t *info)
|
|
||||||
{
|
|
||||||
upc_t *upc = (upc_t *) malloc(sizeof(upc_t));
|
|
||||||
memset(upc, 0, sizeof(upc_t));
|
|
||||||
upc->local = info->local;
|
|
||||||
|
|
||||||
if (upc->local == 710) {
|
|
||||||
upc->regs[0] = 0x0c;
|
|
||||||
upc->regs[1] = 0x00;
|
|
||||||
upc->regs[2] = 0x00;
|
|
||||||
upc->regs[3] = 0x00;
|
|
||||||
upc->regs[4] = 0xfe;
|
|
||||||
upc->regs[5] = 0x00;
|
|
||||||
upc->regs[6] = 0x9e;
|
|
||||||
upc->regs[7] = 0x00;
|
|
||||||
upc->regs[8] = 0x00;
|
|
||||||
upc->regs[9] = 0xb0;
|
|
||||||
upc->regs[10] = 0x00;
|
|
||||||
upc->regs[11] = 0x00;
|
|
||||||
upc->regs[12] = 0xa0;
|
|
||||||
upc->regs[13] = 0x00;
|
|
||||||
upc->regs[14] = 0x00;
|
|
||||||
|
|
||||||
upc->fdc = device_add(&fdc_at_device);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (upc->local == 606) {
|
|
||||||
/* Set power-on defaults. */
|
|
||||||
upc->regs[0] = 0x00; /* Enable */
|
|
||||||
upc->regs[1] = 0x00; /* Configuration Register */
|
|
||||||
upc->regs[2] = 0x00; /* Ext Baud Rate Select */
|
|
||||||
upc->regs[3] = 0xb0; /* RTC Base */
|
|
||||||
upc->regs[4] = 0xfe; /* UART1 Base */
|
|
||||||
upc->regs[5] = 0xbe; /* UART2 Base */
|
|
||||||
upc->regs[6] = 0x9e; /* Parallel Base */
|
|
||||||
upc->regs[7] = 0x80; /* Game Base */
|
|
||||||
upc->regs[8] = 0xec; /* Interrupt Select */
|
|
||||||
|
|
||||||
upc->nvr = device_add(&at_nvr_old_device);
|
|
||||||
upc->gameport = gameport_add(&gameport_sio_device);
|
|
||||||
}
|
|
||||||
|
|
||||||
upc->uart[0] = device_add_inst(&ns16450_device, 1);
|
|
||||||
upc->uart[1] = device_add_inst(&ns16450_device, 2);
|
|
||||||
|
|
||||||
io_sethandler(0x02fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, upc);
|
|
||||||
io_sethandler(0x03fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, upc);
|
|
||||||
|
|
||||||
f82c710_reset(upc);
|
|
||||||
|
|
||||||
if (upc->local == 710)
|
|
||||||
f82c710_update_ports(upc);
|
|
||||||
if (upc->local == 606)
|
|
||||||
f82c606_update_ports(upc);
|
|
||||||
|
|
||||||
return upc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
f82c710_close(void *priv)
|
f82c710_close(void *priv)
|
||||||
{
|
{
|
||||||
upc_t *upc = (upc_t *)priv;
|
upc_t *dev = (upc_t *) priv;
|
||||||
|
|
||||||
free(upc);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
f82c710_init(const device_t *info)
|
||||||
|
{
|
||||||
|
upc_t *dev = (upc_t *) malloc(sizeof(upc_t));
|
||||||
|
memset(dev, 0, sizeof(upc_t));
|
||||||
|
dev->local = info->local;
|
||||||
|
|
||||||
|
if (dev->local == 606) {
|
||||||
|
dev->nvr = device_add(&at_nvr_old_device);
|
||||||
|
dev->gameport = gameport_add(&gameport_sio_device);
|
||||||
|
} else if (dev->local == 710)
|
||||||
|
dev->fdc = device_add(&fdc_at_device);
|
||||||
|
|
||||||
|
dev->uart[0] = device_add_inst(&ns16450_device, 1);
|
||||||
|
dev->uart[1] = device_add_inst(&ns16450_device, 2);
|
||||||
|
|
||||||
|
io_sethandler(0x02fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, dev);
|
||||||
|
io_sethandler(0x03fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, dev);
|
||||||
|
|
||||||
|
f82c710_reset(dev);
|
||||||
|
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const device_t f82c606_device = {
|
const device_t f82c606_device = {
|
||||||
"82C606 CHIPSpak Multifunction Controller",
|
"82C606 CHIPSpak Multifunction Controller",
|
||||||
0,
|
0,
|
||||||
606,
|
606,
|
||||||
f82c710_init, f82c710_close, NULL,
|
f82c710_init, f82c710_close, f82c710_reset,
|
||||||
{ NULL }, NULL, NULL,
|
{ NULL }, NULL, NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t f82c710_device = {
|
const device_t f82c710_device = {
|
||||||
"F82C710 UPC Super I/O",
|
"F82C710 UPC Super I/O",
|
||||||
0,
|
0,
|
||||||
710,
|
710,
|
||||||
f82c710_init, f82c710_close, NULL,
|
f82c710_init, f82c710_close, f82c710_reset,
|
||||||
{ NULL }, NULL, NULL,
|
{ NULL }, NULL, NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user