Rewrite IT8661F and add IT8671F
This commit is contained in:
@@ -42,6 +42,7 @@ 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 it8671f_device;
|
||||
extern const device_t i82091aa_device;
|
||||
extern const device_t i82091aa_398_device;
|
||||
extern const device_t i82091aa_ide_pri_device;
|
||||
|
@@ -15,7 +15,7 @@
|
||||
|
||||
add_library(sio OBJECT sio_acc3221.c sio_ali5123.c sio_f82c710.c sio_82091aa.c
|
||||
sio_fdc37c6xx.c sio_fdc37c67x.c sio_fdc37c669.c sio_fdc37c93x.c sio_fdc37m60x.c
|
||||
sio_it8661f.c
|
||||
sio_it86x1f.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
|
||||
|
@@ -1,353 +0,0 @@
|
||||
/*
|
||||
* 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 <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_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>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
#define LDN dev->regs[7]
|
||||
|
||||
typedef struct it8661f_t {
|
||||
fdc_t *fdc_controller;
|
||||
serial_t *uart[2];
|
||||
|
||||
uint8_t index;
|
||||
uint8_t regs[256];
|
||||
uint8_t device_regs[6][256];
|
||||
int unlocked;
|
||||
int enumerator;
|
||||
} it8661f_t;
|
||||
|
||||
static 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);
|
||||
|
||||
#ifdef ENABLE_IT8661_LOG
|
||||
int it8661_do_log = ENABLE_IT8661_LOG;
|
||||
|
||||
void
|
||||
it8661_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (it8661_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define it8661_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
static 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;
|
||||
|
||||
default:
|
||||
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);
|
||||
|
||||
it8661_log("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);
|
||||
}
|
||||
}
|
||||
|
||||
static 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;
|
||||
|
||||
default:
|
||||
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);
|
||||
|
||||
it8661_log("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;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
lpt1_init((dev->device_regs[3][0x60] << 8) | (dev->device_regs[3][0x61]));
|
||||
lpt1_irq(dev->device_regs[3][0x70] & 0x0f);
|
||||
|
||||
it8661_log("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) - 1, addr, val, dev);
|
||||
break;
|
||||
case 3:
|
||||
it8661_lpt(addr, val, dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
it8661f_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
it8661f_t *dev = (it8661f_t *) priv;
|
||||
|
||||
switch (addr) {
|
||||
case FDC_SECONDARY_ADDR:
|
||||
if (!dev->unlocked) {
|
||||
(val == mb_pnp_key[dev->enumerator]) ? dev->enumerator++ : (dev->enumerator = 0);
|
||||
if (dev->enumerator == 31) {
|
||||
dev->unlocked = 1;
|
||||
it8661_log("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;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
it8661f_read(uint16_t addr, void *priv)
|
||||
{
|
||||
const it8661f_t *dev = (it8661f_t *) priv;
|
||||
|
||||
it8661_log("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(UNUSED(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(FDC_SECONDARY_ADDR, 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 = {
|
||||
.name = "ITE IT8661F",
|
||||
.internal_name = "it8661f",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = it8661f_init,
|
||||
.close = it8661f_close,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
862
src/sio/sio_it86x1f.c
Normal file
862
src/sio/sio_it86x1f.c
Normal file
@@ -0,0 +1,862 @@
|
||||
/*
|
||||
* 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 ITE IT86x1F Super I/O chips.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: RichardG, <richardg867@gmail.com>
|
||||
*
|
||||
* Copyright 2023 RichardG.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/pci.h>
|
||||
#include <86box/lpt.h>
|
||||
#include <86box/serial.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/gameport.h>
|
||||
#include <86box/sio.h>
|
||||
#include <86box/isapnp.h>
|
||||
#include <86box/plat_fallthrough.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
enum {
|
||||
ITE_IT8661F = 0x8661,
|
||||
ITE_IT8671F = 0x8681
|
||||
};
|
||||
|
||||
#define CHIP_ID *((uint16_t *) &dev->global_regs[0])
|
||||
|
||||
static void it8671f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv);
|
||||
static void it8661f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv);
|
||||
|
||||
static const struct {
|
||||
uint16_t chip_id;
|
||||
uint16_t unlock_id;
|
||||
uint8_t gpio_ldn;
|
||||
/* Fake ROMs to delegate all the logical device register handling over to the ISAPnP subsystem.
|
||||
The actual ROMs/IDs used by real chips when those are set to ISAPnP mode remain to be seen. */
|
||||
uint8_t *pnp_rom;
|
||||
|
||||
const isapnp_device_config_t *pnp_defaults;
|
||||
|
||||
void (*pnp_config_changed)(uint8_t ld, isapnp_device_config_t *config, void *priv);
|
||||
} it86x1f_models[] = {
|
||||
{
|
||||
.chip_id = ITE_IT8661F,
|
||||
.unlock_id = 0x8661,
|
||||
.gpio_ldn = 0x05,
|
||||
.pnp_rom = (uint8_t[]) {
|
||||
0x26, 0x85, 0x86, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, /* ITE8661, dummy checksum (filled in by isapnp_add_card) */
|
||||
0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */
|
||||
|
||||
0x15, 0x41, 0xd0, 0x07, 0x00, 0x01, /* logical device PNP0700, can participate in boot */
|
||||
0x23, 0xf8, 0x0f, 0x02, /* IRQ 3/4/5/6/7/8/9/10/11, low true edge sensitive */
|
||||
0x2a, 0x0f, 0x0c, /* DMA 0/1/2/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */
|
||||
0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */
|
||||
|
||||
0x15, 0x41, 0xd0, 0x05, 0x01, 0x01, /* logical device PNP0501, can participate in boot */
|
||||
0x23, 0xf8, 0x0f, 0x02, /* IRQ 3/4/5/6/7/8/9/10/11, low true edge sensitive */
|
||||
0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */
|
||||
|
||||
0x15, 0x41, 0xd0, 0x05, 0x01, 0x01, /* logical device PNP0501, can participate in boot */
|
||||
0x23, 0xf8, 0x0f, 0x02, /* IRQ 3/4/5/6/7/8/9/10/11, low true edge sensitive */
|
||||
0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */
|
||||
|
||||
0x15, 0x41, 0xd0, 0x04, 0x00, 0x01, /* logical device PNP0400, can participate in boot */
|
||||
0x23, 0xf8, 0x0f, 0x02, /* IRQ 3/4/5/6/7/8/9/10/11, low true edge sensitive */
|
||||
0x2a, 0x0f, 0x0c, /* DMA 0/1/2/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */
|
||||
0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */
|
||||
0x47, 0x01, 0x00, 0x01, 0xfc, 0x0f, 0x04, 0x04, /* I/O 0x100-0xFFC, decodes 16-bit, 4-byte alignment, 4 addresses */
|
||||
|
||||
0x15, 0x41, 0xd0, 0x05, 0x10, 0x01, /* logical device PNP0510, can participate in boot */
|
||||
0x23, 0xf8, 0x0f, 0x02, /* IRQ 3/4/5/6/7/8/9/10/11, low true edge sensitive */
|
||||
0x23, 0xf8, 0x0f, 0x02, /* IRQ 3/4/5/6/7/8/9/10/11, low true edge sensitive */
|
||||
0x2a, 0x0f, 0x0c, /* DMA 0/1/2/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */
|
||||
0x2a, 0x0f, 0x0c, /* DMA 0/1/2/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */
|
||||
0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */
|
||||
0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */
|
||||
|
||||
0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */
|
||||
},
|
||||
.pnp_defaults = (const isapnp_device_config_t[]) {
|
||||
{
|
||||
.activate = 0,
|
||||
.io = { { .base = FDC_PRIMARY_ADDR }, },
|
||||
.irq = { { .irq = FDC_PRIMARY_IRQ }, },
|
||||
.dma = { { .dma = FDC_PRIMARY_DMA }, }
|
||||
}, {
|
||||
.activate = 0,
|
||||
.io = { { .base = COM1_ADDR }, },
|
||||
.irq = { { .irq = COM1_IRQ }, }
|
||||
}, {
|
||||
.activate = 0,
|
||||
.io = { { .base = COM2_ADDR }, },
|
||||
.irq = { { .irq = COM2_IRQ }, }
|
||||
}, {
|
||||
.activate = 0,
|
||||
.io = { { .base = LPT1_ADDR }, { .base = 0x778 }, },
|
||||
.irq = { { .irq = LPT1_IRQ }, },
|
||||
.dma = { { .dma = 3 }, }
|
||||
}, {
|
||||
.activate = 0,
|
||||
.io = { { .base = COM4_ADDR }, { .base = 0x300 }, },
|
||||
.irq = { { .irq = 10 }, { .irq = 11 }, },
|
||||
.dma = { { .dma = 1 }, { .dma = 0 }, }
|
||||
}, {
|
||||
.activate = -1
|
||||
}
|
||||
},
|
||||
.pnp_config_changed = it8661f_pnp_config_changed
|
||||
}, {
|
||||
.chip_id = ITE_IT8671F,
|
||||
.unlock_id = 0x8680,
|
||||
.gpio_ldn = 0x07,
|
||||
.pnp_rom = (uint8_t[]) {
|
||||
0x26, 0x85, 0x86, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, /* ITE8671, dummy checksum (filled in by isapnp_add_card) */
|
||||
0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */
|
||||
|
||||
0x15, 0x41, 0xd0, 0x07, 0x00, 0x01, /* logical device PNP0700, can participate in boot */
|
||||
0x23, 0xfa, 0x1f, 0x02, /* IRQ 1/3/4/5/6/7/8/9/10/11/12, low true edge sensitive */
|
||||
0x2a, 0x0f, 0x0c, /* DMA 0/1/2/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */
|
||||
0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */
|
||||
|
||||
0x15, 0x41, 0xd0, 0x05, 0x01, 0x01, /* logical device PNP0501, can participate in boot */
|
||||
0x23, 0xfa, 0x1f, 0x02, /* IRQ 1/3/4/5/6/7/8/9/10/11/12, low true edge sensitive */
|
||||
0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */
|
||||
|
||||
0x15, 0x41, 0xd0, 0x05, 0x10, 0x01, /* logical device PNP0510, can participate in boot */
|
||||
0x23, 0xfa, 0x1f, 0x02, /* IRQ 1/3/4/5/6/7/8/9/10/11/12, low true edge sensitive */
|
||||
0x23, 0xfa, 0x1f, 0x02, /* IRQ 1/3/4/5/6/7/8/9/10/11/12, low true edge sensitive */
|
||||
0x2a, 0x0f, 0x0c, /* DMA 0/1/2/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */
|
||||
0x2a, 0x0f, 0x0c, /* DMA 0/1/2/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */
|
||||
0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */
|
||||
0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */
|
||||
|
||||
0x15, 0x41, 0xd0, 0x04, 0x00, 0x01, /* logical device PNP0400, can participate in boot */
|
||||
0x23, 0xfa, 0x1f, 0x02, /* IRQ 1/3/4/5/6/7/8/9/10/11/12, low true edge sensitive */
|
||||
0x2a, 0x0f, 0x0c, /* DMA 0/1/2/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */
|
||||
0x47, 0x01, 0x00, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x100-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */
|
||||
0x47, 0x01, 0x00, 0x01, 0xfc, 0x0f, 0x04, 0x04, /* I/O 0x100-0xFFC, decodes 16-bit, 4-byte alignment, 4 addresses */
|
||||
|
||||
0x15, 0x41, 0xd0, 0xff, 0xff, 0x00, /* logical device PNPFFFF (dummy to create APC gap in LDNs) */
|
||||
|
||||
0x15, 0x41, 0xd0, 0x03, 0x03, 0x01, /* logical device PNP0303, can participate in boot */
|
||||
0x23, 0xfa, 0x1f, 0x02, /* IRQ 1/3/4/5/6/7/8/9/10/11/12, low true edge sensitive */
|
||||
0x47, 0x01, 0x00, 0x00, 0xff, 0x0f, 0x01, 0x01, /* I/O 0x0-0xFFF, decodes 16-bit, 1-byte alignment, 1 address */
|
||||
0x47, 0x01, 0x00, 0x00, 0xff, 0x0f, 0x01, 0x01, /* I/O 0x0-0xFFF, decodes 16-bit, 1-byte alignment, 1 address */
|
||||
|
||||
0x15, 0x41, 0xd0, 0x0f, 0x13, 0x01, /* logical device PNP0F13, can participate in boot */
|
||||
0x23, 0xfa, 0x1f, 0x02, /* IRQ 1/3/4/5/6/7/8/9/10/11/12, low true edge sensitive */
|
||||
|
||||
0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */
|
||||
},
|
||||
.pnp_defaults = (const isapnp_device_config_t[]) {
|
||||
{
|
||||
.activate = 0,
|
||||
.io = { { .base = FDC_PRIMARY_ADDR }, },
|
||||
.irq = { { .irq = FDC_PRIMARY_IRQ }, },
|
||||
.dma = { { .dma = FDC_PRIMARY_DMA }, }
|
||||
}, {
|
||||
.activate = 0,
|
||||
.io = { { .base = COM1_ADDR }, },
|
||||
.irq = { { .irq = COM1_IRQ }, }
|
||||
}, {
|
||||
.activate = 0,
|
||||
.io = { { .base = COM2_ADDR }, { .base = 0x300 }, },
|
||||
.irq = { { .irq = COM2_IRQ }, { .irq = 10 }, },
|
||||
.dma = { { .dma = 0 }, { .dma = 1 }, }
|
||||
}, {
|
||||
.activate = 0,
|
||||
.io = { { .base = LPT1_ADDR }, { .base = 0x778 }, },
|
||||
.irq = { { .irq = LPT1_IRQ }, },
|
||||
.dma = { { .dma = 3 }, }
|
||||
}, {
|
||||
.activate = 0
|
||||
}, {
|
||||
.activate = 1,
|
||||
.io = { { .base = 0x60 }, { .base = 0x64 }, },
|
||||
.irq = { { .irq = 1 }, }
|
||||
}, {
|
||||
.activate = 0,
|
||||
.irq = { { .irq = 12 }, }
|
||||
}, {
|
||||
.activate = -1
|
||||
}
|
||||
},
|
||||
.pnp_config_changed = it8671f_pnp_config_changed
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef ENABLE_IT86X1F_LOG
|
||||
int it86x1f_do_log = ENABLE_IT86X1F_LOG;
|
||||
|
||||
static void
|
||||
it86x1f_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (it86x1f_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define it86x1f_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
typedef struct it86x1f_t {
|
||||
uint8_t instance;
|
||||
uint8_t locked;
|
||||
uint8_t cur_ldn;
|
||||
uint8_t cur_reg;
|
||||
void *pnp_card;
|
||||
uint8_t global_regs[16]; /* [0x20:0x2f] */
|
||||
uint8_t ldn_regs[8][16]; /* [0xf0:0xff] */
|
||||
uint8_t gpio_regs[36]; /* [0x60:0x7f] then [0xe0:0xe3] */
|
||||
uint8_t gpio_ldn;
|
||||
|
||||
uint16_t unlock_id;
|
||||
uint16_t addr_port;
|
||||
uint16_t data_port;
|
||||
uint8_t unlock_val;
|
||||
uint8_t unlock_pos : 2;
|
||||
uint8_t key_pos : 5;
|
||||
|
||||
fdc_t *fdc;
|
||||
serial_t *uart[2];
|
||||
void *gameport;
|
||||
} it86x1f_t;
|
||||
|
||||
static void it86x1f_remap(it86x1f_t *dev, uint16_t addr_port, uint16_t data_port);
|
||||
|
||||
static void
|
||||
it8661f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv)
|
||||
{
|
||||
if (ld > 5) {
|
||||
it86x1f_log("IT86x1F: Unknown logical device %d\n", ld);
|
||||
return;
|
||||
}
|
||||
|
||||
it86x1f_t *dev = (it86x1f_t *) priv;
|
||||
|
||||
switch (ld) {
|
||||
case 0:
|
||||
fdc_remove(dev->fdc);
|
||||
|
||||
if (config->activate) {
|
||||
it86x1f_log("IT86x1F: FDC enabled at port %04X IRQ %d DMA %d\n", config->io[0].base, config->irq[0].irq, (config->dma[0].dma == ISAPNP_DMA_DISABLED) ? -1 : config->dma[0].dma);
|
||||
|
||||
if (config->io[0].base != ISAPNP_IO_DISABLED)
|
||||
fdc_set_base(dev->fdc, config->io[0].base);
|
||||
|
||||
fdc_set_irq(dev->fdc, config->irq[0].irq);
|
||||
fdc_set_dma_ch(dev->fdc, (config->dma[0].dma == ISAPNP_DMA_DISABLED) ? -1 : config->dma[0].dma);
|
||||
} else {
|
||||
it86x1f_log("IT86x1F: FDC disabled\n");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
serial_remove(dev->uart[ld - 1]);
|
||||
|
||||
if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) {
|
||||
it86x1f_log("IT86x1F: UART %d enabled at port %04X IRQ %d\n", ld - 1, config->io[0].base, config->irq[0].irq);
|
||||
serial_setup(dev->uart[ld - 1], config->io[0].base, config->irq[0].irq);
|
||||
} else {
|
||||
it86x1f_log("IT86x1F: UART %d disabled\n", ld - 1);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 3:
|
||||
lpt1_remove();
|
||||
|
||||
if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) {
|
||||
it86x1f_log("IT86x1F: LPT enabled at port %04X IRQ %d\n", config->io[0].base, config->irq[0].irq);
|
||||
lpt1_init(config->io[0].base);
|
||||
} else {
|
||||
it86x1f_log("IT86x1F: LPT disabled\n");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) {
|
||||
it86x1f_log("IT86x1F: IR enabled at ports %04X %04X IRQs %d %d DMAs %d %d\n", config->io[0].base, config->io[1].base, config->irq[0].irq, config->irq[1].irq, (config->dma[0].dma == ISAPNP_DMA_DISABLED) ? -1 : config->dma[0].dma, (config->dma[1].dma == ISAPNP_DMA_DISABLED) ? -1 : config->dma[1].dma);
|
||||
} else {
|
||||
it86x1f_log("IT86x1F: IR disabled\n");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
it8671f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv)
|
||||
{
|
||||
it86x1f_t *dev = (it86x1f_t *) priv;
|
||||
|
||||
switch (ld) {
|
||||
case 2:
|
||||
it8661f_pnp_config_changed(4, config, dev); /* just for logging, should change if IR UART is implemented */
|
||||
fallthrough;
|
||||
|
||||
case 0 ... 1:
|
||||
case 3:
|
||||
it8661f_pnp_config_changed(ld, config, dev);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED) && (config->io[1].base != ISAPNP_IO_DISABLED)) {
|
||||
it86x1f_log("IT86x1F: KBC enabled at ports %04X %04X IRQ %d\n", config->io[0].base, config->io[1].base, config->irq[0].irq);
|
||||
} else {
|
||||
it86x1f_log("IT86x1F: KBC disabled\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
if (config->activate) {
|
||||
it86x1f_log("IT86x1F: KBC mouse enabled at IRQ %d\n", config->irq[0].irq);
|
||||
} else {
|
||||
it86x1f_log("IT86x1F: KBC mouse disabled\n");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
it86x1f_pnp_read_vendor_reg(uint8_t ld, uint8_t reg, void *priv)
|
||||
{
|
||||
it86x1f_t *dev = (it86x1f_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
switch (reg) {
|
||||
case 0x20 ... 0x2f:
|
||||
ret = dev->global_regs[reg & 0x0f];
|
||||
break;
|
||||
|
||||
case 0x60 ... 0x7f:
|
||||
if (ld != dev->gpio_ldn)
|
||||
break;
|
||||
|
||||
ret = dev->gpio_regs[reg & 0x1f];
|
||||
break;
|
||||
|
||||
case 0xe0 ... 0xe3:
|
||||
if (ld != dev->gpio_ldn)
|
||||
break;
|
||||
|
||||
ret = dev->gpio_regs[0x20 | (reg & 0x03)];
|
||||
break;
|
||||
|
||||
case 0xf0 ... 0xff:
|
||||
if (ld > dev->gpio_ldn)
|
||||
break;
|
||||
|
||||
ret = dev->ldn_regs[ld][reg & 0x0f];
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
it86x1f_log("IT86x1F: read_vendor_reg(%X, %02X) = %02X\n", ld, reg, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
it86x1f_pnp_write_vendor_reg(uint8_t ld, uint8_t reg, uint8_t val, void *priv)
|
||||
{
|
||||
it86x1f_t *dev = (it86x1f_t *) priv;
|
||||
|
||||
it86x1f_log("IT86x1F: write_vendor_reg(%X, %02X, %02X)\n", ld, reg, val);
|
||||
|
||||
switch (reg) {
|
||||
case 0x22:
|
||||
if (CHIP_ID == ITE_IT8661F) {
|
||||
dev->global_regs[reg & 0x0f] = (val & 0x30) | (dev->global_regs[reg & 0x0f] & ~0x30);
|
||||
uint8_t mcc = (val & 0x30) >> 4;
|
||||
if (mcc != dev->instance) {
|
||||
it86x1f_log("IT86x1F: Instance %d unmapping as ID %d was written\n", dev->instance, mcc);
|
||||
it86x1f_remap(dev, 0, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x23:
|
||||
val &= (1 << dev->gpio_ldn) - 1;
|
||||
dev->global_regs[reg & 0x0f] = val;
|
||||
if (val)
|
||||
pclog("IT86x1F: Warning: ISAPnP mode enabled.\n");
|
||||
break;
|
||||
|
||||
case 0x24:
|
||||
dev->global_regs[reg & 0x0f] = val & ((CHIP_ID == ITE_IT8661F) ? 0x03 : 0x5f);
|
||||
break;
|
||||
|
||||
case 0x25:
|
||||
val &= (CHIP_ID == ITE_IT8661F) ? 0x1f : 0xf0;
|
||||
fallthrough;
|
||||
|
||||
case 0x26:
|
||||
if (ld == dev->gpio_ldn)
|
||||
dev->global_regs[reg & 0x0f] = val;
|
||||
break;
|
||||
|
||||
case 0x2e ... 0x2f:
|
||||
if ((CHIP_ID == ITE_IT8671F) && (ld == 0xf4))
|
||||
dev->global_regs[reg & 0x0f] = val;
|
||||
break;
|
||||
|
||||
case 0x60 ... 0x7f:
|
||||
if (ld != dev->gpio_ldn)
|
||||
break;
|
||||
|
||||
dev->gpio_regs[reg & 0x1f] = val;
|
||||
break;
|
||||
|
||||
case 0xe0 ... 0xe3:
|
||||
if (ld != dev->gpio_ldn)
|
||||
break;
|
||||
|
||||
dev->gpio_regs[0x20 | (reg & 0x0f)] = val;
|
||||
break;
|
||||
|
||||
case 0xf0 ... 0xff:
|
||||
/* Translate GPIO LDN to 7 for the switch block. */
|
||||
uint8_t effective_ldn;
|
||||
if (ld == dev->gpio_ldn)
|
||||
effective_ldn = 7;
|
||||
else if (ld == 7)
|
||||
effective_ldn = 8; /* dummy */
|
||||
else
|
||||
effective_ldn = ld;
|
||||
|
||||
switch ((effective_ldn << 8) | reg) {
|
||||
case 0x0f0:
|
||||
dev->ldn_regs[ld][reg & 0x0f] = val & 0x0f;
|
||||
fdc_set_swwp(dev->fdc, !!(val & 0x01));
|
||||
fdc_set_swap(dev->fdc, !!(val & 0x04));
|
||||
break;
|
||||
|
||||
case 0x1f0:
|
||||
dev->ldn_regs[ld][reg & 0x0f] = val & 0x03;
|
||||
break;
|
||||
|
||||
case 0x2f0:
|
||||
dev->ldn_regs[ld][reg & 0x0f] = val & ((CHIP_ID == ITE_IT8661F) ? 0x03 : 0xf3);
|
||||
break;
|
||||
|
||||
case 0x2f1:
|
||||
if (CHIP_ID == ITE_IT8671F)
|
||||
dev->ldn_regs[ld][reg & 0x0f] = val & 0xb7;
|
||||
break;
|
||||
|
||||
case 0x3f0:
|
||||
dev->ldn_regs[ld][reg & 0x0f] = val & 0x07;
|
||||
break;
|
||||
|
||||
case 0x4f0:
|
||||
if (CHIP_ID == ITE_IT8661F)
|
||||
val &= 0x3f;
|
||||
dev->ldn_regs[ld][reg & 0x0f] = val;
|
||||
break;
|
||||
|
||||
case 0x4f1:
|
||||
if (CHIP_ID == ITE_IT8671F)
|
||||
dev->ldn_regs[ld][reg & 0x0f] = val & 0x7f;
|
||||
break;
|
||||
|
||||
case 0x4f2:
|
||||
case 0x4f6:
|
||||
if (CHIP_ID == ITE_IT8671F)
|
||||
dev->ldn_regs[ld][reg & 0x0f] = val;
|
||||
break;
|
||||
|
||||
case 0x4f7:
|
||||
if (CHIP_ID == ITE_IT8671F)
|
||||
dev->ldn_regs[ld][reg & 0x0f] = val & 0x7f;
|
||||
break;
|
||||
|
||||
case 0x4f8:
|
||||
if (CHIP_ID == ITE_IT8671F)
|
||||
dev->ldn_regs[ld][reg & 0x0f] = val & 0x07;
|
||||
break;
|
||||
|
||||
case 0x5f0:
|
||||
dev->ldn_regs[ld][reg & 0x0f] = val & 0x1f;
|
||||
break;
|
||||
|
||||
case 0x6f0:
|
||||
if (CHIP_ID == ITE_IT8671F)
|
||||
dev->ldn_regs[ld][reg & 0x0f] = val & 0x03;
|
||||
break;
|
||||
|
||||
case 0x760:
|
||||
case 0x762:
|
||||
case 0x764:
|
||||
case 0x766:
|
||||
dev->gpio_regs[reg & 0x1f] = val & 0x0f;
|
||||
break;
|
||||
|
||||
case 0x772:
|
||||
if (CHIP_ID != ITE_IT8671F)
|
||||
break;
|
||||
fallthrough;
|
||||
|
||||
case 0x761:
|
||||
case 0x763:
|
||||
case 0x765:
|
||||
case 0x767:
|
||||
case 0x770:
|
||||
dev->gpio_regs[reg & 0x1f] = val;
|
||||
|
||||
case 0x771:
|
||||
if (CHIP_ID == ITE_IT8671F)
|
||||
dev->gpio_regs[reg & 0x1f] = val & 0xde;
|
||||
break;
|
||||
|
||||
case 0x7e0:
|
||||
if (CHIP_ID == ITE_IT8671F)
|
||||
dev->gpio_regs[0x20 | (reg & 0x03)] = val & 0xef;
|
||||
break;
|
||||
|
||||
case 0x7e1:
|
||||
if (CHIP_ID == ITE_IT8671F)
|
||||
dev->gpio_regs[0x20 | (reg & 0x03)] = val & 0x7f;
|
||||
break;
|
||||
|
||||
case 0x7e3:
|
||||
if ((CHIP_ID == ITE_IT8671F) && (val & 0x80))
|
||||
*((uint16_t *) &dev->gpio_regs[0x22]) = 0x0000;
|
||||
break;
|
||||
|
||||
case 0x7fb:
|
||||
if (CHIP_ID == ITE_IT8671F)
|
||||
val &= 0x7f;
|
||||
fallthrough;
|
||||
|
||||
case 0x7f0 ... 0x7f5:
|
||||
dev->ldn_regs[ld][reg & 0x0f] = val;
|
||||
break;
|
||||
|
||||
case 0x7f6:
|
||||
dev->ldn_regs[ld][reg & 0x0f] = val & ((CHIP_ID == ITE_IT8661F) ? 0x3f : 0xcf);
|
||||
break;
|
||||
|
||||
case 0x7f7:
|
||||
dev->ldn_regs[ld][reg & 0x0f] = val & ((CHIP_ID == ITE_IT8661F) ? 0x9f : 0xdf);
|
||||
break;
|
||||
|
||||
case 0x7f8 ... 0x7fa:
|
||||
dev->ldn_regs[ld][reg & 0x0f] = val & ((CHIP_ID == ITE_IT8661F) ? 0x1f : 0x0f);
|
||||
break;
|
||||
|
||||
case 0x7fc:
|
||||
if (CHIP_ID == ITE_IT8661F)
|
||||
dev->ldn_regs[ld][reg & 0x0f] = val;
|
||||
break;
|
||||
|
||||
case 0x7ff:
|
||||
if (CHIP_ID == ITE_IT8671F)
|
||||
dev->ldn_regs[ld][reg & 0x0f] = val & 0x2f;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
it86x1f_write_addr(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
it86x1f_t *dev = (it86x1f_t *) priv;
|
||||
|
||||
it86x1f_log("IT86x1F: write_addr(%04X, %02X)\n", port, val);
|
||||
|
||||
if (dev->locked) {
|
||||
if (val == isapnp_init_key[dev->key_pos]) {
|
||||
if (++dev->key_pos == 0) {
|
||||
it86x1f_log("IT86x1F: Unlocked\n");
|
||||
dev->locked = 0;
|
||||
}
|
||||
} else {
|
||||
dev->key_pos = 0;
|
||||
}
|
||||
} else {
|
||||
dev->cur_reg = val;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
it86x1f_write_data(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
it86x1f_t *dev = (it86x1f_t *) priv;
|
||||
|
||||
it86x1f_log("IT86x1F: write_data(%04X, %02X)\n", port, val);
|
||||
|
||||
if (dev->locked)
|
||||
return;
|
||||
|
||||
switch (dev->cur_reg) {
|
||||
case 0x00 ... 0x01:
|
||||
case 0x03 ... 0x06:
|
||||
case 0x31:
|
||||
case 0x71:
|
||||
case 0x73:
|
||||
break; /* ISAPnP-only */
|
||||
|
||||
case 0x07:
|
||||
dev->cur_ldn = val;
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
if (val & 0x02) {
|
||||
it86x1f_log("IT86x1F: Locked => ");
|
||||
dev->locked = 1;
|
||||
it86x1f_remap(dev, 0, 0);
|
||||
}
|
||||
fallthrough;
|
||||
|
||||
default:
|
||||
isapnp_write_reg(dev->pnp_card, dev->cur_ldn, dev->cur_reg, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
it86x1f_read_addr(uint16_t port, void *priv)
|
||||
{
|
||||
it86x1f_t *dev = (it86x1f_t *) priv;
|
||||
uint8_t ret = dev->locked ? 0xff : dev->cur_reg;
|
||||
|
||||
it86x1f_log("IT86x1F: read_addr(%04X) = %02X\n", port, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
it86x1f_read_data(uint16_t port, void *priv)
|
||||
{
|
||||
it86x1f_t *dev = (it86x1f_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
switch (dev->cur_reg) {
|
||||
case 0x00 ... 0x01:
|
||||
case 0x03 ... 0x06:
|
||||
case 0x31:
|
||||
case 0x71:
|
||||
case 0x73:
|
||||
break; /* ISAPnP-only */
|
||||
|
||||
case 0x07:
|
||||
ret = dev->cur_ldn;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = isapnp_read_reg(dev->pnp_card, dev->cur_ldn, dev->cur_reg);
|
||||
break;
|
||||
}
|
||||
|
||||
it86x1f_log("IT86x1F: read_data(%04X) = %02X\n", port, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
it86x1f_remap(it86x1f_t *dev, uint16_t addr_port, uint16_t data_port)
|
||||
{
|
||||
if (dev->addr_port)
|
||||
io_removehandler(dev->addr_port, 1, it86x1f_read_addr, NULL, NULL, it86x1f_write_addr, NULL, NULL, dev);
|
||||
if (dev->data_port)
|
||||
io_removehandler(dev->data_port, 1, it86x1f_read_data, NULL, NULL, it86x1f_write_data, NULL, NULL, dev);
|
||||
|
||||
it86x1f_log("IT86x1F: remap(%04X, %04X)\n", addr_port, data_port);
|
||||
dev->addr_port = addr_port;
|
||||
dev->data_port = data_port;
|
||||
|
||||
if (dev->addr_port)
|
||||
io_sethandler(dev->addr_port, 1, it86x1f_read_addr, NULL, NULL, it86x1f_write_addr, NULL, NULL, dev);
|
||||
if (dev->data_port)
|
||||
io_sethandler(dev->data_port, 1, it86x1f_read_data, NULL, NULL, it86x1f_write_data, NULL, NULL, dev);
|
||||
}
|
||||
|
||||
static void
|
||||
it86x1f_write_unlock(UNUSED(uint16_t port), uint8_t val, void *priv)
|
||||
{
|
||||
it86x1f_t *dev = (it86x1f_t *) priv;
|
||||
|
||||
it86x1f_log("IT86x1F: write_unlock(%04X, %02X)\n", port, val);
|
||||
|
||||
if (!dev->locked)
|
||||
dev->unlock_pos = 0;
|
||||
|
||||
switch (dev->unlock_pos++) {
|
||||
case 0:
|
||||
if (val != (dev->unlock_id >> 8))
|
||||
dev->unlock_pos = 0;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (val != (dev->unlock_id & 0xff))
|
||||
dev->unlock_pos = 0;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if ((val != 0x55) && (val != 0xaa))
|
||||
dev->unlock_pos = 0;
|
||||
else
|
||||
dev->unlock_val = val;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
switch ((dev->unlock_val << 8) | val) {
|
||||
case 0x5555:
|
||||
it86x1f_remap(dev, 0x3f0, 0x3f1);
|
||||
break;
|
||||
|
||||
case 0x55aa:
|
||||
it86x1f_remap(dev, 0x3bd, 0x3bf);
|
||||
break;
|
||||
|
||||
case 0xaa55:
|
||||
it86x1f_remap(dev, 0x370, 0x371);
|
||||
break;
|
||||
|
||||
default:
|
||||
it86x1f_remap(dev, 0, 0);
|
||||
break;
|
||||
}
|
||||
dev->unlock_pos = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
it86x1f_reset(it86x1f_t *dev)
|
||||
{
|
||||
it86x1f_log("IT86x1F: reset()\n");
|
||||
|
||||
fdc_reset(dev->fdc);
|
||||
|
||||
serial_remove(dev->uart[0]);
|
||||
|
||||
serial_remove(dev->uart[1]);
|
||||
|
||||
lpt1_remove();
|
||||
|
||||
isapnp_enable_card(dev->pnp_card, ISAPNP_CARD_DISABLE);
|
||||
|
||||
dev->locked = 1;
|
||||
|
||||
isapnp_reset_card(dev->pnp_card);
|
||||
}
|
||||
|
||||
static void
|
||||
it86x1f_close(void *priv)
|
||||
{
|
||||
it86x1f_t *dev = (it86x1f_t *) priv;
|
||||
|
||||
it86x1f_log("IT86x1F: close()\n");
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static void *
|
||||
it86x1f_init(UNUSED(const device_t *info))
|
||||
{
|
||||
it86x1f_t *dev = (it86x1f_t *) malloc(sizeof(it86x1f_t));
|
||||
memset(dev, 0, sizeof(it86x1f_t));
|
||||
|
||||
uint8_t i;
|
||||
for (i = 0; i < (sizeof(it86x1f_models) / sizeof(it86x1f_models[0])); i++) {
|
||||
if (it86x1f_models[i].chip_id == info->local)
|
||||
break;
|
||||
}
|
||||
if (i >= (sizeof(it86x1f_models) / sizeof(it86x1f_models[0]))) {
|
||||
fatal("IT86x1F: Unknown type %04X selected\n", info->local);
|
||||
return NULL;
|
||||
}
|
||||
it86x1f_log("IT86x1F: init(%04X)\n", info->local);
|
||||
|
||||
/* Let the resource data parser figure out the ROM size. */
|
||||
dev->pnp_card = isapnp_add_card(it86x1f_models[i].pnp_rom, -1, it86x1f_models[i].pnp_config_changed, NULL, it86x1f_pnp_read_vendor_reg, it86x1f_pnp_write_vendor_reg, dev);
|
||||
for (uint8_t j = 0; it86x1f_models[i].pnp_defaults[j].activate != (uint8_t) -1; j++)
|
||||
isapnp_set_device_defaults(dev->pnp_card, j, &it86x1f_models[i].pnp_defaults[j]);
|
||||
|
||||
dev->fdc = device_add(&fdc_at_smc_device);
|
||||
|
||||
dev->uart[0] = device_add_inst(&ns16550_device, 1);
|
||||
dev->uart[1] = device_add_inst(&ns16550_device, 2);
|
||||
|
||||
dev->gameport = gameport_add(&gameport_sio_device);
|
||||
|
||||
dev->instance = device_get_instance();
|
||||
dev->gpio_ldn = it86x1f_models[i].gpio_ldn;
|
||||
CHIP_ID = it86x1f_models[i].chip_id;
|
||||
dev->unlock_id = it86x1f_models[i].unlock_id;
|
||||
io_sethandler(0x279, 1, NULL, NULL, NULL, it86x1f_write_unlock, NULL, NULL, dev);
|
||||
|
||||
it86x1f_reset(dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
const device_t it8661f_device = {
|
||||
.name = "ITE IT8661F Super I/O",
|
||||
.internal_name = "it8661f",
|
||||
.flags = 0,
|
||||
.local = ITE_IT8661F,
|
||||
.init = it86x1f_init,
|
||||
.close = it86x1f_close,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t it8671f_device = {
|
||||
.name = "ITE IT8671F Super I/O",
|
||||
.internal_name = "it8671f",
|
||||
.flags = 0,
|
||||
.local = ITE_IT8671F,
|
||||
.init = it86x1f_init,
|
||||
.close = it86x1f_close,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
@@ -633,7 +633,7 @@ DEVOBJ := bugger.o cartridge.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm
|
||||
SIOOBJ := sio_acc3221.o sio_ali5123.o \
|
||||
sio_f82c710.o sio_82091aa.o sio_fdc37c6xx.o \
|
||||
sio_fdc37c67x.o sio_fdc37c669.o sio_fdc37c93x.o sio_fdc37m60x.o \
|
||||
sio_it8661f.o \
|
||||
sio_it86x1f.o \
|
||||
sio_pc87306.o sio_pc87307.o sio_pc87309.o sio_pc87310.o sio_pc87311.o sio_pc87332.o \
|
||||
sio_prime3b.o sio_prime3c.o \
|
||||
sio_w83787f.o \
|
||||
|
Reference in New Issue
Block a user