diff --git a/src/chipset/stpc.c b/src/chipset/stpc.c index c3b7d7cc2..bf14981fc 100644 --- a/src/chipset/stpc.c +++ b/src/chipset/stpc.c @@ -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 +}; diff --git a/src/device/postcard.c b/src/device/postcard.c index 91eb29fcd..df2c1f96d 100644 --- a/src/device/postcard.c +++ b/src/device/postcard.c @@ -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); } } diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index a7f313627..e63cf99d1 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -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 */ diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 9183fe2ba..c7affdfe4 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -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 *); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index e19bd448f..1cd7b60fa 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -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;