From c5be6e3e0a1fe1bdea7f0526fb150037f04ad9a9 Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Wed, 21 Apr 2021 22:05:59 +0300 Subject: [PATCH] Added the missing IT8661F --- src/include/86box/sio.h | 2 +- src/sio/CMakeLists.txt | 1 + src/sio/sio_it8661f.c | 312 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 314 insertions(+), 1 deletion(-) create mode 100644 src/sio/sio_it8661f.c diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index 4de9653aa..cc8db7924 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -35,6 +35,7 @@ extern const device_t fdc37c932qf_device; extern const device_t fdc37c935_device; extern const device_t fdc37m60x_device; extern const device_t fdc37m60x_370_device; +extern const device_t it8661f_device; extern const device_t i82091aa_device; extern const device_t i82091aa_398_device; extern const device_t i82091aa_ide_device; @@ -62,7 +63,6 @@ extern const device_t um8669f_device; extern const device_t via_vt82c686_sio_device; extern const device_t w83787f_device; extern const device_t w83787f_ide_device; -extern const device_t w83787f_ide_sec_device; extern const device_t w83877f_device; extern const device_t w83877f_president_device; extern const device_t w83877tf_device; diff --git a/src/sio/CMakeLists.txt b/src/sio/CMakeLists.txt index 62debb1b5..d19a8e251 100644 --- a/src/sio/CMakeLists.txt +++ b/src/sio/CMakeLists.txt @@ -15,6 +15,7 @@ add_library(sio OBJECT sio_acc3221.c sio_f82c710.c sio_82091aa.c sio_fdc37c661.c sio_fdc37c66x.c sio_fdc37c669.c sio_fdc37c93x.c sio_fdc37m60x.c + sio_it8661f.c sio_pc87306.c sio_pc87307.c sio_pc87309.c sio_pc87310.c sio_pc87311.c sio_pc87332.c sio_prime3b.c sio_prime3c.c sio_w83787f.c sio_w83877f.c sio_w83977f.c sio_um8669f.c diff --git a/src/sio/sio_it8661f.c b/src/sio/sio_it8661f.c new file mode 100644 index 000000000..e6cd131a3 --- /dev/null +++ b/src/sio/sio_it8661f.c @@ -0,0 +1,312 @@ +/* + * 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. + * + * Implementation of the ITE IT8661F chipset. + * + * Note: This Super I/O is partially incomplete and intended only for having the intended machine to function + * + * Authors: Tiseno100 + * + * Copyright 2021 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/fdd.h> +#include <86box/fdc.h> +#include <86box/fdd_common.h> +#include <86box/sio.h> + +#define LDN dev->regs[7] + +typedef struct +{ + fdc_t *fdc_controller; + serial_t *uart[2]; + + uint8_t index, regs[256], device_regs[6][256]; + int unlocked, enumerator; +} it8661f_t; + +uint8_t mb_pnp_key[32] = {0x6a, 0xb5, 0xda, 0xed, 0xf6, 0xfb, 0x7d, 0xbe, 0xdf, 0x6f, 0x37, 0x1b, 0x0d, 0x86, 0xc3, 0x61, 0xb0, 0x58, 0x2c, 0x16, 0x8b, 0x45, 0xa2, 0xd1, 0xe8, 0x74, 0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39}; +static void it8661f_reset(void *priv); + +void it8661_fdc(uint16_t addr, uint8_t val, it8661f_t *dev) +{ + fdc_remove(dev->fdc_controller); + + if (((addr == 0x30) && (val & 1)) || (dev->device_regs[0][0x30] & 1)) + { + switch (addr) + { + case 0x30: + dev->device_regs[0][addr] = val & 1; + break; + + case 0x31: + dev->device_regs[0][addr] = val & 3; + if (val & 1) + dev->device_regs[0][addr] |= 0x55; + break; + + case 0x60: + case 0x61: + dev->device_regs[0][addr] = val & ((addr == 0x61) ? 0xff : 0xf8); + break; + + case 0x70: + dev->device_regs[0][addr] = val & 0x0f; + break; + + case 0x74: + dev->device_regs[0][addr] = val & 7; + break; + + case 0xf0: + dev->device_regs[0][addr] = val & 0x0f; + break; + } + fdc_set_base(dev->fdc_controller, (dev->device_regs[0][0x60] << 8) | (dev->device_regs[0][0x61])); + fdc_set_irq(dev->fdc_controller, dev->device_regs[0][0x70] & 0x0f); + fdc_set_dma_ch(dev->fdc_controller, dev->device_regs[0][0x74] & 7); + + if (dev->device_regs[0][0xf0] & 1) + fdc_writeprotect(dev->fdc_controller); + + // if (dev->device_regs[0][0xf0] & 4) + // fdc_swap(dev->fdc_controller); + pclog("ITE 8661-FDC: BASE %04x IRQ %02x\n", (dev->device_regs[0][0x60] << 8) | (dev->device_regs[0][0x61]), dev->device_regs[0][0x70] & 0x0f); + } +} + +void it8661_serial(int uart, uint16_t addr, uint8_t val, it8661f_t *dev) +{ + serial_remove(dev->uart[uart]); + if (((addr == 0x30) && (val & 1)) || (dev->device_regs[1 + uart][0x30] & 1)) + { + switch (addr) + { + case 0x30: + dev->device_regs[1 + uart][addr] = val & 1; + break; + + case 0x60: + case 0x61: + dev->device_regs[1 + uart][addr] = val & ((addr == 0x61) ? 0xff : 0xf8); + break; + + case 0x70: + dev->device_regs[1 + uart][addr] = val & 0x0f; + break; + + case 0x74: + dev->device_regs[1 + uart][addr] = val & 7; + break; + + case 0xf0: + dev->device_regs[1 + uart][addr] = val & 3; + break; + } + serial_setup(dev->uart[uart], (dev->device_regs[1 + uart][0x60] << 8) | (dev->device_regs[1 + uart][0x61]), dev->device_regs[1 + uart][0x70] & 0x0f); + pclog("ITE 8661-UART%01x: BASE %04x IRQ %02x\n", 1 + (LDN % 1), (dev->device_regs[1 + uart][0x60] << 8) | (dev->device_regs[1 + uart][0x61]), dev->device_regs[1 + uart][0x70] & 0x0f); + } +} + +void it8661_lpt(uint16_t addr, uint8_t val, it8661f_t *dev) +{ + lpt1_remove(); + if (((addr == 0x30) && (val & 1)) || (dev->device_regs[3][0x30] & 1)) + { + switch (addr) + { + case 0x30: + dev->device_regs[3][addr] = val & 1; + break; + + case 0x60: + case 0x61: + dev->device_regs[3][addr] = val & ((addr == 0x61) ? 0xff : 0xf8); + break; + + case 0x70: + dev->device_regs[3][addr] = val & 0x0f; + break; + + case 0x74: + dev->device_regs[3][addr] = val & 7; + break; + + case 0xf0: + dev->device_regs[3][addr] = val & 3; + break; + } + lpt1_init((dev->device_regs[3][0x60] << 8) | (dev->device_regs[3][0x61])); + lpt1_irq(dev->device_regs[3][0x70] & 0x0f); + pclog("ITE 8661-LPT: BASE %04x IRQ %02x\n", (dev->device_regs[3][0x60] << 8) | (dev->device_regs[3][0x61]), dev->device_regs[3][0x70] & 0x0f); + } +} + +void it8661_ldn(uint16_t addr, uint8_t val, it8661f_t *dev) +{ + switch (LDN) + { + case 0: + it8661_fdc(addr, val, dev); + break; + case 1: + case 2: + it8661_serial(LDN & 2, addr, val, dev); + break; + case 3: + it8661_lpt(addr, val, dev); + break; + } +} + +static void +it8661f_write(uint16_t addr, uint8_t val, void *priv) +{ + it8661f_t *dev = (it8661f_t *)priv; + + switch (addr) + { + case 0x370: + if (!dev->unlocked) + { + (val == mb_pnp_key[dev->enumerator]) ? dev->enumerator++ : (dev->enumerator = 0); + if (dev->enumerator == 31) + { + dev->unlocked = 1; + pclog("ITE8661F: Unlocked!\n"); + } + } + else + dev->index = val; + break; + + case 0x371: + if (dev->unlocked) + { + switch (dev->index) + { + case 0x02: + dev->regs[dev->index] = val; + if (val & 1) + it8661f_reset(dev); + if (val & 2) + dev->unlocked = 0; + break; + case 0x07: + dev->regs[dev->index] = val; + break; + case 0x22: + dev->regs[dev->index] = val & 0x30; + break; + case 0x23: + dev->regs[dev->index] = val & 0x1f; + break; + default: + it8661_ldn(dev->index, val, dev); + break; + } + } + break; + } + + return; +} + +static uint8_t +it8661f_read(uint16_t addr, void *priv) +{ + it8661f_t *dev = (it8661f_t *)priv; + + pclog("IT8661F:\n", addr, dev->regs[dev->index]); + return (addr == 0xa79) ? dev->regs[dev->index] : 0xff; +} + +static void +it8661f_reset(void *priv) +{ + it8661f_t *dev = (it8661f_t *)priv; + dev->regs[0x20] = 0x86; + dev->regs[0x21] = 0x61; + + dev->device_regs[0][0x60] = 3; + dev->device_regs[0][0x61] = 0xf0; + dev->device_regs[0][0x70] = 6; + dev->device_regs[0][0x71] = 2; + dev->device_regs[0][0x74] = 2; + + dev->device_regs[1][0x60] = 3; + dev->device_regs[1][0x61] = 0xf8; + dev->device_regs[1][0x70] = 4; + dev->device_regs[1][0x71] = 2; + + dev->device_regs[2][0x60] = 2; + dev->device_regs[2][0x61] = 0xf8; + dev->device_regs[2][0x70] = 3; + dev->device_regs[2][0x71] = 2; + + dev->device_regs[3][0x60] = 3; + dev->device_regs[3][0x61] = 0x78; + dev->device_regs[3][0x70] = 7; + dev->device_regs[3][0x71] = 2; + dev->device_regs[3][0x74] = 3; + dev->device_regs[3][0xf0] = 3; +} + +static void +it8661f_close(void *priv) +{ + it8661f_t *dev = (it8661f_t *)priv; + + free(dev); +} + +static void * +it8661f_init(const device_t *info) +{ + it8661f_t *dev = (it8661f_t *)malloc(sizeof(it8661f_t)); + memset(dev, 0, sizeof(it8661f_t)); + + dev->fdc_controller = device_add(&fdc_at_smc_device); + fdc_reset(dev->fdc_controller); + + dev->uart[0] = device_add_inst(&ns16550_device, 1); + dev->uart[1] = device_add_inst(&ns16550_device, 2); + + io_sethandler(0x0370, 0x0002, it8661f_read, NULL, NULL, it8661f_write, NULL, NULL, dev); + + dev->enumerator = 0; + dev->unlocked = 0; + + it8661f_reset(dev); + return dev; +} + +const device_t it8661f_device = { + "ITE IT8661F", + 0, + 0, + it8661f_init, + it8661f_close, + NULL, + {NULL}, + NULL, + NULL, + NULL};