diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 56ee11e66..b64e246d2 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -419,6 +419,7 @@ extern int machine_at_p65up5_cp55t2d_init(const machine_t *); extern int machine_at_p55tvp4_init(const machine_t *); extern int machine_at_p55va_init(const machine_t *); extern int machine_at_i430vx_init(const machine_t *); +extern int machine_at_5ivg_init(const machine_t *); extern int machine_at_brio80xx_init(const machine_t *); extern int machine_at_8500tvxa_init(const machine_t *); extern int machine_at_presario4500_init(const machine_t *); diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index 3c4702ffa..afac7606e 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -44,6 +44,8 @@ extern const device_t pc87309_15c_device; extern const device_t pc87332_device; extern const device_t pc87332_ps1_device; extern const device_t pc97307_device; +extern const device_t prime3c_device; +extern const device_t prime3c_ide_device; extern const device_t ps1_m2133_sio; extern const device_t sio_detect_device; extern const device_t um8669f_device; diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index 9e750c3c3..acdb2278e 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -580,6 +580,34 @@ machine_at_p55tvp4_init(const machine_t *model) return ret; } +int +machine_at_5ivg_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/5ivg/5IVG.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&i430vx_device); + device_add(&piix3_device); + device_add(&keyboard_ps2_pci_device); + device_add(&prime3c_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + int machine_at_i430vx_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index b1483da17..05536c7e1 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -309,6 +309,7 @@ const machine_t machines[] = { /* 430VX */ { "[i430VX] ASUS P/I-P55TVP4", "p55tvp4", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p55tvp4_init, NULL }, + { "[i430VX] Azza 5IVG", "5ivg", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_5ivg_init, NULL }, { "[i430VX] Biostar MB-8500TVX-A", "8500tvxa", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2600, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_8500tvxa_init, NULL }, { "[i430VX] Compaq Presario 4500", "presario4500", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_presario4500_init, NULL }, { "[i430VX] Epox P55-VA", "p55va", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p55va_init, NULL }, diff --git a/src/sio/sio_prime3c.c b/src/sio/sio_prime3c.c new file mode 100644 index 000000000..5daa51e2b --- /dev/null +++ b/src/sio/sio_prime3c.c @@ -0,0 +1,339 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the LG Prime3C Super I/O + * + * Authors: Tiseno100 + * Copyright 2020 Tiseno100 + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/timer.h> +#include <86box/device.h> +#include <86box/lpt.h> +#include <86box/serial.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/sio.h> + +#ifdef ENABLE_PRIME3C_LOG +int prime3c_do_log = ENABLE_PRIME3C_LOG; +static void +prime3c_log(const char *fmt, ...) +{ + va_list ap; + + if (prime3c_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define prime3c_log(fmt, ...) +#endif + +/* Function Select(Note on prime3c_enable) */ +#define FUNCTION_SELECT dev->regs[0xc2] + +/* Base Address Registers */ +#define FDC_BASE_ADDRESS dev->regs[0xc3] +#define IDE_BASE_ADDRESS dev->regs[0xc4] +#define IDE_SIDE_ADDRESS dev->regs[0xc5] +#define LPT_BASE_ADDRESS dev->regs[0xc6] +#define UART1_BASE_ADDRESS dev->regs[0xc7] +#define UART2_BASE_ADDRESS dev->regs[0xc8] + +/* FDC/LPT Configuration */ +#define FDC_LPT_DMA dev->regs[0xc9] +#define FDC_LPT_IRQ dev->regs[0xca] + +/* UART 1/2 Configuration */ +#define UART_IRQ dev->regs[0xcb] + +/* Miscellaneous Configuration*/ +#define FDC_SWAP (dev->regs[0xd6] & 0x01) + +/* IDE functionality(Note on Init) */ +#define HAS_IDE_FUNCTIONALITY dev->ide_function + +typedef struct +{ + uint8_t index, regs[256], cfg_lock, ide_function; + + fdc_t *fdc_controller; + serial_t *uart[2]; + +} prime3c_t; + +void prime3c_fdc_handler(prime3c_t *dev); +void prime3c_uart_handler(uint8_t num, prime3c_t *dev); +void prime3c_lpt_handler(prime3c_t *dev); +void prime3c_ide_handler(prime3c_t *dev); +void prime3c_enable(prime3c_t *dev); + +static void +prime3c_write(uint16_t addr, uint8_t val, void *priv) +{ + prime3c_t *dev = (prime3c_t *)priv; + + switch (addr) + { + case 0x398: + dev->index = val; + + /* Enter/Escape Configuration Mode */ + if (val == 0x33) + dev->cfg_lock = 0; + else if (val == 0x55) + dev->cfg_lock = 1; + break; + + case 0x399: + if (!dev->cfg_lock) + { + switch (dev->index) + { + case 0xc2: + FUNCTION_SELECT = val & 0xbf; + prime3c_enable(dev); + break; + + case 0xc3: + FDC_BASE_ADDRESS = val & 0xfc; + prime3c_fdc_handler(dev); + break; + + case 0xc4: + IDE_BASE_ADDRESS = val & 0xfc; + if (HAS_IDE_FUNCTIONALITY) + prime3c_ide_handler(dev); + break; + + case 0xc5: + IDE_SIDE_ADDRESS = (val & 0xfc) | 0x02; + prime3c_ide_handler(dev); + break; + + case 0xc6: + LPT_BASE_ADDRESS = val; + break; + + case 0xc7: + UART1_BASE_ADDRESS = val & 0xfe; + prime3c_uart_handler(0, dev); + break; + + case 0xc8: + UART2_BASE_ADDRESS = val & 0xfe; + prime3c_uart_handler(1, dev); + break; + + case 0xc9: + FDC_LPT_DMA = val; + prime3c_fdc_handler(dev); + break; + + case 0xca: + FDC_LPT_IRQ = val; + prime3c_fdc_handler(dev); + prime3c_lpt_handler(dev); + break; + + case 0xcb: + UART_IRQ = val; + prime3c_uart_handler(0, dev); + prime3c_uart_handler(1, dev); + break; + + case 0xcd: + case 0xce: + dev->regs[dev->index] = val; + break; + + case 0xcf: + dev->regs[dev->index] = val & 0x3f; + break; + + case 0xd0: + dev->regs[dev->index] = val & 0xfc; + break; + + case 0xd1: + dev->regs[dev->index] = val & 0x3f; + break; + + case 0xd3: + dev->regs[dev->index] = val & 0x7c; + break; + + case 0xd5: + case 0xd6: + case 0xd7: + case 0xd8: + dev->regs[dev->index] = val; + break; + } + } + break; + } +} + +static uint8_t +prime3c_read(uint16_t addr, void *priv) +{ + prime3c_t *dev = (prime3c_t *)priv; + + return dev->regs[addr]; +} + +void prime3c_fdc_handler(prime3c_t *dev) +{ + fdc_remove(dev->fdc_controller); + if (FUNCTION_SELECT & 0x10) + { + fdc_set_base(dev->fdc_controller, FDC_BASE_ADDRESS << 2); + fdc_set_irq(dev->fdc_controller, (FDC_LPT_IRQ >> 4) & 0xf); + fdc_set_dma_ch(dev->fdc_controller, (FDC_LPT_DMA >> 4) & 0xf); + fdc_set_swap(dev->fdc_controller, FDC_SWAP); + prime3c_log("Prime3C-FDC: BASE %04x IRQ %01x DMA %01x\n", FDC_BASE_ADDRESS << 2, (FDC_LPT_IRQ >> 4) & 0xf, (FDC_LPT_DMA >> 4) & 0xf); + } +} + +void prime3c_uart_handler(uint8_t num, prime3c_t *dev) +{ + serial_remove(dev->uart[num & 1]); + if (FUNCTION_SELECT & (!(num & 1) ? 0x04 : 0x08)) + { + serial_setup(dev->uart[num & 1], (!(num & 1) ? UART1_BASE_ADDRESS : UART2_BASE_ADDRESS) << 2, (UART_IRQ >> (!(num & 1) ? 4 : 0)) & 0xf); + prime3c_log("Prime3C-UART%01x: BASE %04x IRQ %01x\n", num & 1, (!(num & 1) ? UART1_BASE_ADDRESS : UART2_BASE_ADDRESS) << 2, (UART_IRQ >> (!(num & 1) ? 4 : 0)) & 0xf); + } +} + +void prime3c_lpt_handler(prime3c_t *dev) +{ + lpt1_remove(); + if (!(FUNCTION_SELECT & 0x03)) + { + + lpt1_init(LPT_BASE_ADDRESS << 2); + lpt1_irq(FDC_LPT_IRQ & 0xf); + prime3c_log("Prime3C-LPT: BASE %04x IRQ %02x\n", LPT_BASE_ADDRESS << 2, FDC_LPT_IRQ & 0xf); + } +} + +void prime3c_ide_handler(prime3c_t *dev) +{ + ide_pri_disable(); + if (FUNCTION_SELECT & 0x20) + { + ide_set_base(0, IDE_BASE_ADDRESS << 2); + ide_set_side(0, IDE_SIDE_ADDRESS << 2); + ide_pri_enable(); + prime3c_log("Prime3C-IDE: BASE %04x SIDE %04x\n", IDE_BASE_ADDRESS << 2, IDE_SIDE_ADDRESS << 2); + } +} + +void prime3c_enable(prime3c_t *dev) +{ +/* +Simulate a device enable/disable scenario + +Register C2: Function Select +Bit 7: Gameport +Bit 6: Reserved +Bit 5: IDE +Bit 4: FDC +Bit 3: UART 2 +Bit 2: UART 1 +Bit 1/0: PIO (0/0 Unidirectional , 0/1 ECP, 1/0 EPP, 1/1 Disabled) + +Note: 86Box LPT is simplistic and can't do ECP or EPP. +*/ + +!(FUNCTION_SELECT & 0x03) ? prime3c_lpt_handler(dev) : lpt1_remove(); +(FUNCTION_SELECT & 0x04) ? prime3c_uart_handler(0, dev) : serial_remove(dev->uart[0]); +(FUNCTION_SELECT & 0x08) ? prime3c_uart_handler(1, dev) : serial_remove(dev->uart[1]); +(FUNCTION_SELECT & 0x10) ? prime3c_fdc_handler(dev) : fdc_remove(dev->fdc_controller); +if (HAS_IDE_FUNCTIONALITY) + (FUNCTION_SELECT & 0x20) ? prime3c_ide_handler(dev) : ide_pri_disable(); +} + +static void +prime3c_close(void *priv) +{ + prime3c_t *dev = (prime3c_t *)priv; + + free(dev); +} + +static void * +prime3c_init(const device_t *info) +{ + prime3c_t *dev = (prime3c_t *)malloc(sizeof(prime3c_t)); + memset(dev, 0, sizeof(prime3c_t)); + + /* Avoid conflicting with machines that make no use of the Prime3C Internal IDE */ + HAS_IDE_FUNCTIONALITY = info->local; + + dev->regs[0xc0] = 0x3c; + dev->regs[0xc2] = 0x03; + dev->regs[0xc3] = 0x3c; + dev->regs[0xc4] = 0x3c; + dev->regs[0xc5] = 0x3d; + dev->regs[0xd5] = 0x3c; + + dev->fdc_controller = device_add(&fdc_at_device); + dev->uart[0] = device_add_inst(&ns16550_device, 1); + dev->uart[1] = device_add_inst(&ns16550_device, 2); + if (HAS_IDE_FUNCTIONALITY) + device_add(&ide_isa_device); + + prime3c_fdc_handler(dev); + prime3c_uart_handler(0, dev); + prime3c_uart_handler(1, dev); + prime3c_lpt_handler(dev); + if (HAS_IDE_FUNCTIONALITY) + prime3c_ide_handler(dev); + + io_sethandler(0x0398, 0x0002, prime3c_read, NULL, NULL, prime3c_write, NULL, NULL, dev); + + return dev; +} + +const device_t prime3c_device = { + "Goldstar Prime3C", + 0, + 0, + prime3c_init, + prime3c_close, + NULL, + {NULL}, + NULL, + NULL, + NULL}; + +const device_t prime3c_ide_device = { + "Goldstar Prime3C with IDE functionality", + 0, + 1, + prime3c_init, + prime3c_close, + NULL, + {NULL}, + NULL, + NULL, + NULL}; diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 78977a784..d0d24f36e 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -641,6 +641,7 @@ SIOOBJ := sio_acc3221.o \ sio_f82c710.o sio_82091aa.o \ sio_fdc37c661.o sio_fdc37c66x.o sio_fdc37c669.o sio_fdc37c93x.o \ sio_pc87306.o sio_pc87307.o sio_pc87309.o sio_pc87332.o \ + sio_prime3c.o \ sio_w83787f.o \ sio_w83877f.o sio_w83977f.o \ sio_um8669f.o \