Conflict resolution.

This commit is contained in:
BurnedPinguin
2024-01-18 11:45:21 +01:00
717 changed files with 72500 additions and 41900 deletions

View File

@@ -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

View File

@@ -209,9 +209,9 @@ i82091aa_write(uint16_t port, uint8_t val, void *priv)
uint8_t
i82091aa_read(uint16_t port, void *priv)
{
i82091aa_t *dev = (i82091aa_t *) priv;
uint8_t ret = 0xff;
uint8_t index;
const i82091aa_t *dev = (i82091aa_t *) priv;
uint8_t ret = 0xff;
uint8_t index;
index = (port & 1) ? 0 : 1;

View File

@@ -416,7 +416,7 @@ acc3221_write(uint16_t addr, uint8_t val, void *priv)
static uint8_t
acc3221_read(uint16_t addr, void *priv)
{
acc3221_t *dev = (acc3221_t *) priv;
const acc3221_t *dev = (acc3221_t *) priv;
if (!(addr & 1))
return dev->reg_idx;

View File

@@ -428,10 +428,10 @@ ali5123_write(uint16_t port, uint8_t val, void *priv)
static uint8_t
ali5123_read(uint16_t port, void *priv)
{
ali5123_t *dev = (ali5123_t *) priv;
uint8_t index = (port & 1) ? 0 : 1;
uint8_t ret = 0xff;
uint8_t cur_ld;
const ali5123_t *dev = (ali5123_t *) priv;
uint8_t index = (port & 1) ? 0 : 1;
uint8_t ret = 0xff;
uint8_t cur_ld;
if (dev->locked) {
if (index)

View File

@@ -47,7 +47,7 @@ sio_detect_write(uint16_t port, uint8_t val, void *priv)
static uint8_t
sio_detect_read(uint16_t port, void *priv)
{
sio_detect_t *dev = (sio_detect_t *) priv;
const sio_detect_t *dev = (sio_detect_t *) priv;
pclog("sio_detect_read : port=%04x = %02X\n", port, dev->regs[port & 1]);

View File

@@ -18,11 +18,9 @@
*
*
*
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Eluan Costa Miranda <eluancm@gmail.com>
* Authors: Eluan Costa Miranda <eluancm@gmail.com>
* Lubomir Rintel <lkundrak@v3.sk>
*
* Copyright 2020 Sarah Walker.
* Copyright 2020 Eluan Costa Miranda.
* Copyright 2021 Lubomir Rintel.
*/
@@ -230,8 +228,8 @@ f82c606_update_ports(upc_t *dev, int set)
static uint8_t
f82c710_config_read(uint16_t port, void *priv)
{
upc_t *dev = (upc_t *) priv;
uint8_t temp = 0xff;
const upc_t *dev = (upc_t *) priv;
uint8_t temp = 0xff;
if (dev->configuration_mode) {
if (port == dev->cri_addr) {

View File

@@ -12,13 +12,15 @@
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2016-2018 Miran Grca.
* Copyright 2016-2024 Miran Grca.
*/
#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/io.h>
#include <86box/timer.h>
@@ -45,35 +47,67 @@ typedef struct fdc37c669_t {
static int next_id = 0;
static uint16_t
make_port(fdc37c669_t *dev, uint8_t reg)
#ifdef ENABLE_FDC37C669_LOG
int fdc37c669_do_log = ENABLE_FDC37C669_LOG;
static void
fdc37c669_log(const char *fmt, ...)
{
uint16_t p = 0;
uint16_t mask = 0;
va_list ap;
switch (reg) {
case 0x20:
case 0x21:
case 0x22:
mask = 0xfc;
break;
case 0x23:
mask = 0xff;
break;
case 0x24:
case 0x25:
mask = 0xfe;
break;
default:
break;
if (fdc37c669_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define fdc37c669_log(fmt, ...)
#endif
p = ((uint16_t) (dev->regs[reg] & mask)) << 2;
if (reg == 0x22)
p |= 6;
static void
fdc37c669_fdc_handler(fdc37c669_t *dev)
{
fdc_remove(dev->fdc);
if (dev->regs[0x20] & 0xc0)
fdc_set_base(dev->fdc, ((uint16_t) dev->regs[0x20]) << 2);
}
return p;
static void
fdc37c669_uart_handler(fdc37c669_t *dev, uint8_t uart)
{
uint8_t uart_reg = 0x24 + uart;
uint8_t pwrdn_mask = 0x08 << (uart << 2);
uint8_t uart_shift = ((uart ^ 1) << 2);
serial_remove(dev->uart[uart]);
if ((dev->regs[0x02] & pwrdn_mask) && (dev->regs[uart_reg] & 0xc0))
serial_setup(dev->uart[0], ((uint16_t) dev->regs[0x24]) << 2,
(dev->regs[0x28] >> uart_shift) & 0x0f);
}
static double
fdc37c669_uart_get_clock_src(fdc37c669_t *dev, uint8_t uart)
{
double clock_srcs[4] = { 24000000.0 / 13.0, 24000000.0 / 12.0, 24000000.0 / 3.0, 24000000.0 / 3.0 };
double ret;
uint8_t clock_src_0 = !!(dev->regs[0x04] & (0x10 << uart));
uint8_t clock_src_1 = !!(dev->regs[0x0c] & (0x40 << uart));
uint8_t clock_src = clock_src_0 | (clock_src_1 << 1);
ret = clock_srcs[clock_src];
return ret;
}
static void
fdc37c669_lpt_handler(fdc37c669_t *dev)
{
uint8_t mask = ~(dev->regs[0x04] & 0x01);
lpt_port_remove(dev->id);
if ((dev->regs[0x01] & 0x04) && (dev->regs[0x23] >= 0x40))
lpt_port_init(dev->id, ((uint16_t) (dev->regs[0x23] & mask)) << 2);
}
static void
@@ -81,149 +115,153 @@ fdc37c669_write(uint16_t port, uint8_t val, void *priv)
{
fdc37c669_t *dev = (fdc37c669_t *) priv;
uint8_t index = (port & 1) ? 0 : 1;
uint8_t valxor = 0;
uint8_t max = 42;
uint8_t valxor = val ^ dev->regs[dev->cur_reg];
fdc37c669_log("[%04X:%08X] [W] %04X = %02X (%i, %i)\n", CS, cpu_state.pc, port, val,
dev->tries, dev->locked);
if (index) {
if ((val == 0x55) && !dev->locked) {
if (dev->tries) {
dev->tries = (dev->tries + 1) & 1;
if (!dev->tries)
dev->locked = 1;
dev->tries = 0;
} else
dev->tries++;
} else {
if (dev->locked) {
if (val < max)
dev->cur_reg = val;
if (val == 0xaa)
dev->locked = 0;
} else {
if (dev->tries)
dev->tries = 0;
}
else
dev->cur_reg = val;
} else
dev->tries = 0;
}
return;
} else {
if (dev->locked) {
if ((dev->cur_reg < 0x18) && (dev->rw_locked))
return;
if ((dev->cur_reg >= 0x26) && (dev->cur_reg <= 0x27))
return;
if (dev->cur_reg == 0x29)
return;
valxor = val ^ dev->regs[dev->cur_reg];
} else if (!dev->rw_locked || (dev->cur_reg > 0x0f)) switch (dev->cur_reg) {
case 0x00:
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x74) | (val & 0x8b);
if (!dev->id && (valxor & 8))
fdc_set_power_down(dev->fdc, !(val & 0x08));
break;
case 0x01:
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x73) | (val & 0x8c);
if (valxor & 0x04)
fdc37c669_lpt_handler(dev);
if (valxor & 0x80)
dev->rw_locked = !(val & 0x80);
break;
case 0x02:
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x77) | (val & 0x88);
if (valxor & 0x08)
fdc37c669_uart_handler(dev, 0);
if (valxor & 0x80)
fdc37c669_uart_handler(dev, 1);
break;
case 0x03:
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x08) | (val & 0xf7);
if (!dev->id && (valxor & 0x02))
fdc_update_enh_mode(dev->fdc, !!(val & 0x02));
break;
case 0x04:
dev->regs[dev->cur_reg] = val;
} else
return;
}
switch (dev->cur_reg) {
case 0:
if (!dev->id && (valxor & 8)) {
fdc_remove(dev->fdc);
if ((dev->regs[0] & 8) && (dev->regs[0x20] & 0xc0))
fdc_set_base(dev->fdc, make_port(dev, 0x20));
}
if (valxor & 0x03)
fdc37c669_lpt_handler(dev);
if (valxor & 0x10)
serial_set_clock_src(dev->uart[0], fdc37c669_uart_get_clock_src(dev, 0));
if (valxor & 0x20)
serial_set_clock_src(dev->uart[1], fdc37c669_uart_get_clock_src(dev, 1));
break;
case 1:
if (valxor & 4) {
if (dev->id) {
lpt2_remove();
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
lpt2_init(make_port(dev, 0x23));
} else {
lpt1_remove();
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
lpt1_init(make_port(dev, 0x23));
}
}
if (valxor & 7)
dev->rw_locked = (val & 8) ? 0 : 1;
break;
case 2:
if (valxor & 8) {
serial_remove(dev->uart[0]);
if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40))
serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4);
}
if (valxor & 0x80) {
serial_remove(dev->uart[1]);
if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40))
serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f);
}
break;
case 3:
if (!dev->id && (valxor & 2))
fdc_update_enh_mode(dev->fdc, (val & 2) ? 1 : 0);
break;
case 5:
case 0x05:
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x83) | (val & 0x7c);
if (!dev->id && (valxor & 0x18))
fdc_update_densel_force(dev->fdc, (val & 0x18) >> 3);
if (!dev->id && (valxor & 0x20))
fdc_set_swap(dev->fdc, (val & 0x20) >> 5);
break;
case 0xB:
if (!dev->id && (valxor & 3))
fdc_update_rwc(dev->fdc, 0, val & 3);
if (!dev->id && (valxor & 0xC))
fdc_update_rwc(dev->fdc, 1, (val & 0xC) >> 2);
case 0x06:
dev->regs[dev->cur_reg] = val;
break;
case 0x07:
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x06) | (val & 0xf9);
break;
case 0x08:
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x0f) | (val & 0xf0);
break;
case 0x09:
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x38) | (val & 0xc7);
break;
case 0x0a:
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0xf0) | (val & 0x0f);
break;
case 0x0b:
dev->regs[dev->cur_reg] = val;
if (!dev->id && (valxor & 0x03))
fdc_update_rwc(dev->fdc, 0, val & 0x03);
if (!dev->id && (valxor & 0x0c))
fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2);
break;
case 0x0c:
dev->regs[dev->cur_reg] = val;
if (valxor & 0x40)
serial_set_clock_src(dev->uart[0], fdc37c669_uart_get_clock_src(dev, 0));
if (valxor & 0x80)
serial_set_clock_src(dev->uart[1], fdc37c669_uart_get_clock_src(dev, 1));
break;
case 0x0f:
case 0x12 ... 0x1f:
dev->regs[dev->cur_reg] = val;
break;
case 0x10:
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x07) | (val & 0xf8);
break;
case 0x11:
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0xfc) | (val & 0x03);
break;
case 0x20:
if (!dev->id && (valxor & 0xfc)) {
fdc_remove(dev->fdc);
if ((dev->regs[0] & 8) && (dev->regs[0x20] & 0xc0))
fdc_set_base(dev->fdc, make_port(dev, 0x20));
}
dev->regs[dev->cur_reg] = val & 0xfc;
if (!dev->id && (valxor & 0xfc))
fdc37c669_fdc_handler(dev);
break;
case 0x21:
dev->regs[dev->cur_reg] = val & 0xfc;
break;
case 0x22:
dev->regs[dev->cur_reg] = (dev->regs[dev->cur_reg] & 0x03) | (val & 0xfc);
break;
case 0x23:
if (valxor) {
if (dev->id) {
lpt2_remove();
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
lpt2_init(make_port(dev, 0x23));
} else {
lpt1_remove();
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
lpt1_init(make_port(dev, 0x23));
}
}
dev->regs[dev->cur_reg] = val;
if (valxor)
fdc37c669_lpt_handler(dev);
break;
case 0x24:
if (valxor & 0xfe) {
serial_remove(dev->uart[0]);
if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40))
serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4);
}
dev->regs[dev->cur_reg] = val & 0xfe;
if (valxor & 0xfe)
fdc37c669_uart_handler(dev, 0);
break;
case 0x25:
if (valxor & 0xfe) {
serial_remove(dev->uart[1]);
if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40))
serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f);
}
dev->regs[dev->cur_reg] = val & 0xfe;
if (valxor & 0xfe)
fdc37c669_uart_handler(dev, 1);
break;
case 0x26:
dev->regs[dev->cur_reg] = val;
if (valxor & 0xf0)
fdc_set_dma_ch(dev->fdc, val >> 4);
break;
case 0x27:
if (valxor & 0xf) {
if (dev->id)
lpt2_irq(val & 0xf);
else
lpt1_irq(val & 0xf);
}
dev->regs[dev->cur_reg] = val;
if (valxor & 0xf0)
fdc_set_irq(dev->fdc, val >> 4);
if (valxor & 0x0f)
lpt_port_irq(dev->id, val & 0x0f);
break;
case 0x28:
if (valxor & 0xf) {
serial_remove(dev->uart[1]);
if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40))
serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f);
}
if (valxor & 0xf0) {
serial_remove(dev->uart[0]);
if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40))
serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4);
}
dev->regs[dev->cur_reg] = val;
if (valxor & 0xf0)
fdc37c669_uart_handler(dev, 0);
if (valxor & 0x0f)
fdc37c669_uart_handler(dev, 1);
break;
default:
case 0x29:
dev->regs[dev->cur_reg] = val & 0x0f;
break;
}
}
@@ -231,30 +269,30 @@ fdc37c669_write(uint16_t port, uint8_t val, void *priv)
static uint8_t
fdc37c669_read(uint16_t port, void *priv)
{
fdc37c669_t *dev = (fdc37c669_t *) priv;
uint8_t index = (port & 1) ? 0 : 1;
uint8_t ret = 0xff;
const fdc37c669_t *dev = (fdc37c669_t *) priv;
uint8_t index = (port & 1) ? 0 : 1;
uint8_t ret = 0xff;
if (dev->locked) {
if (index)
ret = dev->cur_reg;
else if ((dev->cur_reg >= 0x18) || !dev->rw_locked)
else if (!dev->rw_locked || (dev->cur_reg > 0x0f))
ret = dev->regs[dev->cur_reg];
}
fdc37c669_log("[%04X:%08X] [R] %04X = %02X (%i, %i)\n", CS, cpu_state.pc, port, ret,
dev->tries, dev->locked);
return ret;
}
static void
fdc37c669_reset(fdc37c669_t *dev)
fdc37c669_reset(void *priv)
{
serial_remove(dev->uart[0]);
serial_setup(dev->uart[0], COM1_ADDR, COM1_IRQ);
fdc37c669_t *dev = (fdc37c669_t *) priv;
serial_remove(dev->uart[1]);
serial_setup(dev->uart[1], COM2_ADDR, COM2_IRQ);
memset(dev->regs, 0x00, 42);
memset(dev->regs, 0, 42);
dev->regs[0x00] = 0x28;
dev->regs[0x01] = 0x9c;
dev->regs[0x02] = 0x88;
@@ -262,32 +300,23 @@ fdc37c669_reset(fdc37c669_t *dev)
dev->regs[0x06] = 0xff;
dev->regs[0x0d] = 0x03;
dev->regs[0x0e] = 0x02;
dev->regs[0x1e] = 0x80; /* Gameport controller. */
dev->regs[0x20] = (FDC_PRIMARY_ADDR >> 2) & 0xfc;
dev->regs[0x21] = (0x1f0 >> 2) & 0xfc;
dev->regs[0x22] = ((0x3f6 >> 2) & 0xfc) | 1;
dev->regs[0x1e] = 0x3c; /* Gameport controller. */
dev->regs[0x20] = 0x3c;
dev->regs[0x21] = 0x3c;
dev->regs[0x22] = 0x3d;
if (dev->id == 1) {
dev->regs[0x23] = (LPT2_ADDR >> 2);
lpt2_remove();
lpt2_init(LPT2_ADDR);
dev->regs[0x24] = (COM3_ADDR >> 2) & 0xfe;
dev->regs[0x25] = (COM4_ADDR >> 2) & 0xfe;
} else {
fdc_reset(dev->fdc);
lpt1_remove();
lpt1_init(LPT1_ADDR);
dev->regs[0x23] = (LPT1_ADDR >> 2);
dev->regs[0x24] = (COM1_ADDR >> 2) & 0xfe;
dev->regs[0x25] = (COM2_ADDR >> 2) & 0xfe;
fdc37c669_fdc_handler(dev);
}
dev->regs[0x26] = (2 << 4) | 3;
dev->regs[0x27] = (6 << 4) | (dev->id ? 5 : 7);
dev->regs[0x28] = (4 << 4) | 3;
fdc37c669_uart_handler(dev, 0);
serial_set_clock_src(dev->uart[0], fdc37c669_uart_get_clock_src(dev, 0));
fdc37c669_uart_handler(dev, 1);
serial_set_clock_src(dev->uart[1], fdc37c669_uart_get_clock_src(dev, 1));
fdc37c669_lpt_handler(dev);
dev->locked = 0;
dev->rw_locked = 0;
@@ -317,8 +346,8 @@ fdc37c669_init(const device_t *info)
dev->uart[0] = device_add_inst(&ns16550_device, (next_id << 1) + 1);
dev->uart[1] = device_add_inst(&ns16550_device, (next_id << 1) + 2);
io_sethandler(info->local ? FDC_SECONDARY_ADDR : (next_id ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR), 0x0002,
fdc37c669_read, NULL, NULL, fdc37c669_write, NULL, NULL, dev);
io_sethandler(info->local ? FDC_SECONDARY_ADDR : (next_id ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR),
0x0002, fdc37c669_read, NULL, NULL, fdc37c669_write, NULL, NULL, dev);
fdc37c669_reset(dev);
@@ -334,7 +363,7 @@ const device_t fdc37c669_device = {
.local = 0,
.init = fdc37c669_init,
.close = fdc37c669_close,
.reset = NULL,
.reset = fdc37c669_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
@@ -348,7 +377,7 @@ const device_t fdc37c669_370_device = {
.local = 1,
.init = fdc37c669_init,
.close = fdc37c669_close,
.reset = NULL,
.reset = fdc37c669_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,

View File

@@ -71,7 +71,7 @@ make_port(fdc37c67x_t *dev, uint8_t ld)
static uint8_t
fdc37c67x_auxio_read(UNUSED(uint16_t port), void *priv)
{
fdc37c67x_t *dev = (fdc37c67x_t *) priv;
const fdc37c67x_t *dev = (fdc37c67x_t *) priv;
return dev->auxio_reg;
}
@@ -87,8 +87,8 @@ fdc37c67x_auxio_write(UNUSED(uint16_t port), uint8_t val, void *priv)
static uint8_t
fdc37c67x_gpio_read(uint16_t port, void *priv)
{
fdc37c67x_t *dev = (fdc37c67x_t *) priv;
uint8_t ret = 0xff;
const fdc37c67x_t *dev = (fdc37c67x_t *) priv;
uint8_t ret = 0xff;
ret = dev->gpio_regs[port & 1];
@@ -316,6 +316,7 @@ fdc37c67x_write(uint16_t port, uint8_t val, void *priv)
case 0x26:
case 0x27:
fdc37c67x_sio_handler(dev);
break;
default:
break;

View File

@@ -11,10 +11,8 @@
*
*
*
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2020 Sarah Walker.
* Copyright 2016-2020 Miran Grca.
*/
#include <stdio.h>
@@ -230,8 +228,8 @@ fdc37c6xx_write(uint16_t port, uint8_t val, void *priv)
static uint8_t
fdc37c6xx_read(uint16_t port, void *priv)
{
fdc37c6xx_t *dev = (fdc37c6xx_t *) priv;
uint8_t ret = 0xff;
const fdc37c6xx_t *dev = (fdc37c6xx_t *) priv;
uint8_t ret = 0xff;
if (dev->tries == 2) {
if (port == 0x3f1)

View File

@@ -93,7 +93,7 @@ make_port_sec(fdc37c93x_t *dev, uint8_t ld)
static uint8_t
fdc37c93x_auxio_read(UNUSED(uint16_t port), void *priv)
{
fdc37c93x_t *dev = (fdc37c93x_t *) priv;
const fdc37c93x_t *dev = (fdc37c93x_t *) priv;
return dev->auxio_reg;
}
@@ -109,8 +109,8 @@ fdc37c93x_auxio_write(UNUSED(uint16_t port), uint8_t val, void *priv)
static uint8_t
fdc37c93x_gpio_read(uint16_t port, void *priv)
{
fdc37c93x_t *dev = (fdc37c93x_t *) priv;
uint8_t ret = 0xff;
const fdc37c93x_t *dev = (fdc37c93x_t *) priv;
uint8_t ret = 0xff;
ret = dev->gpio_regs[port & 1];
@@ -257,8 +257,8 @@ fdc37c93x_gpio_handler(fdc37c93x_t *dev)
static uint8_t
fdc37c93x_access_bus_read(uint16_t port, void *priv)
{
access_bus_t *dev = (access_bus_t *) priv;
uint8_t ret = 0xff;
const access_bus_t *dev = (access_bus_t *) priv;
uint8_t ret = 0xff;
switch (port & 3) {
case 0:

View File

@@ -163,8 +163,8 @@ fdc37m60x_write(uint16_t addr, uint8_t val, void *priv)
static uint8_t
fdc37m60x_read(uint16_t addr, void *priv)
{
fdc37m60x_t *dev = (fdc37m60x_t *) priv;
uint8_t ret = 0xff;
const fdc37m60x_t *dev = (fdc37m60x_t *) priv;
uint8_t ret = 0xff;
if (addr & 1)
ret = (INDEX >= 0x30) ? dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] : dev->regs[INDEX];

View File

@@ -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)
{
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
};

871
src/sio/sio_it86x1f.c Normal file
View File

@@ -0,0 +1,871 @@
/*
* 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 <inttypes.h>
#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/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;
uint8_t effective_ldn;
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. */
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]))) {
#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)
fatal("IT86x1F: Unknown type %04" PRIX64 " selected\n", info->local);
#else
fatal("IT86x1F: Unknown type %04X selected\n", info->local);
#endif
return NULL;
}
#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)
it86x1f_log("IT86x1F: init(%04" PRIX64 ")\n", info->local);
#else
it86x1f_log("IT86x1F: init(%04X)\n", info->local);
#endif
/* 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
};

View File

@@ -35,11 +35,13 @@
#include <86box/fdc.h>
#include <86box/sio.h>
#include <86box/plat_unused.h>
#include <86box/machine.h>
typedef struct pc87306_t {
uint8_t tries;
uint8_t regs[29];
uint8_t gpio[2];
uint16_t gpioba;
int cur_reg;
fdc_t *fdc;
serial_t *uart[2];
@@ -50,37 +52,66 @@ static void
pc87306_gpio_write(uint16_t port, uint8_t val, void *priv)
{
pc87306_t *dev = (pc87306_t *) priv;
uint32_t gpio = 0xffff0000;
dev->gpio[port & 1] = val;
dev->gpio[port & 0x0001] = val;
if (port & 0x0001) {
gpio |= ((uint32_t) val) << 8;
gpio |= dev->gpio[0];
} else {
gpio |= ((uint32_t) dev->gpio[1]) << 8;
gpio |= val;
}
(void) machine_handle_gpio(1, gpio);
}
uint8_t
pc87306_gpio_read(uint16_t port, void *priv)
{
pc87306_t *dev = (pc87306_t *) priv;
uint32_t ret = machine_handle_gpio(0, 0xffffffff);
return dev->gpio[port & 1];
if (port & 0x0001)
ret = (ret >> 8) & 0xff;
else
ret &= 0xff;
return ret;
}
static void
pc87306_gpio_remove(pc87306_t *dev)
{
io_removehandler(dev->regs[0x0f] << 2, 0x0001,
pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev);
io_removehandler((dev->regs[0x0f] << 2) + 1, 0x0001,
pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev);
if (dev->gpioba != 0x0000) {
io_removehandler(dev->gpioba, 0x0001,
pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev);
io_removehandler(dev->gpioba + 1, 0x0001,
pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev);
}
}
static void
pc87306_gpio_init(pc87306_t *dev)
{
if ((dev->regs[0x12]) & 0x10)
io_sethandler(dev->regs[0x0f] << 2, 0x0001,
pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev);
dev->gpioba = ((uint16_t) dev->regs[0x0f]) << 2;
if ((dev->regs[0x12]) & 0x20)
io_sethandler((dev->regs[0x0f] << 2) + 1, 0x0001,
pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev);
if (dev->gpioba != 0x0000) {
if ((dev->regs[0x12]) & 0x10)
io_sethandler(dev->gpioba, 0x0001,
pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev);
if ((dev->regs[0x12]) & 0x20)
io_sethandler(dev->gpioba + 1, 0x0001,
pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev);
}
}
static void
pc87306_gpio_handler(pc87306_t *dev)
{
pc87306_gpio_remove(dev);
pc87306_gpio_init(dev);
}
static void
@@ -222,8 +253,6 @@ pc87306_write(uint16_t port, uint8_t val, void *priv)
if ((dev->cur_reg <= 28) && (dev->cur_reg != 8)) {
if (dev->cur_reg == 0)
val &= 0x5f;
if (((dev->cur_reg == 0x0F) || (dev->cur_reg == 0x12)) && valxor)
pc87306_gpio_remove(dev);
dev->regs[dev->cur_reg] = val;
} else
return;
@@ -234,7 +263,7 @@ pc87306_write(uint16_t port, uint8_t val, void *priv)
}
switch (dev->cur_reg) {
case 0:
case 0x00:
if (valxor & 1) {
lpt1_remove();
if ((val & 1) && !(dev->regs[2] & 1))
@@ -256,7 +285,7 @@ pc87306_write(uint16_t port, uint8_t val, void *priv)
fdc_set_base(dev->fdc, (val & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
}
break;
case 1:
case 0x01:
if (valxor & 3) {
lpt1_remove();
if ((dev->regs[0] & 1) && !(dev->regs[2] & 1))
@@ -273,7 +302,7 @@ pc87306_write(uint16_t port, uint8_t val, void *priv)
serial_handler(dev, 1);
}
break;
case 2:
case 0x02:
if (valxor & 1) {
lpt1_remove();
serial_remove(dev->uart[0]);
@@ -297,19 +326,31 @@ pc87306_write(uint16_t port, uint8_t val, void *priv)
lpt1_handler(dev);
}
break;
case 9:
case 0x04:
if (valxor & 0x80)
nvr_lock_set(0x00, 256, !!(val & 0x80), dev->nvr);
break;
case 0x05:
if (valxor & 0x08)
nvr_at_handler(!!(val & 0x08), 0x0070, dev->nvr);
if (valxor & 0x20)
nvr_bank_set(0, !!(val & 0x20), dev->nvr);
break;
case 0x09:
if (valxor & 0x44) {
fdc_update_enh_mode(dev->fdc, (val & 4) ? 1 : 0);
fdc_update_densel_polarity(dev->fdc, (val & 0x40) ? 1 : 0);
}
break;
case 0xF:
case 0x0f:
if (valxor)
pc87306_gpio_init(dev);
pc87306_gpio_handler(dev);
break;
case 0x12:
if (valxor & 0x01)
nvr_wp_set(!!(val & 0x01), 0, dev->nvr);
if (valxor & 0x30)
pc87306_gpio_init(dev);
pc87306_gpio_handler(dev);
break;
case 0x19:
if (valxor) {
@@ -368,8 +409,10 @@ pc87306_read(uint16_t port, void *priv)
}
void
pc87306_reset(pc87306_t *dev)
pc87306_reset_common(void *priv)
{
pc87306_t *dev = (pc87306_t *) priv;
memset(dev->regs, 0, 29);
dev->regs[0x00] = 0x0B;
@@ -383,9 +426,6 @@ pc87306_reset(pc87306_t *dev)
dev->regs[0x12] = 0x30;
dev->regs[0x19] = 0xEF;
dev->gpio[0] = 0xff;
dev->gpio[1] = 0xfb;
/*
0 = 360 rpm @ 500 kbps for 3.5"
1 = Default, 300 rpm @ 500, 300, 250, 1000 kbps for 3.5"
@@ -398,6 +438,22 @@ pc87306_reset(pc87306_t *dev)
serial_handler(dev, 1);
fdc_reset(dev->fdc);
pc87306_gpio_init(dev);
nvr_lock_set(0x00, 256, 0, dev->nvr);
nvr_at_handler(0, 0x0070, dev->nvr);
nvr_at_handler(1, 0x0070, dev->nvr);
nvr_bank_set(0, 0, dev->nvr);
nvr_wp_set(0, 0, dev->nvr);
}
void
pc87306_reset(void *priv)
{
pc87306_t *dev = (pc87306_t *) priv;
pc87306_gpio_write(0x0000, 0xff, dev);
pc87306_gpio_write(0x0001, 0xff, dev);
pc87306_reset_common(dev);
}
static void
@@ -419,9 +475,11 @@ pc87306_init(UNUSED(const device_t *info))
dev->uart[0] = device_add_inst(&ns16550_device, 1);
dev->uart[1] = device_add_inst(&ns16550_device, 2);
// dev->nvr = device_add(&piix4_nvr_device);
dev->nvr = device_add(&at_mb_nvr_device);
pc87306_reset(dev);
dev->gpio[0] = dev->gpio[1] = 0xff;
pc87306_reset_common(dev);
io_sethandler(0x02e, 0x0002,
pc87306_read, NULL, NULL, pc87306_write, NULL, NULL, dev);
@@ -436,7 +494,7 @@ const device_t pc87306_device = {
.local = 0,
.init = pc87306_init,
.close = pc87306_close,
.reset = NULL,
.reset = pc87306_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,

View File

@@ -67,11 +67,11 @@ pc87307_gpio_write(uint16_t port, uint8_t val, void *priv)
uint8_t
pc87307_gpio_read(uint16_t port, void *priv)
{
pc87307_t *dev = (pc87307_t *) priv;
uint8_t pins = 0xff;
uint8_t bank = ((port & 0xfffc) == dev->gpio_base2);
uint8_t mask;
uint8_t ret = dev->gpio[bank][port & 0x0003];
const pc87307_t *dev = (pc87307_t *) priv;
uint8_t pins = 0xff;
uint8_t bank = ((port & 0xfffc) == dev->gpio_base2);
uint8_t mask;
uint8_t ret = dev->gpio[bank][port & 0x0003];
switch (port & 0x0003) {
case 0x0000:
@@ -139,7 +139,7 @@ pc87307_pm_write(uint16_t port, uint8_t val, void *priv)
uint8_t
pc87307_pm_read(uint16_t port, void *priv)
{
pc87307_t *dev = (pc87307_t *) priv;
const pc87307_t *dev = (pc87307_t *) priv;
if (port & 1)
return dev->pm[dev->pm_idx];
@@ -456,9 +456,9 @@ pc87307_write(uint16_t port, uint8_t val, void *priv)
uint8_t
pc87307_read(uint16_t port, void *priv)
{
pc87307_t *dev = (pc87307_t *) priv;
uint8_t ret = 0xff;
uint8_t index;
const pc87307_t *dev = (pc87307_t *) priv;
uint8_t ret = 0xff;
uint8_t index;
index = (port & 1) ? 0 : 1;

View File

@@ -77,7 +77,7 @@ pc87309_pm_write(uint16_t port, uint8_t val, void *priv)
uint8_t
pc87309_pm_read(uint16_t port, void *priv)
{
pc87309_t *dev = (pc87309_t *) priv;
const pc87309_t *dev = (pc87309_t *) priv;
if (port & 1)
return dev->pm[dev->pm_idx];
@@ -351,9 +351,9 @@ pc87309_write(uint16_t port, uint8_t val, void *priv)
uint8_t
pc87309_read(uint16_t port, void *priv)
{
pc87309_t *dev = (pc87309_t *) priv;
uint8_t ret = 0xff;
uint8_t index;
const pc87309_t *dev = (pc87309_t *) priv;
uint8_t ret = 0xff;
uint8_t index;
index = (port & 1) ? 0 : 1;

View File

@@ -8,15 +8,13 @@
*
* Emulation of the NatSemi PC87310 Super I/O chip.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Tiseno100
* EngiNerd <webmaster.crrc@yahoo.it>
* EngiNerd, <webmaster.crrc@yahoo.it>
* Tiseno100,
*
* Copyright 2020 Miran Grca.
* Copyright 2020 Tiseno100
* Copyright 2020-2024 Miran Grca.
* Copyright 2021 EngiNerd.
* Copyright 2020 Tiseno100.
*/
#include <stdarg.h>
#include <stdio.h>
@@ -42,7 +40,8 @@
#include <86box/sio.h>
#include <86box/plat_unused.h>
#define HAS_IDE_FUNCTIONALITY dev->ide_function
#define FLAG_IDE 0x00000001
#define FLAG_ALI 0x00000002
#ifdef ENABLE_PC87310_LOG
int pc87310_do_log = ENABLE_PC87310_LOG;
@@ -64,8 +63,8 @@ pc87310_log(const char *fmt, ...)
typedef struct pc87310_t {
uint8_t tries;
uint8_t ide_function;
uint8_t reg;
uint8_t flags;
uint8_t regs[2];
fdc_t *fdc;
serial_t *uart[2];
} pc87310_t;
@@ -83,7 +82,9 @@ lpt1_handler(pc87310_t *dev)
* 10 278h
* 11 disabled
*/
temp = dev->reg & 3;
temp = dev->regs[1] & 0x03;
lpt1_remove();
switch (temp) {
case 0:
@@ -111,23 +112,59 @@ lpt1_handler(pc87310_t *dev)
}
static void
serial_handler(pc87310_t *dev, int uart)
serial_handler(pc87310_t *dev)
{
int temp;
/* bit 2: disable serial port 1
* bit 3: disable serial port 2
* bit 4: swap serial ports
uint8_t temp, temp2 = 0x00;
uint16_t base1 = 0x0000, base2 = 0x0000;
uint8_t irq1, irq2;
/* - Bit 2: Disable serial port 1;
* - Bit 3: Disable serial port 2;
* - Bit 4: Swap serial ports.
*/
temp = (dev->reg >> (2 + uart)) & 1;
temp = (dev->regs[1] >> 2) & 0x07;
// current serial port is enabled
if (!temp) {
// configure serial port as COM2
if (((dev->reg >> 4) & 1) ^ uart)
serial_setup(dev->uart[uart], COM2_ADDR, COM2_IRQ);
// configure serial port as COM1
else
serial_setup(dev->uart[uart], COM1_ADDR, COM1_IRQ);
/* - Bits 1, 0: 0, 0 = Normal (3F8 and 2F8);
* 0, 1 = 2E8 instead of 2F8;
* 1, 0 = 3E8 instead of 3F8 and 2E8 instead of 2F8;
* 1, 1 = 3E8 instead of 3F8.
*
* If we XOR bit 0 with bit 1, we get this:
* 0, 0 = Normal (3F8 and 2F8);
* 0, 1 = 2E8 instead of 2F8;
* 1, 0 = 3E8 instead of 3F8;
* 1, 1 = 3E8 instead of 3F8 and 2E8 instead of 2F8.
*
* Then they become simple toggle bits.
* Therefore, we do this for easier operation.
*/
if (dev->flags & FLAG_ALI) {
temp2 = dev->regs[0] & 0x03;
temp2 ^= ((temp2 & 0x02) >> 1);
}
serial_remove(dev->uart[0]);
serial_remove(dev->uart[1]);
if (!(temp & 0x01)) {
base1 = (temp & 0x04) ? COM2_ADDR : COM1_ADDR;
if ((base1 == COM1_ADDR) && (temp2 & 0x02))
base1 = 0x03e8;
else if ((base1 == COM2_ADDR) && (temp2 & 0x01))
base1 = 0x02e8;
irq1 = (temp & 0x04) ? COM2_IRQ : COM1_IRQ;
serial_setup(dev->uart[0], base1, irq1);
pc87310_log("UART 1 at %04X, IRQ %i\n", base1, irq1);
}
if (!(temp & 0x02)) {
base2 = (temp & 0x04) ? COM1_ADDR : COM2_ADDR;
if ((base2 == COM1_ADDR) && (temp2 & 0x02))
base2 = 0x03e8;
else if ((base2 == COM2_ADDR) && (temp2 & 0x01))
base2 = 0x02e8;
irq2 = (temp & 0x04) ? COM1_IRQ : COM2_IRQ;
serial_setup(dev->uart[1], base2, irq2);
pc87310_log("UART 2 at %04X, IRQ %i\n", base2, irq2);
}
}
@@ -136,61 +173,63 @@ pc87310_write(UNUSED(uint16_t port), uint8_t val, void *priv)
{
pc87310_t *dev = (pc87310_t *) priv;
uint8_t valxor;
uint8_t idx = (uint8_t) ((port & 0x0002) >> 1);
pc87310_log("[%04X:%08X] [W] %02X = %02X (%i)\n", CS, cpu_state.pc, port, val, dev->tries);
// second write to config register
if (dev->tries) {
valxor = val ^ dev->reg;
dev->tries = 0;
dev->reg = val;
// first write to config register
} else {
/* Second write to config register. */
valxor = val ^ dev->regs[idx];
dev->tries = 0;
dev->regs[idx] = val;
if (idx) {
/* Register, common to both PC87310 and ALi M5105. */
pc87310_log("SIO: Common register written %02X\n", val);
/* Reconfigure parallel port. */
if (valxor & 0x03)
/* Bits 1, 0: 1, 1 = Disable parallel port. */
lpt1_handler(dev);
/* Reconfigure serial ports. */
if (valxor & 0x1c)
serial_handler(dev);
/* Reconfigure IDE controller. */
if ((dev->flags & FLAG_IDE) && (valxor & 0x20)) {
pc87310_log("SIO: HDC disabled\n");
ide_pri_disable();
/* Bit 5: 1 = Disable IDE controller. */
if (!(val & 0x20)) {
pc87310_log("SIO: HDC enabled\n");
ide_set_base(0, 0x1f0);
ide_set_side(0, 0x3f6);
ide_pri_enable();
}
}
/* Reconfigure floppy disk controller. */
if (valxor & 0x40) {
pc87310_log("SIO: FDC disabled\n");
fdc_remove(dev->fdc);
/* Bit 6: 1 = Disable FDC. */
if (!(val & 0x40)) {
pc87310_log("SIO: FDC enabled\n");
fdc_set_base(dev->fdc, FDC_PRIMARY_ADDR);
}
}
} else {
/* ALi M5105 extension register. */
pc87310_log("SIO: M5105 extension register written %02X\n", val);
/* Reconfigure serial ports. */
if (valxor & 0x03)
serial_handler(dev);
}
} else
/* First write to config register. */
dev->tries++;
return;
}
pc87310_log("SIO: written %01X\n", val);
/* reconfigure parallel port */
if (valxor & 0x03) {
lpt1_remove();
/* bits 0-1: 11 disable parallel port */
if (!((val & 1) && (val & 2)))
lpt1_handler(dev);
}
/* reconfigure serial ports */
if (valxor & 0x1c) {
serial_remove(dev->uart[0]);
serial_remove(dev->uart[1]);
/* bit 2: 1 disable first serial port */
if (!(val & 4))
serial_handler(dev, 0);
/* bit 3: 1 disable second serial port */
if (!(val & 8))
serial_handler(dev, 1);
}
/* reconfigure IDE controller */
if (valxor & 0x20) {
pc87310_log("SIO: HDC disabled\n");
ide_pri_disable();
/* bit 5: 1 disable ide controller */
if (!(val & 0x20) && HAS_IDE_FUNCTIONALITY) {
pc87310_log("SIO: HDC enabled\n");
ide_set_base(0, 0x1f0);
ide_set_side(0, 0x3f6);
ide_pri_enable();
}
}
/* reconfigure floppy disk controller */
if (valxor & 0x40) {
pc87310_log("SIO: FDC disabled\n");
fdc_remove(dev->fdc);
/* bit 6: 1 disable fdc */
if (!(val & 0x40)) {
pc87310_log("SIO: FDC enabled\n");
fdc_set_base(dev->fdc, FDC_PRIMARY_ADDR);
}
}
return;
}
uint8_t
@@ -198,12 +237,13 @@ pc87310_read(UNUSED(uint16_t port), void *priv)
{
pc87310_t *dev = (pc87310_t *) priv;
uint8_t ret = 0xff;
uint8_t idx = (uint8_t) ((port & 0x0002) >> 1);
dev->tries = 0;
ret = dev->reg;
ret = dev->regs[idx];
pc87310_log("SIO: read %01X\n", ret);
pc87310_log("[%04X:%08X] [R] %02X = %02X\n", CS, cpu_state.pc, port, ret);
return ret;
}
@@ -211,22 +251,18 @@ pc87310_read(UNUSED(uint16_t port), void *priv)
void
pc87310_reset(pc87310_t *dev)
{
dev->reg = 0x0;
dev->tries = 0;
/*
0 = 360 rpm @ 500 kbps for 3.5"
1 = Default, 300 rpm @ 500, 300, 250, 1000 kbps for 3.5"
*/
lpt1_remove();
dev->regs[0] = 0x00;
dev->regs[1] = 0x00;
dev->tries = 0;
lpt1_handler(dev);
serial_remove(dev->uart[0]);
serial_remove(dev->uart[1]);
serial_handler(dev, 0);
serial_handler(dev, 1);
serial_handler(dev);
if (dev->flags & FLAG_IDE) {
ide_pri_disable();
ide_pri_enable();
}
fdc_reset(dev->fdc);
#if 0
ide_pri_enable();
#endif
}
static void
@@ -240,25 +276,28 @@ pc87310_close(void *priv)
static void *
pc87310_init(const device_t *info)
{
pc87310_t *dev = (pc87310_t *) malloc(sizeof(pc87310_t));
memset(dev, 0, sizeof(pc87310_t));
pc87310_t *dev = (pc87310_t *) calloc(1, sizeof(pc87310_t));
/* Avoid conflicting with machines that make no use of the PC87310 Internal IDE */
HAS_IDE_FUNCTIONALITY = info->local;
dev->flags = info->local;
dev->fdc = device_add(&fdc_at_nsc_device);
dev->uart[0] = device_add_inst(&ns16550_device, 1);
dev->uart[1] = device_add_inst(&ns16550_device, 2);
dev->uart[0] = device_add_inst(&ns16450_device, 1);
dev->uart[1] = device_add_inst(&ns16450_device, 2);
if (HAS_IDE_FUNCTIONALITY)
device_add(&ide_isa_device);
if (dev->flags & FLAG_IDE)
device_add((dev->flags & FLAG_ALI) ? &ide_vlb_device : &ide_isa_device);
pc87310_reset(dev);
io_sethandler(0x3f3, 0x0001,
pc87310_read, NULL, NULL, pc87310_write, NULL, NULL, dev);
if (dev->flags & FLAG_ALI)
io_sethandler(0x3f1, 0x0001,
pc87310_read, NULL, NULL, pc87310_write, NULL, NULL, dev);
return dev;
}
@@ -280,7 +319,21 @@ const device_t pc87310_ide_device = {
.name = "National Semiconductor PC87310 Super I/O with IDE functionality",
.internal_name = "pc87310_ide",
.flags = 0,
.local = 1,
.local = FLAG_IDE,
.init = pc87310_init,
.close = pc87310_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t ali5105_device = {
.name = "ALi M5105 Super I/O",
.internal_name = "ali5105",
.flags = 0,
.local = FLAG_ALI,
.init = pc87310_init,
.close = pc87310_close,
.reset = NULL,

View File

@@ -122,7 +122,7 @@ pc87311_write(uint16_t addr, uint8_t val, void *priv)
static uint8_t
pc87311_read(UNUSED(uint16_t addr), void *priv)
{
pc87311_t *dev = (pc87311_t *) priv;
const pc87311_t *dev = (pc87311_t *) priv;
return dev->regs[dev->index];
}

View File

@@ -143,7 +143,7 @@ prime3b_write(uint16_t addr, uint8_t val, void *priv)
static uint8_t
prime3b_read(UNUSED(uint16_t addr), void *priv)
{
prime3b_t *dev = (prime3b_t *) priv;
const prime3b_t *dev = (prime3b_t *) priv;
return dev->regs[dev->index];
}

View File

@@ -207,7 +207,7 @@ prime3c_write(uint16_t addr, uint8_t val, void *priv)
static uint8_t
prime3c_read(UNUSED(uint16_t addr), void *priv)
{
prime3c_t *dev = (prime3c_t *) priv;
const prime3c_t *dev = (prime3c_t *) priv;
return dev->regs[dev->index];
}

View File

@@ -18,6 +18,35 @@
* Copyright 2016-2021 Miran Grca.
* Copyright 2021 RichardG.
*/
/*
UMC UM8669F non-PnP register definitions
C0:
[7] Infrared half duplex
[4:3] LPT mode:
00 SPP
01 EPP
10 ECP
11 ECP + EPP
C1:
[7] Enable PnP access
[6:0] Always set regardless of PnP access enabled/disabled
C2:
[6:5] Potentially pin muxing mode: (names from AMI "IR group" setup option)
00 Reserved
01 A (no IDE)
10 B (no IDE)
11 C
[4:3] Infrared mode:
00 Reserved
01 HPSIR
10 ASKIR
11 Disabled
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
@@ -35,11 +64,15 @@
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/gameport.h>
#include <86box/sio.h>
#include <86box/hdc.h>
#include <86box/isapnp.h>
#include <86box/hdc_ide.h>
#include <86box/sio.h>
#include <86box/plat_unused.h>
/* This ROM was reconstructed out of many assumptions, some of which based on the IT8671F. */
/* Real chips don't have a PnP ROM and instead rely on the BIOS going in blind.
We create a fake ROM here (with values based on the IT8671F) to delegate
all the logical device register handling over to the ISAPnP subsystem. */
static uint8_t um8669f_pnp_rom[] = {
0x55, 0xa3, 0x86, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, /* UMC8669, dummy checksum (filled in by isapnp_add_card) */
0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */
@@ -61,7 +94,9 @@ static uint8_t um8669f_pnp_rom[] = {
0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */
0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */
0x15, 0x41, 0xd0, 0xff, 0xff, 0x00, /* logical device PNPFFFF (just a dummy to create a gap in LDNs) */
0x15, 0x41, 0xd0, 0x06, 0x00, 0x01, /* logical device PNP0600, can participate in boot */
0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */
0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */
0x15, 0x41, 0xd0, 0xb0, 0x2f, 0x01, /* logical device PNPB02F, can participate in boot */
0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */
@@ -87,7 +122,9 @@ static const isapnp_device_config_t um8669f_pnp_defaults[] = {
.io = { { .base = LPT1_ADDR }, },
.irq = { { .irq = LPT1_IRQ }, }
}, {
.activate = 0
.activate = 0,
.io = { { .base = 0x1f0 }, },
.irq = { { .irq = 14 }, }
}, {
.activate = 0,
.io = { { .base = 0x200 }, }
@@ -113,15 +150,14 @@ um8669f_log(const char *fmt, ...)
#endif
typedef struct um8669f_t {
int locked;
int cur_reg_108;
void *pnp_card;
isapnp_device_config_t *pnp_config[5];
uint8_t regs_108[256];
uint8_t locked;
uint8_t cur_reg;
void *pnp_card;
uint8_t regs[3];
fdc_t *fdc;
serial_t *uart[2];
uint8_t ide;
void *gameport;
} um8669f_t;
@@ -178,6 +214,22 @@ um8669f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *pri
break;
case 4:
if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED))
um8669f_log("UM8669F: IDE enabled at port %04X IRQ %d\n", config->io[0].base, config->irq[0].irq);
else
um8669f_log("UM8669F: IDE disabled\n");
if (dev->ide < IDE_BUS_MAX) {
config->io[1].base = config->io[0].base + 0x206; /* status port apparently fixed */
#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)
ide_pnp_config_changed(0, config, (void *) (int64_t) dev->ide);
#else
ide_pnp_config_changed(0, config, (void *) (int) dev->ide);
#endif
}
break;
case 5:
if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) {
um8669f_log("UM8669F: Game port enabled at port %04X\n", config->io[0].base);
@@ -186,6 +238,7 @@ um8669f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *pri
um8669f_log("UM8669F: Game port disabled\n");
gameport_remap(dev->gameport, 0);
}
break;
default:
break;
@@ -207,11 +260,11 @@ um8669f_write(uint16_t port, uint8_t val, void *priv)
if (val == 0x55)
dev->locked = 1;
else
dev->cur_reg_108 = val;
} else {
dev->regs_108[dev->cur_reg_108] = val;
dev->cur_reg = val;
} else if ((dev->cur_reg >= 0xc0) && (dev->cur_reg <= 0xc2)) {
dev->regs[dev->cur_reg & 3] = val;
if (dev->cur_reg_108 == 0xc1) {
if (dev->cur_reg == 0xc1) {
um8669f_log("UM8669F: ISAPnP %sabled\n", (val & 0x80) ? "en" : "dis");
isapnp_enable_card(dev->pnp_card, (val & 0x80) ? ISAPNP_CARD_FORCE_CONFIG : ISAPNP_CARD_DISABLE);
}
@@ -222,14 +275,14 @@ um8669f_write(uint16_t port, uint8_t val, void *priv)
uint8_t
um8669f_read(uint16_t port, void *priv)
{
um8669f_t *dev = (um8669f_t *) priv;
uint8_t ret = 0xff;
const um8669f_t *dev = (um8669f_t *) priv;
uint8_t ret = 0xff;
if (!dev->locked) {
if (port == 0x108)
ret = dev->cur_reg_108; /* ??? */
else
ret = dev->regs_108[dev->cur_reg_108];
ret = dev->cur_reg; /* ??? */
else if ((dev->cur_reg >= 0xc0) && (dev->cur_reg <= 0xc2))
ret = dev->regs[dev->cur_reg & 3];
}
um8669f_log("UM8669F: read(%04X) = %02X\n", port, ret);
@@ -250,6 +303,9 @@ um8669f_reset(um8669f_t *dev)
lpt1_remove();
if (dev->ide < IDE_BUS_MAX)
ide_remove_handlers(dev->ide);
isapnp_enable_card(dev->pnp_card, ISAPNP_CARD_DISABLE);
dev->locked = 1;
@@ -268,9 +324,9 @@ um8669f_close(void *priv)
}
static void *
um8669f_init(UNUSED(const device_t *info))
um8669f_init(const device_t *info)
{
um8669f_log("UM8669F: init()\n");
um8669f_log("UM8669F: init(%02X)\n", info->local);
um8669f_t *dev = (um8669f_t *) malloc(sizeof(um8669f_t));
memset(dev, 0, sizeof(um8669f_t));
@@ -284,6 +340,10 @@ um8669f_init(UNUSED(const device_t *info))
dev->uart[0] = device_add_inst(&ns16550_device, 1);
dev->uart[1] = device_add_inst(&ns16550_device, 2);
dev->ide = info->local;
if (dev->ide < IDE_BUS_MAX)
device_add(&ide_isa_device);
dev->gameport = gameport_add(&gameport_sio_device);
io_sethandler(0x0108, 0x0002,
@@ -298,6 +358,20 @@ const device_t um8669f_device = {
.name = "UMC UM8669F Super I/O",
.internal_name = "um8669f",
.flags = 0,
.local = 0xff,
.init = um8669f_init,
.close = um8669f_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t um8669f_ide_device = {
.name = "UMC UM8669F Super I/O (With IDE)",
.internal_name = "um8669f_ide",
.flags = 0,
.local = 0,
.init = um8669f_init,
.close = um8669f_close,
@@ -307,3 +381,17 @@ const device_t um8669f_device = {
.force_redraw = NULL,
.config = NULL
};
const device_t um8669f_ide_sec_device = {
.name = "UMC UM8669F Super I/O (With Secondary IDE)",
.internal_name = "um8669f_ide_sec",
.flags = 0,
.local = 1,
.init = um8669f_init,
.close = um8669f_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -374,6 +374,8 @@ w83787f_read(uint16_t port, void *priv)
static void
w83787f_reset(w83787f_t *dev)
{
uint16_t hefere = dev->reg_init & 0x0100;
lpt1_remove();
lpt1_init(LPT1_ADDR);
lpt1_irq(LPT1_IRQ);
@@ -410,7 +412,7 @@ w83787f_reset(w83787f_t *dev)
dev->regs[0x07] = 0xF5;
dev->regs[0x09] = dev->reg_init & 0xff;
dev->regs[0x0a] = 0x1F;
dev->regs[0x0c] = 0x2C;
dev->regs[0x0c] = 0x0C | (hefere >> 3);
dev->regs[0x0d] = 0xA3;
gameport_remap(dev->gameport, 0);
@@ -420,7 +422,7 @@ w83787f_reset(w83787f_t *dev)
w83787f_lpt_handler(dev);
dev->key = 0x89;
dev->key = 0x88 | (hefere >> 8);
w83787f_remap(dev);
@@ -456,17 +458,31 @@ w83787f_init(const device_t *info)
dev->ide_start = !!(info->local & 0x40);
dev->reg_init = info->local & 0x0f;
dev->reg_init = info->local & 0x010f;
w83787f_reset(dev);
return dev;
}
const device_t w83787f_88h_device = {
.name = "Winbond W83787F/IF Super I/O",
.internal_name = "w83787f",
.flags = 0,
.local = 0x0009,
.init = w83787f_init,
.close = w83787f_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t w83787f_device = {
.name = "Winbond W83787F/IF Super I/O",
.internal_name = "w83787f",
.flags = 0,
.local = 0x09,
.local = 0x0109,
.init = w83787f_init,
.close = w83787f_close,
.reset = NULL,
@@ -480,7 +496,7 @@ const device_t w83787f_ide_device = {
.name = "Winbond W83787F/IF Super I/O (With IDE)",
.internal_name = "w83787f_ide",
.flags = 0,
.local = 0x19,
.local = 0x0119,
.init = w83787f_init,
.close = w83787f_close,
.reset = NULL,
@@ -494,7 +510,7 @@ const device_t w83787f_ide_en_device = {
.name = "Winbond W83787F/IF Super I/O (With IDE Enabled)",
.internal_name = "w83787f_ide_en",
.flags = 0,
.local = 0x59,
.local = 0x0159,
.init = w83787f_init,
.close = w83787f_close,
.reset = NULL,
@@ -508,7 +524,7 @@ const device_t w83787f_ide_sec_device = {
.name = "Winbond W83787F/IF Super I/O (With Secondary IDE)",
.internal_name = "w83787f_ide_sec",
.flags = 0,
.local = 0x39,
.local = 0x0139,
.init = w83787f_init,
.close = w83787f_close,
.reset = NULL,