STPC serial and parallel support

This commit is contained in:
RichardG867
2020-07-14 22:24:22 -03:00
parent 639807cd3e
commit a1e273b13b
5 changed files with 259 additions and 19 deletions

View File

@@ -6,7 +6,7 @@
*
* This file is part of the 86Box distribution.
*
* Implementation of the STPC series of SoCs.
* Implementation of the STMicroelectronics STPC series of SoCs.
*
*
*
@@ -35,6 +35,8 @@
#include <86box/usb.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/serial.h>
#include <86box/lpt.h>
#include <86box/chipset.h>
@@ -70,6 +72,19 @@ typedef struct stpc_t
sff8038i_t *bm[2];
} stpc_t;
typedef struct stpc_serial_t
{
serial_t *uart[2];
} stpc_serial_t;
typedef struct stpc_lpt_t
{
uint8_t unlocked;
uint8_t offset;
uint8_t reg1;
uint8_t reg4;
} stpc_lpt_t;
#ifdef ENABLE_STPC_LOG
int stpc_do_log = ENABLE_STPC_LOG;
@@ -576,6 +591,50 @@ stpc_remap_localbus(stpc_t *dev, uint16_t localbus_base)
}
static uint8_t
stpc_serial_handlers(uint8_t val)
{
stpc_serial_t *dev;
if (!(dev = device_get_priv(&stpc_serial_device))) {
stpc_log("STPC: Not remapping UARTs, disabled by strap (raw %02X)\n", val);
return 0;
}
uint16_t uart0_io = 0x3f8, uart0_irq = 4, uart1_io = 0x3f8, uart1_irq = 3;
if (val & 0x10)
uart1_io -= 0x100;
if (val & 0x20)
uart1_io -= 0x10;
if (val & 0x40)
uart0_io -= 0x100;
if (val & 0x80)
uart0_io -= 0x10;
if (uart0_io == uart1_io) {
/* Apply defaults if both UARTs are set to the same address. */
stpc_log("STPC: Both UARTs set to %02X, resetting to defaults\n", uart0_io);
uart0_io = 0x3f8;
uart1_io = 0x2f8;
}
if ((uart0_io & 0x0f00) < 0x300) {
/* The address for UART0 defines the IRQs for both ports. */
uart0_irq = 3;
uart1_irq = 4;
}
stpc_log("STPC: Remapping UART0 to %04X %d and UART1 to %04X %d (raw %02X)\n", uart0_io, uart0_irq, uart1_io, uart1_irq, val);
serial_remove(dev->uart[0]);
serial_setup(dev->uart[0], uart0_io, uart0_irq);
serial_remove(dev->uart[1]);
serial_setup(dev->uart[1], uart1_io, uart1_irq);
return 1;
}
static void
stpc_reg_write(uint16_t addr, uint8_t val, void *priv)
{
@@ -635,11 +694,15 @@ stpc_reg_write(uint16_t addr, uint8_t val, void *priv)
break;
case 0x56: case 0x57:
/* ELCR goes here */
elcr_write(dev->reg_offset, val, NULL);
if (dev->reg_offset == 0x57)
refresh_at_enable = val & 0x01;
break;
case 0x59:
val &= 0xf1;
stpc_serial_handlers(val);
break;
}
dev->regs[dev->reg_offset] = val;
@@ -678,11 +741,10 @@ stpc_reset(void *priv)
memset(dev->regs, 0, sizeof(dev->regs));
dev->regs[0x7b] = 0xff;
io_removehandler(0x22, 2,
stpc_reg_read, NULL, NULL, stpc_reg_write, NULL, NULL, dev);
io_sethandler(0x22, 2,
stpc_reg_read, NULL, NULL, stpc_reg_write, NULL, NULL, dev);
if (device_get_priv(&stpc_lpt_device))
dev->regs[0x4c] |= 0x80; /* LPT strap */
if (stpc_serial_handlers(0))
dev->regs[0x4c] |= 0x03; /* UART straps */
}
@@ -691,6 +753,10 @@ stpc_setup(stpc_t *dev)
{
stpc_log("STPC: setup()\n");
/* Main register interface */
io_sethandler(0x22, 2,
stpc_reg_read, NULL, NULL, stpc_reg_write, NULL, NULL, dev);
/* Northbridge */
if (dev->local & STPC_NB_CLIENT) {
/* Client */
@@ -832,6 +898,9 @@ stpc_close(void *priv)
stpc_log("STPC: close()\n");
io_removehandler(0x22, 2,
stpc_reg_read, NULL, NULL, stpc_reg_write, NULL, NULL, dev);
free(dev);
}
@@ -886,6 +955,152 @@ stpc_init(const device_t *info)
}
static void
stpc_serial_close(void *priv)
{
stpc_serial_t *dev = (stpc_serial_t *) priv;
stpc_log("STPC: serial_close()\n");
free(dev);
}
static void *
stpc_serial_init(const device_t *info)
{
stpc_log("STPC: serial_init()\n");
stpc_serial_t *dev = (stpc_serial_t *) malloc(sizeof(stpc_serial_t));
memset(dev, 0, sizeof(stpc_serial_t));
dev->uart[0] = device_add_inst(&ns16550_device, 1);
dev->uart[1] = device_add_inst(&ns16550_device, 2);
/* Initialization is performed by stpc_reset. */
return dev;
}
static void
stpc_lpt_handlers(stpc_lpt_t *dev, uint8_t val)
{
uint8_t old_addr = (dev->reg1 & 0x03), new_addr = (val & 0x03);
switch (old_addr) {
case 0x1:
lpt3_remove();
break;
case 0x2:
lpt1_remove();
break;
case 0x3:
lpt2_remove();
break;
}
switch (new_addr) {
case 0x1:
stpc_log("STPC: Remapping parallel port to LPT3\n");
lpt3_init(0x3bc);
break;
case 0x2:
stpc_log("STPC: Remapping parallel port to LPT1\n");
lpt1_init(0x378);
break;
case 0x3:
stpc_log("STPC: Remapping parallel port to LPT2\n");
lpt2_init(0x278);
break;
default:
stpc_log("STPC: Disabling parallel port\n");
break;
}
dev->reg1 = (val & 0x08);
dev->reg1 |= new_addr;
dev->reg1 |= 0x84; /* reserved bits that default to 1 - hardwired? */
}
static void
stpc_lpt_write(uint16_t addr, uint8_t val, void *priv)
{
stpc_lpt_t *dev = (stpc_lpt_t *) priv;
if (dev->unlocked < 2) {
if (addr == 0x3f0) {
if (val == 0x55)
dev->unlocked++;
else
dev->unlocked = 0;
}
} else if (addr == 0x3f0) {
if (val == 0xaa)
dev->unlocked = 0;
else
dev->offset = val;
} else if (dev->offset == 1) {
stpc_lpt_handlers(dev, val);
} else if (dev->offset == 4) {
dev->reg4 = (val & 0x03);
}
}
static void
stpc_lpt_reset(void *priv)
{
stpc_lpt_t *dev = (stpc_lpt_t *) priv;
stpc_log("STPC: lpt_reset()\n");
dev->unlocked = 0;
dev->offset = 0x00;
dev->reg1 = 0x9f;
dev->reg4 = 0x00;
stpc_lpt_handlers(dev, dev->reg1);
}
static void
stpc_lpt_close(void *priv)
{
stpc_lpt_t *dev = (stpc_lpt_t *) priv;
stpc_log("STPC: lpt_close()\n");
io_removehandler(0x3f0, 2,
NULL, NULL, NULL, stpc_lpt_write, NULL, NULL, dev);
free(dev);
}
static void *
stpc_lpt_init(const device_t *info)
{
stpc_log("STPC: lpt_init()\n");
stpc_lpt_t *dev = (stpc_lpt_t *) malloc(sizeof(stpc_lpt_t));
memset(dev, 0, sizeof(stpc_lpt_t));
stpc_lpt_reset(dev);
io_sethandler(0x3f0, 2,
NULL, NULL, NULL, stpc_lpt_write, NULL, NULL, dev);
return dev;
}
/* STPC SoCs */
const device_t stpc_client_device =
{
"STPC Client",
@@ -941,3 +1156,32 @@ const device_t stpc_atlas_device =
NULL,
NULL
};
/* Auxiliary devices */
const device_t stpc_serial_device =
{
"STPC Serial UARTs",
0,
0,
stpc_serial_init,
stpc_serial_close,
NULL,
NULL,
NULL,
NULL,
NULL
};
const device_t stpc_lpt_device =
{
"STPC Parallel Port",
0,
0,
stpc_lpt_init,
stpc_lpt_close,
stpc_lpt_reset,
NULL,
NULL,
NULL,
NULL
};

View File

@@ -76,11 +76,7 @@ postcard_setui(void)
if (postcard_do_log) {
/* log same string sent to the UI */
int len = strlen(postcard_str);
postcard_str[len + 1] = '\0';
postcard_str[len] = '\n';
postcard_log("[%04X:%08X] ", CS, cpu_state.pc);
postcard_log(postcard_str);
postcard_log("[%04X:%08X] %s\n", CS, cpu_state.pc, postcard_str);
}
}

View File

@@ -90,6 +90,8 @@ extern const device_t stpc_client_device;
extern const device_t stpc_consumer2_device;
extern const device_t stpc_elite_device;
extern const device_t stpc_atlas_device;
extern const device_t stpc_serial_device;
extern const device_t stpc_lpt_device;
#endif
/* VIA */

View File

@@ -251,7 +251,7 @@ extern const device_t *at_commodore_sl386sx_get_device(void);
extern int machine_at_acc386_init(const machine_t *);
extern int machine_at_asus386_init(const machine_t *);
extern int machine_at_ecs386_init(const machine_t *);
extern int machine_at_ecs386_init(const machine_t *);
extern int machine_at_micronics386_init(const machine_t *);
extern int machine_at_rycleopardlx_init(const machine_t *);
@@ -305,7 +305,7 @@ extern const device_t *at_cpqiii_get_device(void);
#endif
/* m_at_socket4_5.c */
extern int machine_at_excalibur_init(const machine_t *);
extern int machine_at_excalibur_init(const machine_t *);
extern int machine_at_batman_init(const machine_t *);
extern int machine_at_ambradp60_init(const machine_t *);

View File

@@ -634,7 +634,6 @@ machine_at_itoxstar_init(const machine_t *model)
device_add(&w83977f_device);
device_add(&keyboard_ps2_ami_pci_device);
device_add(&stpc_client_device);
device_add(&ide_vlb_device);
device_add(&sst_flash_29ee020_device);
hwm_values_t machine_hwm = {
@@ -683,7 +682,6 @@ machine_at_arb1479_init(const machine_t *model)
device_add(&w83977f_device);
device_add(&keyboard_ps2_ami_pci_device);
device_add(&stpc_consumer2_device);
device_add(&ide_vlb_2ch_device);
device_add(&sst_flash_29ee020_device);
return ret;
@@ -709,10 +707,10 @@ machine_at_pcm9340_init(const machine_t *model)
pci_register_slot(0x1D, PCI_CARD_NORMAL, 4, 1, 2, 3);
pci_register_slot(0x1E, PCI_CARD_NORMAL, 3, 4, 1, 2);
pci_register_slot(0x1F, PCI_CARD_NORMAL, 2, 3, 4, 1);
device_add(&w83977f_device);
device_add_inst(&w83977f_device, 1);
device_add_inst(&w83977f_device, 2);
device_add(&keyboard_ps2_ami_pci_device);
device_add(&stpc_elite_device);
device_add(&ide_vlb_device);
device_add(&sst_flash_29ee020_device);
return ret;
@@ -738,10 +736,10 @@ machine_at_pcm5330_init(const machine_t *model)
pci_register_slot(0x0D, PCI_CARD_SPECIAL, 0, 0, 0, 0);
pci_register_slot(0x0E, PCI_CARD_SPECIAL, 1, 2, 3, 4);
pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4);
device_add(&stpc_serial_device);
device_add(&w83977f_370_device);
device_add(&keyboard_ps2_ami_pci_device);
device_add(&stpc_atlas_device);
device_add(&ide_vlb_device);
device_add(&sst_flash_29ee020_device);
return ret;