Added the missing IT8661F
This commit is contained in:
@@ -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;
|
||||
|
@@ -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
|
||||
|
312
src/sio/sio_it8661f.c
Normal file
312
src/sio/sio_it8661f.c
Normal file
@@ -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 <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#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};
|
Reference in New Issue
Block a user