clang-format in src/sio/

This commit is contained in:
Jasmine Iwanek
2022-09-18 17:17:00 -04:00
parent 645732b7bf
commit 99893d1175
24 changed files with 4626 additions and 4804 deletions

View File

@@ -34,25 +34,22 @@
#include <86box/fdc.h> #include <86box/fdc.h>
#include <86box/sio.h> #include <86box/sio.h>
typedef struct { typedef struct {
uint8_t cur_reg, has_ide, uint8_t cur_reg, has_ide,
regs[81]; regs[81];
uint16_t base_address; uint16_t base_address;
fdc_t * fdc; fdc_t *fdc;
serial_t * uart[2]; serial_t *uart[2];
} i82091aa_t; } i82091aa_t;
static void static void
fdc_handler(i82091aa_t *dev) fdc_handler(i82091aa_t *dev)
{ {
fdc_remove(dev->fdc); fdc_remove(dev->fdc);
if (dev->regs[0x10] & 0x01) if (dev->regs[0x10] & 0x01)
fdc_set_base(dev->fdc, (dev->regs[0x10] & 0x02) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); fdc_set_base(dev->fdc, (dev->regs[0x10] & 0x02) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
} }
static void static void
lpt1_handler(i82091aa_t *dev) lpt1_handler(i82091aa_t *dev)
{ {
@@ -61,67 +58,65 @@ lpt1_handler(i82091aa_t *dev)
lpt1_remove(); lpt1_remove();
switch ((dev->regs[0x20] >> 1) & 0x03) { switch ((dev->regs[0x20] >> 1) & 0x03) {
case 0x00: case 0x00:
lpt_port = LPT1_ADDR; lpt_port = LPT1_ADDR;
break; break;
case 1: case 1:
lpt_port = LPT2_ADDR; lpt_port = LPT2_ADDR;
break; break;
case 2: case 2:
lpt_port = LPT_MDA_ADDR; lpt_port = LPT_MDA_ADDR;
break; break;
case 3: case 3:
lpt_port = 0x000; lpt_port = 0x000;
break; break;
} }
if ((dev->regs[0x20] & 0x01) && lpt_port) if ((dev->regs[0x20] & 0x01) && lpt_port)
lpt1_init(lpt_port); lpt1_init(lpt_port);
lpt1_irq((dev->regs[0x20] & 0x08) ? LPT1_IRQ : LPT2_IRQ); lpt1_irq((dev->regs[0x20] & 0x08) ? LPT1_IRQ : LPT2_IRQ);
} }
static void static void
serial_handler(i82091aa_t *dev, int uart) serial_handler(i82091aa_t *dev, int uart)
{ {
int reg = (0x30 + (uart << 4)); int reg = (0x30 + (uart << 4));
uint16_t uart_port = COM1_ADDR; uint16_t uart_port = COM1_ADDR;
serial_remove(dev->uart[uart]); serial_remove(dev->uart[uart]);
switch ((dev->regs[reg] >> 1) & 0x07) { switch ((dev->regs[reg] >> 1) & 0x07) {
case 0x00: case 0x00:
uart_port = COM1_ADDR; uart_port = COM1_ADDR;
break; break;
case 0x01: case 0x01:
uart_port = COM2_ADDR; uart_port = COM2_ADDR;
break; break;
case 0x02: case 0x02:
uart_port = 0x220; uart_port = 0x220;
break; break;
case 0x03: case 0x03:
uart_port = 0x228; uart_port = 0x228;
break; break;
case 0x04: case 0x04:
uart_port = 0x238; uart_port = 0x238;
break; break;
case 0x05: case 0x05:
uart_port = COM4_ADDR; uart_port = COM4_ADDR;
break; break;
case 0x06: case 0x06:
uart_port = 0x338; uart_port = 0x338;
break; break;
case 0x07: case 0x07:
uart_port = COM3_ADDR; uart_port = COM3_ADDR;
break; break;
} }
if (dev->regs[reg] & 0x01) if (dev->regs[reg] & 0x01)
serial_setup(dev->uart[uart], uart_port, (dev->regs[reg] & 0x10) ? COM1_IRQ : COM2_IRQ); serial_setup(dev->uart[uart], uart_port, (dev->regs[reg] & 0x10) ? COM1_IRQ : COM2_IRQ);
} }
static void static void
ide_handler(i82091aa_t *dev) ide_handler(i82091aa_t *dev)
{ {
@@ -131,91 +126,90 @@ ide_handler(i82091aa_t *dev)
ide_set_base(board, (dev->regs[0x50] & 0x02) ? 0x170 : 0x1f0); ide_set_base(board, (dev->regs[0x50] & 0x02) ? 0x170 : 0x1f0);
ide_set_side(board, (dev->regs[0x50] & 0x02) ? 0x376 : 0x3f6); ide_set_side(board, (dev->regs[0x50] & 0x02) ? 0x376 : 0x3f6);
if (dev->regs[0x50] & 0x01) if (dev->regs[0x50] & 0x01)
ide_set_handlers(board); ide_set_handlers(board);
} }
static void static void
i82091aa_write(uint16_t port, uint8_t val, void *priv) i82091aa_write(uint16_t port, uint8_t val, void *priv)
{ {
i82091aa_t *dev = (i82091aa_t *) priv; i82091aa_t *dev = (i82091aa_t *) priv;
uint8_t index, valxor; uint8_t index, valxor;
uint8_t uart = (dev->cur_reg >> 4) - 0x03; uint8_t uart = (dev->cur_reg >> 4) - 0x03;
uint8_t *reg = &(dev->regs[dev->cur_reg]); uint8_t *reg = &(dev->regs[dev->cur_reg]);
index = (port & 1) ? 0 : 1; index = (port & 1) ? 0 : 1;
if (index) { if (index) {
dev->cur_reg = val; dev->cur_reg = val;
return; return;
} else if (dev->cur_reg < 0x51) } else if (dev->cur_reg < 0x51)
valxor = val ^ *reg; valxor = val ^ *reg;
else if (dev->cur_reg >= 0x51) else if (dev->cur_reg >= 0x51)
return; return;
switch(dev->cur_reg) { switch (dev->cur_reg) {
case 0x02: case 0x02:
*reg = (*reg & 0x78) | (val & 0x01); *reg = (*reg & 0x78) | (val & 0x01);
break; break;
case 0x03: case 0x03:
*reg = (val & 0xf8); *reg = (val & 0xf8);
break; break;
case 0x10: case 0x10:
*reg = (val & 0x83); *reg = (val & 0x83);
if (valxor & 0x03) if (valxor & 0x03)
fdc_handler(dev); fdc_handler(dev);
break; break;
case 0x11: case 0x11:
*reg = (val & 0x0f); *reg = (val & 0x0f);
if ((valxor & 0x04) && (val & 0x04)) if ((valxor & 0x04) && (val & 0x04))
fdc_reset(dev->fdc); fdc_reset(dev->fdc);
break; break;
case 0x20: case 0x20:
*reg = (val & 0xef); *reg = (val & 0xef);
if (valxor & 0x07) if (valxor & 0x07)
lpt1_handler(dev); lpt1_handler(dev);
break; break;
case 0x21: case 0x21:
*reg = (val & 0x2f); *reg = (val & 0x2f);
break; break;
case 0x30: case 0x40: case 0x30:
*reg = (val & 0x9f); case 0x40:
if (valxor & 0x1f) *reg = (val & 0x9f);
serial_handler(dev, uart); if (valxor & 0x1f)
if (valxor & 0x80) serial_handler(dev, uart);
serial_set_clock_src(dev->uart[uart], (val & 0x80) ? 2000000.0 : (24000000.0 / 13.0)); if (valxor & 0x80)
break; serial_set_clock_src(dev->uart[uart], (val & 0x80) ? 2000000.0 : (24000000.0 / 13.0));
case 0x31: case 0x41: break;
*reg = (val & 0x1f); case 0x31:
if ((valxor & 0x04) && (val & 0x04)) case 0x41:
serial_reset_port(dev->uart[uart]); *reg = (val & 0x1f);
break; if ((valxor & 0x04) && (val & 0x04))
case 0x50: serial_reset_port(dev->uart[uart]);
*reg = (val & 0x07); break;
if (dev->has_ide && (valxor & 0x03)) case 0x50:
ide_handler(dev); *reg = (val & 0x07);
break; if (dev->has_ide && (valxor & 0x03))
ide_handler(dev);
break;
} }
} }
uint8_t uint8_t
i82091aa_read(uint16_t port, void *priv) i82091aa_read(uint16_t port, void *priv)
{ {
i82091aa_t *dev = (i82091aa_t *) priv; i82091aa_t *dev = (i82091aa_t *) priv;
uint8_t ret = 0xff, index; uint8_t ret = 0xff, index;
index = (port & 1) ? 0 : 1; index = (port & 1) ? 0 : 1;
if (index) if (index)
ret = dev->cur_reg; ret = dev->cur_reg;
else if (dev->cur_reg < 0x51) else if (dev->cur_reg < 0x51)
ret = dev->regs[dev->cur_reg]; ret = dev->regs[dev->cur_reg];
return ret; return ret;
} }
void void
i82091aa_reset(i82091aa_t *dev) i82091aa_reset(i82091aa_t *dev)
{ {
@@ -224,7 +218,7 @@ i82091aa_reset(i82091aa_t *dev)
dev->regs[0x00] = 0xa0; dev->regs[0x00] = 0xa0;
dev->regs[0x10] = 0x01; dev->regs[0x10] = 0x01;
dev->regs[0x31] = dev->regs[0x41] = 0x02; dev->regs[0x31] = dev->regs[0x41] = 0x02;
dev->regs[0x50] = 0x01; dev->regs[0x50] = 0x01;
fdc_reset(dev->fdc); fdc_reset(dev->fdc);
@@ -236,10 +230,9 @@ i82091aa_reset(i82091aa_t *dev)
serial_set_clock_src(dev->uart[1], (24000000.0 / 13.0)); serial_set_clock_src(dev->uart[1], (24000000.0 / 13.0));
if (dev->has_ide) if (dev->has_ide)
ide_handler(dev); ide_handler(dev);
} }
static void static void
i82091aa_close(void *priv) i82091aa_close(void *priv)
{ {
@@ -248,7 +241,6 @@ i82091aa_close(void *priv)
free(dev); free(dev);
} }
static void * static void *
i82091aa_init(const device_t *info) i82091aa_init(const device_t *info)
{ {
@@ -267,68 +259,68 @@ i82091aa_init(const device_t *info)
dev->regs[0x02] = info->local & 0xff; dev->regs[0x02] = info->local & 0xff;
if (info->local & 0x08) if (info->local & 0x08)
dev->base_address = (info->local & 0x100) ? 0x0398 : 0x0024; dev->base_address = (info->local & 0x100) ? 0x0398 : 0x0024;
else else
dev->base_address = (info->local & 0x100) ? 0x026e : 0x0022; dev->base_address = (info->local & 0x100) ? 0x026e : 0x0022;
io_sethandler(dev->base_address, 0x0002, io_sethandler(dev->base_address, 0x0002,
i82091aa_read, NULL, NULL, i82091aa_write, NULL, NULL, dev); i82091aa_read, NULL, NULL, i82091aa_write, NULL, NULL, dev);
return dev; return dev;
} }
const device_t i82091aa_device = { const device_t i82091aa_device = {
.name = "Intel 82091AA Super I/O", .name = "Intel 82091AA Super I/O",
.internal_name = "i82091aa", .internal_name = "i82091aa",
.flags = 0, .flags = 0,
.local = 0x40, .local = 0x40,
.init = i82091aa_init, .init = i82091aa_init,
.close = i82091aa_close, .close = i82091aa_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t i82091aa_398_device = { const device_t i82091aa_398_device = {
.name = "Intel 82091AA Super I/O (Port 398h)", .name = "Intel 82091AA Super I/O (Port 398h)",
.internal_name = "i82091aa_398", .internal_name = "i82091aa_398",
.flags = 0, .flags = 0,
.local = 0x148, .local = 0x148,
.init = i82091aa_init, .init = i82091aa_init,
.close = i82091aa_close, .close = i82091aa_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t i82091aa_ide_pri_device = { const device_t i82091aa_ide_pri_device = {
.name = "Intel 82091AA Super I/O (With Primary IDE)", .name = "Intel 82091AA Super I/O (With Primary IDE)",
.internal_name = "i82091aa_ide", .internal_name = "i82091aa_ide",
.flags = 0, .flags = 0,
.local = 0x240, .local = 0x240,
.init = i82091aa_init, .init = i82091aa_init,
.close = i82091aa_close, .close = i82091aa_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t i82091aa_ide_device = { const device_t i82091aa_ide_device = {
.name = "Intel 82091AA Super I/O (With IDE)", .name = "Intel 82091AA Super I/O (With IDE)",
.internal_name = "i82091aa_ide", .internal_name = "i82091aa_ide",
.flags = 0, .flags = 0,
.local = 0x440, .local = 0x440,
.init = i82091aa_init, .init = i82091aa_init,
.close = i82091aa_close, .close = i82091aa_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

View File

@@ -32,86 +32,84 @@
#include <86box/fdc.h> #include <86box/fdc.h>
#include <86box/sio.h> #include <86box/sio.h>
typedef struct acc3221_t typedef struct acc3221_t {
{ int reg_idx;
int reg_idx; uint8_t regs[256];
uint8_t regs[256]; fdc_t *fdc;
fdc_t * fdc; serial_t *uart[2];
serial_t * uart[2];
} acc3221_t; } acc3221_t;
/* Configuration Register Index, BE (R/W): /* Configuration Register Index, BE (R/W):
Bit Function Bit Function
7 PIRQ 5 polarity. 7 PIRQ 5 polarity.
1 = active high, default 1 = active high, default
0 = active low 0 = active low
6 PIRQ 7 polarity. 6 PIRQ 7 polarity.
1 = active high, default 1 = active high, default
0 = active low 0 = active low
5 Primary Parallel Port Extended Mode 5 Primary Parallel Port Extended Mode
0 = Compatible mode, default 0 = Compatible mode, default
1 = Extended/Bidirectional mode. 1 = Extended/Bidirectional mode.
4 Primary Parallel Port Disable 4 Primary Parallel Port Disable
1 = Disable, 0 = Enable 1 = Disable, 0 = Enable
Power Up Default is set by pin 120 Power Up Default is set by pin 120
(3221-DP)/pin 96 (3221-SP) (3221-DP)/pin 96 (3221-SP)
3 Primary Parallel Port Power Down 3 Primary Parallel Port Power Down
1 = Power Down, default = 0 1 = Power Down, default = 0
2** Secondary Parallel Port Extended 2** Secondary Parallel Port Extended
Mode Mode
0 = Compatible mode, default 0 = Compatible mode, default
1 = Extended/Bidirectional mode. 1 = Extended/Bidirectional mode.
1** Secondary Parallel Port Disable 1** Secondary Parallel Port Disable
1 = Disable, 0 = Enable 1 = Disable, 0 = Enable
Power Up Default is set by pin 77 Power Up Default is set by pin 77
(3221-DP) (3221-DP)
0** Secondary Parallel Port Power Down 0** Secondary Parallel Port Power Down
1 = Power Down 1 = Power Down
0 = Enable, default 0 = Enable, default
Note: Power Up not applicable to 3221-EP. */ Note: Power Up not applicable to 3221-EP. */
#define REG_BE_LPT1_DISABLE (3 << 3) #define REG_BE_LPT1_DISABLE (3 << 3)
#define REG_BE_LPT2_DISABLE (3 << 0) /* 3221-DP/EP only */ #define REG_BE_LPT2_DISABLE (3 << 0) /* 3221-DP/EP only */
/* Configuration Register Index, BF (R/W): /* Configuration Register Index, BF (R/W):
Bit Function Bit Function
7-0 The 8 most significant address bits of 7-0 The 8 most significant address bits of
the primary parallel port (A9-2) the primary parallel port (A9-2)
Default 9E (LPT2, at 278-27B) */ Default 9E (LPT2, at 278-27B) */
/* Configuration Register Index, DA (R/W)**: /* Configuration Register Index, DA (R/W)**:
Bit Function Bit Function
7-0 The 8 most significant address bits of 7-0 The 8 most significant address bits of
the secondary parallel port (A9-2) the secondary parallel port (A9-2)
Default DE (LPT1, at 378-37B) */ Default DE (LPT1, at 378-37B) */
/* Configuration Register Index, DB (R/W): /* Configuration Register Index, DB (R/W):
Bit Function Bit Function
7 SIRQ4 polarity. 7 SIRQ4 polarity.
1 = active high; default 1 = active high; default
0 = active low 0 = active low
6 SIRQ3 polarity. 6 SIRQ3 polarity.
1 = active high; default 1 = active high; default
0 = active low 0 = active low
5 SXTAL clock off. 1 = SCLK off, 5 SXTAL clock off. 1 = SCLK off,
0 = SCKL on, default 0 = SCKL on, default
4 Primary serial port disable 4 Primary serial port disable
1 = Disable, 0 = Enable 1 = Disable, 0 = Enable
Power Up default is set by pin 116 Power Up default is set by pin 116
(3221-DP)/pin 93 (3221-SP) (3221-DP)/pin 93 (3221-SP)
3 Primary serial port power down 3 Primary serial port power down
1 = Power down, 0 = Enable 1 = Power down, 0 = Enable
Power Up default is set by pin 116 Power Up default is set by pin 116
(3221-DP)/pin 93 (3221-SP) (3221-DP)/pin 93 (3221-SP)
2 Reserved 2 Reserved
1 Secondary serial port disable 1 Secondary serial port disable
1 = Disable, 0 = Enable 1 = Disable, 0 = Enable
Power Up default is set by pin 121 Power Up default is set by pin 121
(3221-DP)/pin 97 (3221-SP) (3221-DP)/pin 97 (3221-SP)
0 Secondary serial port power down 0 Secondary serial port power down
1 = Power down, 0 = Enable 1 = Power down, 0 = Enable
Power Up default is set by pin 121 Power Up default is set by pin 121
(3221-DP)/pin 97 (3221-SP) (3221-DP)/pin 97 (3221-SP)
Note: Power Up not applicable to 3221-EP. */ Note: Power Up not applicable to 3221-EP. */
#define REG_DB_SERIAL1_DISABLE (3 << 3) #define REG_DB_SERIAL1_DISABLE (3 << 3)
#define REG_DB_SERIAL2_DISABLE (3 << 0) #define REG_DB_SERIAL2_DISABLE (3 << 0)
@@ -119,56 +117,56 @@ typedef struct acc3221_t
/* Configuration Register Index, DC (R/W): /* Configuration Register Index, DC (R/W):
Bit Function Bit Function
7-1 The MSB of the Primary Serial Port 7-1 The MSB of the Primary Serial Port
Address (bits A9-3). Address (bits A9-3).
Default = 7F (COM1, at 3F8-3FF). Default = 7F (COM1, at 3F8-3FF).
0 When this bit is set to 1, bit A2 of 0 When this bit is set to 1, bit A2 of
primary parallel port is decoded. primary parallel port is decoded.
Default is 0. */ Default is 0. */
/* Configuration Register Index, DD (R/W): /* Configuration Register Index, DD (R/W):
Bit Function Bit Function
7-1 The MSB of the Secondary Serial Port 7-1 The MSB of the Secondary Serial Port
Address (bits A9-3). Address (bits A9-3).
Default = 5F (COM2, at 2F8-2FF). Default = 5F (COM2, at 2F8-2FF).
0** When this bit is set to 1, bit A2 of 0** When this bit is set to 1, bit A2 of
secondary parallel port is decoded. secondary parallel port is decoded.
Default is 0. */ Default is 0. */
/* Configuration Register Index, DE (R/W): /* Configuration Register Index, DE (R/W):
Bit Function Bit Function
7-6 SIRQ3 source 7-6 SIRQ3 source
b7 b6 b7 b6
0 0 Disabled, tri-stated 0 0 Disabled, tri-stated
0 1 Disabled, tri-stated** 0 1 Disabled, tri-stated**
1 0 Primary serial port 1 0 Primary serial port
1 1 Secondary serial port, 1 1 Secondary serial port,
default default
5-4 SIRQ4 source 5-4 SIRQ4 source
b5 b4 b5 b4
0 0 Disabled, tri-stated 0 0 Disabled, tri-stated
0 1 Disabled, tri-stated** 0 1 Disabled, tri-stated**
1 0 Primary serial port, 1 0 Primary serial port,
default default
1 1 Secondary serial port 1 1 Secondary serial port
3-2** PIRQ7 source 3-2** PIRQ7 source
b3 b2 b3 b2
0 0 Diabled, tri-stated, 0 0 Diabled, tri-stated,
default default
0 1 Primary serial port 0 1 Primary serial port
1 0 Primary parallel port 1 0 Primary parallel port
1 1 Secondary parallel 1 1 Secondary parallel
port port
Note: Bits 3-2 are reserved in 3221-SP. Note: Bits 3-2 are reserved in 3221-SP.
1-0 PIRQ5 source 1-0 PIRQ5 source
b1 b0 b1 b0
0 0 Disabled, tri-stated 0 0 Disabled, tri-stated
0 1 Secondary serial port 0 1 Secondary serial port
1 0 Primary parallel port, 1 0 Primary parallel port,
default default
1 1 Secondary parallel 1 1 Secondary parallel
port** */ port** */
#define REG_DE_SIRQ3_SOURCE (3 << 6) #define REG_DE_SIRQ3_SOURCE (3 << 6)
#define REG_DE_SIRQ3_SERIAL1 (1 << 6) #define REG_DE_SIRQ3_SERIAL1 (1 << 6)
#define REG_DE_SIRQ3_SERIAL2 (3 << 6) #define REG_DE_SIRQ3_SERIAL2 (3 << 6)
@@ -188,29 +186,29 @@ typedef struct acc3221_t
Bit Function Bit Function
7-6 Reserved 7-6 Reserved
5 RTC interface disable 5 RTC interface disable
1 = /RTCCS disabled 1 = /RTCCS disabled
0 = /RTCCS enabled, default 0 = /RTCCS enabled, default
4 Disable Modem Select 4 Disable Modem Select
1 = Moden CS disabled, default 1 = Moden CS disabled, default
0 = Modem CS enabled 0 = Modem CS enabled
3-2 3-2
b3 b2 b3 b2
1 1 Reserved 1 1 Reserved
1 0 Modem port address 1 0 Modem port address
= 3E8-3EF (default) = 3E8-3EF (default)
0 1 Modem port address: 0 1 Modem port address:
2F8-2FF 2F8-2FF
0 0 Modem port address: 0 0 Modem port address:
3F8-3FF 3F8-3FF
1-0 1-0
b1 b0 b1 b0
1 1 Reserved 1 1 Reserved
1 0 Mode 2, EISA Mode 1 0 Mode 2, EISA Mode
0 1 Mode 1, AT BUS, 0 1 Mode 1, AT BUS,
0 0 Mode 0, Two parallel 0 0 Mode 0, Two parallel
ports, default */ ports, default */
/* Configuration Register Index, FA (R/W)**: /* Configuration Register Index, FA (R/W)**:
Bit Function Bit Function
@@ -227,90 +225,88 @@ typedef struct acc3221_t
Bit Function Bit Function
7 Reserved 7 Reserved
6** 0/2 EXG (Read Only) 6** 0/2 EXG (Read Only)
In mode 1 and mode 2 In mode 1 and mode 2
operation, when the third operation, when the third
floppy drive is installed, pin floppy drive is installed, pin
EXTFDD should be pulled EXTFDD should be pulled
high to enable the third floppy high to enable the third floppy
drive or be pulled low to drive or be pulled low to
disable the third floppy drive. disable the third floppy drive.
1 = Third floppy drive enabled 1 = Third floppy drive enabled
0 = Third floppy drive disabled 0 = Third floppy drive disabled
5** EXTFDD (Read Only) 5** EXTFDD (Read Only)
In mode 1 and mode 2 In mode 1 and mode 2
operation, when the third operation, when the third
floppy drive is installed and floppy drive is installed and
pin 0/2 EXG is pulled high, pin 0/2 EXG is pulled high,
the third floppy drive becomes the third floppy drive becomes
the bootable drive (drive 0). the bootable drive (drive 0).
When pi 0/2 EXG is pulled low, When pi 0/2 EXG is pulled low,
the third floppy drive acts as the third floppy drive acts as
drive 2. drive 2.
1 = Third floppy drive as drive 0 (bootable) 1 = Third floppy drive as drive 0 (bootable)
0 = Third floppy drive as drive 2 0 = Third floppy drive as drive 2
4** MS 4** MS
In mode 1 and mode 2, t his bit is to In mode 1 and mode 2, t his bit is to
control the output pin MS to support a control the output pin MS to support a
special 3 1/2", 1.2M drive. When this special 3 1/2", 1.2M drive. When this
bit is set to high (1), the MS pin sends bit is set to high (1), the MS pin sends
a low signal. When this bit is set to a low signal. When this bit is set to
low (0), the MS pin sends a high low (0), the MS pin sends a high
signal to support a 3 1/2", 1.2M drive. signal to support a 3 1/2", 1.2M drive.
3 FDC, Clock disable 3 FDC, Clock disable
0 = enable, default 0 = enable, default
1 = disable 1 = disable
2 Reserved 2 Reserved
1 FDC disable 1 FDC disable
0 = enable, 1= disable 0 = enable, 1= disable
Power Upd efault set by pin 117 (3221- Power Upd efault set by pin 117 (3221-
DP)/pin 94 (3221-SP) DP)/pin 94 (3221-SP)
0 FDC address 0 FDC address
0 = Primary, default 0 = Primary, default
1 = Secondary 1 = Secondary
Note: Bits 6-4 are reserved in 3221-SP. */ Note: Bits 6-4 are reserved in 3221-SP. */
#define REG_FB_FDC_DISABLE (1 << 1) #define REG_FB_FDC_DISABLE (1 << 1)
/* Configuration Register Index, FB (R/W)**: /* Configuration Register Index, FB (R/W)**:
Bit Function Bit Function
7** Disable general chip select 1 7** Disable general chip select 1
1 = disable, default 1 = disable, default
0 = enable 0 = enable
6** Disable general chip select 2 6** Disable general chip select 2
1 = disable, default 1 = disable, default
0 = enable 0 = enable
5** Enable SA2 decoding for general chip 5** Enable SA2 decoding for general chip
select 1 select 1
1 = enable 1 = enable
0 = disable, default 0 = disable, default
4** Enable SA2 decoding for general chip 4** Enable SA2 decoding for general chip
select 2 select 2
1 = enable 1 = enable
0 = disable, default 0 = disable, default
3 Reserved 3 Reserved
2 IDE XT selected 2 IDE XT selected
0 = IDE AT interface, default 0 = IDE AT interface, default
1 = IDE XT interface 1 = IDE XT interface
1 IDE disable, 1 = IDE disable 1 IDE disable, 1 = IDE disable
0 = IDE enable 0 = IDE enable
Power Up default set by pin 13 (3221- Power Up default set by pin 13 (3221-
DP)/pin 13 (3221-SP) DP)/pin 13 (3221-SP)
0 Secondary IDE 0 Secondary IDE
1 = secondary 1 = secondary
0 = primary, default 0 = primary, default
Note: Bits 6-4 are reserved in 3221-SP. */ Note: Bits 6-4 are reserved in 3221-SP. */
#define REG_FE_IDE_DISABLE (1 << 1) #define REG_FE_IDE_DISABLE (1 << 1)
static void static void
acc3221_lpt_handle(acc3221_t *dev) acc3221_lpt_handle(acc3221_t *dev)
{ {
lpt1_remove(); lpt1_remove();
if (!(dev->regs[0xbe] & REG_BE_LPT1_DISABLE)) if (!(dev->regs[0xbe] & REG_BE_LPT1_DISABLE))
lpt1_init(dev->regs[0xbf] << 2); lpt1_init(dev->regs[0xbf] << 2);
} }
static void static void
acc3221_serial1_handler(acc3221_t *dev) acc3221_serial1_handler(acc3221_t *dev)
{ {
@@ -319,16 +315,15 @@ acc3221_serial1_handler(acc3221_t *dev)
serial_remove(dev->uart[0]); serial_remove(dev->uart[0]);
if (!(dev->regs[0xdb] & REG_DB_SERIAL1_DISABLE)) { if (!(dev->regs[0xdb] & REG_DB_SERIAL1_DISABLE)) {
com_addr = ((dev->regs[0xdc] & 0xfe) << 2); com_addr = ((dev->regs[0xdc] & 0xfe) << 2);
if ((dev->regs[0xde] & REG_DE_SIRQ3_SOURCE) == REG_DE_SIRQ3_SERIAL1) if ((dev->regs[0xde] & REG_DE_SIRQ3_SOURCE) == REG_DE_SIRQ3_SERIAL1)
serial_setup(dev->uart[0], com_addr, 3); serial_setup(dev->uart[0], com_addr, 3);
else if ((dev->regs[0xde] & REG_DE_SIRQ4_SOURCE) == REG_DE_SIRQ4_SERIAL1) else if ((dev->regs[0xde] & REG_DE_SIRQ4_SOURCE) == REG_DE_SIRQ4_SERIAL1)
serial_setup(dev->uart[0], com_addr, 4); serial_setup(dev->uart[0], com_addr, 4);
} }
} }
static void static void
acc3221_serial2_handler(acc3221_t *dev) acc3221_serial2_handler(acc3221_t *dev)
{ {
@@ -337,100 +332,97 @@ acc3221_serial2_handler(acc3221_t *dev)
serial_remove(dev->uart[1]); serial_remove(dev->uart[1]);
if (!(dev->regs[0xdb] & REG_DB_SERIAL2_DISABLE)) { if (!(dev->regs[0xdb] & REG_DB_SERIAL2_DISABLE)) {
com_addr = ((dev->regs[0xdd] & 0xfe) << 2); com_addr = ((dev->regs[0xdd] & 0xfe) << 2);
if ((dev->regs[0xde] & REG_DE_SIRQ3_SOURCE) == REG_DE_SIRQ3_SERIAL2) if ((dev->regs[0xde] & REG_DE_SIRQ3_SOURCE) == REG_DE_SIRQ3_SERIAL2)
serial_setup(dev->uart[1], com_addr, 3); serial_setup(dev->uart[1], com_addr, 3);
else if ((dev->regs[0xde] & REG_DE_SIRQ4_SOURCE) == REG_DE_SIRQ4_SERIAL2) else if ((dev->regs[0xde] & REG_DE_SIRQ4_SOURCE) == REG_DE_SIRQ4_SERIAL2)
serial_setup(dev->uart[1], com_addr, 4); serial_setup(dev->uart[1], com_addr, 4);
else if ((dev->regs[0xde] & REG_DE_PIRQ5_SOURCE) == REG_DE_PIRQ5_SERIAL2) else if ((dev->regs[0xde] & REG_DE_PIRQ5_SOURCE) == REG_DE_PIRQ5_SERIAL2)
serial_setup(dev->uart[1], com_addr, 5); serial_setup(dev->uart[1], com_addr, 5);
} }
} }
static void static void
acc3221_write(uint16_t addr, uint8_t val, void *p) acc3221_write(uint16_t addr, uint8_t val, void *p)
{ {
acc3221_t *dev = (acc3221_t *)p; acc3221_t *dev = (acc3221_t *) p;
uint8_t old; uint8_t old;
if (!(addr & 1)) if (!(addr & 1))
dev->reg_idx = val; dev->reg_idx = val;
else { else {
old = dev->regs[dev->reg_idx]; old = dev->regs[dev->reg_idx];
dev->regs[dev->reg_idx] = val; dev->regs[dev->reg_idx] = val;
switch (dev->reg_idx) { switch (dev->reg_idx) {
case 0xbe: case 0xbe:
if ((old ^ val) & REG_BE_LPT1_DISABLE) if ((old ^ val) & REG_BE_LPT1_DISABLE)
acc3221_lpt_handle(dev); acc3221_lpt_handle(dev);
break; break;
case 0xbf: case 0xbf:
if (old != val) if (old != val)
acc3221_lpt_handle(dev); acc3221_lpt_handle(dev);
break; break;
case 0xdb: case 0xdb:
if ((old ^ val) & REG_DB_SERIAL2_DISABLE) if ((old ^ val) & REG_DB_SERIAL2_DISABLE)
acc3221_serial2_handler(dev); acc3221_serial2_handler(dev);
if ((old ^ val) & REG_DB_SERIAL1_DISABLE) if ((old ^ val) & REG_DB_SERIAL1_DISABLE)
acc3221_serial1_handler(dev); acc3221_serial1_handler(dev);
break; break;
case 0xdc: case 0xdc:
if (old != val) if (old != val)
acc3221_serial1_handler(dev); acc3221_serial1_handler(dev);
break; break;
case 0xdd: case 0xdd:
if (old != val) if (old != val)
acc3221_serial2_handler(dev); acc3221_serial2_handler(dev);
break; break;
case 0xde: case 0xde:
if ((old ^ val) & (REG_DE_SIRQ3_SOURCE | REG_DE_SIRQ4_SOURCE)) { if ((old ^ val) & (REG_DE_SIRQ3_SOURCE | REG_DE_SIRQ4_SOURCE)) {
acc3221_serial2_handler(dev); acc3221_serial2_handler(dev);
acc3221_serial1_handler(dev); acc3221_serial1_handler(dev);
} }
break; break;
case 0xfb: case 0xfb:
if ((old ^ val) & REG_FB_FDC_DISABLE) { if ((old ^ val) & REG_FB_FDC_DISABLE) {
fdc_remove(dev->fdc); fdc_remove(dev->fdc);
if (!(dev->regs[0xfb] & REG_FB_FDC_DISABLE)) if (!(dev->regs[0xfb] & REG_FB_FDC_DISABLE))
fdc_set_base(dev->fdc, FDC_PRIMARY_ADDR); fdc_set_base(dev->fdc, FDC_PRIMARY_ADDR);
} }
break; break;
case 0xfe: case 0xfe:
if ((old ^ val) & REG_FE_IDE_DISABLE) { if ((old ^ val) & REG_FE_IDE_DISABLE) {
ide_pri_disable(); ide_pri_disable();
if (!(dev->regs[0xfe] & REG_FE_IDE_DISABLE)) if (!(dev->regs[0xfe] & REG_FE_IDE_DISABLE))
ide_pri_enable(); ide_pri_enable();
} }
break; break;
} }
} }
} }
static uint8_t static uint8_t
acc3221_read(uint16_t addr, void *p) acc3221_read(uint16_t addr, void *p)
{ {
acc3221_t *dev = (acc3221_t *)p; acc3221_t *dev = (acc3221_t *) p;
if (!(addr & 1)) if (!(addr & 1))
return dev->reg_idx; return dev->reg_idx;
if (dev->reg_idx < 0xbc) if (dev->reg_idx < 0xbc)
return 0xff; return 0xff;
return dev->regs[dev->reg_idx]; return dev->regs[dev->reg_idx];
} }
static void static void
acc3221_reset(acc3221_t *dev) acc3221_reset(acc3221_t *dev)
{ {
@@ -455,7 +447,6 @@ acc3221_close(void *priv)
free(dev); free(dev);
} }
static void * static void *
acc3221_init(const device_t *info) acc3221_init(const device_t *info)
{ {
@@ -467,24 +458,23 @@ acc3221_init(const device_t *info)
dev->uart[0] = device_add_inst(&ns16450_device, 1); dev->uart[0] = device_add_inst(&ns16450_device, 1);
dev->uart[1] = device_add_inst(&ns16450_device, 2); dev->uart[1] = device_add_inst(&ns16450_device, 2);
io_sethandler(0x00f2, 0x0002, acc3221_read, NULL, NULL, acc3221_write, NULL, NULL, dev); io_sethandler(0x00f2, 0x0002, acc3221_read, NULL, NULL, acc3221_write, NULL, NULL, dev);
acc3221_reset(dev); acc3221_reset(dev);
return dev; return dev;
} }
const device_t acc3221_device = { const device_t acc3221_device = {
.name = "ACC 3221-SP Super I/O", .name = "ACC 3221-SP Super I/O",
.internal_name = "acc3221", .internal_name = "acc3221",
.flags = 0, .flags = 0,
.local = 0, .local = 0,
.init = acc3221_init, .init = acc3221_init,
.close = acc3221_close, .close = acc3221_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

View File

@@ -34,25 +34,21 @@
#include "cpu.h" #include "cpu.h"
#include <86box/sio.h> #include <86box/sio.h>
#define AB_RST 0x80
#define AB_RST 0x80
typedef struct { typedef struct {
uint8_t chip_id, is_apm, uint8_t chip_id, is_apm,
tries, tries,
regs[48], regs[48],
ld_regs[13][256]; ld_regs[13][256];
int locked, int locked,
cur_reg; cur_reg;
fdc_t *fdc; fdc_t *fdc;
serial_t *uart[3]; serial_t *uart[3];
} ali5123_t; } ali5123_t;
static void ali5123_write(uint16_t port, uint8_t val, void *priv);
static void ali5123_write(uint16_t port, uint8_t val, void *priv); static uint8_t ali5123_read(uint16_t port, void *priv);
static uint8_t ali5123_read(uint16_t port, void *priv);
static uint16_t static uint16_t
make_port(ali5123_t *dev, uint8_t ld) make_port(ali5123_t *dev, uint8_t ld)
@@ -65,74 +61,71 @@ make_port(ali5123_t *dev, uint8_t ld)
return p; return p;
} }
static void static void
ali5123_fdc_handler(ali5123_t *dev) ali5123_fdc_handler(ali5123_t *dev)
{ {
uint16_t ld_port = 0; uint16_t ld_port = 0;
uint8_t global_enable = !!(dev->regs[0x22] & (1 << 0)); uint8_t global_enable = !!(dev->regs[0x22] & (1 << 0));
uint8_t local_enable = !!dev->ld_regs[0][0x30]; uint8_t local_enable = !!dev->ld_regs[0][0x30];
fdc_remove(dev->fdc); fdc_remove(dev->fdc);
if (global_enable && local_enable) { if (global_enable && local_enable) {
ld_port = make_port(dev, 0) & 0xFFF8; ld_port = make_port(dev, 0) & 0xFFF8;
if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8))
fdc_set_base(dev->fdc, ld_port); fdc_set_base(dev->fdc, ld_port);
} }
} }
static void static void
ali5123_lpt_handler(ali5123_t *dev) ali5123_lpt_handler(ali5123_t *dev)
{ {
uint16_t ld_port = 0; uint16_t ld_port = 0;
uint8_t global_enable = !!(dev->regs[0x22] & (1 << 3)); uint8_t global_enable = !!(dev->regs[0x22] & (1 << 3));
uint8_t local_enable = !!dev->ld_regs[3][0x30]; uint8_t local_enable = !!dev->ld_regs[3][0x30];
uint8_t lpt_irq = dev->ld_regs[3][0x70]; uint8_t lpt_irq = dev->ld_regs[3][0x70];
if (lpt_irq > 15) if (lpt_irq > 15)
lpt_irq = 0xff; lpt_irq = 0xff;
lpt1_remove(); lpt1_remove();
if (global_enable && local_enable) { if (global_enable && local_enable) {
ld_port = make_port(dev, 3) & 0xFFFC; ld_port = make_port(dev, 3) & 0xFFFC;
if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC))
lpt1_init(ld_port); lpt1_init(ld_port);
} }
lpt1_irq(lpt_irq); lpt1_irq(lpt_irq);
} }
static void static void
ali5123_serial_handler(ali5123_t *dev, int uart) ali5123_serial_handler(ali5123_t *dev, int uart)
{ {
uint16_t ld_port = 0; uint16_t ld_port = 0;
uint8_t uart_no = (uart == 2) ? 0x0b : (4 + uart); uint8_t uart_no = (uart == 2) ? 0x0b : (4 + uart);
uint8_t global_enable = !!(dev->regs[0x22] & (1 << uart_no)); uint8_t global_enable = !!(dev->regs[0x22] & (1 << uart_no));
uint8_t local_enable = !!dev->ld_regs[uart_no][0x30]; uint8_t local_enable = !!dev->ld_regs[uart_no][0x30];
uint8_t mask = (uart == 1) ? 0x04 : 0x05; uint8_t mask = (uart == 1) ? 0x04 : 0x05;
serial_remove(dev->uart[uart]); serial_remove(dev->uart[uart]);
if (global_enable && local_enable) { if (global_enable && local_enable) {
ld_port = make_port(dev, uart_no) & 0xFFF8; ld_port = make_port(dev, uart_no) & 0xFFF8;
if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8))
serial_setup(dev->uart[uart], ld_port, dev->ld_regs[uart_no][0x70]); serial_setup(dev->uart[uart], ld_port, dev->ld_regs[uart_no][0x70]);
} }
switch (dev->ld_regs[uart_no][0xf0] & mask) { switch (dev->ld_regs[uart_no][0xf0] & mask) {
case 0x00: case 0x00:
serial_set_clock_src(dev->uart[uart], 1843200.0); serial_set_clock_src(dev->uart[uart], 1843200.0);
break; break;
case 0x04: case 0x04:
serial_set_clock_src(dev->uart[uart], 8000000.0); serial_set_clock_src(dev->uart[uart], 8000000.0);
break; break;
case 0x01: case 0x05: case 0x01:
serial_set_clock_src(dev->uart[uart], 2000000.0); case 0x05:
break; serial_set_clock_src(dev->uart[uart], 2000000.0);
break;
} }
} }
static void static void
ali5123_reset(ali5123_t *dev) ali5123_reset(ali5123_t *dev)
{ {
@@ -145,7 +138,7 @@ ali5123_reset(ali5123_t *dev)
dev->regs[0x2d] = 0x20; dev->regs[0x2d] = 0x20;
for (i = 0; i < 13; i++) for (i = 0; i < 13; i++)
memset(dev->ld_regs[i], 0, 256); memset(dev->ld_regs[i], 0, 256);
/* Logical device 0: FDD */ /* Logical device 0: FDD */
dev->ld_regs[0][0x60] = 3; dev->ld_regs[0][0x60] = 3;
@@ -208,227 +201,228 @@ ali5123_reset(ali5123_t *dev)
dev->locked = 0; dev->locked = 0;
} }
static void static void
ali5123_write(uint16_t port, uint8_t val, void *priv) ali5123_write(uint16_t port, uint8_t val, void *priv)
{ {
ali5123_t *dev = (ali5123_t *) priv; ali5123_t *dev = (ali5123_t *) priv;
uint8_t index = (port & 1) ? 0 : 1; uint8_t index = (port & 1) ? 0 : 1;
uint8_t valxor = 0x00, keep = 0x00; uint8_t valxor = 0x00, keep = 0x00;
uint8_t cur_ld; uint8_t cur_ld;
if (index) { if (index) {
if (((val == 0x51) && (!dev->tries) && (!dev->locked)) || if (((val == 0x51) && (!dev->tries) && (!dev->locked)) || ((val == 0x23) && (dev->tries) && (!dev->locked))) {
((val == 0x23) && (dev->tries) && (!dev->locked))) { if (dev->tries) {
if (dev->tries) { dev->locked = 1;
dev->locked = 1; fdc_3f1_enable(dev->fdc, 0);
fdc_3f1_enable(dev->fdc, 0); dev->tries = 0;
dev->tries = 0; } else
} else dev->tries++;
dev->tries++; } else {
} else { if (dev->locked) {
if (dev->locked) { if (val == 0xbb) {
if (val == 0xbb) { dev->locked = 0;
dev->locked = 0; fdc_3f1_enable(dev->fdc, 1);
fdc_3f1_enable(dev->fdc, 1); return;
return; }
} dev->cur_reg = val;
dev->cur_reg = val; } else {
} else { if (dev->tries)
if (dev->tries) dev->tries = 0;
dev->tries = 0; }
} }
} return;
return;
} else { } else {
if (dev->locked) { if (dev->locked) {
if (dev->cur_reg < 48) { if (dev->cur_reg < 48) {
valxor = val ^ dev->regs[dev->cur_reg]; valxor = val ^ dev->regs[dev->cur_reg];
if ((val == 0x1f) || (val == 0x20) || (val == 0x21)) if ((val == 0x1f) || (val == 0x20) || (val == 0x21))
return; return;
dev->regs[dev->cur_reg] = val; dev->regs[dev->cur_reg] = val;
} else { } else {
valxor = val ^ dev->ld_regs[dev->regs[7]][dev->cur_reg]; valxor = val ^ dev->ld_regs[dev->regs[7]][dev->cur_reg];
if (((dev->cur_reg & 0xf0) == 0x70) && (dev->regs[7] < 4)) if (((dev->cur_reg & 0xf0) == 0x70) && (dev->regs[7] < 4))
return; return;
/* Block writes to some logical devices. */ /* Block writes to some logical devices. */
if (dev->regs[7] > 0x0c) if (dev->regs[7] > 0x0c)
return; return;
else switch (dev->regs[7]) { else
case 0x01: case 0x02: case 0x06: case 0x08: switch (dev->regs[7]) {
case 0x09: case 0x0a: case 0x01:
return; case 0x02:
} case 0x06:
dev->ld_regs[dev->regs[7]][dev->cur_reg] = val | keep; case 0x08:
} case 0x09:
} else case 0x0a:
return; return;
}
dev->ld_regs[dev->regs[7]][dev->cur_reg] = val | keep;
}
} else
return;
} }
if (dev->cur_reg < 48) { if (dev->cur_reg < 48) {
switch(dev->cur_reg) { switch (dev->cur_reg) {
case 0x02: case 0x02:
if (val & 0x01) if (val & 0x01)
ali5123_reset(dev); ali5123_reset(dev);
dev->regs[0x02] = 0x00; dev->regs[0x02] = 0x00;
break; break;
case 0x22: case 0x22:
if (valxor & 0x01) if (valxor & 0x01)
ali5123_fdc_handler(dev); ali5123_fdc_handler(dev);
if (valxor & 0x08) if (valxor & 0x08)
ali5123_lpt_handler(dev); ali5123_lpt_handler(dev);
if (valxor & 0x10) if (valxor & 0x10)
ali5123_serial_handler(dev, 0); ali5123_serial_handler(dev, 0);
if (valxor & 0x20) if (valxor & 0x20)
ali5123_serial_handler(dev, 1); ali5123_serial_handler(dev, 1);
if (valxor & 0x40) if (valxor & 0x40)
ali5123_serial_handler(dev, 2); ali5123_serial_handler(dev, 2);
break; break;
} }
return; return;
} }
cur_ld = dev->regs[7]; cur_ld = dev->regs[7];
if ((dev->regs[7] == 5) && (dev->regs[0x2d] & 0x20)) if ((dev->regs[7] == 5) && (dev->regs[0x2d] & 0x20))
cur_ld = 0x0b; cur_ld = 0x0b;
else if ((dev->regs[7] == 0x0b) && (dev->regs[0x2d] & 0x20)) else if ((dev->regs[7] == 0x0b) && (dev->regs[0x2d] & 0x20))
cur_ld = 5; cur_ld = 5;
switch(cur_ld) { switch (cur_ld) {
case 0: case 0:
/* FDD */ /* FDD */
switch(dev->cur_reg) { switch (dev->cur_reg) {
case 0x30: case 0x30:
case 0x60: case 0x60:
case 0x61: case 0x61:
if ((dev->cur_reg == 0x30) && (val & 0x01)) if ((dev->cur_reg == 0x30) && (val & 0x01))
dev->regs[0x22] |= 0x01; dev->regs[0x22] |= 0x01;
if (valxor) if (valxor)
ali5123_fdc_handler(dev); ali5123_fdc_handler(dev);
break; break;
case 0xf0: case 0xf0:
if (valxor & 0x08) if (valxor & 0x08)
fdc_update_enh_mode(dev->fdc, !(val & 0x08)); fdc_update_enh_mode(dev->fdc, !(val & 0x08));
if (valxor & 0x10) if (valxor & 0x10)
fdc_set_swap(dev->fdc, (val & 0x10) >> 4); fdc_set_swap(dev->fdc, (val & 0x10) >> 4);
break; break;
case 0xf1: case 0xf1:
if (valxor & 0xc) if (valxor & 0xc)
fdc_update_densel_force(dev->fdc, (val & 0xc) >> 2); fdc_update_densel_force(dev->fdc, (val & 0xc) >> 2);
break; break;
case 0xf4: case 0xf4:
if (valxor & 0x08) if (valxor & 0x08)
fdc_update_drvrate(dev->fdc, 0, (val & 0x08) >> 3); fdc_update_drvrate(dev->fdc, 0, (val & 0x08) >> 3);
break; break;
case 0xf5: case 0xf5:
if (valxor & 0x08) if (valxor & 0x08)
fdc_update_drvrate(dev->fdc, 1, (val & 0x08) >> 3); fdc_update_drvrate(dev->fdc, 1, (val & 0x08) >> 3);
break; break;
case 0xf6: case 0xf6:
if (valxor & 0x08) if (valxor & 0x08)
fdc_update_drvrate(dev->fdc, 2, (val & 0x08) >> 3); fdc_update_drvrate(dev->fdc, 2, (val & 0x08) >> 3);
break; break;
case 0xf7: case 0xf7:
if (valxor & 0x08) if (valxor & 0x08)
fdc_update_drvrate(dev->fdc, 3, (val & 0x08) >> 3); fdc_update_drvrate(dev->fdc, 3, (val & 0x08) >> 3);
break; break;
} }
break; break;
case 3: case 3:
/* Parallel port */ /* Parallel port */
switch(dev->cur_reg) { switch (dev->cur_reg) {
case 0x30: case 0x30:
case 0x60: case 0x60:
case 0x61: case 0x61:
case 0x70: case 0x70:
if ((dev->cur_reg == 0x30) && (val & 0x01)) if ((dev->cur_reg == 0x30) && (val & 0x01))
dev->regs[0x22] |= 0x08; dev->regs[0x22] |= 0x08;
if (valxor) if (valxor)
ali5123_lpt_handler(dev); ali5123_lpt_handler(dev);
break; break;
} }
break; break;
case 4: case 4:
/* Serial port 1 */ /* Serial port 1 */
switch(dev->cur_reg) { switch (dev->cur_reg) {
case 0x30: case 0x30:
case 0x60: case 0x60:
case 0x61: case 0x61:
case 0x70: case 0x70:
case 0xf0: case 0xf0:
if ((dev->cur_reg == 0x30) && (val & 0x01)) if ((dev->cur_reg == 0x30) && (val & 0x01))
dev->regs[0x22] |= 0x10; dev->regs[0x22] |= 0x10;
if (valxor) if (valxor)
ali5123_serial_handler(dev, 0); ali5123_serial_handler(dev, 0);
break; break;
} }
break; break;
case 5: case 5:
/* Serial port 2 - HP like module */ /* Serial port 2 - HP like module */
switch(dev->cur_reg) { switch (dev->cur_reg) {
case 0x30: case 0x30:
case 0x60: case 0x60:
case 0x61: case 0x61:
case 0x70: case 0x70:
case 0xf0: case 0xf0:
if ((dev->cur_reg == 0x30) && (val & 0x01)) if ((dev->cur_reg == 0x30) && (val & 0x01))
dev->regs[0x22] |= 0x20; dev->regs[0x22] |= 0x20;
if (valxor) if (valxor)
ali5123_serial_handler(dev, 1); ali5123_serial_handler(dev, 1);
break; break;
} }
break; break;
case 0x0b: case 0x0b:
/* Serial port 3 */ /* Serial port 3 */
switch(dev->cur_reg) { switch (dev->cur_reg) {
case 0x30: case 0x30:
case 0x60: case 0x60:
case 0x61: case 0x61:
case 0x70: case 0x70:
case 0xf0: case 0xf0:
if ((dev->cur_reg == 0x30) && (val & 0x01)) if ((dev->cur_reg == 0x30) && (val & 0x01))
dev->regs[0x22] |= 0x40; dev->regs[0x22] |= 0x40;
if (valxor) if (valxor)
ali5123_serial_handler(dev, 2); ali5123_serial_handler(dev, 2);
break; break;
} }
break; break;
} }
} }
static uint8_t static uint8_t
ali5123_read(uint16_t port, void *priv) ali5123_read(uint16_t port, void *priv)
{ {
ali5123_t *dev = (ali5123_t *) priv; ali5123_t *dev = (ali5123_t *) priv;
uint8_t index = (port & 1) ? 0 : 1; uint8_t index = (port & 1) ? 0 : 1;
uint8_t ret = 0xff, cur_ld; uint8_t ret = 0xff, cur_ld;
if (dev->locked) { if (dev->locked) {
if (index) if (index)
ret = dev->cur_reg; ret = dev->cur_reg;
else { else {
if (dev->cur_reg < 0x30) { if (dev->cur_reg < 0x30) {
if (dev->cur_reg == 0x20) if (dev->cur_reg == 0x20)
ret = dev->chip_id; ret = dev->chip_id;
else else
ret = dev->regs[dev->cur_reg]; ret = dev->regs[dev->cur_reg];
} else { } else {
cur_ld = dev->regs[7]; cur_ld = dev->regs[7];
if ((dev->regs[7] == 5) && (dev->regs[0x2d] & 0x20)) if ((dev->regs[7] == 5) && (dev->regs[0x2d] & 0x20))
cur_ld = 0x0b; cur_ld = 0x0b;
else if ((dev->regs[7] == 0x0b) && (dev->regs[0x2d] & 0x20)) else if ((dev->regs[7] == 0x0b) && (dev->regs[0x2d] & 0x20))
cur_ld = 5; cur_ld = 5;
ret = dev->ld_regs[cur_ld][dev->cur_reg]; ret = dev->ld_regs[cur_ld][dev->cur_reg];
} }
} }
} }
return ret; return ret;
} }
static void static void
ali5123_close(void *priv) ali5123_close(void *priv)
{ {
@@ -437,7 +431,6 @@ ali5123_close(void *priv)
free(dev); free(dev);
} }
static void * static void *
ali5123_init(const device_t *info) ali5123_init(const device_t *info)
{ {
@@ -455,24 +448,23 @@ ali5123_init(const device_t *info)
ali5123_reset(dev); ali5123_reset(dev);
io_sethandler(FDC_PRIMARY_ADDR, 0x0002, io_sethandler(FDC_PRIMARY_ADDR, 0x0002,
ali5123_read, NULL, NULL, ali5123_write, NULL, NULL, dev); ali5123_read, NULL, NULL, ali5123_write, NULL, NULL, dev);
device_add(&keyboard_ps2_ali_pci_device); device_add(&keyboard_ps2_ali_pci_device);
return dev; return dev;
} }
const device_t ali5123_device = { const device_t ali5123_device = {
.name = "ALi M5123/M1543C Super I/O", .name = "ALi M5123/M1543C Super I/O",
.internal_name = "ali5123", .internal_name = "ali5123",
.flags = 0, .flags = 0,
.local = 0x40, .local = 0x40,
.init = ali5123_init, .init = ali5123_init,
.close = ali5123_close, .close = ali5123_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

View File

@@ -27,12 +27,10 @@
#include <86box/fdc.h> #include <86box/fdc.h>
#include <86box/sio.h> #include <86box/sio.h>
typedef struct { typedef struct {
uint8_t regs[2]; uint8_t regs[2];
} sio_detect_t; } sio_detect_t;
static void static void
sio_detect_write(uint16_t port, uint8_t val, void *priv) sio_detect_write(uint16_t port, uint8_t val, void *priv)
{ {
@@ -45,7 +43,6 @@ sio_detect_write(uint16_t port, uint8_t val, void *priv)
return; return;
} }
static uint8_t static uint8_t
sio_detect_read(uint16_t port, void *priv) sio_detect_read(uint16_t port, void *priv)
{ {
@@ -56,7 +53,6 @@ sio_detect_read(uint16_t port, void *priv)
return 0xff /*dev->regs[port & 1]*/; return 0xff /*dev->regs[port & 1]*/;
} }
static void static void
sio_detect_close(void *priv) sio_detect_close(void *priv)
{ {
@@ -65,7 +61,6 @@ sio_detect_close(void *priv)
free(dev); free(dev);
} }
static void * static void *
sio_detect_init(const device_t *info) sio_detect_init(const device_t *info)
{ {
@@ -75,48 +70,47 @@ sio_detect_init(const device_t *info)
device_add(&fdc_at_smc_device); device_add(&fdc_at_smc_device);
io_sethandler(0x0022, 0x0006, io_sethandler(0x0022, 0x0006,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
io_sethandler(0x002e, 0x0002, io_sethandler(0x002e, 0x0002,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
io_sethandler(0x0044, 0x0004, io_sethandler(0x0044, 0x0004,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
io_sethandler(0x004e, 0x0002, io_sethandler(0x004e, 0x0002,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
io_sethandler(0x0108, 0x0002, io_sethandler(0x0108, 0x0002,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
io_sethandler(0x015c, 0x0002, io_sethandler(0x015c, 0x0002,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
io_sethandler(0x0250, 0x0003, io_sethandler(0x0250, 0x0003,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
io_sethandler(0x026e, 0x0002, io_sethandler(0x026e, 0x0002,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
io_sethandler(0x0279, 0x0001, io_sethandler(0x0279, 0x0001,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
io_sethandler(FDC_SECONDARY_ADDR, 0x0002, io_sethandler(FDC_SECONDARY_ADDR, 0x0002,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
io_sethandler(0x0398, 0x0002, io_sethandler(0x0398, 0x0002,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
io_sethandler(0x03e3, 0x0001, io_sethandler(0x03e3, 0x0001,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
io_sethandler(FDC_PRIMARY_ADDR, 0x0002, io_sethandler(FDC_PRIMARY_ADDR, 0x0002,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
io_sethandler(0x0a79, 0x0001, io_sethandler(0x0a79, 0x0001,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev); sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
return dev; return dev;
} }
const device_t sio_detect_device = { const device_t sio_detect_device = {
.name = "Super I/O Detection Helper", .name = "Super I/O Detection Helper",
.internal_name = "sio_detect", .internal_name = "sio_detect",
.flags = 0, .flags = 0,
.local = 0, .local = 0,
.init = sio_detect_init, .init = sio_detect_init,
.close = sio_detect_close, .close = sio_detect_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

View File

@@ -43,26 +43,23 @@
#include <86box/nvr.h> #include <86box/nvr.h>
#include <86box/sio.h> #include <86box/sio.h>
typedef struct upc_t {
typedef struct upc_t uint32_t local;
{ int configuration_state; /* state of algorithm to enter configuration mode */
uint32_t local; int configuration_mode;
int configuration_state; /* state of algorithm to enter configuration mode */ uint16_t cri_addr; /* cri = configuration index register, addr is even */
int configuration_mode; uint16_t cap_addr; /* cap = configuration access port, addr is odd and is cri_addr + 1 */
uint16_t cri_addr; /* cri = configuration index register, addr is even */ uint8_t cri; /* currently indexed register */
uint16_t cap_addr; /* cap = configuration access port, addr is odd and is cri_addr + 1 */ uint8_t last_write;
uint8_t cri; /* currently indexed register */
uint8_t last_write;
/* these regs are not affected by reset */ /* these regs are not affected by reset */
uint8_t regs[15]; /* there are 16 indexes, but there is no need to store the last one which is: R = cri_addr / 4, W = exit config mode */ uint8_t regs[15]; /* there are 16 indexes, but there is no need to store the last one which is: R = cri_addr / 4, W = exit config mode */
fdc_t * fdc; fdc_t *fdc;
nvr_t * nvr; nvr_t *nvr;
void * gameport; void *gameport;
serial_t * uart[2]; serial_t *uart[2];
} upc_t; } upc_t;
static void static void
f82c710_update_ports(upc_t *dev, int set) f82c710_update_ports(upc_t *dev, int set)
{ {
@@ -77,40 +74,39 @@ f82c710_update_ports(upc_t *dev, int set)
ide_pri_disable(); ide_pri_disable();
if (!set) if (!set)
return; return;
if (dev->regs[0] & 4) { if (dev->regs[0] & 4) {
com_addr = dev->regs[4] * 4; com_addr = dev->regs[4] * 4;
if (com_addr == COM1_ADDR) if (com_addr == COM1_ADDR)
serial_setup(dev->uart[0], com_addr, COM1_IRQ); serial_setup(dev->uart[0], com_addr, COM1_IRQ);
else if (com_addr == COM2_ADDR) else if (com_addr == COM2_ADDR)
serial_setup(dev->uart[1], com_addr, COM2_IRQ); serial_setup(dev->uart[1], com_addr, COM2_IRQ);
} }
if (dev->regs[0] & 8) { if (dev->regs[0] & 8) {
lpt_addr = dev->regs[6] * 4; lpt_addr = dev->regs[6] * 4;
lpt1_init(lpt_addr); lpt1_init(lpt_addr);
if ((lpt_addr == LPT1_ADDR) || (lpt_addr == LPT_MDA_ADDR)) if ((lpt_addr == LPT1_ADDR) || (lpt_addr == LPT_MDA_ADDR))
lpt1_irq(LPT1_IRQ); lpt1_irq(LPT1_IRQ);
else if (lpt_addr == LPT2_ADDR) else if (lpt_addr == LPT2_ADDR)
lpt1_irq(LPT2_IRQ); lpt1_irq(LPT2_IRQ);
} }
if (dev->regs[12] & 0x80) if (dev->regs[12] & 0x80)
ide_pri_enable(); ide_pri_enable();
if (dev->regs[12] & 0x20) if (dev->regs[12] & 0x20)
fdc_set_base(dev->fdc, FDC_PRIMARY_ADDR); fdc_set_base(dev->fdc, FDC_PRIMARY_ADDR);
} }
static void static void
f82c606_update_ports(upc_t *dev, int set) f82c606_update_ports(upc_t *dev, int set)
{ {
uint8_t uart1_int = 0xff; uint8_t uart1_int = 0xff;
uint8_t uart2_int = 0xff; uint8_t uart2_int = 0xff;
uint8_t lpt1_int = 0xff; uint8_t lpt1_int = 0xff;
int nvr_int = -1; int nvr_int = -1;
serial_remove(dev->uart[0]); serial_remove(dev->uart[0]);
serial_remove(dev->uart[1]); serial_remove(dev->uart[1]);
@@ -123,51 +119,75 @@ f82c606_update_ports(upc_t *dev, int set)
gameport_remap(dev->gameport, 0); gameport_remap(dev->gameport, 0);
if (!set) if (!set)
return; return;
switch (dev->regs[8] & 0xc0) { switch (dev->regs[8] & 0xc0) {
case 0x40: nvr_int = 3; break; case 0x40:
case 0x80: uart1_int = COM2_IRQ; break; nvr_int = 3;
case 0xc0: uart2_int = COM2_IRQ; break; break;
case 0x80:
uart1_int = COM2_IRQ;
break;
case 0xc0:
uart2_int = COM2_IRQ;
break;
} }
switch (dev->regs[8] & 0x30) { switch (dev->regs[8] & 0x30) {
case 0x10: nvr_int = 4; break; case 0x10:
case 0x20: uart1_int = COM1_IRQ; break; nvr_int = 4;
case 0x30: uart2_int = COM1_IRQ; break; break;
case 0x20:
uart1_int = COM1_IRQ;
break;
case 0x30:
uart2_int = COM1_IRQ;
break;
} }
switch (dev->regs[8] & 0x0c) { switch (dev->regs[8] & 0x0c) {
case 0x04: nvr_int = 5; break; case 0x04:
case 0x08: uart1_int = 5; break; nvr_int = 5;
case 0x0c: lpt1_int = LPT2_IRQ; break; break;
case 0x08:
uart1_int = 5;
break;
case 0x0c:
lpt1_int = LPT2_IRQ;
break;
} }
switch (dev->regs[8] & 0x03) { switch (dev->regs[8] & 0x03) {
case 0x01: nvr_int = 7; break; case 0x01:
case 0x02: uart2_int = 7; break; nvr_int = 7;
case 0x03: lpt1_int = LPT1_IRQ; break; break;
case 0x02:
uart2_int = 7;
break;
case 0x03:
lpt1_int = LPT1_IRQ;
break;
} }
if (dev->regs[0] & 1) { if (dev->regs[0] & 1) {
gameport_remap(dev->gameport, ((uint16_t) dev->regs[7]) << 2); gameport_remap(dev->gameport, ((uint16_t) dev->regs[7]) << 2);
pclog("Game port at %04X\n", ((uint16_t) dev->regs[7]) << 2); pclog("Game port at %04X\n", ((uint16_t) dev->regs[7]) << 2);
} }
if (dev->regs[0] & 2) { if (dev->regs[0] & 2) {
serial_setup(dev->uart[0], ((uint16_t) dev->regs[4]) << 2, uart1_int); serial_setup(dev->uart[0], ((uint16_t) dev->regs[4]) << 2, uart1_int);
pclog("UART 1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[4]) << 2, uart1_int); pclog("UART 1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[4]) << 2, uart1_int);
} }
if (dev->regs[0] & 4) { if (dev->regs[0] & 4) {
serial_setup(dev->uart[1], ((uint16_t) dev->regs[5]) << 2, uart2_int); serial_setup(dev->uart[1], ((uint16_t) dev->regs[5]) << 2, uart2_int);
pclog("UART 2 at %04X, IRQ %i\n", ((uint16_t) dev->regs[5]) << 2, uart2_int); pclog("UART 2 at %04X, IRQ %i\n", ((uint16_t) dev->regs[5]) << 2, uart2_int);
} }
if (dev->regs[0] & 8) { if (dev->regs[0] & 8) {
lpt1_init(((uint16_t) dev->regs[6]) << 2); lpt1_init(((uint16_t) dev->regs[6]) << 2);
lpt1_irq(lpt1_int); lpt1_irq(lpt1_int);
pclog("LPT1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[6]) << 2, lpt1_int); pclog("LPT1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[6]) << 2, lpt1_int);
} }
nvr_at_handler(1, ((uint16_t) dev->regs[3]) << 2, dev->nvr); nvr_at_handler(1, ((uint16_t) dev->regs[3]) << 2, dev->nvr);
@@ -175,97 +195,94 @@ f82c606_update_ports(upc_t *dev, int set)
pclog("RTC at %04X, IRQ %i\n", ((uint16_t) dev->regs[3]) << 2, nvr_int); pclog("RTC at %04X, IRQ %i\n", ((uint16_t) dev->regs[3]) << 2, nvr_int);
} }
static uint8_t static uint8_t
f82c710_config_read(uint16_t port, void *priv) f82c710_config_read(uint16_t port, void *priv)
{ {
upc_t *dev = (upc_t *) priv; upc_t *dev = (upc_t *) priv;
uint8_t temp = 0xff; uint8_t temp = 0xff;
if (dev->configuration_mode) { if (dev->configuration_mode) {
if (port == dev->cri_addr) { if (port == dev->cri_addr) {
temp = dev->cri; temp = dev->cri;
} else if (port == dev->cap_addr) { } else if (port == dev->cap_addr) {
if (dev->cri == 0xf) if (dev->cri == 0xf)
temp = dev->cri_addr / 4; temp = dev->cri_addr / 4;
else else
temp = dev->regs[dev->cri]; temp = dev->regs[dev->cri];
} }
} }
return temp; return temp;
} }
static void static void
f82c710_config_write(uint16_t port, uint8_t val, void *priv) f82c710_config_write(uint16_t port, uint8_t val, void *priv)
{ {
upc_t *dev = (upc_t *) priv; upc_t *dev = (upc_t *) priv;
int configuration_state_event = 0; int configuration_state_event = 0;
switch (port) { switch (port) {
case 0x2fa: case 0x2fa:
if ((dev->configuration_state == 0) && (val != 0x00) && (val != 0xff) && (dev->local == 606)) { if ((dev->configuration_state == 0) && (val != 0x00) && (val != 0xff) && (dev->local == 606)) {
configuration_state_event = 1; configuration_state_event = 1;
dev->last_write = val; dev->last_write = val;
} else if ((dev->configuration_state == 0) && (val == 0x55) && (dev->local == 710)) } else if ((dev->configuration_state == 0) && (val == 0x55) && (dev->local == 710))
configuration_state_event = 1; configuration_state_event = 1;
else if (dev->configuration_state == 4) { else if (dev->configuration_state == 4) {
if ((val | dev->last_write) == 0xff) { if ((val | dev->last_write) == 0xff) {
dev->cri_addr = ((uint16_t) dev->last_write) << 2; dev->cri_addr = ((uint16_t) dev->last_write) << 2;
dev->cap_addr = dev->cri_addr + 1; dev->cap_addr = dev->cri_addr + 1;
dev->configuration_mode = 1; dev->configuration_mode = 1;
if (dev->local == 606) if (dev->local == 606)
f82c606_update_ports(dev, 0); f82c606_update_ports(dev, 0);
else if (dev->local == 710) else if (dev->local == 710)
f82c710_update_ports(dev, 0); f82c710_update_ports(dev, 0);
/* TODO: is the value of cri reset here or when exiting configuration mode? */ /* TODO: is the value of cri reset here or when exiting configuration mode? */
io_sethandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev); io_sethandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev);
} else } else
dev->configuration_mode = 0; dev->configuration_mode = 0;
} }
break; break;
case 0x3fa: case 0x3fa:
if ((dev->configuration_state == 1) && ((val | dev->last_write) == 0xff) && (dev->local == 606)) if ((dev->configuration_state == 1) && ((val | dev->last_write) == 0xff) && (dev->local == 606))
configuration_state_event = 1; configuration_state_event = 1;
else if ((dev->configuration_state == 1) && (val == 0xaa) && (dev->local == 710)) else if ((dev->configuration_state == 1) && (val == 0xaa) && (dev->local == 710))
configuration_state_event = 1; configuration_state_event = 1;
else if ((dev->configuration_state == 2) && (val == 0x36)) else if ((dev->configuration_state == 2) && (val == 0x36))
configuration_state_event = 1; configuration_state_event = 1;
else if (dev->configuration_state == 3) { else if (dev->configuration_state == 3) {
dev->last_write = val; dev->last_write = val;
configuration_state_event = 1; configuration_state_event = 1;
} }
break; break;
default: default:
break; break;
} }
if (dev->configuration_mode) { if (dev->configuration_mode) {
if (port == dev->cri_addr) { if (port == dev->cri_addr) {
dev->cri = val & 0xf; dev->cri = val & 0xf;
} else if (port == dev->cap_addr) { } else if (port == dev->cap_addr) {
if (dev->cri == 0xf) { if (dev->cri == 0xf) {
dev->configuration_mode = 0; dev->configuration_mode = 0;
io_removehandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev); io_removehandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev);
/* TODO: any benefit in updating at each register write instead of when exiting config mode? */ /* TODO: any benefit in updating at each register write instead of when exiting config mode? */
if (dev->local == 606) if (dev->local == 606)
f82c606_update_ports(dev, 1); f82c606_update_ports(dev, 1);
else if (dev->local == 710) else if (dev->local == 710)
f82c710_update_ports(dev, 1); f82c710_update_ports(dev, 1);
} else } else
dev->regs[dev->cri] = val; dev->regs[dev->cri] = val;
} }
} }
/* TODO: is the state only reset when accessing 0x2fa and 0x3fa wrongly? */ /* TODO: is the state only reset when accessing 0x2fa and 0x3fa wrongly? */
if ((port == 0x2fa || port == 0x3fa) && configuration_state_event) if ((port == 0x2fa || port == 0x3fa) && configuration_state_event)
dev->configuration_state++; dev->configuration_state++;
else else
dev->configuration_state = 0; dev->configuration_state = 0;
} }
static void static void
f82c710_reset(void *priv) f82c710_reset(void *priv)
{ {
@@ -273,40 +290,39 @@ f82c710_reset(void *priv)
/* Set power-on defaults. */ /* Set power-on defaults. */
if (dev->local == 606) { if (dev->local == 606) {
dev->regs[0] = 0x00; /* Enable */ dev->regs[0] = 0x00; /* Enable */
dev->regs[1] = 0x00; /* Configuration Register */ dev->regs[1] = 0x00; /* Configuration Register */
dev->regs[2] = 0x00; /* Ext Baud Rate Select */ dev->regs[2] = 0x00; /* Ext Baud Rate Select */
dev->regs[3] = 0xb0; /* RTC Base */ dev->regs[3] = 0xb0; /* RTC Base */
dev->regs[4] = 0xfe; /* UART1 Base */ dev->regs[4] = 0xfe; /* UART1 Base */
dev->regs[5] = 0xbe; /* UART2 Base */ dev->regs[5] = 0xbe; /* UART2 Base */
dev->regs[6] = 0x9e; /* Parallel Base */ dev->regs[6] = 0x9e; /* Parallel Base */
dev->regs[7] = 0x80; /* Game Base */ dev->regs[7] = 0x80; /* Game Base */
dev->regs[8] = 0xec; /* Interrupt Select */ dev->regs[8] = 0xec; /* Interrupt Select */
} else if (dev->local == 710) { } else if (dev->local == 710) {
dev->regs[0] = 0x0c; dev->regs[0] = 0x0c;
dev->regs[1] = 0x00; dev->regs[1] = 0x00;
dev->regs[2] = 0x00; dev->regs[2] = 0x00;
dev->regs[3] = 0x00; dev->regs[3] = 0x00;
dev->regs[4] = 0xfe; dev->regs[4] = 0xfe;
dev->regs[5] = 0x00; dev->regs[5] = 0x00;
dev->regs[6] = 0x9e; dev->regs[6] = 0x9e;
dev->regs[7] = 0x00; dev->regs[7] = 0x00;
dev->regs[8] = 0x00; dev->regs[8] = 0x00;
dev->regs[9] = 0xb0; dev->regs[9] = 0xb0;
dev->regs[10] = 0x00; dev->regs[10] = 0x00;
dev->regs[11] = 0x00; dev->regs[11] = 0x00;
dev->regs[12] = 0xa0; dev->regs[12] = 0xa0;
dev->regs[13] = 0x00; dev->regs[13] = 0x00;
dev->regs[14] = 0x00; dev->regs[14] = 0x00;
} }
if (dev->local == 606) if (dev->local == 606)
f82c606_update_ports(dev, 1); f82c606_update_ports(dev, 1);
else if (dev->local == 710) else if (dev->local == 710)
f82c710_update_ports(dev, 1); f82c710_update_ports(dev, 1);
} }
static void static void
f82c710_close(void *priv) f82c710_close(void *priv)
{ {
@@ -315,7 +331,6 @@ f82c710_close(void *priv)
free(dev); free(dev);
} }
static void * static void *
f82c710_init(const device_t *info) f82c710_init(const device_t *info)
{ {
@@ -324,10 +339,10 @@ f82c710_init(const device_t *info)
dev->local = info->local; dev->local = info->local;
if (dev->local == 606) { if (dev->local == 606) {
dev->nvr = device_add(&at_nvr_old_device); dev->nvr = device_add(&at_nvr_old_device);
dev->gameport = gameport_add(&gameport_sio_device); dev->gameport = gameport_add(&gameport_sio_device);
} else if (dev->local == 710) } else if (dev->local == 710)
dev->fdc = device_add(&fdc_at_device); dev->fdc = device_add(&fdc_at_device);
dev->uart[0] = device_add_inst(&ns16450_device, 1); dev->uart[0] = device_add_inst(&ns16450_device, 1);
dev->uart[1] = device_add_inst(&ns16450_device, 2); dev->uart[1] = device_add_inst(&ns16450_device, 2);
@@ -341,29 +356,29 @@ f82c710_init(const device_t *info)
} }
const device_t f82c606_device = { const device_t f82c606_device = {
.name = "82C606 CHIPSpak Multifunction Controller", .name = "82C606 CHIPSpak Multifunction Controller",
.internal_name = "f82c606", .internal_name = "f82c606",
.flags = 0, .flags = 0,
.local = 606, .local = 606,
.init = f82c710_init, .init = f82c710_init,
.close = f82c710_close, .close = f82c710_close,
.reset = f82c710_reset, .reset = f82c710_reset,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t f82c710_device = { const device_t f82c710_device = {
.name = "F82C710 UPC Super I/O", .name = "F82C710 UPC Super I/O",
.internal_name = "f82c710", .internal_name = "f82c710",
.flags = 0, .flags = 0,
.local = 710, .local = 710,
.init = f82c710_init, .init = f82c710_init,
.close = f82c710_close, .close = f82c710_close,
.reset = f82c710_reset, .reset = f82c710_reset,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

View File

@@ -31,217 +31,211 @@
#include <86box/fdc.h> #include <86box/fdc.h>
#include <86box/sio.h> #include <86box/sio.h>
typedef struct { typedef struct {
uint8_t id, tries, uint8_t id, tries,
regs[42]; regs[42];
int locked, rw_locked, int locked, rw_locked,
cur_reg; cur_reg;
fdc_t *fdc; fdc_t *fdc;
serial_t *uart[2]; serial_t *uart[2];
} fdc37c669_t; } fdc37c669_t;
static int next_id = 0;
static int next_id = 0;
static uint16_t static uint16_t
make_port(fdc37c669_t *dev, uint8_t reg) make_port(fdc37c669_t *dev, uint8_t reg)
{ {
uint16_t p = 0; uint16_t p = 0;
uint16_t mask = 0; uint16_t mask = 0;
switch(reg) { switch (reg) {
case 0x20: case 0x20:
case 0x21: case 0x21:
case 0x22: case 0x22:
mask = 0xfc; mask = 0xfc;
break; break;
case 0x23: case 0x23:
mask = 0xff; mask = 0xff;
break; break;
case 0x24: case 0x24:
case 0x25: case 0x25:
mask = 0xfe; mask = 0xfe;
break; break;
} }
p = ((uint16_t) (dev->regs[reg] & mask)) << 2; p = ((uint16_t) (dev->regs[reg] & mask)) << 2;
if (reg == 0x22) if (reg == 0x22)
p |= 6; p |= 6;
return p; return p;
} }
static void static void
fdc37c669_write(uint16_t port, uint8_t val, void *priv) fdc37c669_write(uint16_t port, uint8_t val, void *priv)
{ {
fdc37c669_t *dev = (fdc37c669_t *) priv; fdc37c669_t *dev = (fdc37c669_t *) priv;
uint8_t index = (port & 1) ? 0 : 1; uint8_t index = (port & 1) ? 0 : 1;
uint8_t valxor = 0; uint8_t valxor = 0;
uint8_t max = 42; uint8_t max = 42;
if (index) { if (index) {
if ((val == 0x55) && !dev->locked) { if ((val == 0x55) && !dev->locked) {
if (dev->tries) { if (dev->tries) {
dev->locked = 1; dev->locked = 1;
dev->tries = 0; dev->tries = 0;
} else } else
dev->tries++; dev->tries++;
} else { } else {
if (dev->locked) { if (dev->locked) {
if (val < max) if (val < max)
dev->cur_reg = val; dev->cur_reg = val;
if (val == 0xaa) if (val == 0xaa)
dev->locked = 0; dev->locked = 0;
} else { } else {
if (dev->tries) if (dev->tries)
dev->tries = 0; dev->tries = 0;
} }
} }
return; return;
} else { } else {
if (dev->locked) { if (dev->locked) {
if ((dev->cur_reg < 0x18) && (dev->rw_locked)) if ((dev->cur_reg < 0x18) && (dev->rw_locked))
return; return;
if ((dev->cur_reg >= 0x26) && (dev->cur_reg <= 0x27)) if ((dev->cur_reg >= 0x26) && (dev->cur_reg <= 0x27))
return; return;
if (dev->cur_reg == 0x29) if (dev->cur_reg == 0x29)
return; return;
valxor = val ^ dev->regs[dev->cur_reg]; valxor = val ^ dev->regs[dev->cur_reg];
dev->regs[dev->cur_reg] = val; dev->regs[dev->cur_reg] = val;
} else } else
return; return;
} }
switch(dev->cur_reg) { switch (dev->cur_reg) {
case 0: case 0:
if (!dev->id && (valxor & 8)) { if (!dev->id && (valxor & 8)) {
fdc_remove(dev->fdc); fdc_remove(dev->fdc);
if ((dev->regs[0] & 8) && (dev->regs[0x20] & 0xc0)) if ((dev->regs[0] & 8) && (dev->regs[0x20] & 0xc0))
fdc_set_base(dev->fdc, make_port(dev, 0x20)); fdc_set_base(dev->fdc, make_port(dev, 0x20));
} }
break; break;
case 1: case 1:
if (valxor & 4) { if (valxor & 4) {
if (dev->id) { if (dev->id) {
lpt2_remove(); lpt2_remove();
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40)) if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
lpt2_init(make_port(dev, 0x23)); lpt2_init(make_port(dev, 0x23));
} else { } else {
lpt1_remove(); lpt1_remove();
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40)) if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
lpt1_init(make_port(dev, 0x23)); lpt1_init(make_port(dev, 0x23));
} }
} }
if (valxor & 7) if (valxor & 7)
dev->rw_locked = (val & 8) ? 0 : 1; dev->rw_locked = (val & 8) ? 0 : 1;
break; break;
case 2: case 2:
if (valxor & 8) { if (valxor & 8) {
serial_remove(dev->uart[0]); serial_remove(dev->uart[0]);
if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40)) if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40))
serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4); serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4);
} }
if (valxor & 0x80) { if (valxor & 0x80) {
serial_remove(dev->uart[1]); serial_remove(dev->uart[1]);
if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40)) if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40))
serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f); serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f);
} }
break; break;
case 3: case 3:
if (!dev->id && (valxor & 2)) if (!dev->id && (valxor & 2))
fdc_update_enh_mode(dev->fdc, (val & 2) ? 1 : 0); fdc_update_enh_mode(dev->fdc, (val & 2) ? 1 : 0);
break; break;
case 5: case 5:
if (!dev->id && (valxor & 0x18)) if (!dev->id && (valxor & 0x18))
fdc_update_densel_force(dev->fdc, (val & 0x18) >> 3); fdc_update_densel_force(dev->fdc, (val & 0x18) >> 3);
if (!dev->id && (valxor & 0x20)) if (!dev->id && (valxor & 0x20))
fdc_set_swap(dev->fdc, (val & 0x20) >> 5); fdc_set_swap(dev->fdc, (val & 0x20) >> 5);
break; break;
case 0xB: case 0xB:
if (!dev->id && (valxor & 3)) if (!dev->id && (valxor & 3))
fdc_update_rwc(dev->fdc, 0, val & 3); fdc_update_rwc(dev->fdc, 0, val & 3);
if (!dev->id && (valxor & 0xC)) if (!dev->id && (valxor & 0xC))
fdc_update_rwc(dev->fdc, 1, (val & 0xC) >> 2); fdc_update_rwc(dev->fdc, 1, (val & 0xC) >> 2);
break; break;
case 0x20: case 0x20:
if (!dev->id && (valxor & 0xfc)) { if (!dev->id && (valxor & 0xfc)) {
fdc_remove(dev->fdc); fdc_remove(dev->fdc);
if ((dev->regs[0] & 8) && (dev->regs[0x20] & 0xc0)) if ((dev->regs[0] & 8) && (dev->regs[0x20] & 0xc0))
fdc_set_base(dev->fdc, make_port(dev, 0x20)); fdc_set_base(dev->fdc, make_port(dev, 0x20));
} }
break; break;
case 0x23: case 0x23:
if (valxor) { if (valxor) {
if (dev->id) { if (dev->id) {
lpt2_remove(); lpt2_remove();
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40)) if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
lpt2_init(make_port(dev, 0x23)); lpt2_init(make_port(dev, 0x23));
} else { } else {
lpt1_remove(); lpt1_remove();
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40)) if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
lpt1_init(make_port(dev, 0x23)); lpt1_init(make_port(dev, 0x23));
} }
} }
break; break;
case 0x24: case 0x24:
if (valxor & 0xfe) { if (valxor & 0xfe) {
serial_remove(dev->uart[0]); serial_remove(dev->uart[0]);
if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40)) if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40))
serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4); serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4);
} }
break; break;
case 0x25: case 0x25:
if (valxor & 0xfe) { if (valxor & 0xfe) {
serial_remove(dev->uart[1]); serial_remove(dev->uart[1]);
if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40)) if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40))
serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f); serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f);
} }
break; break;
case 0x27: case 0x27:
if (valxor & 0xf) { if (valxor & 0xf) {
if (dev->id) if (dev->id)
lpt2_irq(val & 0xf); lpt2_irq(val & 0xf);
else else
lpt1_irq(val & 0xf); lpt1_irq(val & 0xf);
} }
break; break;
case 0x28: case 0x28:
if (valxor & 0xf) { if (valxor & 0xf) {
serial_remove(dev->uart[1]); serial_remove(dev->uart[1]);
if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40)) if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40))
serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f); serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f);
} }
if (valxor & 0xf0) { if (valxor & 0xf0) {
serial_remove(dev->uart[0]); serial_remove(dev->uart[0]);
if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40)) if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40))
serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4); serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4);
} }
break; break;
} }
} }
static uint8_t static uint8_t
fdc37c669_read(uint16_t port, void *priv) fdc37c669_read(uint16_t port, void *priv)
{ {
fdc37c669_t *dev = (fdc37c669_t *) priv; fdc37c669_t *dev = (fdc37c669_t *) priv;
uint8_t index = (port & 1) ? 0 : 1; uint8_t index = (port & 1) ? 0 : 1;
uint8_t ret = 0xff; uint8_t ret = 0xff;
if (dev->locked) { if (dev->locked) {
if (index) if (index)
ret = dev->cur_reg; ret = dev->cur_reg;
else if ((dev->cur_reg >= 0x18) || !dev->rw_locked) else if ((dev->cur_reg >= 0x18) || !dev->rw_locked)
ret = dev->regs[dev->cur_reg]; ret = dev->regs[dev->cur_reg];
} }
return ret; return ret;
} }
static void static void
fdc37c669_reset(fdc37c669_t *dev) fdc37c669_reset(fdc37c669_t *dev)
{ {
@@ -259,38 +253,37 @@ fdc37c669_reset(fdc37c669_t *dev)
dev->regs[0x06] = 0xff; dev->regs[0x06] = 0xff;
dev->regs[0x0d] = 0x03; dev->regs[0x0d] = 0x03;
dev->regs[0x0e] = 0x02; dev->regs[0x0e] = 0x02;
dev->regs[0x1e] = 0x80; /* Gameport controller. */ dev->regs[0x1e] = 0x80; /* Gameport controller. */
dev->regs[0x20] = (FDC_PRIMARY_ADDR >> 2) & 0xfc; dev->regs[0x20] = (FDC_PRIMARY_ADDR >> 2) & 0xfc;
dev->regs[0x21] = (0x1f0 >> 2) & 0xfc; dev->regs[0x21] = (0x1f0 >> 2) & 0xfc;
dev->regs[0x22] = ((0x3f6 >> 2) & 0xfc) | 1; dev->regs[0x22] = ((0x3f6 >> 2) & 0xfc) | 1;
if (dev->id == 1) { if (dev->id == 1) {
dev->regs[0x23] = (LPT2_ADDR >> 2); dev->regs[0x23] = (LPT2_ADDR >> 2);
lpt2_remove(); lpt2_remove();
lpt2_init(LPT2_ADDR); lpt2_init(LPT2_ADDR);
dev->regs[0x24] = (COM3_ADDR >> 2) & 0xfe; dev->regs[0x24] = (COM3_ADDR >> 2) & 0xfe;
dev->regs[0x25] = (COM4_ADDR >> 2) & 0xfe; dev->regs[0x25] = (COM4_ADDR >> 2) & 0xfe;
} else { } else {
fdc_reset(dev->fdc); fdc_reset(dev->fdc);
lpt1_remove(); lpt1_remove();
lpt1_init(LPT1_ADDR); lpt1_init(LPT1_ADDR);
dev->regs[0x23] = (LPT1_ADDR >> 2); dev->regs[0x23] = (LPT1_ADDR >> 2);
dev->regs[0x24] = (COM1_ADDR >> 2) & 0xfe; dev->regs[0x24] = (COM1_ADDR >> 2) & 0xfe;
dev->regs[0x25] = (COM2_ADDR >> 2) & 0xfe; dev->regs[0x25] = (COM2_ADDR >> 2) & 0xfe;
} }
dev->regs[0x26] = (2 << 4) | 3; dev->regs[0x26] = (2 << 4) | 3;
dev->regs[0x27] = (6 << 4) | (dev->id ? 5 : 7); dev->regs[0x27] = (6 << 4) | (dev->id ? 5 : 7);
dev->regs[0x28] = (4 << 4) | 3; dev->regs[0x28] = (4 << 4) | 3;
dev->locked = 0; dev->locked = 0;
dev->rw_locked = 0; dev->rw_locked = 0;
} }
static void static void
fdc37c669_close(void *priv) fdc37c669_close(void *priv)
{ {
@@ -301,7 +294,6 @@ fdc37c669_close(void *priv)
free(dev); free(dev);
} }
static void * static void *
fdc37c669_init(const device_t *info) fdc37c669_init(const device_t *info)
{ {
@@ -311,13 +303,13 @@ fdc37c669_init(const device_t *info)
dev->id = next_id; dev->id = next_id;
if (next_id != 1) if (next_id != 1)
dev->fdc = device_add(&fdc_at_smc_device); dev->fdc = device_add(&fdc_at_smc_device);
dev->uart[0] = device_add_inst(&ns16550_device, (next_id << 1) + 1); dev->uart[0] = device_add_inst(&ns16550_device, (next_id << 1) + 1);
dev->uart[1] = device_add_inst(&ns16550_device, (next_id << 1) + 2); 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, 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_read, NULL, NULL, fdc37c669_write, NULL, NULL, dev);
fdc37c669_reset(dev); fdc37c669_reset(dev);
@@ -327,30 +319,29 @@ fdc37c669_init(const device_t *info)
} }
const device_t fdc37c669_device = { const device_t fdc37c669_device = {
.name = "SMC FDC37C669 Super I/O", .name = "SMC FDC37C669 Super I/O",
.internal_name = "fdc37c669", .internal_name = "fdc37c669",
.flags = 0, .flags = 0,
.local = 0, .local = 0,
.init = fdc37c669_init, .init = fdc37c669_init,
.close = fdc37c669_close, .close = fdc37c669_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t fdc37c669_370_device = { const device_t fdc37c669_370_device = {
.name = "SMC FDC37C669 Super I/O (Port 370h)", .name = "SMC FDC37C669 Super I/O (Port 370h)",
.internal_name = "fdc37c669_370", .internal_name = "fdc37c669_370",
.flags = 0, .flags = 0,
.local = 1, .local = 1,
fdc37c669_init, fdc37c669_init,
fdc37c669_close, fdc37c669_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

View File

@@ -33,28 +33,24 @@
#include "cpu.h" #include "cpu.h"
#include <86box/sio.h> #include <86box/sio.h>
#define AB_RST 0x80
#define AB_RST 0x80
typedef struct { typedef struct {
uint8_t chip_id, is_apm, uint8_t chip_id, is_apm,
tries, tries,
gpio_regs[2], auxio_reg, gpio_regs[2], auxio_reg,
regs[48], regs[48],
ld_regs[11][256]; ld_regs[11][256];
uint16_t gpio_base, /* Set to EA */ uint16_t gpio_base, /* Set to EA */
auxio_base, sio_base; auxio_base, sio_base;
int locked, int locked,
cur_reg; cur_reg;
fdc_t *fdc; fdc_t *fdc;
serial_t *uart[2]; serial_t *uart[2];
} fdc37c67x_t; } fdc37c67x_t;
static void fdc37c67x_write(uint16_t port, uint8_t val, void *priv);
static void fdc37c67x_write(uint16_t port, uint8_t val, void *priv); static uint8_t fdc37c67x_read(uint16_t port, void *priv);
static uint8_t fdc37c67x_read(uint16_t port, void *priv);
static uint16_t static uint16_t
make_port(fdc37c67x_t *dev, uint8_t ld) make_port(fdc37c67x_t *dev, uint8_t ld)
@@ -67,7 +63,6 @@ make_port(fdc37c67x_t *dev, uint8_t ld)
return p; return p;
} }
static uint8_t static uint8_t
fdc37c67x_auxio_read(uint16_t port, void *priv) fdc37c67x_auxio_read(uint16_t port, void *priv)
{ {
@@ -76,7 +71,6 @@ fdc37c67x_auxio_read(uint16_t port, void *priv)
return dev->auxio_reg; return dev->auxio_reg;
} }
static void static void
fdc37c67x_auxio_write(uint16_t port, uint8_t val, void *priv) fdc37c67x_auxio_write(uint16_t port, uint8_t val, void *priv)
{ {
@@ -85,100 +79,93 @@ fdc37c67x_auxio_write(uint16_t port, uint8_t val, void *priv)
dev->auxio_reg = val; dev->auxio_reg = val;
} }
static uint8_t static uint8_t
fdc37c67x_gpio_read(uint16_t port, void *priv) fdc37c67x_gpio_read(uint16_t port, void *priv)
{ {
fdc37c67x_t *dev = (fdc37c67x_t *) priv; fdc37c67x_t *dev = (fdc37c67x_t *) priv;
uint8_t ret = 0xff; uint8_t ret = 0xff;
ret = dev->gpio_regs[port & 1]; ret = dev->gpio_regs[port & 1];
return ret; return ret;
} }
static void static void
fdc37c67x_gpio_write(uint16_t port, uint8_t val, void *priv) fdc37c67x_gpio_write(uint16_t port, uint8_t val, void *priv)
{ {
fdc37c67x_t *dev = (fdc37c67x_t *) priv; fdc37c67x_t *dev = (fdc37c67x_t *) priv;
if (!(port & 1)) if (!(port & 1))
dev->gpio_regs[0] = (dev->gpio_regs[0] & 0xfc) | (val & 0x03); dev->gpio_regs[0] = (dev->gpio_regs[0] & 0xfc) | (val & 0x03);
} }
static void static void
fdc37c67x_fdc_handler(fdc37c67x_t *dev) fdc37c67x_fdc_handler(fdc37c67x_t *dev)
{ {
uint16_t ld_port = 0; uint16_t ld_port = 0;
uint8_t global_enable = !!(dev->regs[0x22] & (1 << 0)); uint8_t global_enable = !!(dev->regs[0x22] & (1 << 0));
uint8_t local_enable = !!dev->ld_regs[0][0x30]; uint8_t local_enable = !!dev->ld_regs[0][0x30];
fdc_remove(dev->fdc); fdc_remove(dev->fdc);
if (global_enable && local_enable) { if (global_enable && local_enable) {
ld_port = make_port(dev, 0) & 0xFFF8; ld_port = make_port(dev, 0) & 0xFFF8;
if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8))
fdc_set_base(dev->fdc, ld_port); fdc_set_base(dev->fdc, ld_port);
} }
} }
static void static void
fdc37c67x_lpt_handler(fdc37c67x_t *dev) fdc37c67x_lpt_handler(fdc37c67x_t *dev)
{ {
uint16_t ld_port = 0; uint16_t ld_port = 0;
uint8_t global_enable = !!(dev->regs[0x22] & (1 << 3)); uint8_t global_enable = !!(dev->regs[0x22] & (1 << 3));
uint8_t local_enable = !!dev->ld_regs[3][0x30]; uint8_t local_enable = !!dev->ld_regs[3][0x30];
uint8_t lpt_irq = dev->ld_regs[3][0x70]; uint8_t lpt_irq = dev->ld_regs[3][0x70];
if (lpt_irq > 15) if (lpt_irq > 15)
lpt_irq = 0xff; lpt_irq = 0xff;
lpt1_remove(); lpt1_remove();
if (global_enable && local_enable) { if (global_enable && local_enable) {
ld_port = make_port(dev, 3) & 0xFFFC; ld_port = make_port(dev, 3) & 0xFFFC;
if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC))
lpt1_init(ld_port); lpt1_init(ld_port);
} }
lpt1_irq(lpt_irq); lpt1_irq(lpt_irq);
} }
static void static void
fdc37c67x_serial_handler(fdc37c67x_t *dev, int uart) fdc37c67x_serial_handler(fdc37c67x_t *dev, int uart)
{ {
uint16_t ld_port = 0; uint16_t ld_port = 0;
uint8_t uart_no = 4 + uart; uint8_t uart_no = 4 + uart;
uint8_t global_enable = !!(dev->regs[0x22] & (1 << uart_no)); uint8_t global_enable = !!(dev->regs[0x22] & (1 << uart_no));
uint8_t local_enable = !!dev->ld_regs[uart_no][0x30]; uint8_t local_enable = !!dev->ld_regs[uart_no][0x30];
serial_remove(dev->uart[uart]); serial_remove(dev->uart[uart]);
if (global_enable && local_enable) { if (global_enable && local_enable) {
ld_port = make_port(dev, uart_no) & 0xFFF8; ld_port = make_port(dev, uart_no) & 0xFFF8;
if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8))
serial_setup(dev->uart[uart], ld_port, dev->ld_regs[uart_no][0x70]); serial_setup(dev->uart[uart], ld_port, dev->ld_regs[uart_no][0x70]);
} }
} }
static void static void
fdc37c67x_auxio_handler(fdc37c67x_t *dev) fdc37c67x_auxio_handler(fdc37c67x_t *dev)
{ {
uint16_t ld_port = 0; uint16_t ld_port = 0;
uint8_t local_enable = !!dev->ld_regs[8][0x30]; uint8_t local_enable = !!dev->ld_regs[8][0x30];
io_removehandler(dev->auxio_base, 0x0001, io_removehandler(dev->auxio_base, 0x0001,
fdc37c67x_auxio_read, NULL, NULL, fdc37c67x_auxio_write, NULL, NULL, dev); fdc37c67x_auxio_read, NULL, NULL, fdc37c67x_auxio_write, NULL, NULL, dev);
if (local_enable) { if (local_enable) {
dev->auxio_base = ld_port = make_port(dev, 8); dev->auxio_base = ld_port = make_port(dev, 8);
if ((ld_port >= 0x0100) && (ld_port <= 0x0FFF)) if ((ld_port >= 0x0100) && (ld_port <= 0x0FFF))
io_sethandler(dev->auxio_base, 0x0001, io_sethandler(dev->auxio_base, 0x0001,
fdc37c67x_auxio_read, NULL, NULL, fdc37c67x_auxio_write, NULL, NULL, dev); fdc37c67x_auxio_read, NULL, NULL, fdc37c67x_auxio_write, NULL, NULL, dev);
} }
} }
static void static void
fdc37c67x_sio_handler(fdc37c67x_t *dev) fdc37c67x_sio_handler(fdc37c67x_t *dev)
{ {
@@ -195,40 +182,38 @@ fdc37c67x_sio_handler(fdc37c67x_t *dev)
#endif #endif
} }
static void static void
fdc37c67x_gpio_handler(fdc37c67x_t *dev) fdc37c67x_gpio_handler(fdc37c67x_t *dev)
{ {
uint16_t ld_port = 0; uint16_t ld_port = 0;
uint8_t local_enable; uint8_t local_enable;
local_enable = !!(dev->regs[0x03] & 0x80); local_enable = !!(dev->regs[0x03] & 0x80);
io_removehandler(dev->gpio_base, 0x0002, io_removehandler(dev->gpio_base, 0x0002,
fdc37c67x_gpio_read, NULL, NULL, fdc37c67x_gpio_write, NULL, NULL, dev); fdc37c67x_gpio_read, NULL, NULL, fdc37c67x_gpio_write, NULL, NULL, dev);
if (local_enable) { if (local_enable) {
switch (dev->regs[0x03] & 0x03) { switch (dev->regs[0x03] & 0x03) {
case 0: case 0:
ld_port = 0xe0; ld_port = 0xe0;
break; break;
case 1: case 1:
ld_port = 0xe2; ld_port = 0xe2;
break; break;
case 2: case 2:
ld_port = 0xe4; ld_port = 0xe4;
break; break;
case 3: case 3:
ld_port = 0xea; /* Default */ ld_port = 0xea; /* Default */
break; break;
} }
dev->gpio_base = ld_port; dev->gpio_base = ld_port;
if (ld_port > 0x0000) if (ld_port > 0x0000)
io_sethandler(dev->gpio_base, 0x0002, io_sethandler(dev->gpio_base, 0x0002,
fdc37c67x_gpio_read, NULL, NULL, fdc37c67x_gpio_write, NULL, NULL, dev); fdc37c67x_gpio_read, NULL, NULL, fdc37c67x_gpio_write, NULL, NULL, dev);
} }
} }
static void static void
fdc37c67x_smi_handler(fdc37c67x_t *dev) fdc37c67x_smi_handler(fdc37c67x_t *dev)
{ {
@@ -243,253 +228,251 @@ fdc37c67x_smi_handler(fdc37c67x_t *dev)
pic_set_smi_irq_mask(10, dev->ld_regs[8][0xb5] & 0x80); pic_set_smi_irq_mask(10, dev->ld_regs[8][0xb5] & 0x80);
} }
static void static void
fdc37c67x_write(uint16_t port, uint8_t val, void *priv) fdc37c67x_write(uint16_t port, uint8_t val, void *priv)
{ {
fdc37c67x_t *dev = (fdc37c67x_t *) priv; fdc37c67x_t *dev = (fdc37c67x_t *) priv;
uint8_t index = (port & 1) ? 0 : 1; uint8_t index = (port & 1) ? 0 : 1;
uint8_t valxor = 0x00, keep = 0x00; uint8_t valxor = 0x00, keep = 0x00;
if (index) { if (index) {
if ((val == 0x55) && !dev->locked) { if ((val == 0x55) && !dev->locked) {
if (dev->tries) { if (dev->tries) {
dev->locked = 1; dev->locked = 1;
fdc_3f1_enable(dev->fdc, 0); fdc_3f1_enable(dev->fdc, 0);
dev->tries = 0; dev->tries = 0;
} else } else
dev->tries++; dev->tries++;
} else { } else {
if (dev->locked) { if (dev->locked) {
if (val == 0xaa) { if (val == 0xaa) {
dev->locked = 0; dev->locked = 0;
fdc_3f1_enable(dev->fdc, 1); fdc_3f1_enable(dev->fdc, 1);
return; return;
} }
dev->cur_reg = val; dev->cur_reg = val;
} else { } else {
if (dev->tries) if (dev->tries)
dev->tries = 0; dev->tries = 0;
} }
} }
return; return;
} else { } else {
if (dev->locked) { if (dev->locked) {
if (dev->cur_reg < 48) { if (dev->cur_reg < 48) {
valxor = val ^ dev->regs[dev->cur_reg]; valxor = val ^ dev->regs[dev->cur_reg];
if ((val == 0x20) || (val == 0x21)) if ((val == 0x20) || (val == 0x21))
return; return;
dev->regs[dev->cur_reg] = val; dev->regs[dev->cur_reg] = val;
} else { } else {
valxor = val ^ dev->ld_regs[dev->regs[7]][dev->cur_reg]; valxor = val ^ dev->ld_regs[dev->regs[7]][dev->cur_reg];
if (((dev->cur_reg & 0xF0) == 0x70) && (dev->regs[7] < 4)) if (((dev->cur_reg & 0xF0) == 0x70) && (dev->regs[7] < 4))
return; return;
/* Block writes to some logical devices. */ /* Block writes to some logical devices. */
if (dev->regs[7] > 0x0a) if (dev->regs[7] > 0x0a)
return; return;
else switch (dev->regs[7]) { else
case 0x01: switch (dev->regs[7]) {
case 0x02: case 0x01:
case 0x07: case 0x02:
return; case 0x07:
} return;
dev->ld_regs[dev->regs[7]][dev->cur_reg] = val | keep; }
} dev->ld_regs[dev->regs[7]][dev->cur_reg] = val | keep;
} else }
return; } else
return;
} }
if (dev->cur_reg < 48) { if (dev->cur_reg < 48) {
switch(dev->cur_reg) { switch (dev->cur_reg) {
case 0x03: case 0x03:
if (valxor & 0x83) if (valxor & 0x83)
fdc37c67x_gpio_handler(dev); fdc37c67x_gpio_handler(dev);
dev->regs[0x03] &= 0x83; dev->regs[0x03] &= 0x83;
break; break;
case 0x22: case 0x22:
if (valxor & 0x01) if (valxor & 0x01)
fdc37c67x_fdc_handler(dev); fdc37c67x_fdc_handler(dev);
if (valxor & 0x08) if (valxor & 0x08)
fdc37c67x_lpt_handler(dev); fdc37c67x_lpt_handler(dev);
if (valxor & 0x10) if (valxor & 0x10)
fdc37c67x_serial_handler(dev, 0); fdc37c67x_serial_handler(dev, 0);
if (valxor & 0x20) if (valxor & 0x20)
fdc37c67x_serial_handler(dev, 1); fdc37c67x_serial_handler(dev, 1);
break; break;
case 0x26: case 0x27: case 0x26:
fdc37c67x_sio_handler(dev); case 0x27:
} fdc37c67x_sio_handler(dev);
}
return; return;
} }
switch(dev->regs[7]) { switch (dev->regs[7]) {
case 0: case 0:
/* FDD */ /* FDD */
switch(dev->cur_reg) { switch (dev->cur_reg) {
case 0x30: case 0x30:
case 0x60: case 0x60:
case 0x61: case 0x61:
if ((dev->cur_reg == 0x30) && (val & 0x01)) if ((dev->cur_reg == 0x30) && (val & 0x01))
dev->regs[0x22] |= 0x01; dev->regs[0x22] |= 0x01;
if (valxor) if (valxor)
fdc37c67x_fdc_handler(dev); fdc37c67x_fdc_handler(dev);
break; break;
case 0xF0: case 0xF0:
if (valxor & 0x01) if (valxor & 0x01)
fdc_update_enh_mode(dev->fdc, val & 0x01); fdc_update_enh_mode(dev->fdc, val & 0x01);
if (valxor & 0x10) if (valxor & 0x10)
fdc_set_swap(dev->fdc, (val & 0x10) >> 4); fdc_set_swap(dev->fdc, (val & 0x10) >> 4);
break; break;
case 0xF1: case 0xF1:
if (valxor & 0xC) if (valxor & 0xC)
fdc_update_densel_force(dev->fdc, (val & 0xc) >> 2); fdc_update_densel_force(dev->fdc, (val & 0xc) >> 2);
break; break;
case 0xF2: case 0xF2:
if (valxor & 0xC0) if (valxor & 0xC0)
fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6); fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6);
if (valxor & 0x30) if (valxor & 0x30)
fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4); fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4);
if (valxor & 0x0C) if (valxor & 0x0C)
fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2); fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2);
if (valxor & 0x03) if (valxor & 0x03)
fdc_update_rwc(dev->fdc, 0, (val & 0x03)); fdc_update_rwc(dev->fdc, 0, (val & 0x03));
break; break;
case 0xF4: case 0xF4:
if (valxor & 0x18) if (valxor & 0x18)
fdc_update_drvrate(dev->fdc, 0, (val & 0x18) >> 3); fdc_update_drvrate(dev->fdc, 0, (val & 0x18) >> 3);
break; break;
case 0xF5: case 0xF5:
if (valxor & 0x18) if (valxor & 0x18)
fdc_update_drvrate(dev->fdc, 1, (val & 0x18) >> 3); fdc_update_drvrate(dev->fdc, 1, (val & 0x18) >> 3);
break; break;
case 0xF6: case 0xF6:
if (valxor & 0x18) if (valxor & 0x18)
fdc_update_drvrate(dev->fdc, 2, (val & 0x18) >> 3); fdc_update_drvrate(dev->fdc, 2, (val & 0x18) >> 3);
break; break;
case 0xF7: case 0xF7:
if (valxor & 0x18) if (valxor & 0x18)
fdc_update_drvrate(dev->fdc, 3, (val & 0x18) >> 3); fdc_update_drvrate(dev->fdc, 3, (val & 0x18) >> 3);
break; break;
} }
break; break;
case 3: case 3:
/* Parallel port */ /* Parallel port */
switch(dev->cur_reg) { switch (dev->cur_reg) {
case 0x30: case 0x30:
case 0x60: case 0x60:
case 0x61: case 0x61:
case 0x70: case 0x70:
if ((dev->cur_reg == 0x30) && (val & 0x01)) if ((dev->cur_reg == 0x30) && (val & 0x01))
dev->regs[0x22] |= 0x08; dev->regs[0x22] |= 0x08;
if (valxor) if (valxor)
fdc37c67x_lpt_handler(dev); fdc37c67x_lpt_handler(dev);
if (dev->cur_reg == 0x70) if (dev->cur_reg == 0x70)
fdc37c67x_smi_handler(dev); fdc37c67x_smi_handler(dev);
break; break;
} }
break; break;
case 4: case 4:
/* Serial port 1 */ /* Serial port 1 */
switch(dev->cur_reg) { switch (dev->cur_reg) {
case 0x30: case 0x30:
case 0x60: case 0x60:
case 0x61: case 0x61:
case 0x70: case 0x70:
if ((dev->cur_reg == 0x30) && (val & 0x01)) if ((dev->cur_reg == 0x30) && (val & 0x01))
dev->regs[0x22] |= 0x10; dev->regs[0x22] |= 0x10;
if (valxor) if (valxor)
fdc37c67x_serial_handler(dev, 0); fdc37c67x_serial_handler(dev, 0);
if (dev->cur_reg == 0x70) if (dev->cur_reg == 0x70)
fdc37c67x_smi_handler(dev); fdc37c67x_smi_handler(dev);
break; break;
} }
break; break;
case 5: case 5:
/* Serial port 2 */ /* Serial port 2 */
switch(dev->cur_reg) { switch (dev->cur_reg) {
case 0x30: case 0x30:
case 0x60: case 0x60:
case 0x61: case 0x61:
case 0x70: case 0x70:
if ((dev->cur_reg == 0x30) && (val & 0x01)) if ((dev->cur_reg == 0x30) && (val & 0x01))
dev->regs[0x22] |= 0x20; dev->regs[0x22] |= 0x20;
if (valxor) if (valxor)
fdc37c67x_serial_handler(dev, 1); fdc37c67x_serial_handler(dev, 1);
if (dev->cur_reg == 0x70) if (dev->cur_reg == 0x70)
fdc37c67x_smi_handler(dev); fdc37c67x_smi_handler(dev);
break; break;
} }
break; break;
case 8: case 8:
/* Auxiliary I/O */ /* Auxiliary I/O */
switch(dev->cur_reg) { switch (dev->cur_reg) {
case 0x30: case 0x30:
case 0x60: case 0x60:
case 0x61: case 0x61:
case 0x70: case 0x70:
if (valxor) if (valxor)
fdc37c67x_auxio_handler(dev); fdc37c67x_auxio_handler(dev);
break; break;
case 0xb4: case 0xb4:
case 0xb5: case 0xb5:
fdc37c67x_smi_handler(dev); fdc37c67x_smi_handler(dev);
break; break;
} }
break; break;
} }
} }
static uint8_t static uint8_t
fdc37c67x_read(uint16_t port, void *priv) fdc37c67x_read(uint16_t port, void *priv)
{ {
fdc37c67x_t *dev = (fdc37c67x_t *) priv; fdc37c67x_t *dev = (fdc37c67x_t *) priv;
uint8_t index = (port & 1) ? 0 : 1; uint8_t index = (port & 1) ? 0 : 1;
uint8_t ret = 0xff; uint8_t ret = 0xff;
uint16_t smi_stat = pic_get_smi_irq_status(); uint16_t smi_stat = pic_get_smi_irq_status();
int f_irq = dev->ld_regs[0][0x70]; int f_irq = dev->ld_regs[0][0x70];
int p_irq = dev->ld_regs[3][0x70]; int p_irq = dev->ld_regs[3][0x70];
int s1_irq = dev->ld_regs[4][0x70]; int s1_irq = dev->ld_regs[4][0x70];
int s2_irq = dev->ld_regs[5][0x70]; int s2_irq = dev->ld_regs[5][0x70];
if (dev->locked) { if (dev->locked) {
if (index) if (index)
ret = dev->cur_reg; ret = dev->cur_reg;
else { else {
if (dev->cur_reg < 0x30) { if (dev->cur_reg < 0x30) {
if (dev->cur_reg == 0x20) if (dev->cur_reg == 0x20)
ret = dev->chip_id; ret = dev->chip_id;
else else
ret = dev->regs[dev->cur_reg]; ret = dev->regs[dev->cur_reg];
} else { } else {
if ((dev->regs[7] == 0) && (dev->cur_reg == 0xF2)) { if ((dev->regs[7] == 0) && (dev->cur_reg == 0xF2)) {
ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6));
(fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6)); } else
} else ret = dev->ld_regs[dev->regs[7]][dev->cur_reg];
ret = dev->ld_regs[dev->regs[7]][dev->cur_reg];
/* TODO: 8042 P1.2 SMI#. */ /* TODO: 8042 P1.2 SMI#. */
if ((dev->regs[7] == 8) && (dev->cur_reg == 0xb6)) { if ((dev->regs[7] == 8) && (dev->cur_reg == 0xb6)) {
ret = dev->ld_regs[dev->regs[7]][dev->cur_reg] & 0xe1; ret = dev->ld_regs[dev->regs[7]][dev->cur_reg] & 0xe1;
ret |= ((!!(smi_stat & (1 << p_irq))) << 1); ret |= ((!!(smi_stat & (1 << p_irq))) << 1);
ret |= ((!!(smi_stat & (1 << s2_irq))) << 2); ret |= ((!!(smi_stat & (1 << s2_irq))) << 2);
ret |= ((!!(smi_stat & (1 << s1_irq))) << 3); ret |= ((!!(smi_stat & (1 << s1_irq))) << 3);
ret |= ((!!(smi_stat & (1 << f_irq))) << 4); ret |= ((!!(smi_stat & (1 << f_irq))) << 4);
} else if ((dev->regs[7] == 8) && (dev->cur_reg == 0xb7)) { } else if ((dev->regs[7] == 8) && (dev->cur_reg == 0xb7)) {
ret = dev->ld_regs[dev->regs[7]][dev->cur_reg] & 0xec; ret = dev->ld_regs[dev->regs[7]][dev->cur_reg] & 0xec;
ret |= ((!!(smi_stat & (1 << 12))) << 0); ret |= ((!!(smi_stat & (1 << 12))) << 0);
ret |= ((!!(smi_stat & (1 << 1))) << 1); ret |= ((!!(smi_stat & (1 << 1))) << 1);
ret |= ((!!(smi_stat & (1 << 10))) << 4); ret |= ((!!(smi_stat & (1 << 10))) << 4);
} }
} }
} }
} }
return ret; return ret;
} }
static void static void
fdc37c67x_reset(fdc37c67x_t *dev) fdc37c67x_reset(fdc37c67x_t *dev)
{ {
@@ -505,7 +488,7 @@ fdc37c67x_reset(fdc37c67x_t *dev)
dev->regs[0x27] = 0x03; dev->regs[0x27] = 0x03;
for (i = 0; i < 11; i++) for (i = 0; i < 11; i++)
memset(dev->ld_regs[i], 0, 256); memset(dev->ld_regs[i], 0, 256);
/* Logical device 0: FDD */ /* Logical device 0: FDD */
dev->ld_regs[0][0x30] = 1; dev->ld_regs[0][0x30] = 1;
@@ -565,7 +548,6 @@ fdc37c67x_reset(fdc37c67x_t *dev)
dev->locked = 0; dev->locked = 0;
} }
static void static void
fdc37c67x_close(void *priv) fdc37c67x_close(void *priv)
{ {
@@ -574,7 +556,6 @@ fdc37c67x_close(void *priv)
free(dev); free(dev);
} }
static void * static void *
fdc37c67x_init(const device_t *info) fdc37c67x_init(const device_t *info)
{ {
@@ -595,24 +576,23 @@ fdc37c67x_init(const device_t *info)
fdc37c67x_reset(dev); fdc37c67x_reset(dev);
io_sethandler(FDC_SECONDARY_ADDR, 0x0002, io_sethandler(FDC_SECONDARY_ADDR, 0x0002,
fdc37c67x_read, NULL, NULL, fdc37c67x_write, NULL, NULL, dev); fdc37c67x_read, NULL, NULL, fdc37c67x_write, NULL, NULL, dev);
io_sethandler(FDC_PRIMARY_ADDR, 0x0002, io_sethandler(FDC_PRIMARY_ADDR, 0x0002,
fdc37c67x_read, NULL, NULL, fdc37c67x_write, NULL, NULL, dev); fdc37c67x_read, NULL, NULL, fdc37c67x_write, NULL, NULL, dev);
return dev; return dev;
} }
const device_t fdc37c67x_device = { const device_t fdc37c67x_device = {
.name = "SMC FDC37C67X Super I/O", .name = "SMC FDC37C67X Super I/O",
.internal_name = "fdc37c67x", .internal_name = "fdc37c67x",
.flags = 0, .flags = 0,
.local = 0x40, .local = 0x40,
.init = fdc37c67x_init, .init = fdc37c67x_init,
.close = fdc37c67x_close, .close = fdc37c67x_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

View File

@@ -35,207 +35,197 @@
#include <86box/fdc.h> #include <86box/fdc.h>
#include <86box/sio.h> #include <86box/sio.h>
typedef struct { typedef struct {
uint8_t max_reg, chip_id, uint8_t max_reg, chip_id,
tries, has_ide, tries, has_ide,
regs[16]; regs[16];
int cur_reg, int cur_reg,
com3_addr, com4_addr; com3_addr, com4_addr;
fdc_t *fdc; fdc_t *fdc;
serial_t *uart[2]; serial_t *uart[2];
} fdc37c6xx_t; } fdc37c6xx_t;
static void static void
set_com34_addr(fdc37c6xx_t *dev) set_com34_addr(fdc37c6xx_t *dev)
{ {
switch (dev->regs[1] & 0x60) { switch (dev->regs[1] & 0x60) {
case 0x00: case 0x00:
dev->com3_addr = 0x338; dev->com3_addr = 0x338;
dev->com4_addr = 0x238; dev->com4_addr = 0x238;
break; break;
case 0x20: case 0x20:
dev->com3_addr = COM3_ADDR; dev->com3_addr = COM3_ADDR;
dev->com4_addr = COM4_ADDR; dev->com4_addr = COM4_ADDR;
break; break;
case 0x40: case 0x40:
dev->com3_addr = COM3_ADDR; dev->com3_addr = COM3_ADDR;
dev->com4_addr = 0x2e0; dev->com4_addr = 0x2e0;
break; break;
case 0x60: case 0x60:
dev->com3_addr = 0x220; dev->com3_addr = 0x220;
dev->com4_addr = 0x228; dev->com4_addr = 0x228;
break; break;
} }
} }
static void static void
set_serial_addr(fdc37c6xx_t *dev, int port) set_serial_addr(fdc37c6xx_t *dev, int port)
{ {
uint8_t shift = (port << 2); uint8_t shift = (port << 2);
double clock_src = 24000000.0 / 13.0; double clock_src = 24000000.0 / 13.0;
if (dev->regs[4] & (1 << (4 + port))) if (dev->regs[4] & (1 << (4 + port)))
clock_src = 24000000.0 / 12.0; clock_src = 24000000.0 / 12.0;
serial_remove(dev->uart[port]); serial_remove(dev->uart[port]);
if (dev->regs[2] & (4 << shift)) { if (dev->regs[2] & (4 << shift)) {
switch ((dev->regs[2] >> shift) & 3) { switch ((dev->regs[2] >> shift) & 3) {
case 0: case 0:
serial_setup(dev->uart[port], COM1_ADDR, COM1_IRQ); serial_setup(dev->uart[port], COM1_ADDR, COM1_IRQ);
break; break;
case 1: case 1:
serial_setup(dev->uart[port], COM2_ADDR, COM2_IRQ); serial_setup(dev->uart[port], COM2_ADDR, COM2_IRQ);
break; break;
case 2: case 2:
serial_setup(dev->uart[port], dev->com3_addr, COM3_IRQ); serial_setup(dev->uart[port], dev->com3_addr, COM3_IRQ);
break; break;
case 3: case 3:
serial_setup(dev->uart[port], dev->com4_addr, COM4_IRQ); serial_setup(dev->uart[port], dev->com4_addr, COM4_IRQ);
break; break;
} }
} }
serial_set_clock_src(dev->uart[port], clock_src); serial_set_clock_src(dev->uart[port], clock_src);
} }
static void static void
lpt1_handler(fdc37c6xx_t *dev) lpt1_handler(fdc37c6xx_t *dev)
{ {
lpt1_remove(); lpt1_remove();
switch (dev->regs[1] & 3) { switch (dev->regs[1] & 3) {
case 1: case 1:
lpt1_init(LPT_MDA_ADDR); lpt1_init(LPT_MDA_ADDR);
lpt1_irq(7); lpt1_irq(7);
break; break;
case 2: case 2:
lpt1_init(LPT1_ADDR); lpt1_init(LPT1_ADDR);
lpt1_irq(7 /*5*/); lpt1_irq(7 /*5*/);
break; break;
case 3: case 3:
lpt1_init(LPT2_ADDR); lpt1_init(LPT2_ADDR);
lpt1_irq(7 /*5*/); lpt1_irq(7 /*5*/);
break; break;
} }
} }
static void static void
fdc_handler(fdc37c6xx_t *dev) fdc_handler(fdc37c6xx_t *dev)
{ {
fdc_remove(dev->fdc); fdc_remove(dev->fdc);
if (dev->regs[0] & 0x10) if (dev->regs[0] & 0x10)
fdc_set_base(dev->fdc, (dev->regs[5] & 0x01) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); fdc_set_base(dev->fdc, (dev->regs[5] & 0x01) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
} }
static void static void
ide_handler(fdc37c6xx_t *dev) ide_handler(fdc37c6xx_t *dev)
{ {
/* TODO: Make an ide_disable(channel) and ide_enable(channel) so we can simplify this. */ /* TODO: Make an ide_disable(channel) and ide_enable(channel) so we can simplify this. */
if (dev->has_ide == 2) { if (dev->has_ide == 2) {
ide_sec_disable(); ide_sec_disable();
ide_set_base(1, (dev->regs[0x05] & 0x02) ? 0x170 : 0x1f0); ide_set_base(1, (dev->regs[0x05] & 0x02) ? 0x170 : 0x1f0);
ide_set_side(1, (dev->regs[0x05] & 0x02) ? 0x376 : 0x3f6); ide_set_side(1, (dev->regs[0x05] & 0x02) ? 0x376 : 0x3f6);
if (dev->regs[0x00] & 0x01) if (dev->regs[0x00] & 0x01)
ide_sec_enable(); ide_sec_enable();
} else if (dev->has_ide == 1) { } else if (dev->has_ide == 1) {
ide_pri_disable(); ide_pri_disable();
ide_set_base(0, (dev->regs[0x05] & 0x02) ? 0x170 : 0x1f0); ide_set_base(0, (dev->regs[0x05] & 0x02) ? 0x170 : 0x1f0);
ide_set_side(0, (dev->regs[0x05] & 0x02) ? 0x376 : 0x3f6); ide_set_side(0, (dev->regs[0x05] & 0x02) ? 0x376 : 0x3f6);
if (dev->regs[0x00] & 0x01) if (dev->regs[0x00] & 0x01)
ide_pri_enable(); ide_pri_enable();
} }
} }
static void static void
fdc37c6xx_write(uint16_t port, uint8_t val, void *priv) fdc37c6xx_write(uint16_t port, uint8_t val, void *priv)
{ {
fdc37c6xx_t *dev = (fdc37c6xx_t *) priv; fdc37c6xx_t *dev = (fdc37c6xx_t *) priv;
uint8_t valxor = 0; uint8_t valxor = 0;
if (dev->tries == 2) { if (dev->tries == 2) {
if (port == FDC_PRIMARY_ADDR) { if (port == FDC_PRIMARY_ADDR) {
if (val == 0xaa) if (val == 0xaa)
dev->tries = 0; dev->tries = 0;
else else
dev->cur_reg = val; dev->cur_reg = val;
} else { } else {
if (dev->cur_reg > dev->max_reg) if (dev->cur_reg > dev->max_reg)
return; return;
valxor = val ^ dev->regs[dev->cur_reg]; valxor = val ^ dev->regs[dev->cur_reg];
dev->regs[dev->cur_reg] = val; dev->regs[dev->cur_reg] = val;
switch(dev->cur_reg) { switch (dev->cur_reg) {
case 0: case 0:
if (dev->has_ide && (valxor & 0x01)) if (dev->has_ide && (valxor & 0x01))
ide_handler(dev); ide_handler(dev);
if (valxor & 0x10) if (valxor & 0x10)
fdc_handler(dev); fdc_handler(dev);
break; break;
case 1: case 1:
if (valxor & 3) if (valxor & 3)
lpt1_handler(dev); lpt1_handler(dev);
if (valxor & 0x60) { if (valxor & 0x60) {
set_com34_addr(dev); set_com34_addr(dev);
set_serial_addr(dev, 0); set_serial_addr(dev, 0);
set_serial_addr(dev, 1); set_serial_addr(dev, 1);
} }
break; break;
case 2: case 2:
if (valxor & 7) if (valxor & 7)
set_serial_addr(dev, 0); set_serial_addr(dev, 0);
if (valxor & 0x70) if (valxor & 0x70)
set_serial_addr(dev, 1); set_serial_addr(dev, 1);
break; break;
case 3: case 3:
if (valxor & 2) if (valxor & 2)
fdc_update_enh_mode(dev->fdc, (dev->regs[3] & 2) ? 1 : 0); fdc_update_enh_mode(dev->fdc, (dev->regs[3] & 2) ? 1 : 0);
break; break;
case 4: case 4:
if (valxor & 0x10) if (valxor & 0x10)
set_serial_addr(dev, 0); set_serial_addr(dev, 0);
if (valxor & 0x20) if (valxor & 0x20)
set_serial_addr(dev, 1); set_serial_addr(dev, 1);
break; break;
case 5: case 5:
if (valxor & 0x01) if (valxor & 0x01)
fdc_handler(dev); fdc_handler(dev);
if (dev->has_ide && (valxor & 0x02)) if (dev->has_ide && (valxor & 0x02))
ide_handler(dev); ide_handler(dev);
if (valxor & 0x18) if (valxor & 0x18)
fdc_update_densel_force(dev->fdc, (dev->regs[5] & 0x18) >> 3); fdc_update_densel_force(dev->fdc, (dev->regs[5] & 0x18) >> 3);
if (valxor & 0x20) if (valxor & 0x20)
fdc_set_swap(dev->fdc, (dev->regs[5] & 0x20) >> 5); fdc_set_swap(dev->fdc, (dev->regs[5] & 0x20) >> 5);
break; break;
} }
} }
} else if ((port == FDC_PRIMARY_ADDR) && (val == 0x55)) } else if ((port == FDC_PRIMARY_ADDR) && (val == 0x55))
dev->tries++; dev->tries++;
} }
static uint8_t static uint8_t
fdc37c6xx_read(uint16_t port, void *priv) fdc37c6xx_read(uint16_t port, void *priv)
{ {
fdc37c6xx_t *dev = (fdc37c6xx_t *) priv; fdc37c6xx_t *dev = (fdc37c6xx_t *) priv;
uint8_t ret = 0x00; uint8_t ret = 0x00;
if (dev->tries == 2) { if (dev->tries == 2) {
if (port == 0x3f1) if (port == 0x3f1)
ret = dev->regs[dev->cur_reg]; ret = dev->regs[dev->cur_reg];
} }
return ret; return ret;
} }
static void static void
fdc37c6xx_reset(fdc37c6xx_t *dev) fdc37c6xx_reset(fdc37c6xx_t *dev)
{ {
@@ -258,18 +248,20 @@ fdc37c6xx_reset(fdc37c6xx_t *dev)
memset(dev->regs, 0, 16); memset(dev->regs, 0, 16);
switch (dev->chip_id) { switch (dev->chip_id) {
case 0x63: case 0x65: case 0x63:
dev->max_reg = 0x0f; case 0x65:
dev->regs[0x0] = 0x3b; dev->max_reg = 0x0f;
break; dev->regs[0x0] = 0x3b;
case 0x64: case 0x66: break;
dev->max_reg = 0x0f; case 0x64:
dev->regs[0x0] = 0x2b; case 0x66:
break; dev->max_reg = 0x0f;
default: dev->regs[0x0] = 0x2b;
dev->max_reg = (dev->chip_id >= 0x61) ? 0x03 : 0x02; break;
dev->regs[0x0] = 0x3f; default:
break; dev->max_reg = (dev->chip_id >= 0x61) ? 0x03 : 0x02;
dev->regs[0x0] = 0x3f;
break;
} }
dev->regs[0x1] = 0x9f; dev->regs[0x1] = 0x9f;
@@ -277,12 +269,12 @@ fdc37c6xx_reset(fdc37c6xx_t *dev)
dev->regs[0x3] = 0x78; dev->regs[0x3] = 0x78;
if (dev->chip_id >= 0x63) { if (dev->chip_id >= 0x63) {
dev->regs[0x6] = 0xff; dev->regs[0x6] = 0xff;
dev->regs[0xd] = dev->chip_id; dev->regs[0xd] = dev->chip_id;
if (dev->chip_id >= 0x65) if (dev->chip_id >= 0x65)
dev->regs[0xe] = 0x02; dev->regs[0xe] = 0x02;
else else
dev->regs[0xe] = 0x01; dev->regs[0xe] = 0x01;
} }
set_serial_addr(dev, 0); set_serial_addr(dev, 0);
@@ -293,10 +285,9 @@ fdc37c6xx_reset(fdc37c6xx_t *dev)
fdc_handler(dev); fdc_handler(dev);
if (dev->has_ide) if (dev->has_ide)
ide_handler(dev); ide_handler(dev);
} }
static void static void
fdc37c6xx_close(void *priv) fdc37c6xx_close(void *priv)
{ {
@@ -305,7 +296,6 @@ fdc37c6xx_close(void *priv)
free(dev); free(dev);
} }
static void * static void *
fdc37c6xx_init(const device_t *info) fdc37c6xx_init(const device_t *info)
{ {
@@ -318,15 +308,15 @@ fdc37c6xx_init(const device_t *info)
dev->has_ide = (info->local >> 8) & 0xff; dev->has_ide = (info->local >> 8) & 0xff;
if (dev->chip_id >= 0x63) { if (dev->chip_id >= 0x63) {
dev->uart[0] = device_add_inst(&ns16550_device, 1); dev->uart[0] = device_add_inst(&ns16550_device, 1);
dev->uart[1] = device_add_inst(&ns16550_device, 2); dev->uart[1] = device_add_inst(&ns16550_device, 2);
} else { } else {
dev->uart[0] = device_add_inst(&ns16450_device, 1); dev->uart[0] = device_add_inst(&ns16450_device, 1);
dev->uart[1] = device_add_inst(&ns16450_device, 2); dev->uart[1] = device_add_inst(&ns16450_device, 2);
} }
io_sethandler(FDC_PRIMARY_ADDR, 0x0002, io_sethandler(FDC_PRIMARY_ADDR, 0x0002,
fdc37c6xx_read, NULL, NULL, fdc37c6xx_write, NULL, NULL, dev); fdc37c6xx_read, NULL, NULL, fdc37c6xx_write, NULL, NULL, dev);
fdc37c6xx_reset(dev); fdc37c6xx_reset(dev);
@@ -336,127 +326,127 @@ fdc37c6xx_init(const device_t *info)
/* The three appear to differ only in the chip ID, if I /* The three appear to differ only in the chip ID, if I
understood their datasheets correctly. */ understood their datasheets correctly. */
const device_t fdc37c651_device = { const device_t fdc37c651_device = {
.name = "SMC FDC37C651 Super I/O", .name = "SMC FDC37C651 Super I/O",
.internal_name = "fdc37c651", .internal_name = "fdc37c651",
.flags = 0, .flags = 0,
.local = 0x51, .local = 0x51,
.init = fdc37c6xx_init, .init = fdc37c6xx_init,
.close = fdc37c6xx_close, .close = fdc37c6xx_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t fdc37c651_ide_device = { const device_t fdc37c651_ide_device = {
.name = "SMC FDC37C651 Super I/O (With IDE)", .name = "SMC FDC37C651 Super I/O (With IDE)",
.internal_name = "fdc37c651_ide", .internal_name = "fdc37c651_ide",
.flags = 0, .flags = 0,
.local = 0x151, .local = 0x151,
.init = fdc37c6xx_init, .init = fdc37c6xx_init,
.close = fdc37c6xx_close, .close = fdc37c6xx_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t fdc37c661_device = { const device_t fdc37c661_device = {
.name = "SMC FDC37C661 Super I/O", .name = "SMC FDC37C661 Super I/O",
.internal_name = "fdc37c661", .internal_name = "fdc37c661",
.flags = 0, .flags = 0,
.local = 0x61, .local = 0x61,
.init = fdc37c6xx_init, .init = fdc37c6xx_init,
.close = fdc37c6xx_close, .close = fdc37c6xx_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t fdc37c661_ide_device = { const device_t fdc37c661_ide_device = {
.name = "SMC FDC37C661 Super I/O (With IDE)", .name = "SMC FDC37C661 Super I/O (With IDE)",
.internal_name = "fdc37c661_ide", .internal_name = "fdc37c661_ide",
.flags = 0, .flags = 0,
.local = 0x161, .local = 0x161,
.init = fdc37c6xx_init, .init = fdc37c6xx_init,
.close = fdc37c6xx_close, .close = fdc37c6xx_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t fdc37c663_device = { const device_t fdc37c663_device = {
.name = "SMC FDC37C663 Super I/O", .name = "SMC FDC37C663 Super I/O",
.internal_name = "fdc37c663", .internal_name = "fdc37c663",
.flags = 0, .flags = 0,
.local = 0x63, .local = 0x63,
.init = fdc37c6xx_init, .init = fdc37c6xx_init,
.close = fdc37c6xx_close, .close = fdc37c6xx_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t fdc37c663_ide_device = { const device_t fdc37c663_ide_device = {
.name = "SMC FDC37C663 Super I/O (With IDE)", .name = "SMC FDC37C663 Super I/O (With IDE)",
.internal_name = "fdc37c663_ide", .internal_name = "fdc37c663_ide",
.flags = 0, .flags = 0,
.local = 0x163, .local = 0x163,
.init = fdc37c6xx_init, .init = fdc37c6xx_init,
.close = fdc37c6xx_close, .close = fdc37c6xx_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t fdc37c665_device = { const device_t fdc37c665_device = {
.name = "SMC FDC37C665 Super I/O", .name = "SMC FDC37C665 Super I/O",
.internal_name = "fdc37c665", .internal_name = "fdc37c665",
.flags = 0, .flags = 0,
.local = 0x65, .local = 0x65,
.init = fdc37c6xx_init, .init = fdc37c6xx_init,
.close = fdc37c6xx_close, .close = fdc37c6xx_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t fdc37c665_ide_device = { const device_t fdc37c665_ide_device = {
.name = "SMC FDC37C665 Super I/O (With IDE)", .name = "SMC FDC37C665 Super I/O (With IDE)",
.internal_name = "fdc37c665_ide", .internal_name = "fdc37c665_ide",
.flags = 0, .flags = 0,
.local = 0x265, .local = 0x265,
.init = fdc37c6xx_init, .init = fdc37c6xx_init,
.close = fdc37c6xx_close, .close = fdc37c6xx_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t fdc37c666_device = { const device_t fdc37c666_device = {
.name = "SMC FDC37C666 Super I/O", .name = "SMC FDC37C666 Super I/O",
.internal_name = "fdc37c666", .internal_name = "fdc37c666",
.flags = 0, .flags = 0,
.local = 0x66, .local = 0x66,
.init = fdc37c6xx_init, .init = fdc37c6xx_init,
.close = fdc37c6xx_close, .close = fdc37c6xx_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -31,23 +31,21 @@
#include <86box/fdc.h> #include <86box/fdc.h>
#include <86box/sio.h> #include <86box/sio.h>
#define SIO_INDEX_PORT dev->sio_index_port #define SIO_INDEX_PORT dev->sio_index_port
#define INDEX dev->index #define INDEX dev->index
/* Current Logical Device Number */ /* Current Logical Device Number */
#define CURRENT_LOGICAL_DEVICE dev->regs[0x07] #define CURRENT_LOGICAL_DEVICE dev->regs[0x07]
/* Global Device Configuration */ /* Global Device Configuration */
#define ENABLED(ld) dev->device_regs[ld][0x30] #define ENABLED(ld) dev->device_regs[ld][0x30]
#define BASE_ADDRESS(ld) ((dev->device_regs[ld][0x60] << 8) | \ #define BASE_ADDRESS(ld) ((dev->device_regs[ld][0x60] << 8) | (dev->device_regs[ld][0x61]))
(dev->device_regs[ld][0x61])) #define IRQ(ld) dev->device_regs[ld][0x70]
#define IRQ(ld) dev->device_regs[ld][0x70] #define DMA(ld) dev->device_regs[ld][0x74]
#define DMA(ld) dev->device_regs[ld][0x74]
/* Miscellaneous Chip Functionality */ /* Miscellaneous Chip Functionality */
#define SOFT_RESET (val & 0x01) #define SOFT_RESET (val & 0x01)
#define POWER_CONTROL dev->regs[0x22] #define POWER_CONTROL dev->regs[0x22]
#ifdef ENABLE_FDC37M60X_LOG #ifdef ENABLE_FDC37M60X_LOG
int fdc37m60x_do_log = ENABLE_FDC37M60X_LOG; int fdc37m60x_do_log = ENABLE_FDC37M60X_LOG;
@@ -57,117 +55,120 @@ fdc37m60x_log(const char *fmt, ...)
{ {
va_list ap; va_list ap;
if (fdc37m60x_do_log) if (fdc37m60x_do_log) {
{
va_start(ap, fmt); va_start(ap, fmt);
pclog_ex(fmt, ap); pclog_ex(fmt, ap);
va_end(ap); va_end(ap);
} }
} }
#else #else
#define fdc37m60x_log(fmt, ...) # define fdc37m60x_log(fmt, ...)
#endif #endif
typedef struct typedef struct
{ {
uint8_t index, regs[256], device_regs[10][256], cfg_lock, ide_function; uint8_t index, regs[256], device_regs[10][256], cfg_lock, ide_function;
uint16_t sio_index_port; uint16_t sio_index_port;
fdc_t * fdc; fdc_t *fdc;
serial_t * uart[2]; serial_t *uart[2];
} fdc37m60x_t; } fdc37m60x_t;
static void fdc37m60x_fdc_handler(fdc37m60x_t *dev);
static void fdc37m60x_fdc_handler(fdc37m60x_t *dev); static void fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev);
static void fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev); static void fdc37m60x_lpt_handler(fdc37m60x_t *dev);
static void fdc37m60x_lpt_handler(fdc37m60x_t *dev); static void fdc37m60x_logical_device_handler(fdc37m60x_t *dev);
static void fdc37m60x_logical_device_handler(fdc37m60x_t *dev); static void fdc37m60x_reset(void *priv);
static void fdc37m60x_reset(void *priv);
static void static void
fdc37m60x_write(uint16_t addr, uint8_t val, void *priv) fdc37m60x_write(uint16_t addr, uint8_t val, void *priv)
{ {
fdc37m60x_t *dev = (fdc37m60x_t *)priv; fdc37m60x_t *dev = (fdc37m60x_t *) priv;
if (addr & 1) { if (addr & 1) {
if (!dev->cfg_lock) { if (!dev->cfg_lock) {
switch (INDEX) { switch (INDEX) {
/* Global Configuration */ /* Global Configuration */
case 0x02: case 0x02:
dev->regs[INDEX] = val; dev->regs[INDEX] = val;
if (SOFT_RESET) if (SOFT_RESET)
fdc37m60x_reset(dev); fdc37m60x_reset(dev);
break; break;
case 0x07: case 0x07:
CURRENT_LOGICAL_DEVICE = val; CURRENT_LOGICAL_DEVICE = val;
break; break;
case 0x22: case 0x22:
POWER_CONTROL = val & 0x3f; POWER_CONTROL = val & 0x3f;
break; break;
case 0x23: case 0x23:
dev->regs[INDEX] = val & 0x3f; dev->regs[INDEX] = val & 0x3f;
break; break;
case 0x24: case 0x24:
dev->regs[INDEX] = val & 0x4e; dev->regs[INDEX] = val & 0x4e;
break; break;
case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2b:
case 0x2f: case 0x2c:
dev->regs[INDEX] = val; case 0x2d:
break; case 0x2e:
case 0x2f:
dev->regs[INDEX] = val;
break;
/* Device Configuration */ /* Device Configuration */
case 0x30: case 0x30:
case 0x60: case 0x61: case 0x60:
case 0x70: case 0x61:
case 0x74: case 0x70:
case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0x74:
case 0xf4: case 0xf5: case 0xf6: case 0xf7: case 0xf0:
if (CURRENT_LOGICAL_DEVICE <= 0x81) /* Avoid Overflow */ case 0xf1:
dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] = (INDEX == 0x30) ? (val & 1) : val; case 0xf2:
fdc37m60x_logical_device_handler(dev); case 0xf3:
break; case 0xf4:
} case 0xf5:
case 0xf6:
case 0xf7:
if (CURRENT_LOGICAL_DEVICE <= 0x81) /* Avoid Overflow */
dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] = (INDEX == 0x30) ? (val & 1) : val;
fdc37m60x_logical_device_handler(dev);
break;
}
} }
} else { } else {
/* Enter/Escape Configuration Mode */ /* Enter/Escape Configuration Mode */
if (val == 0x55) if (val == 0x55)
dev->cfg_lock = 0; dev->cfg_lock = 0;
else if (!dev->cfg_lock && (val == 0xaa)) else if (!dev->cfg_lock && (val == 0xaa))
dev->cfg_lock = 1; dev->cfg_lock = 1;
else if (!dev->cfg_lock) else if (!dev->cfg_lock)
INDEX = val; INDEX = val;
} }
} }
static uint8_t static uint8_t
fdc37m60x_read(uint16_t addr, void *priv) fdc37m60x_read(uint16_t addr, void *priv)
{ {
fdc37m60x_t *dev = (fdc37m60x_t *)priv; fdc37m60x_t *dev = (fdc37m60x_t *) priv;
uint8_t ret = 0xff; uint8_t ret = 0xff;
if (addr & 1) if (addr & 1)
ret = (INDEX >= 0x30) ? dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] : dev->regs[INDEX]; ret = (INDEX >= 0x30) ? dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] : dev->regs[INDEX];
return ret; return ret;
} }
static void static void
fdc37m60x_fdc_handler(fdc37m60x_t *dev) fdc37m60x_fdc_handler(fdc37m60x_t *dev)
{ {
fdc_remove(dev->fdc); fdc_remove(dev->fdc);
if (ENABLED(0) || (POWER_CONTROL & 0x01)) if (ENABLED(0) || (POWER_CONTROL & 0x01)) {
{
fdc_set_base(dev->fdc, BASE_ADDRESS(0)); fdc_set_base(dev->fdc, BASE_ADDRESS(0));
fdc_set_irq(dev->fdc, IRQ(0) & 0xf); fdc_set_irq(dev->fdc, IRQ(0) & 0xf);
fdc_set_dma_ch(dev->fdc, DMA(0) & 0x07); fdc_set_dma_ch(dev->fdc, DMA(0) & 0x07);
@@ -189,70 +190,67 @@ fdc37m60x_fdc_handler(fdc37m60x_t *dev)
fdc_update_drvrate(dev->fdc, 3, (dev->device_regs[0][0xf7] & 0x18) >> 3); fdc_update_drvrate(dev->fdc, 3, (dev->device_regs[0][0xf7] & 0x18) >> 3);
} }
static void static void
fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev) fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev)
{ {
serial_remove(dev->uart[num & 1]); serial_remove(dev->uart[num & 1]);
if (ENABLED(4 + (num & 1)) || (POWER_CONTROL & (1 << (4 + (num & 1))))) if (ENABLED(4 + (num & 1)) || (POWER_CONTROL & (1 << (4 + (num & 1))))) {
{
serial_setup(dev->uart[num & 1], BASE_ADDRESS(4 + (num & 1)), IRQ(4 + (num & 1)) & 0xf); serial_setup(dev->uart[num & 1], BASE_ADDRESS(4 + (num & 1)), IRQ(4 + (num & 1)) & 0xf);
fdc37m60x_log("SMC60x-UART%d: BASE %04x IRQ %d\n", num & 1, BASE_ADDRESS(4 + (num & 1)), IRQ(4 + (num & 1)) & 0xf); fdc37m60x_log("SMC60x-UART%d: BASE %04x IRQ %d\n", num & 1, BASE_ADDRESS(4 + (num & 1)), IRQ(4 + (num & 1)) & 0xf);
} }
} }
void
void fdc37m60x_lpt_handler(fdc37m60x_t *dev) fdc37m60x_lpt_handler(fdc37m60x_t *dev)
{ {
lpt1_remove(); lpt1_remove();
if (ENABLED(3) || (POWER_CONTROL & 0x08)) { if (ENABLED(3) || (POWER_CONTROL & 0x08)) {
lpt1_init(BASE_ADDRESS(3)); lpt1_init(BASE_ADDRESS(3));
lpt1_irq(IRQ(3) & 0xf); lpt1_irq(IRQ(3) & 0xf);
fdc37m60x_log("SMC60x-LPT: BASE %04x IRQ %d\n", BASE_ADDRESS(3), IRQ(3) & 0xf); fdc37m60x_log("SMC60x-LPT: BASE %04x IRQ %d\n", BASE_ADDRESS(3), IRQ(3) & 0xf);
} }
} }
void
void fdc37m60x_logical_device_handler(fdc37m60x_t *dev) fdc37m60x_logical_device_handler(fdc37m60x_t *dev)
{ {
/* Register 07h: /* Register 07h:
Device 0: FDC Device 0: FDC
Device 3: LPT Device 3: LPT
Device 4: UART1 Device 4: UART1
Device 5: UART2 Device 5: UART2
*/ */
switch (CURRENT_LOGICAL_DEVICE) { switch (CURRENT_LOGICAL_DEVICE) {
case 0x00: case 0x00:
fdc37m60x_fdc_handler(dev); fdc37m60x_fdc_handler(dev);
break; break;
case 0x03: case 0x03:
fdc37m60x_lpt_handler(dev); fdc37m60x_lpt_handler(dev);
break; break;
case 0x04: case 0x04:
fdc37m60x_uart_handler(0, dev); fdc37m60x_uart_handler(0, dev);
break; break;
case 0x05: case 0x05:
fdc37m60x_uart_handler(1, dev); fdc37m60x_uart_handler(1, dev);
break; break;
} }
} }
static void static void
fdc37m60x_reset(void *priv) fdc37m60x_reset(void *priv)
{ {
fdc37m60x_t *dev = (fdc37m60x_t *) priv; fdc37m60x_t *dev = (fdc37m60x_t *) priv;
uint8_t i; uint8_t i;
memset(dev->regs, 0, sizeof(dev->regs)); memset(dev->regs, 0, sizeof(dev->regs));
for (i = 0; i < 10; i++) for (i = 0; i < 10; i++)
memset(dev->device_regs[i], 0, sizeof(dev->device_regs[i])); memset(dev->device_regs[i], 0, sizeof(dev->device_regs[i]));
dev->regs[0x20] = 0x47; dev->regs[0x20] = 0x47;
dev->regs[0x24] = 0x04; dev->regs[0x24] = 0x04;
@@ -286,24 +284,22 @@ fdc37m60x_reset(void *priv)
fdc37m60x_lpt_handler(dev); fdc37m60x_lpt_handler(dev);
} }
static void static void
fdc37m60x_close(void *priv) fdc37m60x_close(void *priv)
{ {
fdc37m60x_t *dev = (fdc37m60x_t *)priv; fdc37m60x_t *dev = (fdc37m60x_t *) priv;
free(dev); free(dev);
} }
static void * static void *
fdc37m60x_init(const device_t *info) fdc37m60x_init(const device_t *info)
{ {
fdc37m60x_t *dev = (fdc37m60x_t *)malloc(sizeof(fdc37m60x_t)); fdc37m60x_t *dev = (fdc37m60x_t *) malloc(sizeof(fdc37m60x_t));
memset(dev, 0, sizeof(fdc37m60x_t)); memset(dev, 0, sizeof(fdc37m60x_t));
SIO_INDEX_PORT = info->local; SIO_INDEX_PORT = info->local;
dev->fdc = device_add(&fdc_at_smc_device); dev->fdc = device_add(&fdc_at_smc_device);
dev->uart[0] = device_add_inst(&ns16550_device, 1); dev->uart[0] = device_add_inst(&ns16550_device, 1);
dev->uart[1] = device_add_inst(&ns16550_device, 2); dev->uart[1] = device_add_inst(&ns16550_device, 2);
@@ -315,29 +311,29 @@ fdc37m60x_init(const device_t *info)
} }
const device_t fdc37m60x_device = { const device_t fdc37m60x_device = {
.name = "SMSC FDC37M60X", .name = "SMSC FDC37M60X",
.internal_name = "fdc37m60x", .internal_name = "fdc37m60x",
.flags = 0, .flags = 0,
.local = FDC_PRIMARY_ADDR, .local = FDC_PRIMARY_ADDR,
.init = fdc37m60x_init, .init = fdc37m60x_init,
.close = fdc37m60x_close, .close = fdc37m60x_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t fdc37m60x_370_device = { const device_t fdc37m60x_370_device = {
.name = "SMSC FDC37M60X with 10K Pull Up Resistor", .name = "SMSC FDC37M60X with 10K Pull Up Resistor",
.internal_name = "fdc37m60x_370", .internal_name = "fdc37m60x_370",
.flags = 0, .flags = 0,
.local = FDC_SECONDARY_ADDR, .local = FDC_SECONDARY_ADDR,
.init = fdc37m60x_init, .init = fdc37m60x_init,
.close = fdc37m60x_close, .close = fdc37m60x_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

View File

@@ -33,250 +33,237 @@
#include <86box/fdd_common.h> #include <86box/fdd_common.h>
#include <86box/sio.h> #include <86box/sio.h>
#define LDN dev->regs[7] #define LDN dev->regs[7]
typedef struct typedef struct
{ {
fdc_t *fdc_controller; fdc_t *fdc_controller;
serial_t *uart[2]; serial_t *uart[2];
uint8_t index, regs[256], device_regs[6][256]; uint8_t index, regs[256], device_regs[6][256];
int unlocked, enumerator; int unlocked, enumerator;
} it8661f_t; } 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 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);
static void it8661f_reset(void *priv);
#ifdef ENABLE_IT8661_LOG #ifdef ENABLE_IT8661_LOG
int it8661_do_log = ENABLE_IT8661_LOG; int it8661_do_log = ENABLE_IT8661_LOG;
void void
it8661_log(const char *fmt, ...) it8661_log(const char *fmt, ...)
{ {
va_list ap; va_list ap;
if (it8661_do_log) { if (it8661_do_log) {
va_start(ap, fmt); va_start(ap, fmt);
pclog_ex(fmt, ap); pclog_ex(fmt, ap);
va_end(ap); va_end(ap);
} }
} }
#else #else
#define it8661_log(fmt, ...) # define it8661_log(fmt, ...)
#endif #endif
static void static void
it8661_fdc(uint16_t addr, uint8_t val, it8661f_t *dev) it8661_fdc(uint16_t addr, uint8_t val, it8661f_t *dev)
{ {
fdc_remove(dev->fdc_controller); fdc_remove(dev->fdc_controller);
if (((addr == 0x30) && (val & 1)) || (dev->device_regs[0][0x30] & 1)) { if (((addr == 0x30) && (val & 1)) || (dev->device_regs[0][0x30] & 1)) {
switch (addr) { switch (addr) {
case 0x30: case 0x30:
dev->device_regs[0][addr] = val & 1; dev->device_regs[0][addr] = val & 1;
break; break;
case 0x31: case 0x31:
dev->device_regs[0][addr] = val & 3; dev->device_regs[0][addr] = val & 3;
if (val & 1) if (val & 1)
dev->device_regs[0][addr] |= 0x55; dev->device_regs[0][addr] |= 0x55;
break; break;
case 0x60: case 0x60:
case 0x61: case 0x61:
dev->device_regs[0][addr] = val & ((addr == 0x61) ? 0xff : 0xf8); dev->device_regs[0][addr] = val & ((addr == 0x61) ? 0xff : 0xf8);
break; break;
case 0x70: case 0x70:
dev->device_regs[0][addr] = val & 0x0f; dev->device_regs[0][addr] = val & 0x0f;
break; break;
case 0x74: case 0x74:
dev->device_regs[0][addr] = val & 7; dev->device_regs[0][addr] = val & 7;
break; break;
case 0xf0: case 0xf0:
dev->device_regs[0][addr] = val & 0x0f; dev->device_regs[0][addr] = val & 0x0f;
break; break;
} }
fdc_set_base(dev->fdc_controller, (dev->device_regs[0][0x60] << 8) | (dev->device_regs[0][0x61])); 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_irq(dev->fdc_controller, dev->device_regs[0][0x70] & 0x0f);
fdc_set_dma_ch(dev->fdc_controller, dev->device_regs[0][0x74] & 7); fdc_set_dma_ch(dev->fdc_controller, dev->device_regs[0][0x74] & 7);
if (dev->device_regs[0][0xf0] & 1) if (dev->device_regs[0][0xf0] & 1)
fdc_writeprotect(dev->fdc_controller); 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]), 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); dev->device_regs[0][0x70] & 0x0f);
} }
} }
static void static void
it8661_serial(int uart, uint16_t addr, uint8_t val, it8661f_t *dev) it8661_serial(int uart, uint16_t addr, uint8_t val, it8661f_t *dev)
{ {
serial_remove(dev->uart[uart]); serial_remove(dev->uart[uart]);
if (((addr == 0x30) && (val & 1)) || (dev->device_regs[1 + uart][0x30] & 1)) { if (((addr == 0x30) && (val & 1)) || (dev->device_regs[1 + uart][0x30] & 1)) {
switch (addr) { switch (addr) {
case 0x30: case 0x30:
dev->device_regs[1 + uart][addr] = val & 1; dev->device_regs[1 + uart][addr] = val & 1;
break; break;
case 0x60: case 0x60:
case 0x61: case 0x61:
dev->device_regs[1 + uart][addr] = val & ((addr == 0x61) ? 0xff : 0xf8); dev->device_regs[1 + uart][addr] = val & ((addr == 0x61) ? 0xff : 0xf8);
break; break;
case 0x70: case 0x70:
dev->device_regs[1 + uart][addr] = val & 0x0f; dev->device_regs[1 + uart][addr] = val & 0x0f;
break; break;
case 0x74: case 0x74:
dev->device_regs[1 + uart][addr] = val & 7; dev->device_regs[1 + uart][addr] = val & 7;
break; break;
case 0xf0: case 0xf0:
dev->device_regs[1 + uart][addr] = val & 3; dev->device_regs[1 + uart][addr] = val & 3;
break; 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); 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), 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][0x60] << 8) | (dev->device_regs[1 + uart][0x61]),
dev->device_regs[1 + uart][0x70] & 0x0f); dev->device_regs[1 + uart][0x70] & 0x0f);
} }
} }
void void
it8661_lpt(uint16_t addr, uint8_t val, it8661f_t *dev) it8661_lpt(uint16_t addr, uint8_t val, it8661f_t *dev)
{ {
lpt1_remove(); lpt1_remove();
if (((addr == 0x30) && (val & 1)) || (dev->device_regs[3][0x30] & 1)) { if (((addr == 0x30) && (val & 1)) || (dev->device_regs[3][0x30] & 1)) {
switch (addr) { switch (addr) {
case 0x30: case 0x30:
dev->device_regs[3][addr] = val & 1; dev->device_regs[3][addr] = val & 1;
break; break;
case 0x60: case 0x60:
case 0x61: case 0x61:
dev->device_regs[3][addr] = val & ((addr == 0x61) ? 0xff : 0xf8); dev->device_regs[3][addr] = val & ((addr == 0x61) ? 0xff : 0xf8);
break; break;
case 0x70: case 0x70:
dev->device_regs[3][addr] = val & 0x0f; dev->device_regs[3][addr] = val & 0x0f;
break; break;
case 0x74: case 0x74:
dev->device_regs[3][addr] = val & 7; dev->device_regs[3][addr] = val & 7;
break; break;
case 0xf0: case 0xf0:
dev->device_regs[3][addr] = val & 3; dev->device_regs[3][addr] = val & 3;
break; break;
} }
lpt1_init((dev->device_regs[3][0x60] << 8) | (dev->device_regs[3][0x61])); lpt1_init((dev->device_regs[3][0x60] << 8) | (dev->device_regs[3][0x61]));
lpt1_irq(dev->device_regs[3][0x70] & 0x0f); 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]), 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); dev->device_regs[3][0x70] & 0x0f);
} }
} }
void void
it8661_ldn(uint16_t addr, uint8_t val, it8661f_t *dev) it8661_ldn(uint16_t addr, uint8_t val, it8661f_t *dev)
{ {
switch (LDN) { switch (LDN) {
case 0: case 0:
it8661_fdc(addr, val, dev); it8661_fdc(addr, val, dev);
break; break;
case 1: case 1:
case 2: case 2:
it8661_serial(LDN & 2, addr, val, dev); it8661_serial(LDN & 2, addr, val, dev);
break; break;
case 3: case 3:
it8661_lpt(addr, val, dev); it8661_lpt(addr, val, dev);
break; break;
} }
} }
static void static void
it8661f_write(uint16_t addr, uint8_t val, void *priv) it8661f_write(uint16_t addr, uint8_t val, void *priv)
{ {
it8661f_t *dev = (it8661f_t *)priv; it8661f_t *dev = (it8661f_t *) priv;
switch (addr) { switch (addr) {
case FDC_SECONDARY_ADDR: case FDC_SECONDARY_ADDR:
if (!dev->unlocked) { if (!dev->unlocked) {
(val == mb_pnp_key[dev->enumerator]) ? dev->enumerator++ : (dev->enumerator = 0); (val == mb_pnp_key[dev->enumerator]) ? dev->enumerator++ : (dev->enumerator = 0);
if (dev->enumerator == 31) { if (dev->enumerator == 31) {
dev->unlocked = 1; dev->unlocked = 1;
it8661_log("ITE8661F: Unlocked!\n"); it8661_log("ITE8661F: Unlocked!\n");
} }
} else } else
dev->index = val; dev->index = val;
break; break;
case 0x371: case 0x371:
if (dev->unlocked) { if (dev->unlocked) {
switch (dev->index) { switch (dev->index) {
case 0x02: case 0x02:
dev->regs[dev->index] = val; dev->regs[dev->index] = val;
if (val & 1) if (val & 1)
it8661f_reset(dev); it8661f_reset(dev);
if (val & 2) if (val & 2)
dev->unlocked = 0; dev->unlocked = 0;
break; break;
case 0x07: case 0x07:
dev->regs[dev->index] = val; dev->regs[dev->index] = val;
break; break;
case 0x22: case 0x22:
dev->regs[dev->index] = val & 0x30; dev->regs[dev->index] = val & 0x30;
break; break;
case 0x23: case 0x23:
dev->regs[dev->index] = val & 0x1f; dev->regs[dev->index] = val & 0x1f;
break; break;
default: default:
it8661_ldn(dev->index, val, dev); it8661_ldn(dev->index, val, dev);
break; break;
} }
} }
break; break;
} }
return; return;
} }
static uint8_t static uint8_t
it8661f_read(uint16_t addr, void *priv) it8661f_read(uint16_t addr, void *priv)
{ {
it8661f_t *dev = (it8661f_t *)priv; it8661f_t *dev = (it8661f_t *) priv;
it8661_log("IT8661F:\n", addr, dev->regs[dev->index]); it8661_log("IT8661F:\n", addr, dev->regs[dev->index]);
return (addr == 0xa79) ? dev->regs[dev->index] : 0xff; return (addr == 0xa79) ? dev->regs[dev->index] : 0xff;
} }
static void static void
it8661f_reset(void *priv) it8661f_reset(void *priv)
{ {
it8661f_t *dev = (it8661f_t *)priv; it8661f_t *dev = (it8661f_t *) priv;
dev->regs[0x20] = 0x86; dev->regs[0x20] = 0x86;
dev->regs[0x21] = 0x61; dev->regs[0x21] = 0x61;
@@ -304,20 +291,18 @@ it8661f_reset(void *priv)
dev->device_regs[3][0xf0] = 3; dev->device_regs[3][0xf0] = 3;
} }
static void static void
it8661f_close(void *priv) it8661f_close(void *priv)
{ {
it8661f_t *dev = (it8661f_t *)priv; it8661f_t *dev = (it8661f_t *) priv;
free(dev); free(dev);
} }
static void * static void *
it8661f_init(const device_t *info) it8661f_init(const device_t *info)
{ {
it8661f_t *dev = (it8661f_t *)malloc(sizeof(it8661f_t)); it8661f_t *dev = (it8661f_t *) malloc(sizeof(it8661f_t));
memset(dev, 0, sizeof(it8661f_t)); memset(dev, 0, sizeof(it8661f_t));
dev->fdc_controller = device_add(&fdc_at_smc_device); dev->fdc_controller = device_add(&fdc_at_smc_device);
@@ -329,22 +314,22 @@ it8661f_init(const device_t *info)
io_sethandler(FDC_SECONDARY_ADDR, 0x0002, it8661f_read, NULL, NULL, it8661f_write, NULL, NULL, dev); io_sethandler(FDC_SECONDARY_ADDR, 0x0002, it8661f_read, NULL, NULL, it8661f_write, NULL, NULL, dev);
dev->enumerator = 0; dev->enumerator = 0;
dev->unlocked = 0; dev->unlocked = 0;
it8661f_reset(dev); it8661f_reset(dev);
return dev; return dev;
} }
const device_t it8661f_device = { const device_t it8661f_device = {
.name = "ITE IT8661F", .name = "ITE IT8661F",
.internal_name = "it8661f", .internal_name = "it8661f",
.flags = 0, .flags = 0,
.local = 0, .local = 0,
.init = it8661f_init, .init = it8661f_init,
.close = it8661f_close, .close = it8661f_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

View File

@@ -34,17 +34,15 @@
#include <86box/fdc.h> #include <86box/fdc.h>
#include <86box/sio.h> #include <86box/sio.h>
typedef struct { typedef struct {
uint8_t tries, uint8_t tries,
regs[29], gpio[2]; regs[29], gpio[2];
int cur_reg; int cur_reg;
fdc_t *fdc; fdc_t *fdc;
serial_t *uart[2]; serial_t *uart[2];
nvr_t *nvr; nvr_t *nvr;
} pc87306_t; } pc87306_t;
static void static void
pc87306_gpio_write(uint16_t port, uint8_t val, void *priv) pc87306_gpio_write(uint16_t port, uint8_t val, void *priv)
{ {
@@ -53,7 +51,6 @@ pc87306_gpio_write(uint16_t port, uint8_t val, void *priv)
dev->gpio[port & 1] = val; dev->gpio[port & 1] = val;
} }
uint8_t uint8_t
pc87306_gpio_read(uint16_t port, void *priv) pc87306_gpio_read(uint16_t port, void *priv)
{ {
@@ -62,298 +59,291 @@ pc87306_gpio_read(uint16_t port, void *priv)
return dev->gpio[port & 1]; return dev->gpio[port & 1];
} }
static void static void
pc87306_gpio_remove(pc87306_t *dev) pc87306_gpio_remove(pc87306_t *dev)
{ {
io_removehandler(dev->regs[0x0f] << 2, 0x0001, io_removehandler(dev->regs[0x0f] << 2, 0x0001,
pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev); pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev);
io_removehandler((dev->regs[0x0f] << 2) + 1, 0x0001, io_removehandler((dev->regs[0x0f] << 2) + 1, 0x0001,
pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev); pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev);
} }
static void static void
pc87306_gpio_init(pc87306_t *dev) pc87306_gpio_init(pc87306_t *dev)
{ {
if ((dev->regs[0x12]) & 0x10) if ((dev->regs[0x12]) & 0x10)
io_sethandler(dev->regs[0x0f] << 2, 0x0001, io_sethandler(dev->regs[0x0f] << 2, 0x0001,
pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev); pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev);
if ((dev->regs[0x12]) & 0x20) if ((dev->regs[0x12]) & 0x20)
io_sethandler((dev->regs[0x0f] << 2) + 1, 0x0001, io_sethandler((dev->regs[0x0f] << 2) + 1, 0x0001,
pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev); pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev);
} }
static void static void
lpt1_handler(pc87306_t *dev) lpt1_handler(pc87306_t *dev)
{ {
int temp; int temp;
uint16_t lptba, lpt_port = LPT1_ADDR; uint16_t lptba, lpt_port = LPT1_ADDR;
uint8_t lpt_irq = LPT2_IRQ; uint8_t lpt_irq = LPT2_IRQ;
temp = dev->regs[0x01] & 3; temp = dev->regs[0x01] & 3;
lptba = ((uint16_t) dev->regs[0x19]) << 2; lptba = ((uint16_t) dev->regs[0x19]) << 2;
switch (temp) { switch (temp) {
case 0: case 0:
lpt_port = LPT1_ADDR; lpt_port = LPT1_ADDR;
lpt_irq = (dev->regs[0x02] & 0x08) ? LPT1_IRQ : LPT2_IRQ; lpt_irq = (dev->regs[0x02] & 0x08) ? LPT1_IRQ : LPT2_IRQ;
break; break;
case 1: case 1:
if (dev->regs[0x1b] & 0x40) if (dev->regs[0x1b] & 0x40)
lpt_port = lptba; lpt_port = lptba;
else else
lpt_port = LPT_MDA_ADDR; lpt_port = LPT_MDA_ADDR;
lpt_irq = LPT_MDA_IRQ; lpt_irq = LPT_MDA_IRQ;
break; break;
case 2: case 2:
lpt_port = LPT2_ADDR; lpt_port = LPT2_ADDR;
lpt_irq = LPT2_IRQ; lpt_irq = LPT2_IRQ;
break; break;
case 3: case 3:
lpt_port = 0x000; lpt_port = 0x000;
lpt_irq = 0xff; lpt_irq = 0xff;
break; break;
} }
if (dev->regs[0x1b] & 0x10) if (dev->regs[0x1b] & 0x10)
lpt_irq = (dev->regs[0x1b] & 0x20) ? 7 : 5; lpt_irq = (dev->regs[0x1b] & 0x20) ? 7 : 5;
if (lpt_port) if (lpt_port)
lpt1_init(lpt_port); lpt1_init(lpt_port);
lpt1_irq(lpt_irq); lpt1_irq(lpt_irq);
} }
static void static void
serial_handler(pc87306_t *dev, int uart) serial_handler(pc87306_t *dev, int uart)
{ {
int temp; int temp;
uint8_t fer_irq, pnp1_irq; uint8_t fer_irq, pnp1_irq;
uint8_t fer_shift, pnp_shift; uint8_t fer_shift, pnp_shift;
uint8_t irq; uint8_t irq;
temp = (dev->regs[1] >> (2 << uart)) & 3; temp = (dev->regs[1] >> (2 << uart)) & 3;
fer_shift = 2 << uart; /* 2 for UART 1, 4 for UART 2 */ fer_shift = 2 << uart; /* 2 for UART 1, 4 for UART 2 */
pnp_shift = 2 + (uart << 2); /* 2 for UART 1, 6 for UART 2 */ pnp_shift = 2 + (uart << 2); /* 2 for UART 1, 6 for UART 2 */
/* 0 = COM1 (IRQ 4), 1 = COM2 (IRQ 3), 2 = COM3 (IRQ 4), 3 = COM4 (IRQ 3) */ /* 0 = COM1 (IRQ 4), 1 = COM2 (IRQ 3), 2 = COM3 (IRQ 4), 3 = COM4 (IRQ 3) */
fer_irq = ((dev->regs[1] >> fer_shift) & 1) ? 3 : 4; fer_irq = ((dev->regs[1] >> fer_shift) & 1) ? 3 : 4;
pnp1_irq = ((dev->regs[0x1c] >> pnp_shift) & 1) ? 4 : 3; pnp1_irq = ((dev->regs[0x1c] >> pnp_shift) & 1) ? 4 : 3;
irq = (dev->regs[0x1c] & 1) ? pnp1_irq : fer_irq; irq = (dev->regs[0x1c] & 1) ? pnp1_irq : fer_irq;
switch (temp) { switch (temp) {
case 0: case 0:
serial_setup(dev->uart[uart], COM1_ADDR, irq); serial_setup(dev->uart[uart], COM1_ADDR, irq);
break; break;
case 1: case 1:
serial_setup(dev->uart[uart], COM2_ADDR, irq); serial_setup(dev->uart[uart], COM2_ADDR, irq);
break; break;
case 2: case 2:
switch ((dev->regs[1] >> 6) & 3) { switch ((dev->regs[1] >> 6) & 3) {
case 0: case 0:
serial_setup(dev->uart[uart], COM3_ADDR, irq); serial_setup(dev->uart[uart], COM3_ADDR, irq);
break; break;
case 1: case 1:
serial_setup(dev->uart[uart], 0x338, irq); serial_setup(dev->uart[uart], 0x338, irq);
break; break;
case 2: case 2:
serial_setup(dev->uart[uart], COM4_ADDR, irq); serial_setup(dev->uart[uart], COM4_ADDR, irq);
break; break;
case 3: case 3:
serial_setup(dev->uart[uart], 0x220, irq); serial_setup(dev->uart[uart], 0x220, irq);
break; break;
} }
break; break;
case 3: case 3:
switch ((dev->regs[1] >> 6) & 3) { switch ((dev->regs[1] >> 6) & 3) {
case 0: case 0:
serial_setup(dev->uart[uart], COM4_ADDR, irq); serial_setup(dev->uart[uart], COM4_ADDR, irq);
break; break;
case 1: case 1:
serial_setup(dev->uart[uart], 0x238, irq); serial_setup(dev->uart[uart], 0x238, irq);
break; break;
case 2: case 2:
serial_setup(dev->uart[uart], 0x2e0, irq); serial_setup(dev->uart[uart], 0x2e0, irq);
break; break;
case 3: case 3:
serial_setup(dev->uart[uart], 0x228, irq); serial_setup(dev->uart[uart], 0x228, irq);
break; break;
} }
break; break;
} }
} }
static void static void
pc87306_write(uint16_t port, uint8_t val, void *priv) pc87306_write(uint16_t port, uint8_t val, void *priv)
{ {
pc87306_t *dev = (pc87306_t *) priv; pc87306_t *dev = (pc87306_t *) priv;
uint8_t index, valxor; uint8_t index, valxor;
index = (port & 1) ? 0 : 1; index = (port & 1) ? 0 : 1;
if (index) { if (index) {
dev->cur_reg = val & 0x1f; dev->cur_reg = val & 0x1f;
dev->tries = 0; dev->tries = 0;
return; return;
} else { } else {
if (dev->tries) { if (dev->tries) {
if ((dev->cur_reg == 0) && (val == 8)) if ((dev->cur_reg == 0) && (val == 8))
val = 0x4b; val = 0x4b;
valxor = val ^ dev->regs[dev->cur_reg]; valxor = val ^ dev->regs[dev->cur_reg];
dev->tries = 0; dev->tries = 0;
if ((dev->cur_reg <= 28) && (dev->cur_reg != 8)) { if ((dev->cur_reg <= 28) && (dev->cur_reg != 8)) {
if (dev->cur_reg == 0) if (dev->cur_reg == 0)
val &= 0x5f; val &= 0x5f;
if (((dev->cur_reg == 0x0F) || (dev->cur_reg == 0x12)) && valxor) if (((dev->cur_reg == 0x0F) || (dev->cur_reg == 0x12)) && valxor)
pc87306_gpio_remove(dev); pc87306_gpio_remove(dev);
dev->regs[dev->cur_reg] = val; dev->regs[dev->cur_reg] = val;
} else } else
return; return;
} else { } else {
dev->tries++; dev->tries++;
return; return;
} }
} }
switch(dev->cur_reg) { switch (dev->cur_reg) {
case 0: case 0:
if (valxor & 1) { if (valxor & 1) {
lpt1_remove(); lpt1_remove();
if ((val & 1) && !(dev->regs[2] & 1)) if ((val & 1) && !(dev->regs[2] & 1))
lpt1_handler(dev); lpt1_handler(dev);
} }
if (valxor & 2) { if (valxor & 2) {
serial_remove(dev->uart[0]); serial_remove(dev->uart[0]);
if ((val & 2) && !(dev->regs[2] & 1)) if ((val & 2) && !(dev->regs[2] & 1))
serial_handler(dev, 0); serial_handler(dev, 0);
} }
if (valxor & 4) { if (valxor & 4) {
serial_remove(dev->uart[1]); serial_remove(dev->uart[1]);
if ((val & 4) && !(dev->regs[2] & 1)) if ((val & 4) && !(dev->regs[2] & 1))
serial_handler(dev, 1); serial_handler(dev, 1);
} }
if (valxor & 0x28) { if (valxor & 0x28) {
fdc_remove(dev->fdc); fdc_remove(dev->fdc);
if ((val & 8) && !(dev->regs[2] & 1)) if ((val & 8) && !(dev->regs[2] & 1))
fdc_set_base(dev->fdc, (val & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); fdc_set_base(dev->fdc, (val & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
} }
break; break;
case 1: case 1:
if (valxor & 3) { if (valxor & 3) {
lpt1_remove(); lpt1_remove();
if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) if ((dev->regs[0] & 1) && !(dev->regs[2] & 1))
lpt1_handler(dev); lpt1_handler(dev);
} }
if (valxor & 0xcc) { if (valxor & 0xcc) {
serial_remove(dev->uart[0]); serial_remove(dev->uart[0]);
if ((dev->regs[0] & 2) && !(dev->regs[2] & 1)) if ((dev->regs[0] & 2) && !(dev->regs[2] & 1))
serial_handler(dev, 0); serial_handler(dev, 0);
} }
if (valxor & 0xf0) { if (valxor & 0xf0) {
serial_remove(dev->uart[1]); serial_remove(dev->uart[1]);
if ((dev->regs[0] & 4) && !(dev->regs[2] & 1)) if ((dev->regs[0] & 4) && !(dev->regs[2] & 1))
serial_handler(dev, 1); serial_handler(dev, 1);
} }
break; break;
case 2: case 2:
if (valxor & 1) { if (valxor & 1) {
lpt1_remove(); lpt1_remove();
serial_remove(dev->uart[0]); serial_remove(dev->uart[0]);
serial_remove(dev->uart[1]); serial_remove(dev->uart[1]);
fdc_remove(dev->fdc); fdc_remove(dev->fdc);
if (!(val & 1)) { if (!(val & 1)) {
if (dev->regs[0] & 1) if (dev->regs[0] & 1)
lpt1_handler(dev); lpt1_handler(dev);
if (dev->regs[0] & 2) if (dev->regs[0] & 2)
serial_handler(dev, 0); serial_handler(dev, 0);
if (dev->regs[0] & 4) if (dev->regs[0] & 4)
serial_handler(dev, 1); serial_handler(dev, 1);
if (dev->regs[0] & 8) if (dev->regs[0] & 8)
fdc_set_base(dev->fdc, (dev->regs[0] & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); fdc_set_base(dev->fdc, (dev->regs[0] & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
} }
} }
if (valxor & 8) { if (valxor & 8) {
lpt1_remove(); lpt1_remove();
if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) if ((dev->regs[0] & 1) && !(dev->regs[2] & 1))
lpt1_handler(dev); lpt1_handler(dev);
} }
break; break;
case 9: case 9:
if (valxor & 0x44) { if (valxor & 0x44) {
fdc_update_enh_mode(dev->fdc, (val & 4) ? 1 : 0); fdc_update_enh_mode(dev->fdc, (val & 4) ? 1 : 0);
fdc_update_densel_polarity(dev->fdc, (val & 0x40) ? 1 : 0); fdc_update_densel_polarity(dev->fdc, (val & 0x40) ? 1 : 0);
} }
break; break;
case 0xF: case 0xF:
if (valxor) if (valxor)
pc87306_gpio_init(dev); pc87306_gpio_init(dev);
break; break;
case 0x12: case 0x12:
if (valxor & 0x30) if (valxor & 0x30)
pc87306_gpio_init(dev); pc87306_gpio_init(dev);
break; break;
case 0x19: case 0x19:
if (valxor) { if (valxor) {
lpt1_remove(); lpt1_remove();
if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) if ((dev->regs[0] & 1) && !(dev->regs[2] & 1))
lpt1_handler(dev); lpt1_handler(dev);
} }
break; break;
case 0x1B: case 0x1B:
if (valxor & 0x70) { if (valxor & 0x70) {
lpt1_remove(); lpt1_remove();
if (!(val & 0x40)) if (!(val & 0x40))
dev->regs[0x19] = 0xEF; dev->regs[0x19] = 0xEF;
if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) if ((dev->regs[0] & 1) && !(dev->regs[2] & 1))
lpt1_handler(dev); lpt1_handler(dev);
} }
break; break;
case 0x1C: case 0x1C:
if (valxor) { if (valxor) {
serial_remove(dev->uart[0]); serial_remove(dev->uart[0]);
serial_remove(dev->uart[1]); serial_remove(dev->uart[1]);
if ((dev->regs[0] & 2) && !(dev->regs[2] & 1)) if ((dev->regs[0] & 2) && !(dev->regs[2] & 1))
serial_handler(dev, 0); serial_handler(dev, 0);
if ((dev->regs[0] & 4) && !(dev->regs[2] & 1)) if ((dev->regs[0] & 4) && !(dev->regs[2] & 1))
serial_handler(dev, 1); serial_handler(dev, 1);
} }
break; break;
} }
} }
uint8_t uint8_t
pc87306_read(uint16_t port, void *priv) pc87306_read(uint16_t port, void *priv)
{ {
pc87306_t *dev = (pc87306_t *) priv; pc87306_t *dev = (pc87306_t *) priv;
uint8_t ret = 0xff, index; uint8_t ret = 0xff, index;
index = (port & 1) ? 0 : 1; index = (port & 1) ? 0 : 1;
dev->tries = 0; dev->tries = 0;
if (index) if (index)
ret = dev->cur_reg & 0x1f; ret = dev->cur_reg & 0x1f;
else { else {
if (dev->cur_reg == 8) if (dev->cur_reg == 8)
ret = 0x70; ret = 0x70;
else if (dev->cur_reg < 28) else if (dev->cur_reg < 28)
ret = dev->regs[dev->cur_reg]; ret = dev->regs[dev->cur_reg];
} }
return ret; return ret;
} }
void void
pc87306_reset(pc87306_t *dev) pc87306_reset(pc87306_t *dev)
{ {
@@ -374,8 +364,8 @@ pc87306_reset(pc87306_t *dev)
dev->gpio[1] = 0xfb; dev->gpio[1] = 0xfb;
/* /*
0 = 360 rpm @ 500 kbps for 3.5" 0 = 360 rpm @ 500 kbps for 3.5"
1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5" 1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5"
*/ */
lpt1_remove(); lpt1_remove();
lpt1_handler(dev); lpt1_handler(dev);
@@ -387,7 +377,6 @@ pc87306_reset(pc87306_t *dev)
pc87306_gpio_init(dev); pc87306_gpio_init(dev);
} }
static void static void
pc87306_close(void *priv) pc87306_close(void *priv)
{ {
@@ -396,7 +385,6 @@ pc87306_close(void *priv)
free(dev); free(dev);
} }
static void * static void *
pc87306_init(const device_t *info) pc87306_init(const device_t *info)
{ {
@@ -413,21 +401,21 @@ pc87306_init(const device_t *info)
pc87306_reset(dev); pc87306_reset(dev);
io_sethandler(0x02e, 0x0002, io_sethandler(0x02e, 0x0002,
pc87306_read, NULL, NULL, pc87306_write, NULL, NULL, dev); pc87306_read, NULL, NULL, pc87306_write, NULL, NULL, dev);
return dev; return dev;
} }
const device_t pc87306_device = { const device_t pc87306_device = {
.name = "National Semiconductor PC87306 Super I/O", .name = "National Semiconductor PC87306 Super I/O",
.internal_name = "pc87306", .internal_name = "pc87306",
.flags = 0, .flags = 0,
.local = 0, .local = 0,
.init = pc87306_init, .init = pc87306_init,
.close = pc87306_close, .close = pc87306_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

View File

@@ -34,70 +34,64 @@
#include <86box/fdc.h> #include <86box/fdc.h>
#include <86box/sio.h> #include <86box/sio.h>
typedef struct { typedef struct {
uint8_t id, pm_idx, uint8_t id, pm_idx,
regs[48], ld_regs[256][208], regs[48], ld_regs[256][208],
pcregs[16], gpio[2][4], pcregs[16], gpio[2][4],
pm[8]; pm[8];
uint16_t gpio_base, gpio_base2, uint16_t gpio_base, gpio_base2,
pm_base; pm_base;
int cur_reg; int cur_reg;
fdc_t *fdc; fdc_t *fdc;
serial_t *uart[2]; serial_t *uart[2];
} pc87307_t; } pc87307_t;
static void fdc_handler(pc87307_t *dev);
static void fdc_handler(pc87307_t *dev); static void lpt1_handler(pc87307_t *dev);
static void lpt1_handler(pc87307_t *dev); static void serial_handler(pc87307_t *dev, int uart);
static void serial_handler(pc87307_t *dev, int uart);
static void static void
pc87307_gpio_write(uint16_t port, uint8_t val, void *priv) pc87307_gpio_write(uint16_t port, uint8_t val, void *priv)
{ {
pc87307_t *dev = (pc87307_t *) priv; pc87307_t *dev = (pc87307_t *) priv;
uint8_t bank = ((port & 0xfffc) == dev->gpio_base2); uint8_t bank = ((port & 0xfffc) == dev->gpio_base2);
dev->gpio[bank][port & 3] = val; dev->gpio[bank][port & 3] = val;
} }
uint8_t uint8_t
pc87307_gpio_read(uint16_t port, void *priv) pc87307_gpio_read(uint16_t port, void *priv)
{ {
pc87307_t *dev = (pc87307_t *) priv; pc87307_t *dev = (pc87307_t *) priv;
uint8_t pins = 0xff, bank = ((port & 0xfffc) == dev->gpio_base2); uint8_t pins = 0xff, bank = ((port & 0xfffc) == dev->gpio_base2);
uint8_t mask, ret = dev->gpio[bank][port & 0x0003]; uint8_t mask, ret = dev->gpio[bank][port & 0x0003];
switch (port & 0x0003) { switch (port & 0x0003) {
case 0x0000: case 0x0000:
mask = dev->gpio[bank][0x0001]; mask = dev->gpio[bank][0x0001];
ret = (ret & mask) | (pins & ~mask); ret = (ret & mask) | (pins & ~mask);
break; break;
} }
return ret; return ret;
} }
static void static void
pc87307_gpio_remove(pc87307_t *dev) pc87307_gpio_remove(pc87307_t *dev)
{ {
if (dev->gpio_base != 0xffff) { if (dev->gpio_base != 0xffff) {
io_removehandler(dev->gpio_base, 0x0002, io_removehandler(dev->gpio_base, 0x0002,
pc87307_gpio_read, NULL, NULL, pc87307_gpio_write, NULL, NULL, dev); pc87307_gpio_read, NULL, NULL, pc87307_gpio_write, NULL, NULL, dev);
dev->gpio_base = 0xffff; dev->gpio_base = 0xffff;
} }
if (dev->gpio_base2 != 0xffff) { if (dev->gpio_base2 != 0xffff) {
io_removehandler(dev->gpio_base2, 0x0002, io_removehandler(dev->gpio_base2, 0x0002,
pc87307_gpio_read, NULL, NULL, pc87307_gpio_write, NULL, NULL, dev); pc87307_gpio_read, NULL, NULL, pc87307_gpio_write, NULL, NULL, dev);
dev->gpio_base2 = 0xffff; dev->gpio_base2 = 0xffff;
} }
} }
static void static void
pc87307_gpio_init(pc87307_t *dev, int bank, uint16_t addr) pc87307_gpio_init(pc87307_t *dev, int bank, uint16_t addr)
{ {
@@ -106,352 +100,347 @@ pc87307_gpio_init(pc87307_t *dev, int bank, uint16_t addr)
*bank_base = addr; *bank_base = addr;
io_sethandler(*bank_base, 0x0002, io_sethandler(*bank_base, 0x0002,
pc87307_gpio_read, NULL, NULL, pc87307_gpio_write, NULL, NULL, dev); pc87307_gpio_read, NULL, NULL, pc87307_gpio_write, NULL, NULL, dev);
} }
static void static void
pc87307_pm_write(uint16_t port, uint8_t val, void *priv) pc87307_pm_write(uint16_t port, uint8_t val, void *priv)
{ {
pc87307_t *dev = (pc87307_t *) priv; pc87307_t *dev = (pc87307_t *) priv;
if (port & 1) if (port & 1)
dev->pm[dev->pm_idx] = val; dev->pm[dev->pm_idx] = val;
else { else {
dev->pm_idx = val & 0x07; dev->pm_idx = val & 0x07;
switch (dev->pm_idx) { switch (dev->pm_idx) {
case 0x00: case 0x00:
fdc_handler(dev); fdc_handler(dev);
lpt1_handler(dev); lpt1_handler(dev);
serial_handler(dev, 1); serial_handler(dev, 1);
serial_handler(dev, 0); serial_handler(dev, 0);
break; break;
} }
} }
} }
uint8_t uint8_t
pc87307_pm_read(uint16_t port, void *priv) pc87307_pm_read(uint16_t port, void *priv)
{ {
pc87307_t *dev = (pc87307_t *) priv; pc87307_t *dev = (pc87307_t *) priv;
if (port & 1) if (port & 1)
return dev->pm[dev->pm_idx]; return dev->pm[dev->pm_idx];
else else
return dev->pm_idx; return dev->pm_idx;
} }
static void static void
pc87307_pm_remove(pc87307_t *dev) pc87307_pm_remove(pc87307_t *dev)
{ {
if (dev->pm_base != 0xffff) { if (dev->pm_base != 0xffff) {
io_removehandler(dev->pm_base, 0x0008, io_removehandler(dev->pm_base, 0x0008,
pc87307_pm_read, NULL, NULL, pc87307_pm_write, NULL, NULL, dev); pc87307_pm_read, NULL, NULL, pc87307_pm_write, NULL, NULL, dev);
dev->pm_base = 0xffff; dev->pm_base = 0xffff;
} }
} }
static void static void
pc87307_pm_init(pc87307_t *dev, uint16_t addr) pc87307_pm_init(pc87307_t *dev, uint16_t addr)
{ {
dev->pm_base = addr; dev->pm_base = addr;
io_sethandler(dev->pm_base, 0x0008, io_sethandler(dev->pm_base, 0x0008,
pc87307_pm_read, NULL, NULL, pc87307_pm_write, NULL, NULL, dev); pc87307_pm_read, NULL, NULL, pc87307_pm_write, NULL, NULL, dev);
} }
static void static void
fdc_handler(pc87307_t *dev) fdc_handler(pc87307_t *dev)
{ {
uint8_t irq, active; uint8_t irq, active;
uint16_t addr; uint16_t addr;
fdc_remove(dev->fdc); fdc_remove(dev->fdc);
active = (dev->ld_regs[0x03][0x00] & 0x01) && (dev->pm[0x00] & 0x08); active = (dev->ld_regs[0x03][0x00] & 0x01) && (dev->pm[0x00] & 0x08);
addr = ((dev->ld_regs[0x03][0x30] << 8) | dev->ld_regs[0x03][0x31]) - 0x0002; addr = ((dev->ld_regs[0x03][0x30] << 8) | dev->ld_regs[0x03][0x31]) - 0x0002;
irq = (dev->ld_regs[0x03][0x40] & 0x0f); irq = (dev->ld_regs[0x03][0x40] & 0x0f);
if (active && (addr <= 0xfff8)) { if (active && (addr <= 0xfff8)) {
fdc_set_base(dev->fdc, addr); fdc_set_base(dev->fdc, addr);
fdc_set_irq(dev->fdc, irq); fdc_set_irq(dev->fdc, irq);
} }
} }
static void static void
lpt1_handler(pc87307_t *dev) lpt1_handler(pc87307_t *dev)
{ {
uint8_t irq, active; uint8_t irq, active;
uint16_t addr; uint16_t addr;
lpt1_remove(); lpt1_remove();
active = (dev->ld_regs[0x04][0x00] & 0x01) && (dev->pm[0x00] & 0x10); active = (dev->ld_regs[0x04][0x00] & 0x01) && (dev->pm[0x00] & 0x10);
addr = (dev->ld_regs[0x04][0x30] << 8) | dev->ld_regs[0x04][0x31]; addr = (dev->ld_regs[0x04][0x30] << 8) | dev->ld_regs[0x04][0x31];
irq = (dev->ld_regs[0x04][0x40] & 0x0f); irq = (dev->ld_regs[0x04][0x40] & 0x0f);
if (active && (addr <= 0xfffc)) { if (active && (addr <= 0xfffc)) {
lpt1_init(addr); lpt1_init(addr);
lpt1_irq(irq); lpt1_irq(irq);
} }
} }
static void static void
serial_handler(pc87307_t *dev, int uart) serial_handler(pc87307_t *dev, int uart)
{ {
uint8_t irq, active; uint8_t irq, active;
uint16_t addr; uint16_t addr;
serial_remove(dev->uart[uart]); serial_remove(dev->uart[uart]);
active = (dev->ld_regs[0x06 - uart][0x00] & 0x01) && (dev->pm[0x00] & (1 << (6 - uart))); active = (dev->ld_regs[0x06 - uart][0x00] & 0x01) && (dev->pm[0x00] & (1 << (6 - uart)));
addr = (dev->ld_regs[0x06 - uart][0x30] << 8) | dev->ld_regs[0x06 - uart][0x31]; addr = (dev->ld_regs[0x06 - uart][0x30] << 8) | dev->ld_regs[0x06 - uart][0x31];
irq = (dev->ld_regs[0x06 - uart][0x40] & 0x0f); irq = (dev->ld_regs[0x06 - uart][0x40] & 0x0f);
if (active && (addr <= 0xfff8)) if (active && (addr <= 0xfff8))
serial_setup(dev->uart[uart], addr, irq); serial_setup(dev->uart[uart], addr, irq);
} }
static void static void
gpio_handler(pc87307_t *dev) gpio_handler(pc87307_t *dev)
{ {
uint8_t active; uint8_t active;
uint16_t addr; uint16_t addr;
pc87307_gpio_remove(dev); pc87307_gpio_remove(dev);
active = (dev->ld_regs[0x07][0x00] & 0x01); active = (dev->ld_regs[0x07][0x00] & 0x01);
addr = (dev->ld_regs[0x07][0x30] << 8) | dev->ld_regs[0x07][0x31]; addr = (dev->ld_regs[0x07][0x30] << 8) | dev->ld_regs[0x07][0x31];
if (active) if (active)
pc87307_gpio_init(dev, 0, addr); pc87307_gpio_init(dev, 0, addr);
addr = (dev->ld_regs[0x07][0x32] << 8) | dev->ld_regs[0x07][0x33]; addr = (dev->ld_regs[0x07][0x32] << 8) | dev->ld_regs[0x07][0x33];
if (active) if (active)
pc87307_gpio_init(dev, 1, addr); pc87307_gpio_init(dev, 1, addr);
} }
static void static void
pm_handler(pc87307_t *dev) pm_handler(pc87307_t *dev)
{ {
uint8_t active; uint8_t active;
uint16_t addr; uint16_t addr;
pc87307_pm_remove(dev); pc87307_pm_remove(dev);
active = (dev->ld_regs[0x08][0x00] & 0x01); active = (dev->ld_regs[0x08][0x00] & 0x01);
addr = (dev->ld_regs[0x08][0x30] << 8) | dev->ld_regs[0x08][0x31]; addr = (dev->ld_regs[0x08][0x30] << 8) | dev->ld_regs[0x08][0x31];
if (active) if (active)
pc87307_pm_init(dev, addr); pc87307_pm_init(dev, addr);
} }
static void static void
pc87307_write(uint16_t port, uint8_t val, void *priv) pc87307_write(uint16_t port, uint8_t val, void *priv)
{ {
pc87307_t *dev = (pc87307_t *) priv; pc87307_t *dev = (pc87307_t *) priv;
uint8_t index; uint8_t index;
index = (port & 1) ? 0 : 1; index = (port & 1) ? 0 : 1;
if (index) { if (index) {
dev->cur_reg = val; dev->cur_reg = val;
return; return;
} else { } else {
switch (dev->cur_reg) { switch (dev->cur_reg) {
case 0x00: case 0x02: case 0x03: case 0x06: case 0x00:
case 0x07: case 0x21: case 0x02:
dev->regs[dev->cur_reg] = val; case 0x03:
break; case 0x06:
case 0x22: case 0x07:
dev->regs[dev->cur_reg] = val & 0x7f; case 0x21:
break; dev->regs[dev->cur_reg] = val;
case 0x23: break;
dev->regs[dev->cur_reg] = val & 0x0f; case 0x22:
break; dev->regs[dev->cur_reg] = val & 0x7f;
case 0x24: break;
dev->pcregs[dev->regs[0x23]] = val; case 0x23:
break; dev->regs[dev->cur_reg] = val & 0x0f;
default: break;
if (dev->cur_reg >= 0x30) { case 0x24:
if ((dev->regs[0x07] != 0x06) || !(dev->regs[0x21] & 0x10)) dev->pcregs[dev->regs[0x23]] = val;
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val; break;
} default:
break; if (dev->cur_reg >= 0x30) {
} if ((dev->regs[0x07] != 0x06) || !(dev->regs[0x21] & 0x10))
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val;
}
break;
}
} }
switch(dev->cur_reg) { switch (dev->cur_reg) {
case 0x30: case 0x30:
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x01; dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x01;
switch (dev->regs[0x07]) { switch (dev->regs[0x07]) {
case 0x03: case 0x03:
fdc_handler(dev); fdc_handler(dev);
break; break;
case 0x04: case 0x04:
lpt1_handler(dev); lpt1_handler(dev);
break; break;
case 0x05: case 0x05:
serial_handler(dev, 1); serial_handler(dev, 1);
break; break;
case 0x06: case 0x06:
serial_handler(dev, 0); serial_handler(dev, 0);
break; break;
case 0x07: case 0x07:
gpio_handler(dev); gpio_handler(dev);
break; break;
case 0x08: case 0x08:
pm_handler(dev); pm_handler(dev);
break; break;
} }
break; break;
case 0x60: case 0x62: case 0x60:
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x07; case 0x62:
if ((dev->cur_reg == 0x62) && (dev->regs[0x07] != 0x07)) dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x07;
break; if ((dev->cur_reg == 0x62) && (dev->regs[0x07] != 0x07))
switch (dev->regs[0x07]) { break;
case 0x03: switch (dev->regs[0x07]) {
fdc_handler(dev); case 0x03:
break; fdc_handler(dev);
case 0x04: break;
lpt1_handler(dev); case 0x04:
break; lpt1_handler(dev);
case 0x05: break;
serial_handler(dev, 1); case 0x05:
break; serial_handler(dev, 1);
case 0x06: break;
serial_handler(dev, 0); case 0x06:
break; serial_handler(dev, 0);
case 0x07: break;
gpio_handler(dev); case 0x07:
break; gpio_handler(dev);
case 0x08: break;
pm_handler(dev); case 0x08:
break; pm_handler(dev);
} break;
break; }
case 0x61: break;
switch (dev->regs[0x07]) { case 0x61:
case 0x00: switch (dev->regs[0x07]) {
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfb; case 0x00:
break; dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfb;
case 0x03: break;
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfa) | 0x02; case 0x03:
fdc_handler(dev); dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfa) | 0x02;
break; fdc_handler(dev);
case 0x04: break;
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfc; case 0x04:
lpt1_handler(dev); dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfc;
break; lpt1_handler(dev);
case 0x05: break;
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; case 0x05:
serial_handler(dev, 1); dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8;
break; serial_handler(dev, 1);
case 0x06: break;
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; case 0x06:
serial_handler(dev, 0); dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8;
break; serial_handler(dev, 0);
case 0x07: break;
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; case 0x07:
gpio_handler(dev); dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8;
break; gpio_handler(dev);
case 0x08: break;
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe; case 0x08:
pm_handler(dev); dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe;
break; pm_handler(dev);
} break;
break; }
case 0x63: break;
if (dev->regs[0x07] == 0x00) case 0x63:
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfb) | 0x04; if (dev->regs[0x07] == 0x00)
else if (dev->regs[0x07] == 0x07) { dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfb) | 0x04;
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe; else if (dev->regs[0x07] == 0x07) {
gpio_handler(dev); dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe;
} gpio_handler(dev);
break; }
case 0x70: break;
case 0x74: case 0x75: case 0x70:
switch (dev->regs[0x07]) { case 0x74:
case 0x03: case 0x75:
fdc_handler(dev); switch (dev->regs[0x07]) {
break; case 0x03:
case 0x04: fdc_handler(dev);
lpt1_handler(dev); break;
break; case 0x04:
case 0x05: lpt1_handler(dev);
serial_handler(dev, 1); break;
break; case 0x05:
case 0x06: serial_handler(dev, 1);
serial_handler(dev, 0); break;
break; case 0x06:
case 0x07: serial_handler(dev, 0);
gpio_handler(dev); break;
break; case 0x07:
case 0x08: gpio_handler(dev);
pm_handler(dev); break;
break; case 0x08:
} pm_handler(dev);
break; break;
case 0xf0: }
switch (dev->regs[0x07]) { break;
case 0x00: case 0xf0:
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xc1; switch (dev->regs[0x07]) {
break; case 0x00:
case 0x03: dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xc1;
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xe1; break;
fdc_update_densel_polarity(dev->fdc, (val & 0x20) ? 1 : 0); case 0x03:
fdc_update_enh_mode(dev->fdc, (val & 0x40) ? 1 : 0); dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xe1;
break; fdc_update_densel_polarity(dev->fdc, (val & 0x20) ? 1 : 0);
case 0x04: fdc_update_enh_mode(dev->fdc, (val & 0x40) ? 1 : 0);
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf3; break;
lpt1_handler(dev); case 0x04:
break; dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf3;
case 0x05: case 0x06: lpt1_handler(dev);
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x87; break;
break; case 0x05:
} case 0x06:
break; dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x87;
case 0xf1: break;
if (dev->regs[0x07] == 0x03) }
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x0f; break;
break; case 0xf1:
if (dev->regs[0x07] == 0x03)
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x0f;
break;
} }
} }
uint8_t uint8_t
pc87307_read(uint16_t port, void *priv) pc87307_read(uint16_t port, void *priv)
{ {
pc87307_t *dev = (pc87307_t *) priv; pc87307_t *dev = (pc87307_t *) priv;
uint8_t ret = 0xff, index; uint8_t ret = 0xff, index;
index = (port & 1) ? 0 : 1; index = (port & 1) ? 0 : 1;
if (index) if (index)
ret = dev->cur_reg; ret = dev->cur_reg;
else { else {
if (dev->cur_reg >= 0x30) if (dev->cur_reg >= 0x30)
ret = dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30]; ret = dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30];
else if (dev->cur_reg == 0x24) else if (dev->cur_reg == 0x24)
ret = dev->pcregs[dev->regs[0x23]]; ret = dev->pcregs[dev->regs[0x23]];
else else
ret = dev->regs[dev->cur_reg]; ret = dev->regs[dev->cur_reg];
} }
return ret; return ret;
} }
void void
pc87307_reset(pc87307_t *dev) pc87307_reset(pc87307_t *dev)
{ {
@@ -459,7 +448,7 @@ pc87307_reset(pc87307_t *dev)
memset(dev->regs, 0x00, 0x30); memset(dev->regs, 0x00, 0x30);
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
memset(dev->ld_regs[i], 0x00, 0xd0); memset(dev->ld_regs[i], 0x00, 0xd0);
memset(dev->pcregs, 0x00, 0x10); memset(dev->pcregs, 0x00, 0x10);
memset(dev->gpio, 0xff, 0x08); memset(dev->gpio, 0xff, 0x08);
memset(dev->pm, 0x00, 0x08); memset(dev->pm, 0x00, 0x08);
@@ -544,8 +533,8 @@ pc87307_reset(pc87307_t *dev)
dev->gpio_base = dev->pm_base = 0xffff; dev->gpio_base = dev->pm_base = 0xffff;
/* /*
0 = 360 rpm @ 500 kbps for 3.5" 0 = 360 rpm @ 500 kbps for 3.5"
1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5" 1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5"
*/ */
lpt1_remove(); lpt1_remove();
serial_remove(dev->uart[0]); serial_remove(dev->uart[0]);
@@ -553,7 +542,6 @@ pc87307_reset(pc87307_t *dev)
fdc_reset(dev->fdc); fdc_reset(dev->fdc);
} }
static void static void
pc87307_close(void *priv) pc87307_close(void *priv)
{ {
@@ -562,7 +550,6 @@ pc87307_close(void *priv)
free(dev); free(dev);
} }
static void * static void *
pc87307_init(const device_t *info) pc87307_init(const device_t *info)
{ {
@@ -579,69 +566,69 @@ pc87307_init(const device_t *info)
pc87307_reset(dev); pc87307_reset(dev);
if (info->local & 0x100) { if (info->local & 0x100) {
io_sethandler(0x02e, 0x0002, io_sethandler(0x02e, 0x0002,
pc87307_read, NULL, NULL, pc87307_write, NULL, NULL, dev); pc87307_read, NULL, NULL, pc87307_write, NULL, NULL, dev);
} }
if (info->local & 0x200) { if (info->local & 0x200) {
io_sethandler(0x15c, 0x0002, io_sethandler(0x15c, 0x0002,
pc87307_read, NULL, NULL, pc87307_write, NULL, NULL, dev); pc87307_read, NULL, NULL, pc87307_write, NULL, NULL, dev);
} }
return dev; return dev;
} }
const device_t pc87307_device = { const device_t pc87307_device = {
.name = "National Semiconductor PC87307 Super I/O", .name = "National Semiconductor PC87307 Super I/O",
.internal_name = "pc87307", .internal_name = "pc87307",
.flags = 0, .flags = 0,
.local = 0x1c0, .local = 0x1c0,
.init = pc87307_init, .init = pc87307_init,
.close = pc87307_close, .close = pc87307_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t pc87307_15c_device = { const device_t pc87307_15c_device = {
.name = "National Semiconductor PC87307 Super I/O (Port 15Ch)", .name = "National Semiconductor PC87307 Super I/O (Port 15Ch)",
.internal_name = "pc87307_15c", .internal_name = "pc87307_15c",
.flags = 0, .flags = 0,
.local = 0x2c0, .local = 0x2c0,
.init = pc87307_init, .init = pc87307_init,
.close = pc87307_close, .close = pc87307_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t pc87307_both_device = { const device_t pc87307_both_device = {
.name = "National Semiconductor PC87307 Super I/O (Ports 2Eh and 15Ch)", .name = "National Semiconductor PC87307 Super I/O (Ports 2Eh and 15Ch)",
.internal_name = "pc87307_both", .internal_name = "pc87307_both",
.flags = 0, .flags = 0,
.local = 0x3c0, .local = 0x3c0,
.init = pc87307_init, .init = pc87307_init,
.close = pc87307_close, .close = pc87307_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t pc97307_device = { const device_t pc97307_device = {
.name = "National Semiconductor PC97307 Super I/O", .name = "National Semiconductor PC97307 Super I/O",
.internal_name = "pc97307", .internal_name = "pc97307",
.flags = 0, .flags = 0,
.local = 0x1cf, .local = 0x1cf,
.init = pc87307_init, .init = pc87307_init,
.close = pc87307_close, .close = pc87307_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

View File

@@ -34,22 +34,19 @@
#include <86box/fdc.h> #include <86box/fdc.h>
#include <86box/sio.h> #include <86box/sio.h>
typedef struct { typedef struct {
uint8_t id, pm_idx, uint8_t id, pm_idx,
regs[48], ld_regs[256][208], regs[48], ld_regs[256][208],
pm[8]; pm[8];
uint16_t pm_base; uint16_t pm_base;
int cur_reg; int cur_reg;
fdc_t *fdc; fdc_t *fdc;
serial_t *uart[2]; serial_t *uart[2];
} pc87309_t; } pc87309_t;
static void fdc_handler(pc87309_t *dev);
static void fdc_handler(pc87309_t *dev); static void lpt1_handler(pc87309_t *dev);
static void lpt1_handler(pc87309_t *dev); static void serial_handler(pc87309_t *dev, int uart);
static void serial_handler(pc87309_t *dev, int uart);
static void static void
pc87309_pm_write(uint16_t port, uint8_t val, void *priv) pc87309_pm_write(uint16_t port, uint8_t val, void *priv)
@@ -57,296 +54,293 @@ pc87309_pm_write(uint16_t port, uint8_t val, void *priv)
pc87309_t *dev = (pc87309_t *) priv; pc87309_t *dev = (pc87309_t *) priv;
if (port & 1) { if (port & 1) {
dev->pm[dev->pm_idx] = val; dev->pm[dev->pm_idx] = val;
switch (dev->pm_idx) { switch (dev->pm_idx) {
case 0x00: case 0x00:
fdc_handler(dev); fdc_handler(dev);
lpt1_handler(dev); lpt1_handler(dev);
serial_handler(dev, 1); serial_handler(dev, 1);
serial_handler(dev, 0); serial_handler(dev, 0);
break; break;
} }
} else } else
dev->pm_idx = val & 0x07; dev->pm_idx = val & 0x07;
} }
uint8_t uint8_t
pc87309_pm_read(uint16_t port, void *priv) pc87309_pm_read(uint16_t port, void *priv)
{ {
pc87309_t *dev = (pc87309_t *) priv; pc87309_t *dev = (pc87309_t *) priv;
if (port & 1) if (port & 1)
return dev->pm[dev->pm_idx]; return dev->pm[dev->pm_idx];
else else
return dev->pm_idx; return dev->pm_idx;
} }
static void static void
pc87309_pm_remove(pc87309_t *dev) pc87309_pm_remove(pc87309_t *dev)
{ {
if (dev->pm_base != 0xffff) { if (dev->pm_base != 0xffff) {
io_removehandler(dev->pm_base, 0x0008, io_removehandler(dev->pm_base, 0x0008,
pc87309_pm_read, NULL, NULL, pc87309_pm_write, NULL, NULL, dev); pc87309_pm_read, NULL, NULL, pc87309_pm_write, NULL, NULL, dev);
dev->pm_base = 0xffff; dev->pm_base = 0xffff;
} }
} }
static void static void
pc87309_pm_init(pc87309_t *dev, uint16_t addr) pc87309_pm_init(pc87309_t *dev, uint16_t addr)
{ {
dev->pm_base = addr; dev->pm_base = addr;
io_sethandler(dev->pm_base, 0x0008, io_sethandler(dev->pm_base, 0x0008,
pc87309_pm_read, NULL, NULL, pc87309_pm_write, NULL, NULL, dev); pc87309_pm_read, NULL, NULL, pc87309_pm_write, NULL, NULL, dev);
} }
static void static void
fdc_handler(pc87309_t *dev) fdc_handler(pc87309_t *dev)
{ {
uint8_t irq, active; uint8_t irq, active;
uint16_t addr; uint16_t addr;
fdc_remove(dev->fdc); fdc_remove(dev->fdc);
active = (dev->ld_regs[0x00][0x00] & 0x01) && (dev->pm[0x00] & 0x08); active = (dev->ld_regs[0x00][0x00] & 0x01) && (dev->pm[0x00] & 0x08);
addr = ((dev->ld_regs[0x00][0x30] << 8) | dev->ld_regs[0x00][0x31]) - 0x0002; addr = ((dev->ld_regs[0x00][0x30] << 8) | dev->ld_regs[0x00][0x31]) - 0x0002;
irq = (dev->ld_regs[0x00][0x40] & 0x0f); irq = (dev->ld_regs[0x00][0x40] & 0x0f);
if (active) { if (active) {
fdc_set_base(dev->fdc, addr); fdc_set_base(dev->fdc, addr);
fdc_set_irq(dev->fdc, irq); fdc_set_irq(dev->fdc, irq);
} }
} }
static void static void
lpt1_handler(pc87309_t *dev) lpt1_handler(pc87309_t *dev)
{ {
uint8_t irq, active; uint8_t irq, active;
uint16_t addr; uint16_t addr;
lpt1_remove(); lpt1_remove();
active = (dev->ld_regs[0x01][0x00] & 0x01) && (dev->pm[0x00] & 0x10); active = (dev->ld_regs[0x01][0x00] & 0x01) && (dev->pm[0x00] & 0x10);
addr = (dev->ld_regs[0x01][0x30] << 8) | dev->ld_regs[0x01][0x31]; addr = (dev->ld_regs[0x01][0x30] << 8) | dev->ld_regs[0x01][0x31];
irq = (dev->ld_regs[0x01][0x40] & 0x0f); irq = (dev->ld_regs[0x01][0x40] & 0x0f);
if (active) { if (active) {
lpt1_init(addr); lpt1_init(addr);
lpt1_irq(irq); lpt1_irq(irq);
} }
} }
static void static void
serial_handler(pc87309_t *dev, int uart) serial_handler(pc87309_t *dev, int uart)
{ {
uint8_t irq, active; uint8_t irq, active;
uint16_t addr; uint16_t addr;
serial_remove(dev->uart[uart]); serial_remove(dev->uart[uart]);
active = (dev->ld_regs[0x03 - uart][0x00] & 0x01) && (dev->pm[0x00] & (1 << (6 - uart))); active = (dev->ld_regs[0x03 - uart][0x00] & 0x01) && (dev->pm[0x00] & (1 << (6 - uart)));
addr = (dev->ld_regs[0x03 - uart][0x30] << 8) | dev->ld_regs[0x03 - uart][0x31]; addr = (dev->ld_regs[0x03 - uart][0x30] << 8) | dev->ld_regs[0x03 - uart][0x31];
irq = (dev->ld_regs[0x03 - uart][0x40] & 0x0f); irq = (dev->ld_regs[0x03 - uart][0x40] & 0x0f);
if (active) if (active)
serial_setup(dev->uart[uart], addr, irq); serial_setup(dev->uart[uart], addr, irq);
} }
static void static void
pm_handler(pc87309_t *dev) pm_handler(pc87309_t *dev)
{ {
uint8_t active; uint8_t active;
uint16_t addr; uint16_t addr;
pc87309_pm_remove(dev); pc87309_pm_remove(dev);
active = (dev->ld_regs[0x04][0x00] & 0x01); active = (dev->ld_regs[0x04][0x00] & 0x01);
addr = (dev->ld_regs[0x04][0x30] << 8) | dev->ld_regs[0x04][0x31]; addr = (dev->ld_regs[0x04][0x30] << 8) | dev->ld_regs[0x04][0x31];
if (active) if (active)
pc87309_pm_init(dev, addr); pc87309_pm_init(dev, addr);
} }
static void static void
pc87309_write(uint16_t port, uint8_t val, void *priv) pc87309_write(uint16_t port, uint8_t val, void *priv)
{ {
pc87309_t *dev = (pc87309_t *) priv; pc87309_t *dev = (pc87309_t *) priv;
uint8_t index; uint8_t index;
index = (port & 1) ? 0 : 1; index = (port & 1) ? 0 : 1;
if (index) { if (index) {
dev->cur_reg = val; dev->cur_reg = val;
return; return;
} else { } else {
switch (dev->cur_reg) { switch (dev->cur_reg) {
case 0x00: case 0x02: case 0x03: case 0x06: case 0x00:
case 0x07: case 0x21: case 0x02:
dev->regs[dev->cur_reg] = val; case 0x03:
break; case 0x06:
case 0x22: case 0x07:
dev->regs[dev->cur_reg] = val & 0x7f; case 0x21:
break; dev->regs[dev->cur_reg] = val;
default: break;
if (dev->cur_reg >= 0x30) { case 0x22:
if ((dev->regs[0x07] != 0x06) || !(dev->regs[0x21] & 0x10)) dev->regs[dev->cur_reg] = val & 0x7f;
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val; break;
} default:
break; if (dev->cur_reg >= 0x30) {
} if ((dev->regs[0x07] != 0x06) || !(dev->regs[0x21] & 0x10))
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val;
}
break;
}
} }
switch(dev->cur_reg) { switch (dev->cur_reg) {
case 0x30: case 0x30:
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x01; dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x01;
switch (dev->regs[0x07]) { switch (dev->regs[0x07]) {
case 0x00: case 0x00:
fdc_handler(dev); fdc_handler(dev);
break; break;
case 0x01: case 0x01:
lpt1_handler(dev); lpt1_handler(dev);
break; break;
case 0x02: case 0x02:
serial_handler(dev, 1); serial_handler(dev, 1);
break; break;
case 0x03: case 0x03:
serial_handler(dev, 0); serial_handler(dev, 0);
break; break;
case 0x04: case 0x04:
pm_handler(dev); pm_handler(dev);
break; break;
} }
break; break;
case 0x60: case 0x62: case 0x60:
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x07; case 0x62:
if (dev->cur_reg == 0x62) dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x07;
break; if (dev->cur_reg == 0x62)
switch (dev->regs[0x07]) { break;
case 0x00: switch (dev->regs[0x07]) {
fdc_handler(dev); case 0x00:
break; fdc_handler(dev);
case 0x01: break;
lpt1_handler(dev); case 0x01:
break; lpt1_handler(dev);
case 0x02: break;
serial_handler(dev, 1); case 0x02:
break; serial_handler(dev, 1);
case 0x03: break;
serial_handler(dev, 0); case 0x03:
break; serial_handler(dev, 0);
case 0x04: break;
pm_handler(dev); case 0x04:
break; pm_handler(dev);
} break;
break; }
case 0x63: break;
if (dev->regs[0x07] == 0x06) case 0x63:
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xf8) | 0x04; if (dev->regs[0x07] == 0x06)
break; dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xf8) | 0x04;
case 0x61: break;
switch (dev->regs[0x07]) { case 0x61:
case 0x00: switch (dev->regs[0x07]) {
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfa) | 0x02; case 0x00:
fdc_handler(dev); dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfa) | 0x02;
break; fdc_handler(dev);
case 0x01: break;
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfc; case 0x01:
lpt1_handler(dev); dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfc;
break; lpt1_handler(dev);
case 0x02: break;
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; case 0x02:
serial_handler(dev, 1); dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8;
break; serial_handler(dev, 1);
case 0x03: break;
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; case 0x03:
serial_handler(dev, 0); dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8;
break; serial_handler(dev, 0);
case 0x04: break;
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe; case 0x04:
pm_handler(dev); dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe;
break; pm_handler(dev);
case 0x06: break;
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8; case 0x06:
break; dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8;
} break;
break; }
case 0x70: break;
case 0x74: case 0x75: case 0x70:
switch (dev->regs[0x07]) { case 0x74:
case 0x00: case 0x75:
fdc_handler(dev); switch (dev->regs[0x07]) {
break; case 0x00:
case 0x01: fdc_handler(dev);
lpt1_handler(dev); break;
break; case 0x01:
case 0x02: lpt1_handler(dev);
serial_handler(dev, 1); break;
break; case 0x02:
case 0x03: serial_handler(dev, 1);
serial_handler(dev, 0); break;
break; case 0x03:
case 0x04: serial_handler(dev, 0);
pm_handler(dev); break;
break; case 0x04:
} pm_handler(dev);
break; break;
case 0xf0: }
switch (dev->regs[0x07]) { break;
case 0x00: case 0xf0:
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xe1; switch (dev->regs[0x07]) {
fdc_update_densel_polarity(dev->fdc, (val & 0x20) ? 1 : 0); case 0x00:
fdc_update_enh_mode(dev->fdc, (val & 0x40) ? 1 : 0); dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xe1;
break; fdc_update_densel_polarity(dev->fdc, (val & 0x20) ? 1 : 0);
case 0x01: fdc_update_enh_mode(dev->fdc, (val & 0x40) ? 1 : 0);
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf3; break;
lpt1_handler(dev); case 0x01:
break; dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf3;
case 0x02: case 0x03: lpt1_handler(dev);
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x87; break;
break; case 0x02:
case 0x06: case 0x03:
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xc1; dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x87;
break; break;
} case 0x06:
break; dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xc1;
case 0xf1: break;
if (dev->regs[0x07] == 0x00) }
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x0f; break;
break; case 0xf1:
if (dev->regs[0x07] == 0x00)
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x0f;
break;
} }
} }
uint8_t uint8_t
pc87309_read(uint16_t port, void *priv) pc87309_read(uint16_t port, void *priv)
{ {
pc87309_t *dev = (pc87309_t *) priv; pc87309_t *dev = (pc87309_t *) priv;
uint8_t ret = 0xff, index; uint8_t ret = 0xff, index;
index = (port & 1) ? 0 : 1; index = (port & 1) ? 0 : 1;
if (index) if (index)
ret = dev->cur_reg & 0x1f; ret = dev->cur_reg & 0x1f;
else { else {
if (dev->cur_reg >= 0x30) if (dev->cur_reg >= 0x30)
ret = dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30]; ret = dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30];
else else
ret = dev->regs[dev->cur_reg]; ret = dev->regs[dev->cur_reg];
} }
return ret; return ret;
} }
void void
pc87309_reset(pc87309_t *dev) pc87309_reset(pc87309_t *dev)
{ {
@@ -354,7 +348,7 @@ pc87309_reset(pc87309_t *dev)
memset(dev->regs, 0x00, 0x30); memset(dev->regs, 0x00, 0x30);
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
memset(dev->ld_regs[i], 0x00, 0xd0); memset(dev->ld_regs[i], 0x00, 0xd0);
memset(dev->pm, 0x00, 0x08); memset(dev->pm, 0x00, 0x08);
dev->regs[0x20] = dev->id; dev->regs[0x20] = dev->id;
@@ -426,8 +420,8 @@ pc87309_reset(pc87309_t *dev)
dev->pm_base = 0xffff; dev->pm_base = 0xffff;
/* /*
0 = 360 rpm @ 500 kbps for 3.5" 0 = 360 rpm @ 500 kbps for 3.5"
1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5" 1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5"
*/ */
lpt1_remove(); lpt1_remove();
serial_remove(dev->uart[0]); serial_remove(dev->uart[0]);
@@ -435,7 +429,6 @@ pc87309_reset(pc87309_t *dev)
fdc_reset(dev->fdc); fdc_reset(dev->fdc);
} }
static void static void
pc87309_close(void *priv) pc87309_close(void *priv)
{ {
@@ -444,7 +437,6 @@ pc87309_close(void *priv)
free(dev); free(dev);
} }
static void * static void *
pc87309_init(const device_t *info) pc87309_init(const device_t *info)
{ {
@@ -461,40 +453,40 @@ pc87309_init(const device_t *info)
pc87309_reset(dev); pc87309_reset(dev);
if (info->local & 0x100) { if (info->local & 0x100) {
io_sethandler(0x15c, 0x0002, io_sethandler(0x15c, 0x0002,
pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev); pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev);
} else { } else {
io_sethandler(0x02e, 0x0002, io_sethandler(0x02e, 0x0002,
pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev); pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev);
} }
return dev; return dev;
} }
const device_t pc87309_device = { const device_t pc87309_device = {
.name = "National Semiconductor PC87309 Super I/O", .name = "National Semiconductor PC87309 Super I/O",
.internal_name = "pc87309", .internal_name = "pc87309",
.flags = 0, .flags = 0,
.local = 0xe0, .local = 0xe0,
.init = pc87309_init, .init = pc87309_init,
.close = pc87309_close, .close = pc87309_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t pc87309_15c_device = { const device_t pc87309_15c_device = {
.name = "National Semiconductor PC87309 Super I/O (Port 15Ch)", .name = "National Semiconductor PC87309 Super I/O (Port 15Ch)",
.internal_name = "pc87309_15c", .internal_name = "pc87309_15c",
.flags = 0, .flags = 0,
.local = 0x1e0, .local = 0x1e0,
.init = pc87309_init, .init = pc87309_init,
.close = pc87309_close, .close = pc87309_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

View File

@@ -50,31 +50,29 @@ pc87310_log(const char *fmt, ...)
{ {
va_list ap; va_list ap;
if (pc87310_do_log) if (pc87310_do_log) {
{
va_start(ap, fmt); va_start(ap, fmt);
pclog_ex(fmt, ap); pclog_ex(fmt, ap);
va_end(ap); va_end(ap);
} }
} }
#else #else
#define pc87310_log(fmt, ...) # define pc87310_log(fmt, ...)
#endif #endif
typedef struct { typedef struct {
uint8_t tries, ide_function, uint8_t tries, ide_function,
reg; reg;
fdc_t *fdc; fdc_t *fdc;
serial_t *uart[2]; serial_t *uart[2];
} pc87310_t; } pc87310_t;
static void static void
lpt1_handler(pc87310_t *dev) lpt1_handler(pc87310_t *dev)
{ {
int temp; int temp;
uint16_t lpt_port = LPT1_ADDR; uint16_t lpt_port = LPT1_ADDR;
uint8_t lpt_irq = LPT1_IRQ; uint8_t lpt_irq = LPT1_IRQ;
/* bits 0-1: /* bits 0-1:
* 00 378h * 00 378h
@@ -85,28 +83,27 @@ lpt1_handler(pc87310_t *dev)
temp = dev->reg & 3; temp = dev->reg & 3;
switch (temp) { switch (temp) {
case 0: case 0:
lpt_port = LPT1_ADDR; lpt_port = LPT1_ADDR;
break; break;
case 1: case 1:
lpt_port = LPT_MDA_ADDR; lpt_port = LPT_MDA_ADDR;
break; break;
case 2: case 2:
lpt_port = LPT2_ADDR; lpt_port = LPT2_ADDR;
break; break;
case 3: case 3:
lpt_port = 0x000; lpt_port = 0x000;
lpt_irq = 0xff; lpt_irq = 0xff;
break; break;
} }
if (lpt_port) if (lpt_port)
lpt1_init(lpt_port); lpt1_init(lpt_port);
lpt1_irq(lpt_irq); lpt1_irq(lpt_irq);
} }
static void static void
serial_handler(pc87310_t *dev, int uart) serial_handler(pc87310_t *dev, int uart)
{ {
@@ -117,9 +114,9 @@ serial_handler(pc87310_t *dev, int uart)
*/ */
temp = (dev->reg >> (2 + uart)) & 1; temp = (dev->reg >> (2 + uart)) & 1;
//current serial port is enabled // current serial port is enabled
if (!temp){ if (!temp) {
//configure serial port as COM2 // configure serial port as COM2
if (((dev->reg >> 4) & 1) ^ uart) if (((dev->reg >> 4) & 1) ^ uart)
serial_setup(dev->uart[uart], COM2_ADDR, COM2_IRQ); serial_setup(dev->uart[uart], COM2_ADDR, COM2_IRQ);
// configure serial port as COM1 // configure serial port as COM1
@@ -128,23 +125,22 @@ serial_handler(pc87310_t *dev, int uart)
} }
} }
static void static void
pc87310_write(uint16_t port, uint8_t val, void *priv) pc87310_write(uint16_t port, uint8_t val, void *priv)
{ {
pc87310_t *dev = (pc87310_t *) priv; pc87310_t *dev = (pc87310_t *) priv;
uint8_t valxor; uint8_t valxor;
// second write to config register // second write to config register
if (dev->tries) { if (dev->tries) {
valxor = val ^ dev->reg; valxor = val ^ dev->reg;
dev->tries = 0; dev->tries = 0;
dev->reg = val; dev->reg = val;
// first write to config register // first write to config register
} else { } else {
dev->tries++; dev->tries++;
return; return;
} }
pc87310_log("SIO: written %01X\n", val); pc87310_log("SIO: written %01X\n", val);
@@ -191,12 +187,11 @@ pc87310_write(uint16_t port, uint8_t val, void *priv)
return; return;
} }
uint8_t uint8_t
pc87310_read(uint16_t port, void *priv) pc87310_read(uint16_t port, void *priv)
{ {
pc87310_t *dev = (pc87310_t *) priv; pc87310_t *dev = (pc87310_t *) priv;
uint8_t ret = 0xff; uint8_t ret = 0xff;
dev->tries = 0; dev->tries = 0;
@@ -207,15 +202,14 @@ pc87310_read(uint16_t port, void *priv)
return ret; return ret;
} }
void void
pc87310_reset(pc87310_t *dev) pc87310_reset(pc87310_t *dev)
{ {
dev->reg = 0x0; dev->reg = 0x0;
dev->tries = 0; dev->tries = 0;
/* /*
0 = 360 rpm @ 500 kbps for 3.5" 0 = 360 rpm @ 500 kbps for 3.5"
1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5" 1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5"
*/ */
lpt1_remove(); lpt1_remove();
lpt1_handler(dev); lpt1_handler(dev);
@@ -224,10 +218,9 @@ pc87310_reset(pc87310_t *dev)
serial_handler(dev, 0); serial_handler(dev, 0);
serial_handler(dev, 1); serial_handler(dev, 1);
fdc_reset(dev->fdc); fdc_reset(dev->fdc);
//ide_pri_enable(); // ide_pri_enable();
} }
static void static void
pc87310_close(void *priv) pc87310_close(void *priv)
{ {
@@ -236,7 +229,6 @@ pc87310_close(void *priv)
free(dev); free(dev);
} }
static void * static void *
pc87310_init(const device_t *info) pc87310_init(const device_t *info)
{ {
@@ -257,36 +249,35 @@ pc87310_init(const device_t *info)
pc87310_reset(dev); pc87310_reset(dev);
io_sethandler(0x3f3, 0x0001, io_sethandler(0x3f3, 0x0001,
pc87310_read, NULL, NULL, pc87310_write, NULL, NULL, dev); pc87310_read, NULL, NULL, pc87310_write, NULL, NULL, dev);
return dev; return dev;
} }
const device_t pc87310_device = { const device_t pc87310_device = {
.name = "National Semiconductor PC87310 Super I/O", .name = "National Semiconductor PC87310 Super I/O",
.internal_name = "pc87310", .internal_name = "pc87310",
.flags = 0, .flags = 0,
.local = 0, .local = 0,
.init = pc87310_init, .init = pc87310_init,
.close = pc87310_close, .close = pc87310_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t pc87310_ide_device = { const device_t pc87310_ide_device = {
.name = "National Semiconductor PC87310 Super I/O with IDE functionality", .name = "National Semiconductor PC87310 Super I/O with IDE functionality",
.internal_name = "pc87310_ide", .internal_name = "pc87310_ide",
.flags = 0, .flags = 0,
.local = 1, .local = 1,
.init = pc87310_init, .init = pc87310_init,
.close = pc87310_close, .close = pc87310_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

View File

@@ -33,15 +33,15 @@
#define HAS_IDE_FUNCTIONALITY dev->ide_function #define HAS_IDE_FUNCTIONALITY dev->ide_function
/* Basic Functionalities */ /* Basic Functionalities */
#define FUNCTION_ENABLE dev->regs[0x00] #define FUNCTION_ENABLE dev->regs[0x00]
#define FUNCTION_ADDRESS dev->regs[0x01] #define FUNCTION_ADDRESS dev->regs[0x01]
#define POWER_TEST dev->regs[0x02] #define POWER_TEST dev->regs[0x02]
/* Base Addresses */ /* Base Addresses */
#define LPT_BA (FUNCTION_ADDRESS & 0x03) #define LPT_BA (FUNCTION_ADDRESS & 0x03)
#define UART1_BA ((FUNCTION_ADDRESS >> 2) & 0x03) #define UART1_BA ((FUNCTION_ADDRESS >> 2) & 0x03)
#define UART2_BA ((FUNCTION_ADDRESS >> 4) & 0x03) #define UART2_BA ((FUNCTION_ADDRESS >> 4) & 0x03)
#define COM_BA ((FUNCTION_ADDRESS >> 6) & 0x03) #define COM_BA ((FUNCTION_ADDRESS >> 6) & 0x03)
#ifdef ENABLE_PC87311_LOG #ifdef ENABLE_PC87311_LOG
int pc87311_do_log = ENABLE_PC87311_LOG; int pc87311_do_log = ENABLE_PC87311_LOG;
@@ -50,22 +50,21 @@ pc87311_log(const char *fmt, ...)
{ {
va_list ap; va_list ap;
if (pc87311_do_log) if (pc87311_do_log) {
{
va_start(ap, fmt); va_start(ap, fmt);
pclog_ex(fmt, ap); pclog_ex(fmt, ap);
va_end(ap); va_end(ap);
} }
} }
#else #else
#define pc87311_log(fmt, ...) # define pc87311_log(fmt, ...)
#endif #endif
typedef struct typedef struct
{ {
uint8_t index, regs[256], cfg_lock, ide_function; uint8_t index, regs[256], cfg_lock, ide_function;
uint16_t base, irq; uint16_t base, irq;
fdc_t *fdc_controller; fdc_t *fdc_controller;
serial_t *uart[2]; serial_t *uart[2];
} pc87311_t; } pc87311_t;
@@ -79,30 +78,28 @@ void pc87311_enable(pc87311_t *dev);
static void static void
pc87311_write(uint16_t addr, uint8_t val, void *priv) pc87311_write(uint16_t addr, uint8_t val, void *priv)
{ {
pc87311_t *dev = (pc87311_t *)priv; pc87311_t *dev = (pc87311_t *) priv;
switch (addr) switch (addr) {
{ case 0x398:
case 0x398: case 0x26e:
case 0x26e: dev->index = val;
dev->index = val; break;
break;
case 0x399: case 0x399:
case 0x26f: case 0x26f:
switch (dev->index) switch (dev->index) {
{ case 0x00:
case 0x00: FUNCTION_ENABLE = val;
FUNCTION_ENABLE = val; break;
case 0x01:
FUNCTION_ADDRESS = val;
break;
case 0x02:
POWER_TEST = val;
break;
}
break; break;
case 0x01:
FUNCTION_ADDRESS = val;
break;
case 0x02:
POWER_TEST = val;
break;
}
break;
} }
pc87311_enable(dev); pc87311_enable(dev);
@@ -111,103 +108,105 @@ pc87311_write(uint16_t addr, uint8_t val, void *priv)
static uint8_t static uint8_t
pc87311_read(uint16_t addr, void *priv) pc87311_read(uint16_t addr, void *priv)
{ {
pc87311_t *dev = (pc87311_t *)priv; pc87311_t *dev = (pc87311_t *) priv;
return dev->regs[dev->index]; return dev->regs[dev->index];
} }
void pc87311_fdc_handler(pc87311_t *dev) void
pc87311_fdc_handler(pc87311_t *dev)
{ {
fdc_remove(dev->fdc_controller); fdc_remove(dev->fdc_controller);
fdc_set_base(dev->fdc_controller, (FUNCTION_ENABLE & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); fdc_set_base(dev->fdc_controller, (FUNCTION_ENABLE & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
pc87311_log("PC87311-FDC: BASE %04x\n", (FUNCTION_ENABLE & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); pc87311_log("PC87311-FDC: BASE %04x\n", (FUNCTION_ENABLE & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
} }
uint16_t com3(pc87311_t *dev) uint16_t
com3(pc87311_t *dev)
{ {
switch (COM_BA) switch (COM_BA) {
{ case 0:
case 0: return COM3_ADDR;
return COM3_ADDR; case 1:
case 1: return 0x0338;
return 0x0338; case 2:
case 2: return COM4_ADDR;
return COM4_ADDR; case 3:
case 3: return 0x0220;
return 0x0220; default:
default: return COM3_ADDR;
return COM3_ADDR;
} }
} }
uint16_t com4(pc87311_t *dev) uint16_t
com4(pc87311_t *dev)
{ {
switch (COM_BA) switch (COM_BA) {
{ case 0:
case 0: return COM4_ADDR;
return COM4_ADDR; case 1:
case 1: return 0x0238;
return 0x0238; case 2:
case 2: return 0x02e0;
return 0x02e0; case 3:
case 3: return 0x0228;
return 0x0228; default:
default: return COM4_ADDR;
return COM4_ADDR;
} }
} }
void pc87311_uart_handler(uint8_t num, pc87311_t *dev) void
pc87311_uart_handler(uint8_t num, pc87311_t *dev)
{ {
serial_remove(dev->uart[num & 1]); serial_remove(dev->uart[num & 1]);
switch (!(num & 1) ? UART1_BA : UART2_BA) switch (!(num & 1) ? UART1_BA : UART2_BA) {
{ case 0:
case 0: dev->base = COM1_ADDR;
dev->base = COM1_ADDR; dev->irq = COM1_IRQ;
dev->irq = COM1_IRQ; break;
break; case 1:
case 1: dev->base = COM2_ADDR;
dev->base = COM2_ADDR; dev->irq = COM2_IRQ;
dev->irq = COM2_IRQ; break;
break; case 2:
case 2: dev->base = com3(dev);
dev->base = com3(dev); dev->irq = COM3_IRQ;
dev->irq = COM3_IRQ; break;
break; case 3:
case 3: dev->base = com4(dev);
dev->base = com4(dev); dev->irq = COM4_IRQ;
dev->irq = COM4_IRQ; break;
break;
} }
serial_setup(dev->uart[num & 1], dev->base, dev->irq); serial_setup(dev->uart[num & 1], dev->base, dev->irq);
pc87311_log("PC87311-UART%01x: BASE %04x IRQ %01x\n", num & 1, dev->base, dev->irq); pc87311_log("PC87311-UART%01x: BASE %04x IRQ %01x\n", num & 1, dev->base, dev->irq);
} }
void pc87311_lpt_handler(pc87311_t *dev) void
pc87311_lpt_handler(pc87311_t *dev)
{ {
lpt1_remove(); lpt1_remove();
switch (LPT_BA) switch (LPT_BA) {
{ case 0:
case 0: dev->base = LPT1_ADDR;
dev->base = LPT1_ADDR; dev->irq = (POWER_TEST & 0x08) ? LPT1_IRQ : LPT2_IRQ;
dev->irq = (POWER_TEST & 0x08) ? LPT1_IRQ : LPT2_IRQ; break;
break; case 1:
case 1: dev->base = LPT_MDA_ADDR;
dev->base = LPT_MDA_ADDR; dev->irq = LPT_MDA_IRQ;
dev->irq = LPT_MDA_IRQ; break;
break; case 2:
case 2: dev->base = LPT2_ADDR;
dev->base = LPT2_ADDR; dev->irq = LPT2_IRQ;
dev->irq = LPT2_IRQ; break;
break;
} }
lpt1_init(dev->base); lpt1_init(dev->base);
lpt1_irq(dev->irq); lpt1_irq(dev->irq);
pc87311_log("PC87311-LPT: BASE %04x IRQ %01x\n", dev->base, dev->irq); pc87311_log("PC87311-LPT: BASE %04x IRQ %01x\n", dev->base, dev->irq);
} }
void pc87311_ide_handler(pc87311_t *dev) void
pc87311_ide_handler(pc87311_t *dev)
{ {
ide_pri_disable(); ide_pri_disable();
ide_sec_disable(); ide_sec_disable();
@@ -216,8 +215,7 @@ void pc87311_ide_handler(pc87311_t *dev)
ide_set_side(0, 0x3f6); ide_set_side(0, 0x3f6);
ide_pri_enable(); ide_pri_enable();
if (FUNCTION_ENABLE & 0x80) if (FUNCTION_ENABLE & 0x80) {
{
ide_set_base(1, 0x170); ide_set_base(1, 0x170);
ide_set_side(1, 0x376); ide_set_side(1, 0x376);
ide_sec_enable(); ide_sec_enable();
@@ -225,7 +223,8 @@ void pc87311_ide_handler(pc87311_t *dev)
pc87311_log("PC87311-IDE: PRI %01x SEC %01x\n", (FUNCTION_ENABLE >> 6) & 1, (FUNCTION_ENABLE >> 7) & 1); pc87311_log("PC87311-IDE: PRI %01x SEC %01x\n", (FUNCTION_ENABLE >> 6) & 1, (FUNCTION_ENABLE >> 7) & 1);
} }
void pc87311_enable(pc87311_t *dev) void
pc87311_enable(pc87311_t *dev)
{ {
(FUNCTION_ENABLE & 0x01) ? pc87311_lpt_handler(dev) : lpt1_remove(); (FUNCTION_ENABLE & 0x01) ? pc87311_lpt_handler(dev) : lpt1_remove();
(FUNCTION_ENABLE & 0x02) ? pc87311_uart_handler(0, dev) : serial_remove(dev->uart[0]); (FUNCTION_ENABLE & 0x02) ? pc87311_uart_handler(0, dev) : serial_remove(dev->uart[0]);
@@ -233,8 +232,7 @@ void pc87311_enable(pc87311_t *dev)
(FUNCTION_ENABLE & 0x08) ? pc87311_fdc_handler(dev) : fdc_remove(dev->fdc_controller); (FUNCTION_ENABLE & 0x08) ? pc87311_fdc_handler(dev) : fdc_remove(dev->fdc_controller);
if (FUNCTION_ENABLE & 0x20) if (FUNCTION_ENABLE & 0x20)
pc87311_fdc_handler(dev); pc87311_fdc_handler(dev);
if (HAS_IDE_FUNCTIONALITY) if (HAS_IDE_FUNCTIONALITY) {
{
(FUNCTION_ENABLE & 0x40) ? pc87311_ide_handler(dev) : ide_pri_disable(); (FUNCTION_ENABLE & 0x40) ? pc87311_ide_handler(dev) : ide_pri_disable();
(FUNCTION_ADDRESS & 0x80) ? pc87311_ide_handler(dev) : ide_sec_disable(); (FUNCTION_ADDRESS & 0x80) ? pc87311_ide_handler(dev) : ide_sec_disable();
} }
@@ -243,7 +241,7 @@ void pc87311_enable(pc87311_t *dev)
static void static void
pc87311_close(void *priv) pc87311_close(void *priv)
{ {
pc87311_t *dev = (pc87311_t *)priv; pc87311_t *dev = (pc87311_t *) priv;
free(dev); free(dev);
} }
@@ -251,15 +249,15 @@ pc87311_close(void *priv)
static void * static void *
pc87311_init(const device_t *info) pc87311_init(const device_t *info)
{ {
pc87311_t *dev = (pc87311_t *)malloc(sizeof(pc87311_t)); pc87311_t *dev = (pc87311_t *) malloc(sizeof(pc87311_t));
memset(dev, 0, sizeof(pc87311_t)); memset(dev, 0, sizeof(pc87311_t));
/* Avoid conflicting with machines that make no use of the PC87311 Internal IDE */ /* Avoid conflicting with machines that make no use of the PC87311 Internal IDE */
HAS_IDE_FUNCTIONALITY = info->local; HAS_IDE_FUNCTIONALITY = info->local;
dev->fdc_controller = device_add(&fdc_at_nsc_device); dev->fdc_controller = device_add(&fdc_at_nsc_device);
dev->uart[0] = device_add_inst(&ns16450_device, 1); dev->uart[0] = device_add_inst(&ns16450_device, 1);
dev->uart[1] = device_add_inst(&ns16450_device, 2); dev->uart[1] = device_add_inst(&ns16450_device, 2);
if (HAS_IDE_FUNCTIONALITY) if (HAS_IDE_FUNCTIONALITY)
device_add(&ide_isa_2ch_device); device_add(&ide_isa_2ch_device);
@@ -273,29 +271,29 @@ pc87311_init(const device_t *info)
} }
const device_t pc87311_device = { const device_t pc87311_device = {
.name = "National Semiconductor PC87311", .name = "National Semiconductor PC87311",
.internal_name = "pc87311", .internal_name = "pc87311",
.flags = 0, .flags = 0,
.local = 0, .local = 0,
.init = pc87311_init, .init = pc87311_init,
.close = pc87311_close, .close = pc87311_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t pc87311_ide_device = { const device_t pc87311_ide_device = {
.name = "National Semiconductor PC87311 with IDE functionality", .name = "National Semiconductor PC87311 with IDE functionality",
.internal_name = "pc87311_ide", .internal_name = "pc87311_ide",
.flags = 0, .flags = 0,
.local = 1, .local = 1,
.init = pc87311_init, .init = pc87311_init,
.close = pc87311_close, .close = pc87311_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

View File

@@ -34,51 +34,48 @@
#include <86box/fdc.h> #include <86box/fdc.h>
#include <86box/sio.h> #include <86box/sio.h>
typedef struct { typedef struct {
uint8_t tries, has_ide, uint8_t tries, has_ide,
fdc_on, regs[15]; fdc_on, regs[15];
int cur_reg; int cur_reg;
fdc_t *fdc; fdc_t *fdc;
serial_t *uart[2]; serial_t *uart[2];
} pc87332_t; } pc87332_t;
static void static void
lpt1_handler(pc87332_t *dev) lpt1_handler(pc87332_t *dev)
{ {
int temp; int temp;
uint16_t lpt_port = LPT1_ADDR; uint16_t lpt_port = LPT1_ADDR;
uint8_t lpt_irq = LPT2_IRQ; uint8_t lpt_irq = LPT2_IRQ;
temp = dev->regs[0x01] & 3; temp = dev->regs[0x01] & 3;
switch (temp) { switch (temp) {
case 0: case 0:
lpt_port = LPT1_ADDR; lpt_port = LPT1_ADDR;
lpt_irq = (dev->regs[0x02] & 0x08) ? LPT1_IRQ : LPT2_IRQ; lpt_irq = (dev->regs[0x02] & 0x08) ? LPT1_IRQ : LPT2_IRQ;
break; break;
case 1: case 1:
lpt_port = LPT_MDA_ADDR; lpt_port = LPT_MDA_ADDR;
lpt_irq = LPT_MDA_IRQ; lpt_irq = LPT_MDA_IRQ;
break; break;
case 2: case 2:
lpt_port = LPT2_ADDR; lpt_port = LPT2_ADDR;
lpt_irq = LPT2_IRQ; lpt_irq = LPT2_IRQ;
break; break;
case 3: case 3:
lpt_port = 0x000; lpt_port = 0x000;
lpt_irq = 0xff; lpt_irq = 0xff;
break; break;
} }
if (lpt_port) if (lpt_port)
lpt1_init(lpt_port); lpt1_init(lpt_port);
lpt1_irq(lpt_irq); lpt1_irq(lpt_irq);
} }
static void static void
serial_handler(pc87332_t *dev, int uart) serial_handler(pc87332_t *dev, int uart)
{ {
@@ -87,187 +84,183 @@ serial_handler(pc87332_t *dev, int uart)
temp = (dev->regs[1] >> (2 << uart)) & 3; temp = (dev->regs[1] >> (2 << uart)) & 3;
switch (temp) { switch (temp) {
case 0: case 0:
serial_setup(dev->uart[uart], COM1_ADDR, 4); serial_setup(dev->uart[uart], COM1_ADDR, 4);
break; break;
case 1: case 1:
serial_setup(dev->uart[uart], COM2_ADDR, 3); serial_setup(dev->uart[uart], COM2_ADDR, 3);
break; break;
case 2: case 2:
switch ((dev->regs[1] >> 6) & 3) { switch ((dev->regs[1] >> 6) & 3) {
case 0: case 0:
serial_setup(dev->uart[uart], COM3_ADDR, COM3_IRQ); serial_setup(dev->uart[uart], COM3_ADDR, COM3_IRQ);
break; break;
case 1: case 1:
serial_setup(dev->uart[uart], 0x338, COM3_IRQ); serial_setup(dev->uart[uart], 0x338, COM3_IRQ);
break; break;
case 2: case 2:
serial_setup(dev->uart[uart], COM4_ADDR, COM3_IRQ); serial_setup(dev->uart[uart], COM4_ADDR, COM3_IRQ);
break; break;
case 3: case 3:
serial_setup(dev->uart[uart], 0x220, COM3_IRQ); serial_setup(dev->uart[uart], 0x220, COM3_IRQ);
break; break;
} }
break; break;
case 3: case 3:
switch ((dev->regs[1] >> 6) & 3) { switch ((dev->regs[1] >> 6) & 3) {
case 0: case 0:
serial_setup(dev->uart[uart], COM4_ADDR, COM4_IRQ); serial_setup(dev->uart[uart], COM4_ADDR, COM4_IRQ);
break; break;
case 1: case 1:
serial_setup(dev->uart[uart], 0x238, COM4_IRQ); serial_setup(dev->uart[uart], 0x238, COM4_IRQ);
break; break;
case 2: case 2:
serial_setup(dev->uart[uart], 0x2e0, COM4_IRQ); serial_setup(dev->uart[uart], 0x2e0, COM4_IRQ);
break; break;
case 3: case 3:
serial_setup(dev->uart[uart], 0x228, COM4_IRQ); serial_setup(dev->uart[uart], 0x228, COM4_IRQ);
break; break;
} }
break; break;
} }
} }
static void static void
ide_handler(pc87332_t *dev) ide_handler(pc87332_t *dev)
{ {
/* TODO: Make an ide_disable(channel) and ide_enable(channel) so we can simplify this. */ /* TODO: Make an ide_disable(channel) and ide_enable(channel) so we can simplify this. */
if (dev->has_ide == 2) { if (dev->has_ide == 2) {
ide_sec_disable(); ide_sec_disable();
ide_set_base(1, (dev->regs[0x00] & 0x80) ? 0x170 : 0x1f0); ide_set_base(1, (dev->regs[0x00] & 0x80) ? 0x170 : 0x1f0);
ide_set_side(1, (dev->regs[0x00] & 0x80) ? 0x376 : 0x3f6); ide_set_side(1, (dev->regs[0x00] & 0x80) ? 0x376 : 0x3f6);
if (dev->regs[0x00] & 0x40) if (dev->regs[0x00] & 0x40)
ide_sec_enable(); ide_sec_enable();
} else if (dev->has_ide == 1) { } else if (dev->has_ide == 1) {
ide_pri_disable(); ide_pri_disable();
ide_set_base(0, (dev->regs[0x00] & 0x80) ? 0x170 : 0x1f0); ide_set_base(0, (dev->regs[0x00] & 0x80) ? 0x170 : 0x1f0);
ide_set_side(0, (dev->regs[0x00] & 0x80) ? 0x376 : 0x3f6); ide_set_side(0, (dev->regs[0x00] & 0x80) ? 0x376 : 0x3f6);
if (dev->regs[0x00] & 0x40) if (dev->regs[0x00] & 0x40)
ide_pri_enable(); ide_pri_enable();
} }
} }
static void static void
pc87332_write(uint16_t port, uint8_t val, void *priv) pc87332_write(uint16_t port, uint8_t val, void *priv)
{ {
pc87332_t *dev = (pc87332_t *) priv; pc87332_t *dev = (pc87332_t *) priv;
uint8_t index, valxor; uint8_t index, valxor;
index = (port & 1) ? 0 : 1; index = (port & 1) ? 0 : 1;
if (index) { if (index) {
dev->cur_reg = val & 0x1f; dev->cur_reg = val & 0x1f;
dev->tries = 0; dev->tries = 0;
return; return;
} else { } else {
if (dev->tries) { if (dev->tries) {
valxor = val ^ dev->regs[dev->cur_reg]; valxor = val ^ dev->regs[dev->cur_reg];
dev->tries = 0; dev->tries = 0;
if ((dev->cur_reg <= 14) && (dev->cur_reg != 8)) if ((dev->cur_reg <= 14) && (dev->cur_reg != 8))
dev->regs[dev->cur_reg] = val; dev->regs[dev->cur_reg] = val;
else else
return; return;
} else { } else {
dev->tries++; dev->tries++;
return; return;
} }
} }
switch(dev->cur_reg) { switch (dev->cur_reg) {
case 0: case 0:
if (valxor & 1) { if (valxor & 1) {
lpt1_remove(); lpt1_remove();
if ((val & 1) && !(dev->regs[2] & 1)) if ((val & 1) && !(dev->regs[2] & 1))
lpt1_handler(dev); lpt1_handler(dev);
} }
if (valxor & 2) { if (valxor & 2) {
serial_remove(dev->uart[0]); serial_remove(dev->uart[0]);
if ((val & 2) && !(dev->regs[2] & 1)) if ((val & 2) && !(dev->regs[2] & 1))
serial_handler(dev, 0); serial_handler(dev, 0);
} }
if (valxor & 4) { if (valxor & 4) {
serial_remove(dev->uart[1]); serial_remove(dev->uart[1]);
if ((val & 4) && !(dev->regs[2] & 1)) if ((val & 4) && !(dev->regs[2] & 1))
serial_handler(dev, 1); serial_handler(dev, 1);
} }
if (valxor & 0x28) { if (valxor & 0x28) {
fdc_remove(dev->fdc); fdc_remove(dev->fdc);
if ((val & 8) && !(dev->regs[2] & 1)) if ((val & 8) && !(dev->regs[2] & 1))
fdc_set_base(dev->fdc, (val & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); fdc_set_base(dev->fdc, (val & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
} }
if (dev->has_ide && (valxor & 0xc0)) if (dev->has_ide && (valxor & 0xc0))
ide_handler(dev); ide_handler(dev);
break; break;
case 1: case 1:
if (valxor & 3) { if (valxor & 3) {
lpt1_remove(); lpt1_remove();
if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) if ((dev->regs[0] & 1) && !(dev->regs[2] & 1))
lpt1_handler(dev); lpt1_handler(dev);
} }
if (valxor & 0xcc) { if (valxor & 0xcc) {
serial_remove(dev->uart[0]); serial_remove(dev->uart[0]);
if ((dev->regs[0] & 2) && !(dev->regs[2] & 1)) if ((dev->regs[0] & 2) && !(dev->regs[2] & 1))
serial_handler(dev, 0); serial_handler(dev, 0);
} }
if (valxor & 0xf0) { if (valxor & 0xf0) {
serial_remove(dev->uart[1]); serial_remove(dev->uart[1]);
if ((dev->regs[0] & 4) && !(dev->regs[2] & 1)) if ((dev->regs[0] & 4) && !(dev->regs[2] & 1))
serial_handler(dev, 1); serial_handler(dev, 1);
} }
break; break;
case 2: case 2:
if (valxor & 1) { if (valxor & 1) {
lpt1_remove(); lpt1_remove();
serial_remove(dev->uart[0]); serial_remove(dev->uart[0]);
serial_remove(dev->uart[1]); serial_remove(dev->uart[1]);
fdc_remove(dev->fdc); fdc_remove(dev->fdc);
if (!(val & 1)) { if (!(val & 1)) {
if (dev->regs[0] & 1) if (dev->regs[0] & 1)
lpt1_handler(dev); lpt1_handler(dev);
if (dev->regs[0] & 2) if (dev->regs[0] & 2)
serial_handler(dev, 0); serial_handler(dev, 0);
if (dev->regs[0] & 4) if (dev->regs[0] & 4)
serial_handler(dev, 1); serial_handler(dev, 1);
if (dev->regs[0] & 8) if (dev->regs[0] & 8)
fdc_set_base(dev->fdc, (dev->regs[0] & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); fdc_set_base(dev->fdc, (dev->regs[0] & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
} }
} }
if (valxor & 8) { if (valxor & 8) {
lpt1_remove(); lpt1_remove();
if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) if ((dev->regs[0] & 1) && !(dev->regs[2] & 1))
lpt1_handler(dev); lpt1_handler(dev);
} }
break; break;
} }
} }
uint8_t uint8_t
pc87332_read(uint16_t port, void *priv) pc87332_read(uint16_t port, void *priv)
{ {
pc87332_t *dev = (pc87332_t *) priv; pc87332_t *dev = (pc87332_t *) priv;
uint8_t ret = 0xff, index; uint8_t ret = 0xff, index;
index = (port & 1) ? 0 : 1; index = (port & 1) ? 0 : 1;
dev->tries = 0; dev->tries = 0;
if (index) if (index)
ret = dev->cur_reg & 0x1f; ret = dev->cur_reg & 0x1f;
else { else {
if (dev->cur_reg == 8) if (dev->cur_reg == 8)
ret = 0x10; ret = 0x10;
else if (dev->cur_reg < 14) else if (dev->cur_reg < 14)
ret = dev->regs[dev->cur_reg]; ret = dev->regs[dev->cur_reg];
} }
return ret; return ret;
} }
void void
pc87332_reset(pc87332_t *dev) pc87332_reset(pc87332_t *dev)
{ {
@@ -275,15 +268,15 @@ pc87332_reset(pc87332_t *dev)
dev->regs[0x00] = dev->fdc_on ? 0x4f : 0x07; dev->regs[0x00] = dev->fdc_on ? 0x4f : 0x07;
if (dev->has_ide == 2) if (dev->has_ide == 2)
dev->regs[0x00] |= 0x80; dev->regs[0x00] |= 0x80;
dev->regs[0x01] = 0x10; dev->regs[0x01] = 0x10;
dev->regs[0x03] = 0x01; dev->regs[0x03] = 0x01;
dev->regs[0x05] = 0x0D; dev->regs[0x05] = 0x0D;
dev->regs[0x08] = 0x70; dev->regs[0x08] = 0x70;
/* /*
0 = 360 rpm @ 500 kbps for 3.5" 0 = 360 rpm @ 500 kbps for 3.5"
1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5" 1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5"
*/ */
lpt1_remove(); lpt1_remove();
lpt1_handler(dev); lpt1_handler(dev);
@@ -293,13 +286,12 @@ pc87332_reset(pc87332_t *dev)
serial_handler(dev, 1); serial_handler(dev, 1);
fdc_reset(dev->fdc); fdc_reset(dev->fdc);
if (!dev->fdc_on) if (!dev->fdc_on)
fdc_remove(dev->fdc); fdc_remove(dev->fdc);
if (dev->has_ide) if (dev->has_ide)
ide_handler(dev); ide_handler(dev);
} }
static void static void
pc87332_close(void *priv) pc87332_close(void *priv)
{ {
@@ -308,7 +300,6 @@ pc87332_close(void *priv)
free(dev); free(dev);
} }
static void * static void *
pc87332_init(const device_t *info) pc87332_init(const device_t *info)
{ {
@@ -321,86 +312,86 @@ pc87332_init(const device_t *info)
dev->uart[1] = device_add_inst(&ns16550_device, 2); dev->uart[1] = device_add_inst(&ns16550_device, 2);
dev->has_ide = (info->local >> 8) & 0xff; dev->has_ide = (info->local >> 8) & 0xff;
dev->fdc_on = (info->local >> 16) & 0xff; dev->fdc_on = (info->local >> 16) & 0xff;
pc87332_reset(dev); pc87332_reset(dev);
if ((info->local & 0xff) == (0x01)) { if ((info->local & 0xff) == (0x01)) {
io_sethandler(0x398, 0x0002, io_sethandler(0x398, 0x0002,
pc87332_read, NULL, NULL, pc87332_write, NULL, NULL, dev); pc87332_read, NULL, NULL, pc87332_write, NULL, NULL, dev);
} else { } else {
io_sethandler(0x02e, 0x0002, io_sethandler(0x02e, 0x0002,
pc87332_read, NULL, NULL, pc87332_write, NULL, NULL, dev); pc87332_read, NULL, NULL, pc87332_write, NULL, NULL, dev);
} }
return dev; return dev;
} }
const device_t pc87332_device = { const device_t pc87332_device = {
.name = "National Semiconductor PC87332 Super I/O", .name = "National Semiconductor PC87332 Super I/O",
.internal_name = "pc87332", .internal_name = "pc87332",
.flags = 0, .flags = 0,
.local = 0x00, .local = 0x00,
.init = pc87332_init, .init = pc87332_init,
.close = pc87332_close, .close = pc87332_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t pc87332_398_device = { const device_t pc87332_398_device = {
.name = "National Semiconductor PC87332 Super I/O (Port 398h)", .name = "National Semiconductor PC87332 Super I/O (Port 398h)",
.internal_name = "pc87332_398", .internal_name = "pc87332_398",
.flags = 0, .flags = 0,
.local = 0x01, .local = 0x01,
.init = pc87332_init, .init = pc87332_init,
.close = pc87332_close, .close = pc87332_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t pc87332_398_ide_device = { const device_t pc87332_398_ide_device = {
.name = "National Semiconductor PC87332 Super I/O (Port 398h) (With IDE)", .name = "National Semiconductor PC87332 Super I/O (Port 398h) (With IDE)",
.internal_name = "pc87332_398_ide", .internal_name = "pc87332_398_ide",
.flags = 0, .flags = 0,
.local = 0x101, .local = 0x101,
.init = pc87332_init, .init = pc87332_init,
.close = pc87332_close, .close = pc87332_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t pc87332_398_ide_sec_device = { const device_t pc87332_398_ide_sec_device = {
.name = "National Semiconductor PC87332 Super I/O (Port 398h) (With Secondary IDE)", .name = "National Semiconductor PC87332 Super I/O (Port 398h) (With Secondary IDE)",
.internal_name = "pc87332_398_ide_sec", .internal_name = "pc87332_398_ide_sec",
.flags = 0, .flags = 0,
.local = 0x201, .local = 0x201,
.init = pc87332_init, .init = pc87332_init,
.close = pc87332_close, .close = pc87332_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t pc87332_398_ide_fdcon_device = { const device_t pc87332_398_ide_fdcon_device = {
.name = "National Semiconductor PC87332 Super I/O (Port 398h) (With IDE and FDC on)", .name = "National Semiconductor PC87332 Super I/O (Port 398h) (With IDE and FDC on)",
.internal_name = "pc87332_398_ide_fdcon", .internal_name = "pc87332_398_ide_fdcon",
.flags = 0, .flags = 0,
.local = 0x10101, .local = 0x10101,
.init = pc87332_init, .init = pc87332_init,
.close = pc87332_close, .close = pc87332_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

View File

@@ -30,9 +30,9 @@
#include <86box/fdc.h> #include <86box/fdc.h>
#include <86box/sio.h> #include <86box/sio.h>
#define FSR dev->regs[0xa0] #define FSR dev->regs[0xa0]
#define ASR dev->regs[0xa1] #define ASR dev->regs[0xa1]
#define PDR dev->regs[0xa2] #define PDR dev->regs[0xa2]
#define HAS_IDE_FUNCTIONALITY dev->ide_function #define HAS_IDE_FUNCTIONALITY dev->ide_function
#ifdef ENABLE_PRIME3B_LOG #ifdef ENABLE_PRIME3B_LOG
@@ -42,23 +42,22 @@ prime3b_log(const char *fmt, ...)
{ {
va_list ap; va_list ap;
if (prime3b_do_log) if (prime3b_do_log) {
{
va_start(ap, fmt); va_start(ap, fmt);
pclog_ex(fmt, ap); pclog_ex(fmt, ap);
va_end(ap); va_end(ap);
} }
} }
#else #else
#define prime3b_log(fmt, ...) # define prime3b_log(fmt, ...)
#endif #endif
typedef struct typedef struct
{ {
uint8_t index, regs[256], cfg_lock, ide_function; uint8_t index, regs[256], cfg_lock, ide_function;
uint16_t com3_addr, com4_addr; uint16_t com3_addr, com4_addr;
fdc_t *fdc_controller; fdc_t *fdc_controller;
serial_t *uart[2]; serial_t *uart[2];
} prime3b_t; } prime3b_t;
@@ -73,10 +72,9 @@ void prime3b_powerdown(prime3b_t *dev);
static void static void
prime3b_write(uint16_t addr, uint8_t val, void *priv) prime3b_write(uint16_t addr, uint8_t val, void *priv)
{ {
prime3b_t *dev = (prime3b_t *)priv; prime3b_t *dev = (prime3b_t *) priv;
if (addr == 0x398) if (addr == 0x398) {
{
dev->index = val; dev->index = val;
/* Enter/Escape Configuration Mode */ /* Enter/Escape Configuration Mode */
@@ -84,50 +82,46 @@ prime3b_write(uint16_t addr, uint8_t val, void *priv)
dev->cfg_lock = 0; dev->cfg_lock = 0;
else if (val == 0xcc) else if (val == 0xcc)
dev->cfg_lock = 1; dev->cfg_lock = 1;
} } else if ((addr == 0x399) && !dev->cfg_lock) {
else if ((addr == 0x399) && !dev->cfg_lock) switch (dev->index) {
{ case 0xa0: /* Function Selection Register (FSR) */
switch (dev->index) FSR = val;
{ prime3b_enable(dev);
case 0xa0: /* Function Selection Register (FSR) */
FSR = val;
prime3b_enable(dev);
break;
case 0xa1: /* Address Selection Register (ASR) */
ASR = val;
prime3b_enable(dev);
break;
case 0xa2: /* Power Down Register (PDR) */
dev->regs[0xa2] = val;
break;
case 0xa3: /* Test Mode Register (TMR) */
dev->regs[0xa3] = val;
break;
case 0xa4: /* Miscellaneous Function Register */
dev->regs[0xa4] = val;
switch ((dev->regs[0xa4] >> 6) & 3)
{
case 0:
dev->com3_addr = COM3_ADDR;
dev->com4_addr = COM4_ADDR;
break; break;
case 1: case 0xa1: /* Address Selection Register (ASR) */
dev->com3_addr = 0x338; ASR = val;
dev->com4_addr = 0x238; prime3b_enable(dev);
break; break;
case 2: case 0xa2: /* Power Down Register (PDR) */
dev->com3_addr = COM4_ADDR; dev->regs[0xa2] = val;
dev->com4_addr = 0x2e0;
break; break;
case 3: case 0xa3: /* Test Mode Register (TMR) */
dev->com3_addr = 0x220; dev->regs[0xa3] = val;
dev->com4_addr = 0x228; break;
case 0xa4: /* Miscellaneous Function Register */
dev->regs[0xa4] = val;
switch ((dev->regs[0xa4] >> 6) & 3) {
case 0:
dev->com3_addr = COM3_ADDR;
dev->com4_addr = COM4_ADDR;
break;
case 1:
dev->com3_addr = 0x338;
dev->com4_addr = 0x238;
break;
case 2:
dev->com3_addr = COM4_ADDR;
dev->com4_addr = 0x2e0;
break;
case 3:
dev->com3_addr = 0x220;
dev->com4_addr = 0x228;
break;
}
break;
case 0xa5: /* ECP Register */
dev->regs[0xa5] = val;
break; break;
}
break;
case 0xa5: /* ECP Register */
dev->regs[0xa5] = val;
break;
} }
} }
} }
@@ -135,12 +129,13 @@ prime3b_write(uint16_t addr, uint8_t val, void *priv)
static uint8_t static uint8_t
prime3b_read(uint16_t addr, void *priv) prime3b_read(uint16_t addr, void *priv)
{ {
prime3b_t *dev = (prime3b_t *)priv; prime3b_t *dev = (prime3b_t *) priv;
return dev->regs[dev->index]; return dev->regs[dev->index];
} }
void prime3b_fdc_handler(prime3b_t *dev) void
prime3b_fdc_handler(prime3b_t *dev)
{ {
uint16_t fdc_base = !(ASR & 0x40) ? FDC_PRIMARY_ADDR : FDC_SECONDARY_ADDR; uint16_t fdc_base = !(ASR & 0x40) ? FDC_PRIMARY_ADDR : FDC_SECONDARY_ADDR;
fdc_remove(dev->fdc_controller); fdc_remove(dev->fdc_controller);
@@ -148,7 +143,8 @@ void prime3b_fdc_handler(prime3b_t *dev)
prime3b_log("Prime3B-FDC: Enabled with base %03x\n", fdc_base); prime3b_log("Prime3B-FDC: Enabled with base %03x\n", fdc_base);
} }
void prime3b_uart_handler(uint8_t num, prime3b_t *dev) void
prime3b_uart_handler(uint8_t num, prime3b_t *dev)
{ {
uint16_t uart_base; uint16_t uart_base;
if ((ASR >> (3 + 2 * num)) & 1) if ((ASR >> (3 + 2 * num)) & 1)
@@ -161,7 +157,8 @@ void prime3b_uart_handler(uint8_t num, prime3b_t *dev)
prime3b_log("Prime3B-UART%d: Enabled with base %03x\n", num, uart_base); prime3b_log("Prime3B-UART%d: Enabled with base %03x\n", num, uart_base);
} }
void prime3b_lpt_handler(prime3b_t *dev) void
prime3b_lpt_handler(prime3b_t *dev)
{ {
uint16_t lpt_base = (ASR & 2) ? LPT_MDA_ADDR : (!(ASR & 1) ? LPT1_ADDR : LPT2_ADDR); uint16_t lpt_base = (ASR & 2) ? LPT_MDA_ADDR : (!(ASR & 1) ? LPT1_ADDR : LPT2_ADDR);
lpt1_remove(); lpt1_remove();
@@ -170,7 +167,8 @@ void prime3b_lpt_handler(prime3b_t *dev)
prime3b_log("Prime3B-LPT: Enabled with base %03x\n", lpt_base); prime3b_log("Prime3B-LPT: Enabled with base %03x\n", lpt_base);
} }
void prime3b_ide_handler(prime3b_t *dev) void
prime3b_ide_handler(prime3b_t *dev)
{ {
ide_pri_disable(); ide_pri_disable();
uint16_t ide_base = !(ASR & 0x80) ? 0x1f0 : 0x170; uint16_t ide_base = !(ASR & 0x80) ? 0x1f0 : 0x170;
@@ -180,7 +178,8 @@ void prime3b_ide_handler(prime3b_t *dev)
prime3b_log("Prime3B-IDE: Enabled with base %03x and side %03x\n", ide_base, ide_side); prime3b_log("Prime3B-IDE: Enabled with base %03x and side %03x\n", ide_base, ide_side);
} }
void prime3b_enable(prime3b_t *dev) void
prime3b_enable(prime3b_t *dev)
{ {
/* /*
Simulate a device enable/disable scenario Simulate a device enable/disable scenario
@@ -205,7 +204,8 @@ void prime3b_enable(prime3b_t *dev)
(FSR & 0x20) ? prime3b_ide_handler(dev) : ide_pri_disable(); (FSR & 0x20) ? prime3b_ide_handler(dev) : ide_pri_disable();
} }
void prime3b_powerdown(prime3b_t *dev) void
prime3b_powerdown(prime3b_t *dev)
{ {
/* Note: It can be done more efficiently for sure */ /* Note: It can be done more efficiently for sure */
uint8_t old_base = PDR; uint8_t old_base = PDR;
@@ -235,7 +235,7 @@ void prime3b_powerdown(prime3b_t *dev)
static void static void
prime3b_close(void *priv) prime3b_close(void *priv)
{ {
prime3b_t *dev = (prime3b_t *)priv; prime3b_t *dev = (prime3b_t *) priv;
free(dev); free(dev);
} }
@@ -243,7 +243,7 @@ prime3b_close(void *priv)
static void * static void *
prime3b_init(const device_t *info) prime3b_init(const device_t *info)
{ {
prime3b_t *dev = (prime3b_t *)malloc(sizeof(prime3b_t)); prime3b_t *dev = (prime3b_t *) malloc(sizeof(prime3b_t));
memset(dev, 0, sizeof(prime3b_t)); memset(dev, 0, sizeof(prime3b_t));
/* Avoid conflicting with machines that make no use of the Prime3B Internal IDE */ /* Avoid conflicting with machines that make no use of the Prime3B Internal IDE */
@@ -252,8 +252,8 @@ prime3b_init(const device_t *info)
dev->regs[0xa0] = 3; dev->regs[0xa0] = 3;
dev->fdc_controller = device_add(&fdc_at_device); dev->fdc_controller = device_add(&fdc_at_device);
dev->uart[0] = device_add_inst(&ns16550_device, 1); dev->uart[0] = device_add_inst(&ns16550_device, 1);
dev->uart[1] = device_add_inst(&ns16550_device, 2); dev->uart[1] = device_add_inst(&ns16550_device, 2);
if (HAS_IDE_FUNCTIONALITY) if (HAS_IDE_FUNCTIONALITY)
device_add(&ide_isa_device); device_add(&ide_isa_device);
@@ -269,29 +269,29 @@ prime3b_init(const device_t *info)
} }
const device_t prime3b_device = { const device_t prime3b_device = {
.name = "Goldstar Prime3B", .name = "Goldstar Prime3B",
.internal_name = "prime3b", .internal_name = "prime3b",
.flags = 0, .flags = 0,
.local = 0, .local = 0,
.init = prime3b_init, .init = prime3b_init,
.close = prime3b_close, .close = prime3b_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t prime3b_ide_device = { const device_t prime3b_ide_device = {
.name = "Goldstar Prime3B with IDE functionality", .name = "Goldstar Prime3B with IDE functionality",
.internal_name = "prime3b_ide", .internal_name = "prime3b_ide",
.flags = 0, .flags = 0,
.local = 1, .local = 1,
.init = prime3b_init, .init = prime3b_init,
.close = prime3b_close, .close = prime3b_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

View File

@@ -37,25 +37,24 @@ prime3c_log(const char *fmt, ...)
{ {
va_list ap; va_list ap;
if (prime3c_do_log) if (prime3c_do_log) {
{
va_start(ap, fmt); va_start(ap, fmt);
pclog_ex(fmt, ap); pclog_ex(fmt, ap);
va_end(ap); va_end(ap);
} }
} }
#else #else
#define prime3c_log(fmt, ...) # define prime3c_log(fmt, ...)
#endif #endif
/* Function Select(Note on prime3c_enable) */ /* Function Select(Note on prime3c_enable) */
#define FUNCTION_SELECT dev->regs[0xc2] #define FUNCTION_SELECT dev->regs[0xc2]
/* Base Address Registers */ /* Base Address Registers */
#define FDC_BASE_ADDRESS dev->regs[0xc3] #define FDC_BASE_ADDRESS dev->regs[0xc3]
#define IDE_BASE_ADDRESS dev->regs[0xc4] #define IDE_BASE_ADDRESS dev->regs[0xc4]
#define IDE_SIDE_ADDRESS dev->regs[0xc5] #define IDE_SIDE_ADDRESS dev->regs[0xc5]
#define LPT_BASE_ADDRESS dev->regs[0xc6] #define LPT_BASE_ADDRESS dev->regs[0xc6]
#define UART1_BASE_ADDRESS dev->regs[0xc7] #define UART1_BASE_ADDRESS dev->regs[0xc7]
#define UART2_BASE_ADDRESS dev->regs[0xc8] #define UART2_BASE_ADDRESS dev->regs[0xc8]
@@ -76,7 +75,7 @@ typedef struct
{ {
uint8_t index, regs[256], cfg_lock, ide_function; uint8_t index, regs[256], cfg_lock, ide_function;
fdc_t *fdc_controller; fdc_t *fdc_controller;
serial_t *uart[2]; serial_t *uart[2];
} prime3c_t; } prime3c_t;
@@ -90,124 +89,121 @@ void prime3c_enable(prime3c_t *dev);
static void static void
prime3c_write(uint16_t addr, uint8_t val, void *priv) prime3c_write(uint16_t addr, uint8_t val, void *priv)
{ {
prime3c_t *dev = (prime3c_t *)priv; prime3c_t *dev = (prime3c_t *) priv;
switch (addr) switch (addr) {
{ case 0x398:
case 0x398: dev->index = val;
dev->index = val;
/* Enter/Escape Configuration Mode */ /* Enter/Escape Configuration Mode */
if (val == 0x33) if (val == 0x33)
dev->cfg_lock = 0; dev->cfg_lock = 0;
else if (val == 0x55) else if (val == 0x55)
dev->cfg_lock = 1; dev->cfg_lock = 1;
break; break;
case 0x399: case 0x399:
if (!dev->cfg_lock) if (!dev->cfg_lock) {
{ switch (dev->index) {
switch (dev->index) case 0xc2:
{ FUNCTION_SELECT = val & 0xbf;
case 0xc2: prime3c_enable(dev);
FUNCTION_SELECT = val & 0xbf; break;
prime3c_enable(dev);
break;
case 0xc3: case 0xc3:
FDC_BASE_ADDRESS = val & 0xfc; FDC_BASE_ADDRESS = val & 0xfc;
prime3c_fdc_handler(dev); prime3c_fdc_handler(dev);
break; break;
case 0xc4: case 0xc4:
IDE_BASE_ADDRESS = val & 0xfc; IDE_BASE_ADDRESS = val & 0xfc;
if (HAS_IDE_FUNCTIONALITY) if (HAS_IDE_FUNCTIONALITY)
prime3c_ide_handler(dev); prime3c_ide_handler(dev);
break; break;
case 0xc5: case 0xc5:
IDE_SIDE_ADDRESS = (val & 0xfc) | 0x02; IDE_SIDE_ADDRESS = (val & 0xfc) | 0x02;
if (HAS_IDE_FUNCTIONALITY) if (HAS_IDE_FUNCTIONALITY)
prime3c_ide_handler(dev); prime3c_ide_handler(dev);
break; break;
case 0xc6: case 0xc6:
LPT_BASE_ADDRESS = val; LPT_BASE_ADDRESS = val;
break; break;
case 0xc7: case 0xc7:
UART1_BASE_ADDRESS = val & 0xfe; UART1_BASE_ADDRESS = val & 0xfe;
prime3c_uart_handler(0, dev); prime3c_uart_handler(0, dev);
break; break;
case 0xc8: case 0xc8:
UART2_BASE_ADDRESS = val & 0xfe; UART2_BASE_ADDRESS = val & 0xfe;
prime3c_uart_handler(1, dev); prime3c_uart_handler(1, dev);
break; break;
case 0xc9: case 0xc9:
FDC_LPT_DMA = val; FDC_LPT_DMA = val;
prime3c_fdc_handler(dev); prime3c_fdc_handler(dev);
break; break;
case 0xca: case 0xca:
FDC_LPT_IRQ = val; FDC_LPT_IRQ = val;
prime3c_fdc_handler(dev); prime3c_fdc_handler(dev);
prime3c_lpt_handler(dev); prime3c_lpt_handler(dev);
break; break;
case 0xcb: case 0xcb:
UART_IRQ = val; UART_IRQ = val;
prime3c_uart_handler(0, dev); prime3c_uart_handler(0, dev);
prime3c_uart_handler(1, dev); prime3c_uart_handler(1, dev);
break; break;
case 0xcd: case 0xcd:
case 0xce: case 0xce:
dev->regs[dev->index] = val; dev->regs[dev->index] = val;
break; break;
case 0xcf: case 0xcf:
dev->regs[dev->index] = val & 0x3f; dev->regs[dev->index] = val & 0x3f;
break; break;
case 0xd0: case 0xd0:
dev->regs[dev->index] = val & 0xfc; dev->regs[dev->index] = val & 0xfc;
break; break;
case 0xd1: case 0xd1:
dev->regs[dev->index] = val & 0x3f; dev->regs[dev->index] = val & 0x3f;
break; break;
case 0xd3: case 0xd3:
dev->regs[dev->index] = val & 0x7c; dev->regs[dev->index] = val & 0x7c;
break; break;
case 0xd5: case 0xd5:
case 0xd6: case 0xd6:
case 0xd7: case 0xd7:
case 0xd8: case 0xd8:
dev->regs[dev->index] = val; dev->regs[dev->index] = val;
break; break;
}
} }
} break;
break;
} }
} }
static uint8_t static uint8_t
prime3c_read(uint16_t addr, void *priv) prime3c_read(uint16_t addr, void *priv)
{ {
prime3c_t *dev = (prime3c_t *)priv; prime3c_t *dev = (prime3c_t *) priv;
return dev->regs[dev->index]; return dev->regs[dev->index];
} }
void prime3c_fdc_handler(prime3c_t *dev) void
prime3c_fdc_handler(prime3c_t *dev)
{ {
fdc_remove(dev->fdc_controller); fdc_remove(dev->fdc_controller);
if (FUNCTION_SELECT & 0x10) if (FUNCTION_SELECT & 0x10) {
{
fdc_set_base(dev->fdc_controller, FDC_BASE_ADDRESS << 2); fdc_set_base(dev->fdc_controller, FDC_BASE_ADDRESS << 2);
fdc_set_irq(dev->fdc_controller, (FDC_LPT_IRQ >> 4) & 0xf); fdc_set_irq(dev->fdc_controller, (FDC_LPT_IRQ >> 4) & 0xf);
fdc_set_dma_ch(dev->fdc_controller, (FDC_LPT_DMA >> 4) & 0xf); fdc_set_dma_ch(dev->fdc_controller, (FDC_LPT_DMA >> 4) & 0xf);
@@ -216,21 +212,21 @@ void prime3c_fdc_handler(prime3c_t *dev)
} }
} }
void prime3c_uart_handler(uint8_t num, prime3c_t *dev) void
prime3c_uart_handler(uint8_t num, prime3c_t *dev)
{ {
serial_remove(dev->uart[num & 1]); serial_remove(dev->uart[num & 1]);
if (FUNCTION_SELECT & (!(num & 1) ? 0x04 : 0x08)) if (FUNCTION_SELECT & (!(num & 1) ? 0x04 : 0x08)) {
{
serial_setup(dev->uart[num & 1], (!(num & 1) ? UART1_BASE_ADDRESS : UART2_BASE_ADDRESS) << 2, (UART_IRQ >> (!(num & 1) ? 4 : 0)) & 0xf); serial_setup(dev->uart[num & 1], (!(num & 1) ? UART1_BASE_ADDRESS : UART2_BASE_ADDRESS) << 2, (UART_IRQ >> (!(num & 1) ? 4 : 0)) & 0xf);
prime3c_log("Prime3C-UART%01x: BASE %04x IRQ %01x\n", num & 1, (!(num & 1) ? UART1_BASE_ADDRESS : UART2_BASE_ADDRESS) << 2, (UART_IRQ >> (!(num & 1) ? 4 : 0)) & 0xf); prime3c_log("Prime3C-UART%01x: BASE %04x IRQ %01x\n", num & 1, (!(num & 1) ? UART1_BASE_ADDRESS : UART2_BASE_ADDRESS) << 2, (UART_IRQ >> (!(num & 1) ? 4 : 0)) & 0xf);
} }
} }
void prime3c_lpt_handler(prime3c_t *dev) void
prime3c_lpt_handler(prime3c_t *dev)
{ {
lpt1_remove(); lpt1_remove();
if (!(FUNCTION_SELECT & 0x03)) if (!(FUNCTION_SELECT & 0x03)) {
{
lpt1_init(LPT_BASE_ADDRESS << 2); lpt1_init(LPT_BASE_ADDRESS << 2);
lpt1_irq(FDC_LPT_IRQ & 0xf); lpt1_irq(FDC_LPT_IRQ & 0xf);
@@ -238,11 +234,11 @@ void prime3c_lpt_handler(prime3c_t *dev)
} }
} }
void prime3c_ide_handler(prime3c_t *dev) void
prime3c_ide_handler(prime3c_t *dev)
{ {
ide_pri_disable(); ide_pri_disable();
if (FUNCTION_SELECT & 0x20) if (FUNCTION_SELECT & 0x20) {
{
ide_set_base(0, IDE_BASE_ADDRESS << 2); ide_set_base(0, IDE_BASE_ADDRESS << 2);
ide_set_side(0, IDE_SIDE_ADDRESS << 2); ide_set_side(0, IDE_SIDE_ADDRESS << 2);
ide_pri_enable(); ide_pri_enable();
@@ -250,35 +246,36 @@ void prime3c_ide_handler(prime3c_t *dev)
} }
} }
void prime3c_enable(prime3c_t *dev) void
prime3c_enable(prime3c_t *dev)
{ {
/* /*
Simulate a device enable/disable scenario Simulate a device enable/disable scenario
Register C2: Function Select Register C2: Function Select
Bit 7: Gameport Bit 7: Gameport
Bit 6: Reserved Bit 6: Reserved
Bit 5: IDE Bit 5: IDE
Bit 4: FDC Bit 4: FDC
Bit 3: UART 2 Bit 3: UART 2
Bit 2: UART 1 Bit 2: UART 1
Bit 1/0: PIO (0/0 Unidirectional , 0/1 ECP, 1/0 EPP, 1/1 Disabled) Bit 1/0: PIO (0/0 Unidirectional , 0/1 ECP, 1/0 EPP, 1/1 Disabled)
Note: 86Box LPT is simplistic and can't do ECP or EPP. Note: 86Box LPT is simplistic and can't do ECP or EPP.
*/ */
!(FUNCTION_SELECT & 0x03) ? prime3c_lpt_handler(dev) : lpt1_remove(); !(FUNCTION_SELECT & 0x03) ? prime3c_lpt_handler(dev) : lpt1_remove();
(FUNCTION_SELECT & 0x04) ? prime3c_uart_handler(0, dev) : serial_remove(dev->uart[0]); (FUNCTION_SELECT & 0x04) ? prime3c_uart_handler(0, dev) : serial_remove(dev->uart[0]);
(FUNCTION_SELECT & 0x08) ? prime3c_uart_handler(1, dev) : serial_remove(dev->uart[1]); (FUNCTION_SELECT & 0x08) ? prime3c_uart_handler(1, dev) : serial_remove(dev->uart[1]);
(FUNCTION_SELECT & 0x10) ? prime3c_fdc_handler(dev) : fdc_remove(dev->fdc_controller); (FUNCTION_SELECT & 0x10) ? prime3c_fdc_handler(dev) : fdc_remove(dev->fdc_controller);
if (HAS_IDE_FUNCTIONALITY) if (HAS_IDE_FUNCTIONALITY)
(FUNCTION_SELECT & 0x20) ? prime3c_ide_handler(dev) : ide_pri_disable(); (FUNCTION_SELECT & 0x20) ? prime3c_ide_handler(dev) : ide_pri_disable();
} }
static void static void
prime3c_close(void *priv) prime3c_close(void *priv)
{ {
prime3c_t *dev = (prime3c_t *)priv; prime3c_t *dev = (prime3c_t *) priv;
free(dev); free(dev);
} }
@@ -286,7 +283,7 @@ prime3c_close(void *priv)
static void * static void *
prime3c_init(const device_t *info) prime3c_init(const device_t *info)
{ {
prime3c_t *dev = (prime3c_t *)malloc(sizeof(prime3c_t)); prime3c_t *dev = (prime3c_t *) malloc(sizeof(prime3c_t));
memset(dev, 0, sizeof(prime3c_t)); memset(dev, 0, sizeof(prime3c_t));
/* Avoid conflicting with machines that make no use of the Prime3C Internal IDE */ /* Avoid conflicting with machines that make no use of the Prime3C Internal IDE */
@@ -300,8 +297,8 @@ prime3c_init(const device_t *info)
dev->regs[0xd5] = 0x3c; dev->regs[0xd5] = 0x3c;
dev->fdc_controller = device_add(&fdc_at_device); dev->fdc_controller = device_add(&fdc_at_device);
dev->uart[0] = device_add_inst(&ns16550_device, 1); dev->uart[0] = device_add_inst(&ns16550_device, 1);
dev->uart[1] = device_add_inst(&ns16550_device, 2); dev->uart[1] = device_add_inst(&ns16550_device, 2);
if (HAS_IDE_FUNCTIONALITY) if (HAS_IDE_FUNCTIONALITY)
device_add(&ide_isa_device); device_add(&ide_isa_device);
@@ -318,29 +315,29 @@ prime3c_init(const device_t *info)
} }
const device_t prime3c_device = { const device_t prime3c_device = {
.name = "Goldstar Prime3C", .name = "Goldstar Prime3C",
.internal_name = "prime3c", .internal_name = "prime3c",
.flags = 0, .flags = 0,
.local = 0, .local = 0,
.init = prime3c_init, .init = prime3c_init,
.close = prime3c_close, .close = prime3c_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t prime3c_ide_device = { const device_t prime3c_ide_device = {
.name = "Goldstar Prime3C with IDE functionality", .name = "Goldstar Prime3C with IDE functionality",
.internal_name = "prime3c_ide", .internal_name = "prime3c_ide",
.flags = 0, .flags = 0,
.local = 1, .local = 1,
.init = prime3c_init, .init = prime3c_init,
.close = prime3c_close, .close = prime3c_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

View File

@@ -38,33 +38,32 @@
#include <86box/sio.h> #include <86box/sio.h>
#include <86box/isapnp.h> #include <86box/isapnp.h>
/* This ROM was reconstructed out of many assumptions, some of which based on the IT8671F. */ /* This ROM was reconstructed out of many assumptions, some of which based on the IT8671F. */
static uint8_t um8669f_pnp_rom[] = { static uint8_t um8669f_pnp_rom[] = {
0x55, 0xa3, 0x86, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, /* UMC8669, dummy checksum (filled in by isapnp_add_card) */ 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 */ 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */
0x15, 0x41, 0xd0, 0x07, 0x00, 0x01, /* logical device PNP0700, can participate in boot */ 0x15, 0x41, 0xd0, 0x07, 0x00, 0x01, /* logical device PNP0700, can participate in boot */
0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */ 0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */
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, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */ 0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */
0x15, 0x41, 0xd0, 0x05, 0x01, 0x01, /* logical device PNP0501, can participate in boot */ 0x15, 0x41, 0xd0, 0x05, 0x01, 0x01, /* logical device PNP0501, can participate in boot */
0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */ 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 */ 0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */
0x15, 0x41, 0xd0, 0x05, 0x01, 0x01, /* logical device PNP0501, can participate in boot */ 0x15, 0x41, 0xd0, 0x05, 0x01, 0x01, /* logical device PNP0501, can participate in boot */
0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */ 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 */ 0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */
0x15, 0x41, 0xd0, 0x04, 0x00, 0x01, /* logical device PNP0400, can participate in boot */ 0x15, 0x41, 0xd0, 0x04, 0x00, 0x01, /* logical device PNP0400, can participate in boot */
0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */ 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 */ 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, 0xff, 0xff, 0x00, /* logical device PNPFFFF (just a dummy to create a gap in LDNs) */
0x15, 0x41, 0xd0, 0xb0, 0x2f, 0x01, /* logical device PNPB02F, can participate in boot */ 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 */ 0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */
0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */
}; };
@@ -94,106 +93,100 @@ static const isapnp_device_config_t um8669f_pnp_defaults[] = {
} }
}; };
#ifdef ENABLE_UM8669F_LOG #ifdef ENABLE_UM8669F_LOG
int um8669f_do_log = ENABLE_UM8669F_LOG; int um8669f_do_log = ENABLE_UM8669F_LOG;
static void static void
um8669f_log(const char *fmt, ...) um8669f_log(const char *fmt, ...)
{ {
va_list ap; va_list ap;
if (um8669f_do_log) { if (um8669f_do_log) {
va_start(ap, fmt); va_start(ap, fmt);
pclog_ex(fmt, ap); pclog_ex(fmt, ap);
va_end(ap); va_end(ap);
} }
} }
#else #else
#define um8669f_log(fmt, ...) # define um8669f_log(fmt, ...)
#endif #endif
typedef struct um8669f_t {
typedef struct um8669f_t int locked, cur_reg_108;
{ void *pnp_card;
int locked, cur_reg_108;
void *pnp_card;
isapnp_device_config_t *pnp_config[5]; isapnp_device_config_t *pnp_config[5];
uint8_t regs_108[256]; uint8_t regs_108[256];
fdc_t *fdc; fdc_t *fdc;
serial_t *uart[2]; serial_t *uart[2];
void *gameport; void *gameport;
} um8669f_t; } um8669f_t;
static void static void
um8669f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) um8669f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv)
{ {
if (ld > 5) { if (ld > 5) {
um8669f_log("UM8669F: Unknown logical device %d\n", ld); um8669f_log("UM8669F: Unknown logical device %d\n", ld);
return; return;
} }
um8669f_t *dev = (um8669f_t *) priv; um8669f_t *dev = (um8669f_t *) priv;
switch (ld) { switch (ld) {
case 0: case 0:
fdc_remove(dev->fdc); fdc_remove(dev->fdc);
if (config->activate) { if (config->activate) {
um8669f_log("UM8669F: 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); um8669f_log("UM8669F: 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) if (config->io[0].base != ISAPNP_IO_DISABLED)
fdc_set_base(dev->fdc, config->io[0].base); fdc_set_base(dev->fdc, config->io[0].base);
fdc_set_irq(dev->fdc, config->irq[0].irq); 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); fdc_set_dma_ch(dev->fdc, (config->dma[0].dma == ISAPNP_DMA_DISABLED) ? -1 : config->dma[0].dma);
} else { } else {
um8669f_log("UM8669F: FDC disabled\n"); um8669f_log("UM8669F: FDC disabled\n");
} }
break; break;
case 1: case 1:
case 2: case 2:
serial_remove(dev->uart[ld - 1]); serial_remove(dev->uart[ld - 1]);
if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) { if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) {
um8669f_log("UM8669F: UART %d enabled at port %04X IRQ %d\n", ld - 1, config->io[0].base, config->irq[0].irq); um8669f_log("UM8669F: 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); serial_setup(dev->uart[ld - 1], config->io[0].base, config->irq[0].irq);
} else { } else {
um8669f_log("UM8669F: UART %d disabled\n", ld - 1); um8669f_log("UM8669F: UART %d disabled\n", ld - 1);
} }
break; break;
case 3: case 3:
lpt1_remove(); lpt1_remove();
if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) { if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) {
um8669f_log("UM8669F: LPT enabled at port %04X IRQ %d\n", config->io[0].base, config->irq[0].irq); um8669f_log("UM8669F: LPT enabled at port %04X IRQ %d\n", config->io[0].base, config->irq[0].irq);
lpt1_init(config->io[0].base); lpt1_init(config->io[0].base);
} else { } else {
um8669f_log("UM8669F: LPT disabled\n"); um8669f_log("UM8669F: LPT disabled\n");
} }
break; break;
case 5: case 5:
if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) { if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) {
um8669f_log("UM8669F: Game port enabled at port %04X\n", config->io[0].base); um8669f_log("UM8669F: Game port enabled at port %04X\n", config->io[0].base);
gameport_remap(dev->gameport, config->io[0].base); gameport_remap(dev->gameport, config->io[0].base);
} else { } else {
um8669f_log("UM8669F: Game port disabled\n"); um8669f_log("UM8669F: Game port disabled\n");
gameport_remap(dev->gameport, 0); gameport_remap(dev->gameport, 0);
} }
} }
} }
void void
um8669f_write(uint16_t port, uint8_t val, void *priv) um8669f_write(uint16_t port, uint8_t val, void *priv)
{ {
@@ -202,37 +195,36 @@ um8669f_write(uint16_t port, uint8_t val, void *priv)
um8669f_log("UM8669F: write(%04X, %02X)\n", port, val); um8669f_log("UM8669F: write(%04X, %02X)\n", port, val);
if (dev->locked) { if (dev->locked) {
if ((port == 0x108) && (val == 0xaa)) if ((port == 0x108) && (val == 0xaa))
dev->locked = 0; dev->locked = 0;
} else { } else {
if (port == 0x108) { if (port == 0x108) {
if (val == 0x55) if (val == 0x55)
dev->locked = 1; dev->locked = 1;
else else
dev->cur_reg_108 = val; dev->cur_reg_108 = val;
} else { } else {
dev->regs_108[dev->cur_reg_108] = val; dev->regs_108[dev->cur_reg_108] = val;
if (dev->cur_reg_108 == 0xc1) { if (dev->cur_reg_108 == 0xc1) {
um8669f_log("UM8669F: ISAPnP %sabled\n", (val & 0x80) ? "en" : "dis"); 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); isapnp_enable_card(dev->pnp_card, (val & 0x80) ? ISAPNP_CARD_FORCE_CONFIG : ISAPNP_CARD_DISABLE);
} }
} }
} }
} }
uint8_t uint8_t
um8669f_read(uint16_t port, void *priv) um8669f_read(uint16_t port, void *priv)
{ {
um8669f_t *dev = (um8669f_t *) priv; um8669f_t *dev = (um8669f_t *) priv;
uint8_t ret = 0xff; uint8_t ret = 0xff;
if (!dev->locked) { if (!dev->locked) {
if (port == 0x108) if (port == 0x108)
ret = dev->cur_reg_108; /* ??? */ ret = dev->cur_reg_108; /* ??? */
else else
ret = dev->regs_108[dev->cur_reg_108]; ret = dev->regs_108[dev->cur_reg_108];
} }
um8669f_log("UM8669F: read(%04X) = %02X\n", port, ret); um8669f_log("UM8669F: read(%04X) = %02X\n", port, ret);
@@ -240,7 +232,6 @@ um8669f_read(uint16_t port, void *priv)
return ret; return ret;
} }
void void
um8669f_reset(um8669f_t *dev) um8669f_reset(um8669f_t *dev)
{ {
@@ -261,7 +252,6 @@ um8669f_reset(um8669f_t *dev)
isapnp_reset_card(dev->pnp_card); isapnp_reset_card(dev->pnp_card);
} }
static void static void
um8669f_close(void *priv) um8669f_close(void *priv)
{ {
@@ -272,7 +262,6 @@ um8669f_close(void *priv)
free(dev); free(dev);
} }
static void * static void *
um8669f_init(const device_t *info) um8669f_init(const device_t *info)
{ {
@@ -283,7 +272,7 @@ um8669f_init(const device_t *info)
dev->pnp_card = isapnp_add_card(um8669f_pnp_rom, sizeof(um8669f_pnp_rom), um8669f_pnp_config_changed, NULL, NULL, NULL, dev); dev->pnp_card = isapnp_add_card(um8669f_pnp_rom, sizeof(um8669f_pnp_rom), um8669f_pnp_config_changed, NULL, NULL, NULL, dev);
for (uint8_t i = 0; i < (sizeof(um8669f_pnp_defaults) / sizeof(isapnp_device_config_t)); i++) for (uint8_t i = 0; i < (sizeof(um8669f_pnp_defaults) / sizeof(isapnp_device_config_t)); i++)
isapnp_set_device_defaults(dev->pnp_card, i, &um8669f_pnp_defaults[i]); isapnp_set_device_defaults(dev->pnp_card, i, &um8669f_pnp_defaults[i]);
dev->fdc = device_add(&fdc_at_smc_device); dev->fdc = device_add(&fdc_at_smc_device);
@@ -293,24 +282,23 @@ um8669f_init(const device_t *info)
dev->gameport = gameport_add(&gameport_sio_device); dev->gameport = gameport_add(&gameport_sio_device);
io_sethandler(0x0108, 0x0002, io_sethandler(0x0108, 0x0002,
um8669f_read, NULL, NULL, um8669f_write, NULL, NULL, dev); um8669f_read, NULL, NULL, um8669f_write, NULL, NULL, dev);
um8669f_reset(dev); um8669f_reset(dev);
return dev; return dev;
} }
const device_t um8669f_device = { const device_t um8669f_device = {
.name = "UMC UM8669F Super I/O", .name = "UMC UM8669F Super I/O",
.internal_name = "um8669f", .internal_name = "um8669f",
.flags = 0, .flags = 0,
.local = 0, .local = 0,
.init = um8669f_init, .init = um8669f_init,
.close = um8669f_close, .close = um8669f_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

View File

@@ -32,27 +32,24 @@
#include <86box/fdc.h> #include <86box/fdc.h>
#include <86box/sio.h> #include <86box/sio.h>
typedef struct { typedef struct {
uint8_t cur_reg, last_val, regs[25], uint8_t cur_reg, last_val, regs[25],
fdc_dma, fdc_irq, uart_irq[2], lpt_dma, lpt_irq; fdc_dma, fdc_irq, uart_irq[2], lpt_dma, lpt_irq;
fdc_t *fdc; fdc_t *fdc;
serial_t *uart[2]; serial_t *uart[2];
} vt82c686_t; } vt82c686_t;
static uint8_t static uint8_t
get_lpt_length(vt82c686_t *dev) get_lpt_length(vt82c686_t *dev)
{ {
uint8_t length = 4; /* non-EPP */ uint8_t length = 4; /* non-EPP */
if ((dev->regs[0x02] & 0x03) == 0x02) if ((dev->regs[0x02] & 0x03) == 0x02)
length = 8; /* EPP */ length = 8; /* EPP */
return length; return length;
} }
static void static void
vt82c686_fdc_handler(vt82c686_t *dev) vt82c686_fdc_handler(vt82c686_t *dev)
{ {
@@ -61,47 +58,44 @@ vt82c686_fdc_handler(vt82c686_t *dev)
fdc_remove(dev->fdc); fdc_remove(dev->fdc);
if (dev->regs[0x02] & 0x10) if (dev->regs[0x02] & 0x10)
fdc_set_base(dev->fdc, io_base); fdc_set_base(dev->fdc, io_base);
fdc_set_dma_ch(dev->fdc, dev->fdc_dma); fdc_set_dma_ch(dev->fdc, dev->fdc_dma);
fdc_set_irq(dev->fdc, dev->fdc_irq); fdc_set_irq(dev->fdc, dev->fdc_irq);
fdc_set_swap(dev->fdc, dev->regs[0x16] & 0x01); fdc_set_swap(dev->fdc, dev->regs[0x16] & 0x01);
} }
static void static void
vt82c686_lpt_handler(vt82c686_t *dev) vt82c686_lpt_handler(vt82c686_t *dev)
{ {
uint16_t io_mask, io_base = dev->regs[0x06] << 2; uint16_t io_mask, io_base = dev->regs[0x06] << 2;
int io_len = get_lpt_length(dev); int io_len = get_lpt_length(dev);
io_base &= (0xff8 | io_len); io_base &= (0xff8 | io_len);
io_mask = 0x3fc; /* non-EPP */ io_mask = 0x3fc; /* non-EPP */
if (io_len == 8) if (io_len == 8)
io_mask = 0x3f8; /* EPP */ io_mask = 0x3f8; /* EPP */
lpt1_remove(); lpt1_remove();
if (((dev->regs[0x02] & 0x03) != 0x03) && (io_base >= 0x100) && (io_base <= io_mask)) if (((dev->regs[0x02] & 0x03) != 0x03) && (io_base >= 0x100) && (io_base <= io_mask))
lpt1_init(io_base); lpt1_init(io_base);
if (dev->lpt_irq) { if (dev->lpt_irq) {
lpt1_irq(dev->lpt_irq); lpt1_irq(dev->lpt_irq);
} else { } else {
lpt1_irq(0xff); lpt1_irq(0xff);
} }
} }
static void static void
vt82c686_serial_handler(vt82c686_t *dev, int uart) vt82c686_serial_handler(vt82c686_t *dev, int uart)
{ {
serial_remove(dev->uart[uart]); serial_remove(dev->uart[uart]);
if (dev->regs[0x02] & (0x04 << uart)) if (dev->regs[0x02] & (0x04 << uart))
serial_setup(dev->uart[uart], dev->regs[0x07 + uart] << 2, dev->uart_irq[uart]); serial_setup(dev->uart[uart], dev->regs[0x07 + uart] << 2, dev->uart_irq[uart]);
} }
static void static void
vt82c686_write(uint16_t port, uint8_t val, void *priv) vt82c686_write(uint16_t port, uint8_t val, void *priv)
{ {
@@ -112,86 +106,87 @@ vt82c686_write(uint16_t port, uint8_t val, void *priv)
/* Write current register index on port 0. */ /* Write current register index on port 0. */
if (!(port & 1)) { if (!(port & 1)) {
dev->cur_reg = val; dev->cur_reg = val;
return; return;
} }
/* NOTE: Registers are [0xE0:0xF8] but we store them as [0x00:0x18]. */ /* NOTE: Registers are [0xE0:0xF8] but we store them as [0x00:0x18]. */
if ((dev->cur_reg < 0xe0) || (dev->cur_reg > 0xf8)) if ((dev->cur_reg < 0xe0) || (dev->cur_reg > 0xf8))
return; return;
uint8_t reg = dev->cur_reg & 0x1f; uint8_t reg = dev->cur_reg & 0x1f;
/* Read-only registers. */ /* Read-only registers. */
if ((reg < 0x02) || (reg == 0x0c)) if ((reg < 0x02) || (reg == 0x0c))
return; return;
/* Write current register value on port 1. */ /* Write current register value on port 1. */
dev->regs[reg] = val; dev->regs[reg] = val;
/* Update device state. */ /* Update device state. */
switch (reg) { switch (reg) {
case 0x02: case 0x02:
dev->regs[reg] &= 0xbf; dev->regs[reg] &= 0xbf;
vt82c686_lpt_handler(dev); vt82c686_lpt_handler(dev);
vt82c686_serial_handler(dev, 0); vt82c686_serial_handler(dev, 0);
vt82c686_serial_handler(dev, 1); vt82c686_serial_handler(dev, 1);
vt82c686_fdc_handler(dev); vt82c686_fdc_handler(dev);
break; break;
case 0x03: case 0x03:
dev->regs[reg] &= 0xfc; dev->regs[reg] &= 0xfc;
vt82c686_fdc_handler(dev); vt82c686_fdc_handler(dev);
break; break;
case 0x04: case 0x04:
dev->regs[reg] &= 0xfc; dev->regs[reg] &= 0xfc;
break; break;
case 0x05: case 0x05:
dev->regs[reg] |= 0x03; dev->regs[reg] |= 0x03;
break; break;
case 0x06: case 0x06:
vt82c686_lpt_handler(dev); vt82c686_lpt_handler(dev);
break; break;
case 0x07: case 0x08: case 0x07:
dev->regs[reg] &= 0xfe; case 0x08:
vt82c686_serial_handler(dev, reg == 0x08); dev->regs[reg] &= 0xfe;
break; vt82c686_serial_handler(dev, reg == 0x08);
break;
case 0x0d: case 0x0d:
dev->regs[reg] &= 0x0f; dev->regs[reg] &= 0x0f;
break; break;
case 0x0f: case 0x0f:
dev->regs[reg] &= 0x7f; dev->regs[reg] &= 0x7f;
break; break;
case 0x10: case 0x10:
dev->regs[reg] &= 0xf4; dev->regs[reg] &= 0xf4;
break; break;
case 0x11: case 0x11:
dev->regs[reg] &= 0x3f; dev->regs[reg] &= 0x3f;
break; break;
case 0x13: case 0x13:
dev->regs[reg] &= 0xfb; dev->regs[reg] &= 0xfb;
break; break;
case 0x14: case 0x17: case 0x14:
dev->regs[reg] &= 0xfe; case 0x17:
break; dev->regs[reg] &= 0xfe;
break;
case 0x16: case 0x16:
dev->regs[reg] &= 0xf7; dev->regs[reg] &= 0xf7;
vt82c686_fdc_handler(dev); vt82c686_fdc_handler(dev);
break; break;
} }
} }
static uint8_t static uint8_t
vt82c686_read(uint16_t port, void *priv) vt82c686_read(uint16_t port, void *priv)
{ {
@@ -201,14 +196,13 @@ vt82c686_read(uint16_t port, void *priv)
Real 686B echoes the last read/written value when reading from Real 686B echoes the last read/written value when reading from
registers outside that range. */ registers outside that range. */
if (!(port & 1)) if (!(port & 1))
dev->last_val = dev->cur_reg; dev->last_val = dev->cur_reg;
else if ((dev->cur_reg >= 0xe0) && (dev->cur_reg <= 0xf8)) else if ((dev->cur_reg >= 0xe0) && (dev->cur_reg <= 0xf8))
dev->last_val = dev->regs[dev->cur_reg & 0x1f]; dev->last_val = dev->regs[dev->cur_reg & 0x1f];
return dev->last_val; return dev->last_val;
} }
/* Writes to Super I/O-related configuration space registers /* Writes to Super I/O-related configuration space registers
of the VT82C686 PCI-ISA bridge are sent here by via_pipc.c */ of the VT82C686 PCI-ISA bridge are sent here by via_pipc.c */
void void
@@ -217,36 +211,35 @@ vt82c686_sio_write(uint8_t addr, uint8_t val, void *priv)
vt82c686_t *dev = (vt82c686_t *) priv; vt82c686_t *dev = (vt82c686_t *) priv;
switch (addr) { switch (addr) {
case 0x50: case 0x50:
dev->fdc_dma = val & 0x03; dev->fdc_dma = val & 0x03;
vt82c686_fdc_handler(dev); vt82c686_fdc_handler(dev);
dev->lpt_dma = (val >> 2) & 0x03; dev->lpt_dma = (val >> 2) & 0x03;
vt82c686_lpt_handler(dev); vt82c686_lpt_handler(dev);
break; break;
case 0x51: case 0x51:
dev->fdc_irq = val & 0x0f; dev->fdc_irq = val & 0x0f;
vt82c686_fdc_handler(dev); vt82c686_fdc_handler(dev);
dev->lpt_irq = val >> 4; dev->lpt_irq = val >> 4;
vt82c686_lpt_handler(dev); vt82c686_lpt_handler(dev);
break; break;
case 0x52: case 0x52:
dev->uart_irq[0] = val & 0x0f; dev->uart_irq[0] = val & 0x0f;
vt82c686_serial_handler(dev, 0); vt82c686_serial_handler(dev, 0);
dev->uart_irq[1] = val >> 4; dev->uart_irq[1] = val >> 4;
vt82c686_serial_handler(dev, 1); vt82c686_serial_handler(dev, 1);
break; break;
case 0x85: case 0x85:
io_removehandler(FDC_PRIMARY_ADDR, 2, vt82c686_read, NULL, NULL, vt82c686_write, NULL, NULL, dev); io_removehandler(FDC_PRIMARY_ADDR, 2, vt82c686_read, NULL, NULL, vt82c686_write, NULL, NULL, dev);
if (val & 0x02) if (val & 0x02)
io_sethandler(FDC_PRIMARY_ADDR, 2, vt82c686_read, NULL, NULL, vt82c686_write, NULL, NULL, dev); io_sethandler(FDC_PRIMARY_ADDR, 2, vt82c686_read, NULL, NULL, vt82c686_write, NULL, NULL, dev);
break; break;
} }
} }
static void static void
vt82c686_reset(vt82c686_t *dev) vt82c686_reset(vt82c686_t *dev)
{ {
@@ -272,7 +265,6 @@ vt82c686_reset(vt82c686_t *dev)
vt82c686_sio_write(0x85, 0x00, dev); vt82c686_sio_write(0x85, 0x00, dev);
} }
static void static void
vt82c686_close(void *priv) vt82c686_close(void *priv)
{ {
@@ -281,14 +273,13 @@ vt82c686_close(void *priv)
free(dev); free(dev);
} }
static void * static void *
vt82c686_init(const device_t *info) vt82c686_init(const device_t *info)
{ {
vt82c686_t *dev = (vt82c686_t *) malloc(sizeof(vt82c686_t)); vt82c686_t *dev = (vt82c686_t *) malloc(sizeof(vt82c686_t));
memset(dev, 0, sizeof(vt82c686_t)); memset(dev, 0, sizeof(vt82c686_t));
dev->fdc = device_add(&fdc_at_smc_device); dev->fdc = device_add(&fdc_at_smc_device);
dev->fdc_dma = 2; dev->fdc_dma = 2;
dev->uart[0] = device_add_inst(&ns16550_device, 1); dev->uart[0] = device_add_inst(&ns16550_device, 1);
@@ -301,17 +292,16 @@ vt82c686_init(const device_t *info)
return dev; return dev;
} }
const device_t via_vt82c686_sio_device = { const device_t via_vt82c686_sio_device = {
.name = "VIA VT82C686 Integrated Super I/O", .name = "VIA VT82C686 Integrated Super I/O",
.internal_name = "via_vt82c686_sio", .internal_name = "via_vt82c686_sio",
.flags = 0, .flags = 0,
.local = 0, .local = 0,
.init = vt82c686_init, .init = vt82c686_init,
.close = vt82c686_close, .close = vt82c686_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

View File

@@ -44,64 +44,60 @@ w83787_log(const char *fmt, ...)
{ {
va_list ap; va_list ap;
if (w83787_do_log) if (w83787_do_log) {
{
va_start(ap, fmt); va_start(ap, fmt);
pclog_ex(fmt, ap); pclog_ex(fmt, ap);
va_end(ap); va_end(ap);
} }
} }
#else #else
#define w83787_log(fmt, ...) # define w83787_log(fmt, ...)
#endif #endif
#define FDDA_TYPE (dev->regs[7] & 3) #define FDDA_TYPE (dev->regs[7] & 3)
#define FDDB_TYPE ((dev->regs[7] >> 2) & 3) #define FDDB_TYPE ((dev->regs[7] >> 2) & 3)
#define FDDC_TYPE ((dev->regs[7] >> 4) & 3) #define FDDC_TYPE ((dev->regs[7] >> 4) & 3)
#define FDDD_TYPE ((dev->regs[7] >> 6) & 3) #define FDDD_TYPE ((dev->regs[7] >> 6) & 3)
#define FD_BOOT (dev->regs[8] & 3) #define FD_BOOT (dev->regs[8] & 3)
#define SWWP ((dev->regs[8] >> 4) & 1) #define SWWP ((dev->regs[8] >> 4) & 1)
#define DISFDDWR ((dev->regs[8] >> 5) & 1) #define DISFDDWR ((dev->regs[8] >> 5) & 1)
#define EN3MODE ((dev->regs[9] >> 5) & 1) #define EN3MODE ((dev->regs[9] >> 5) & 1)
#define DRV2EN_NEG (dev->regs[0xB] & 1) /* 0 = drive 2 installed */ #define DRV2EN_NEG (dev->regs[0xB] & 1) /* 0 = drive 2 installed */
#define INVERTZ ((dev->regs[0xB] >> 1) & 1) /* 0 = invert DENSEL polarity */ #define INVERTZ ((dev->regs[0xB] >> 1) & 1) /* 0 = invert DENSEL polarity */
#define IDENT ((dev->regs[0xB] >> 3) & 1) #define IDENT ((dev->regs[0xB] >> 3) & 1)
#define HEFERE ((dev->regs[0xC] >> 5) & 1) #define HEFERE ((dev->regs[0xC] >> 5) & 1)
#define HAS_IDE_FUNCTIONALITY dev->ide_function #define HAS_IDE_FUNCTIONALITY dev->ide_function
typedef struct { typedef struct {
uint8_t tries, regs[42]; uint8_t tries, regs[42];
uint16_t reg_init; uint16_t reg_init;
int locked, rw_locked, int locked, rw_locked,
cur_reg, cur_reg,
key, ide_function, key, ide_function,
ide_start; ide_start;
fdc_t *fdc; fdc_t *fdc;
serial_t *uart[2]; serial_t *uart[2];
void *gameport; void *gameport;
} w83787f_t; } w83787f_t;
static void w83787f_write(uint16_t port, uint8_t val, void *priv);
static void w83787f_write(uint16_t port, uint8_t val, void *priv); static uint8_t w83787f_read(uint16_t port, void *priv);
static uint8_t w83787f_read(uint16_t port, void *priv);
static void static void
w83787f_remap(w83787f_t *dev) w83787f_remap(w83787f_t *dev)
{ {
io_removehandler(0x250, 0x0004, io_removehandler(0x250, 0x0004,
w83787f_read, NULL, NULL, w83787f_write, NULL, NULL, dev); w83787f_read, NULL, NULL, w83787f_write, NULL, NULL, dev);
io_sethandler(0x250, 0x0004, io_sethandler(0x250, 0x0004,
w83787f_read, NULL, NULL, w83787f_write, NULL, NULL, dev); w83787f_read, NULL, NULL, w83787f_write, NULL, NULL, dev);
dev->key = 0x88 | HEFERE; dev->key = 0x88 | HEFERE;
} }
#ifdef FIXME #ifdef FIXME
/* FIXME: Implement EPP (and ECP) parallel port modes. */ /* FIXME: Implement EPP (and ECP) parallel port modes. */
static uint8_t static uint8_t
@@ -110,269 +106,261 @@ get_lpt_length(w83787f_t *dev)
uint8_t length = 4; uint8_t length = 4;
if (dev->regs[9] & 0x80) { if (dev->regs[9] & 0x80) {
if (dev->regs[0] & 0x04) if (dev->regs[0] & 0x04)
length = 8; /* EPP mode. */ length = 8; /* EPP mode. */
if (dev->regs[0] & 0x08) if (dev->regs[0] & 0x08)
length |= 0x80; /* ECP mode. */ length |= 0x80; /* ECP mode. */
} }
return length; return length;
} }
#endif #endif
static void static void
w83787f_serial_handler(w83787f_t *dev, int uart) w83787f_serial_handler(w83787f_t *dev, int uart)
{ {
int urs0 = !!(dev->regs[1] & (1 << uart)); int urs0 = !!(dev->regs[1] & (1 << uart));
int urs1 = !!(dev->regs[1] & (4 << uart)); int urs1 = !!(dev->regs[1] & (4 << uart));
int urs2 = !!(dev->regs[3] & (8 >> uart)); int urs2 = !!(dev->regs[3] & (8 >> uart));
int urs, irq = COM1_IRQ; int urs, irq = COM1_IRQ;
uint16_t addr = COM1_ADDR, enable = 1; uint16_t addr = COM1_ADDR, enable = 1;
urs = (urs1 << 1) | urs0; urs = (urs1 << 1) | urs0;
if (urs2) { if (urs2) {
addr = uart ? COM1_ADDR : COM2_ADDR; addr = uart ? COM1_ADDR : COM2_ADDR;
irq = uart ? COM1_IRQ : COM2_IRQ; irq = uart ? COM1_IRQ : COM2_IRQ;
} else { } else {
switch (urs) { switch (urs) {
case 0: case 0:
addr = uart ? COM3_ADDR : COM4_ADDR; addr = uart ? COM3_ADDR : COM4_ADDR;
irq = uart ? COM3_IRQ : COM4_IRQ; irq = uart ? COM3_IRQ : COM4_IRQ;
break; break;
case 1: case 1:
addr = uart ? COM4_ADDR : COM3_ADDR; addr = uart ? COM4_ADDR : COM3_ADDR;
irq = uart ? COM4_IRQ : COM3_IRQ; irq = uart ? COM4_IRQ : COM3_IRQ;
break; break;
case 2: case 2:
addr = uart ? COM2_ADDR : COM1_ADDR; addr = uart ? COM2_ADDR : COM1_ADDR;
irq = uart ? COM2_IRQ : COM1_IRQ; irq = uart ? COM2_IRQ : COM1_IRQ;
break; break;
case 3: case 3:
default: default:
enable = 0; enable = 0;
break; break;
} }
} }
if (dev->regs[4] & (0x20 >> uart)) if (dev->regs[4] & (0x20 >> uart))
enable = 0; enable = 0;
serial_remove(dev->uart[uart]); serial_remove(dev->uart[uart]);
if (enable) if (enable)
serial_setup(dev->uart[uart], addr, irq); serial_setup(dev->uart[uart], addr, irq);
} }
static void static void
w83787f_lpt_handler(w83787f_t *dev) w83787f_lpt_handler(w83787f_t *dev)
{ {
int ptras = (dev->regs[1] >> 4) & 0x03; int ptras = (dev->regs[1] >> 4) & 0x03;
int irq = LPT1_IRQ; int irq = LPT1_IRQ;
uint16_t addr = LPT1_ADDR, enable = 1; uint16_t addr = LPT1_ADDR, enable = 1;
switch (ptras) { switch (ptras) {
case 0x00: case 0x00:
addr = LPT_MDA_ADDR; addr = LPT_MDA_ADDR;
irq = LPT_MDA_IRQ; irq = LPT_MDA_IRQ;
break; break;
case 0x01: case 0x01:
addr = LPT2_ADDR; addr = LPT2_ADDR;
irq = LPT2_IRQ; irq = LPT2_IRQ;
break; break;
case 0x02: case 0x02:
addr = LPT1_ADDR; addr = LPT1_ADDR;
irq = LPT1_IRQ; irq = LPT1_IRQ;
break; break;
case 0x03: case 0x03:
default: default:
enable = 0; enable = 0;
break; break;
} }
if (dev->regs[4] & 0x80) if (dev->regs[4] & 0x80)
enable = 0; enable = 0;
lpt1_remove(); lpt1_remove();
if (enable) { if (enable) {
lpt1_init(addr); lpt1_init(addr);
lpt1_irq(irq); lpt1_irq(irq);
} }
} }
static void static void
w83787f_gameport_handler(w83787f_t *dev) w83787f_gameport_handler(w83787f_t *dev)
{ {
if (!(dev->regs[3] & 0x40) && !(dev->regs[4] & 0x40)) if (!(dev->regs[3] & 0x40) && !(dev->regs[4] & 0x40))
gameport_remap(dev->gameport, 0x201); gameport_remap(dev->gameport, 0x201);
else else
gameport_remap(dev->gameport, 0); gameport_remap(dev->gameport, 0);
} }
static void static void
w83787f_fdc_handler(w83787f_t *dev) w83787f_fdc_handler(w83787f_t *dev)
{ {
fdc_remove(dev->fdc); fdc_remove(dev->fdc);
if (!(dev->regs[0] & 0x20) && !(dev->regs[6] & 0x08)) if (!(dev->regs[0] & 0x20) && !(dev->regs[6] & 0x08))
fdc_set_base(dev->fdc, (dev->regs[0] & 0x10) ? FDC_PRIMARY_ADDR : FDC_SECONDARY_ADDR); fdc_set_base(dev->fdc, (dev->regs[0] & 0x10) ? FDC_PRIMARY_ADDR : FDC_SECONDARY_ADDR);
} }
static void static void
w83787f_ide_handler(w83787f_t *dev) w83787f_ide_handler(w83787f_t *dev)
{ {
if (dev->ide_function & 0x20) { if (dev->ide_function & 0x20) {
ide_sec_disable(); ide_sec_disable();
if (!(dev->regs[0] & 0x80)) { if (!(dev->regs[0] & 0x80)) {
ide_set_base(1, (dev->regs[0] & 0x40) ? 0x1f0 : 0x170); ide_set_base(1, (dev->regs[0] & 0x40) ? 0x1f0 : 0x170);
ide_set_side(1, (dev->regs[0] & 0x40) ? 0x3f6 : 0x376); ide_set_side(1, (dev->regs[0] & 0x40) ? 0x3f6 : 0x376);
ide_sec_enable(); ide_sec_enable();
} }
} else { } else {
ide_pri_disable(); ide_pri_disable();
if (!(dev->regs[0] & 0x80)) { if (!(dev->regs[0] & 0x80)) {
ide_set_base(0, (dev->regs[0] & 0x40) ? 0x1f0 : 0x170); ide_set_base(0, (dev->regs[0] & 0x40) ? 0x1f0 : 0x170);
ide_set_side(0, (dev->regs[0] & 0x40) ? 0x3f6 : 0x376); ide_set_side(0, (dev->regs[0] & 0x40) ? 0x3f6 : 0x376);
ide_pri_enable(); ide_pri_enable();
} }
} }
} }
static void static void
w83787f_write(uint16_t port, uint8_t val, void *priv) w83787f_write(uint16_t port, uint8_t val, void *priv)
{ {
w83787f_t *dev = (w83787f_t *) priv; w83787f_t *dev = (w83787f_t *) priv;
uint8_t valxor = 0; uint8_t valxor = 0;
uint8_t max = 0x15; uint8_t max = 0x15;
if (port == 0x250) { if (port == 0x250) {
if (val == dev->key) if (val == dev->key)
dev->locked = 1; dev->locked = 1;
else else
dev->locked = 0; dev->locked = 0;
return; return;
} else if (port == 0x251) { } else if (port == 0x251) {
if (val <= max) if (val <= max)
dev->cur_reg = val; dev->cur_reg = val;
return; return;
} else { } else {
if (dev->locked) { if (dev->locked) {
if (dev->rw_locked) if (dev->rw_locked)
return; return;
if (dev->cur_reg == 6) if (dev->cur_reg == 6)
val &= 0xF3; val &= 0xF3;
valxor = val ^ dev->regs[dev->cur_reg]; valxor = val ^ dev->regs[dev->cur_reg];
dev->regs[dev->cur_reg] = val; dev->regs[dev->cur_reg] = val;
} else } else
return; return;
} }
switch (dev->cur_reg) { switch (dev->cur_reg) {
case 0: case 0:
w83787_log("REG 00: %02X\n", val); w83787_log("REG 00: %02X\n", val);
if ((valxor & 0xc0) && (HAS_IDE_FUNCTIONALITY)) if ((valxor & 0xc0) && (HAS_IDE_FUNCTIONALITY))
w83787f_ide_handler(dev); w83787f_ide_handler(dev);
if (valxor & 0x30) if (valxor & 0x30)
w83787f_fdc_handler(dev); w83787f_fdc_handler(dev);
if (valxor & 0x0c) if (valxor & 0x0c)
w83787f_lpt_handler(dev); w83787f_lpt_handler(dev);
break; break;
case 1: case 1:
if (valxor & 0x80) if (valxor & 0x80)
fdc_set_swap(dev->fdc, (dev->regs[1] & 0x80) ? 1 : 0); fdc_set_swap(dev->fdc, (dev->regs[1] & 0x80) ? 1 : 0);
if (valxor & 0x30) if (valxor & 0x30)
w83787f_lpt_handler(dev); w83787f_lpt_handler(dev);
if (valxor & 0x0a) if (valxor & 0x0a)
w83787f_serial_handler(dev, 1); w83787f_serial_handler(dev, 1);
if (valxor & 0x05) if (valxor & 0x05)
w83787f_serial_handler(dev, 0); w83787f_serial_handler(dev, 0);
break; break;
case 3: case 3:
if (valxor & 0x80) if (valxor & 0x80)
w83787f_lpt_handler(dev); w83787f_lpt_handler(dev);
if (valxor & 0x40) if (valxor & 0x40)
w83787f_gameport_handler(dev); w83787f_gameport_handler(dev);
if (valxor & 0x08) if (valxor & 0x08)
w83787f_serial_handler(dev, 0); w83787f_serial_handler(dev, 0);
if (valxor & 0x04) if (valxor & 0x04)
w83787f_serial_handler(dev, 1); w83787f_serial_handler(dev, 1);
break; break;
case 4: case 4:
if (valxor & 0x10) if (valxor & 0x10)
w83787f_serial_handler(dev, 1); w83787f_serial_handler(dev, 1);
if (valxor & 0x20) if (valxor & 0x20)
w83787f_serial_handler(dev, 0); w83787f_serial_handler(dev, 0);
if (valxor & 0x80) if (valxor & 0x80)
w83787f_lpt_handler(dev); w83787f_lpt_handler(dev);
if (valxor & 0x40) if (valxor & 0x40)
w83787f_gameport_handler(dev); w83787f_gameport_handler(dev);
break; break;
case 6: case 6:
if (valxor & 0x08) if (valxor & 0x08)
w83787f_fdc_handler(dev); w83787f_fdc_handler(dev);
break; break;
case 7: case 7:
if (valxor & 0x03) if (valxor & 0x03)
fdc_update_rwc(dev->fdc, 0, FDDA_TYPE); fdc_update_rwc(dev->fdc, 0, FDDA_TYPE);
if (valxor & 0x0c) if (valxor & 0x0c)
fdc_update_rwc(dev->fdc, 1, FDDB_TYPE); fdc_update_rwc(dev->fdc, 1, FDDB_TYPE);
if (valxor & 0x30) if (valxor & 0x30)
fdc_update_rwc(dev->fdc, 2, FDDC_TYPE); fdc_update_rwc(dev->fdc, 2, FDDC_TYPE);
if (valxor & 0xc0) if (valxor & 0xc0)
fdc_update_rwc(dev->fdc, 3, FDDD_TYPE); fdc_update_rwc(dev->fdc, 3, FDDD_TYPE);
break; break;
case 8: case 8:
if (valxor & 0x03) if (valxor & 0x03)
fdc_update_boot_drive(dev->fdc, FD_BOOT); fdc_update_boot_drive(dev->fdc, FD_BOOT);
if (valxor & 0x10) if (valxor & 0x10)
fdc_set_swwp(dev->fdc, SWWP ? 1 : 0); fdc_set_swwp(dev->fdc, SWWP ? 1 : 0);
if (valxor & 0x20) if (valxor & 0x20)
fdc_set_diswr(dev->fdc, DISFDDWR ? 1 : 0); fdc_set_diswr(dev->fdc, DISFDDWR ? 1 : 0);
break; break;
case 9: case 9:
if (valxor & 0x20) if (valxor & 0x20)
fdc_update_enh_mode(dev->fdc, EN3MODE ? 1 : 0); fdc_update_enh_mode(dev->fdc, EN3MODE ? 1 : 0);
if (valxor & 0x40) if (valxor & 0x40)
dev->rw_locked = (val & 0x40) ? 1 : 0; dev->rw_locked = (val & 0x40) ? 1 : 0;
if (valxor & 0x80) if (valxor & 0x80)
w83787f_lpt_handler(dev); w83787f_lpt_handler(dev);
break; break;
case 0xB: case 0xB:
w83787_log("Writing %02X to CRB\n", val); w83787_log("Writing %02X to CRB\n", val);
break; break;
case 0xC: case 0xC:
if (valxor & 0x20) if (valxor & 0x20)
w83787f_remap(dev); w83787f_remap(dev);
break; break;
} }
} }
static uint8_t static uint8_t
w83787f_read(uint16_t port, void *priv) w83787f_read(uint16_t port, void *priv)
{ {
w83787f_t *dev = (w83787f_t *) priv; w83787f_t *dev = (w83787f_t *) priv;
uint8_t ret = 0xff; uint8_t ret = 0xff;
if (dev->locked) { if (dev->locked) {
if (port == 0x251) if (port == 0x251)
ret = dev->cur_reg; ret = dev->cur_reg;
else if (port == 0x252) { else if (port == 0x252) {
if (dev->cur_reg == 7) if (dev->cur_reg == 7)
ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2)); ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2));
else if (!dev->rw_locked) else if (!dev->rw_locked)
ret = dev->regs[dev->cur_reg]; ret = dev->regs[dev->cur_reg];
} }
} }
return ret; return ret;
} }
static void static void
w83787f_reset(w83787f_t *dev) w83787f_reset(w83787f_t *dev)
{ {
@@ -383,27 +371,27 @@ w83787f_reset(w83787f_t *dev)
memset(dev->regs, 0, 0x2A); memset(dev->regs, 0, 0x2A);
if (HAS_IDE_FUNCTIONALITY) { if (HAS_IDE_FUNCTIONALITY) {
if (dev->ide_function & 0x20) { if (dev->ide_function & 0x20) {
dev->regs[0x00] = 0x90; dev->regs[0x00] = 0x90;
ide_sec_disable(); ide_sec_disable();
ide_set_base(1, 0x170); ide_set_base(1, 0x170);
ide_set_side(1, 0x376); ide_set_side(1, 0x376);
} else { } else {
dev->regs[0x00] = 0xd0; dev->regs[0x00] = 0xd0;
ide_pri_disable(); ide_pri_disable();
ide_set_base(0, 0x1f0); ide_set_base(0, 0x1f0);
ide_set_side(0, 0x3f6); ide_set_side(0, 0x3f6);
} }
if (dev->ide_start) { if (dev->ide_start) {
dev->regs[0x00] &= 0x7f; dev->regs[0x00] &= 0x7f;
if (dev->ide_function & 0x20) if (dev->ide_function & 0x20)
ide_sec_enable(); ide_sec_enable();
else else
ide_pri_enable(); ide_pri_enable();
} }
} else } else
dev->regs[0x00] = 0xd0; dev->regs[0x00] = 0xd0;
fdc_reset(dev->fdc); fdc_reset(dev->fdc);
@@ -426,11 +414,10 @@ w83787f_reset(w83787f_t *dev)
w83787f_remap(dev); w83787f_remap(dev);
dev->locked = 0; dev->locked = 0;
dev->rw_locked = 0; dev->rw_locked = 0;
} }
static void static void
w83787f_close(void *priv) w83787f_close(void *priv)
{ {
@@ -439,7 +426,6 @@ w83787f_close(void *priv)
free(dev); free(dev);
} }
static void * static void *
w83787f_init(const device_t *info) w83787f_init(const device_t *info)
{ {
@@ -456,7 +442,7 @@ w83787f_init(const device_t *info)
dev->gameport = gameport_add(&gameport_sio_1io_device); dev->gameport = gameport_add(&gameport_sio_1io_device);
if ((dev->ide_function & 0x30) == 0x10) if ((dev->ide_function & 0x30) == 0x10)
device_add(&ide_isa_device); device_add(&ide_isa_device);
dev->ide_start = !!(info->local & 0x40); dev->ide_start = !!(info->local & 0x40);
@@ -467,57 +453,57 @@ w83787f_init(const device_t *info)
} }
const device_t w83787f_device = { const device_t w83787f_device = {
.name = "Winbond W83787F/IF Super I/O", .name = "Winbond W83787F/IF Super I/O",
.internal_name = "w83787f", .internal_name = "w83787f",
.flags = 0, .flags = 0,
.local = 0x09, .local = 0x09,
.init = w83787f_init, .init = w83787f_init,
.close = w83787f_close, .close = w83787f_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t w83787f_ide_device = { const device_t w83787f_ide_device = {
.name = "Winbond W83787F/IF Super I/O (With IDE)", .name = "Winbond W83787F/IF Super I/O (With IDE)",
.internal_name = "w83787f_ide", .internal_name = "w83787f_ide",
.flags = 0, .flags = 0,
.local = 0x19, .local = 0x19,
.init = w83787f_init, .init = w83787f_init,
.close = w83787f_close, .close = w83787f_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t w83787f_ide_en_device = { const device_t w83787f_ide_en_device = {
.name = "Winbond W83787F/IF Super I/O (With IDE Enabled)", .name = "Winbond W83787F/IF Super I/O (With IDE Enabled)",
.internal_name = "w83787f_ide_en", .internal_name = "w83787f_ide_en",
.flags = 0, .flags = 0,
.local = 0x59, .local = 0x59,
.init = w83787f_init, .init = w83787f_init,
.close = w83787f_close, .close = w83787f_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t w83787f_ide_sec_device = { const device_t w83787f_ide_sec_device = {
.name = "Winbond W83787F/IF Super I/O (With Secondary IDE)", .name = "Winbond W83787F/IF Super I/O (With Secondary IDE)",
.internal_name = "w83787f_ide_sec", .internal_name = "w83787f_ide_sec",
.flags = 0, .flags = 0,
.local = 0x39, .local = 0x39,
.init = w83787f_init, .init = w83787f_init,
.close = w83787f_close, .close = w83787f_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

View File

@@ -34,45 +34,41 @@
#include <86box/fdc.h> #include <86box/fdc.h>
#include <86box/sio.h> #include <86box/sio.h>
#define FDDA_TYPE (dev->regs[7] & 3)
#define FDDB_TYPE ((dev->regs[7] >> 2) & 3)
#define FDDC_TYPE ((dev->regs[7] >> 4) & 3)
#define FDDD_TYPE ((dev->regs[7] >> 6) & 3)
#define FDDA_TYPE (dev->regs[7] & 3) #define FD_BOOT (dev->regs[8] & 3)
#define FDDB_TYPE ((dev->regs[7] >> 2) & 3) #define SWWP ((dev->regs[8] >> 4) & 1)
#define FDDC_TYPE ((dev->regs[7] >> 4) & 3) #define DISFDDWR ((dev->regs[8] >> 5) & 1)
#define FDDD_TYPE ((dev->regs[7] >> 6) & 3)
#define FD_BOOT (dev->regs[8] & 3) #define EN3MODE ((dev->regs[9] >> 5) & 1)
#define SWWP ((dev->regs[8] >> 4) & 1)
#define DISFDDWR ((dev->regs[8] >> 5) & 1)
#define EN3MODE ((dev->regs[9] >> 5) & 1) #define DRV2EN_NEG (dev->regs[0xB] & 1) /* 0 = drive 2 installed */
#define INVERTZ ((dev->regs[0xB] >> 1) & 1) /* 0 = invert DENSEL polarity */
#define IDENT ((dev->regs[0xB] >> 3) & 1)
#define DRV2EN_NEG (dev->regs[0xB] & 1) /* 0 = drive 2 installed */ #define HEFERE ((dev->regs[0xC] >> 5) & 1)
#define INVERTZ ((dev->regs[0xB] >> 1) & 1) /* 0 = invert DENSEL polarity */
#define IDENT ((dev->regs[0xB] >> 3) & 1)
#define HEFERE ((dev->regs[0xC] >> 5) & 1) #define HEFRAS (dev->regs[0x16] & 1)
#define HEFRAS (dev->regs[0x16] & 1)
#define PRTIQS (dev->regs[0x27] & 0x0f)
#define ECPIRQ ((dev->regs[0x27] >> 5) & 0x07)
#define PRTIQS (dev->regs[0x27] & 0x0f)
#define ECPIRQ ((dev->regs[0x27] >> 5) & 0x07)
typedef struct { typedef struct {
uint8_t tries, regs[42]; uint8_t tries, regs[42];
uint16_t reg_init; uint16_t reg_init;
int locked, rw_locked, int locked, rw_locked,
cur_reg, cur_reg,
base_address, key, base_address, key,
key_times; key_times;
fdc_t *fdc; fdc_t *fdc;
serial_t *uart[2]; serial_t *uart[2];
} w83877f_t; } w83877f_t;
static void w83877f_write(uint16_t port, uint8_t val, void *priv);
static void w83877f_write(uint16_t port, uint8_t val, void *priv); static uint8_t w83877f_read(uint16_t port, void *priv);
static uint8_t w83877f_read(uint16_t port, void *priv);
static void static void
w83877f_remap(w83877f_t *dev) w83877f_remap(w83877f_t *dev)
@@ -80,83 +76,83 @@ w83877f_remap(w83877f_t *dev)
uint8_t hefras = HEFRAS; uint8_t hefras = HEFRAS;
io_removehandler(0x250, 0x0002, io_removehandler(0x250, 0x0002,
w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev); w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev);
io_removehandler(FDC_PRIMARY_ADDR, 0x0002, io_removehandler(FDC_PRIMARY_ADDR, 0x0002,
w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev); w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev);
dev->base_address = (hefras ? FDC_PRIMARY_ADDR : 0x250); dev->base_address = (hefras ? FDC_PRIMARY_ADDR : 0x250);
io_sethandler(dev->base_address, 0x0002, io_sethandler(dev->base_address, 0x0002,
w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev); w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev);
dev->key_times = hefras + 1; dev->key_times = hefras + 1;
dev->key = (hefras ? 0x86 : 0x88) | HEFERE; dev->key = (hefras ? 0x86 : 0x88) | HEFERE;
} }
static uint8_t static uint8_t
get_lpt_length(w83877f_t *dev) get_lpt_length(w83877f_t *dev)
{ {
uint8_t length = 4; uint8_t length = 4;
if (dev->regs[9] & 0x80) { if (dev->regs[9] & 0x80) {
if (dev->regs[0] & 0x04) if (dev->regs[0] & 0x04)
length = 8; /* EPP mode. */ length = 8; /* EPP mode. */
if (dev->regs[0] & 0x08) if (dev->regs[0] & 0x08)
length |= 0x80; /* ECP mode. */ length |= 0x80; /* ECP mode. */
} }
return length; return length;
} }
static uint16_t static uint16_t
make_port(w83877f_t *dev, uint8_t reg) make_port(w83877f_t *dev, uint8_t reg)
{ {
uint16_t p = 0; uint16_t p = 0;
uint8_t l; uint8_t l;
switch (reg) { switch (reg) {
case 0x20: case 0x20:
p = ((uint16_t) (dev->regs[reg] & 0xfc)) << 2; p = ((uint16_t) (dev->regs[reg] & 0xfc)) << 2;
p &= 0xFF0; p &= 0xFF0;
if ((p < 0x100) || (p > 0x3F0)) p = 0x3F0; if ((p < 0x100) || (p > 0x3F0))
break; p = 0x3F0;
case 0x23: break;
l = get_lpt_length(dev); case 0x23:
p = ((uint16_t) (dev->regs[reg] & 0xff)) << 2; l = get_lpt_length(dev);
/* 8 ports in EPP mode, 4 in non-EPP mode. */ p = ((uint16_t) (dev->regs[reg] & 0xff)) << 2;
if ((l & 0x0f) == 8) /* 8 ports in EPP mode, 4 in non-EPP mode. */
p &= 0x3F8; if ((l & 0x0f) == 8)
else p &= 0x3F8;
p &= 0x3FC; else
if ((p < 0x100) || (p > 0x3FF)) p = LPT1_ADDR; p &= 0x3FC;
/* In ECP mode, A10 is active. */ if ((p < 0x100) || (p > 0x3FF))
if (l & 0x80) p = LPT1_ADDR;
p |= 0x400; /* In ECP mode, A10 is active. */
break; if (l & 0x80)
case 0x24: p |= 0x400;
p = ((uint16_t) (dev->regs[reg] & 0xfe)) << 2; break;
p &= 0xFF8; case 0x24:
if ((p < 0x100) || (p > 0x3F8)) p = COM1_ADDR; p = ((uint16_t) (dev->regs[reg] & 0xfe)) << 2;
break; p &= 0xFF8;
case 0x25: if ((p < 0x100) || (p > 0x3F8))
p = ((uint16_t) (dev->regs[reg] & 0xfe)) << 2; p = COM1_ADDR;
p &= 0xFF8; break;
if ((p < 0x100) || (p > 0x3F8)) p = COM2_ADDR; case 0x25:
break; p = ((uint16_t) (dev->regs[reg] & 0xfe)) << 2;
p &= 0xFF8;
if ((p < 0x100) || (p > 0x3F8))
p = COM2_ADDR;
break;
} }
return p; return p;
} }
static void static void
w83877f_fdc_handler(w83877f_t *dev) w83877f_fdc_handler(w83877f_t *dev)
{ {
fdc_remove(dev->fdc); fdc_remove(dev->fdc);
if (!(dev->regs[6] & 0x08) && (dev->regs[0x20] & 0xc0)) if (!(dev->regs[6] & 0x08) && (dev->regs[0x20] & 0xc0))
fdc_set_base(dev->fdc, FDC_PRIMARY_ADDR); fdc_set_base(dev->fdc, FDC_PRIMARY_ADDR);
} }
static void static void
w83877f_lpt_handler(w83877f_t *dev) w83877f_lpt_handler(w83877f_t *dev)
{ {
@@ -165,230 +161,226 @@ w83877f_lpt_handler(w83877f_t *dev)
lpt1_remove(); lpt1_remove();
if (!(dev->regs[4] & 0x80) && (dev->regs[0x23] & 0xc0)) if (!(dev->regs[4] & 0x80) && (dev->regs[0x23] & 0xc0))
lpt1_init(make_port(dev, 0x23)); lpt1_init(make_port(dev, 0x23));
lpt_irq = 0xff; lpt_irq = 0xff;
lpt_irq = lpt_irqs[ECPIRQ]; lpt_irq = lpt_irqs[ECPIRQ];
if (lpt_irq == 0) if (lpt_irq == 0)
lpt_irq = PRTIQS; lpt_irq = PRTIQS;
lpt1_irq(lpt_irq); lpt1_irq(lpt_irq);
} }
static void static void
w83877f_serial_handler(w83877f_t *dev, int uart) w83877f_serial_handler(w83877f_t *dev, int uart)
{ {
int reg_mask = uart ? 0x10 : 0x20; int reg_mask = uart ? 0x10 : 0x20;
int reg_id = uart ? 0x25 : 0x24; int reg_id = uart ? 0x25 : 0x24;
int irq_mask = uart ? 0x0f : 0xf0; int irq_mask = uart ? 0x0f : 0xf0;
int irq_shift = uart ? 0 : 4; int irq_shift = uart ? 0 : 4;
double clock_src = 24000000.0 / 13.0; double clock_src = 24000000.0 / 13.0;
serial_remove(dev->uart[uart]); serial_remove(dev->uart[uart]);
if (!(dev->regs[4] & reg_mask) && (dev->regs[reg_id] & 0xc0)) if (!(dev->regs[4] & reg_mask) && (dev->regs[reg_id] & 0xc0))
serial_setup(dev->uart[uart], make_port(dev, reg_id), (dev->regs[0x28] & irq_mask) >> irq_shift); serial_setup(dev->uart[uart], make_port(dev, reg_id), (dev->regs[0x28] & irq_mask) >> irq_shift);
if (dev->regs[0x19] & (0x02 >> uart)) { if (dev->regs[0x19] & (0x02 >> uart)) {
clock_src = 14769000.0; clock_src = 14769000.0;
} else if (dev->regs[0x03] & (0x02 >> uart)) { } else if (dev->regs[0x03] & (0x02 >> uart)) {
clock_src = 24000000.0 / 12.0; clock_src = 24000000.0 / 12.0;
} else { } else {
clock_src = 24000000.0 / 13.0; clock_src = 24000000.0 / 13.0;
} }
serial_set_clock_src(dev->uart[uart], clock_src); serial_set_clock_src(dev->uart[uart], clock_src);
} }
static void static void
w83877f_write(uint16_t port, uint8_t val, void *priv) w83877f_write(uint16_t port, uint8_t val, void *priv)
{ {
w83877f_t *dev = (w83877f_t *) priv; w83877f_t *dev = (w83877f_t *) priv;
uint8_t valxor = 0; uint8_t valxor = 0;
uint8_t max = 0x2A; uint8_t max = 0x2A;
if (port == 0x250) { if (port == 0x250) {
if (val == dev->key) if (val == dev->key)
dev->locked = 1; dev->locked = 1;
else else
dev->locked = 0; dev->locked = 0;
return; return;
} else if (port == 0x251) { } else if (port == 0x251) {
if (val <= max) if (val <= max)
dev->cur_reg = val; dev->cur_reg = val;
return; return;
} else if (port == FDC_PRIMARY_ADDR) { } else if (port == FDC_PRIMARY_ADDR) {
if ((val == dev->key) && !dev->locked) { if ((val == dev->key) && !dev->locked) {
if (dev->key_times == 2) { if (dev->key_times == 2) {
if (dev->tries) { if (dev->tries) {
dev->locked = 1; dev->locked = 1;
dev->tries = 0; dev->tries = 0;
} else } else
dev->tries++; dev->tries++;
} else { } else {
dev->locked = 1; dev->locked = 1;
dev->tries = 0; dev->tries = 0;
} }
} else { } else {
if (dev->locked) { if (dev->locked) {
if (val < max) if (val < max)
dev->cur_reg = val; dev->cur_reg = val;
if (val == 0xaa) if (val == 0xaa)
dev->locked = 0; dev->locked = 0;
} else { } else {
if (dev->tries) if (dev->tries)
dev->tries = 0; dev->tries = 0;
} }
} }
return; return;
} else if ((port == 0x252) || (port == 0x3f1)) { } else if ((port == 0x252) || (port == 0x3f1)) {
if (dev->locked) { if (dev->locked) {
if (dev->rw_locked) if (dev->rw_locked)
return; return;
if ((dev->cur_reg >= 0x26) && (dev->cur_reg <= 0x27)) if ((dev->cur_reg >= 0x26) && (dev->cur_reg <= 0x27))
return; return;
if (dev->cur_reg == 0x29) if (dev->cur_reg == 0x29)
return; return;
if (dev->cur_reg == 6) if (dev->cur_reg == 6)
val &= 0xF3; val &= 0xF3;
valxor = val ^ dev->regs[dev->cur_reg]; valxor = val ^ dev->regs[dev->cur_reg];
dev->regs[dev->cur_reg] = val; dev->regs[dev->cur_reg] = val;
} else } else
return; return;
} }
switch (dev->cur_reg) { switch (dev->cur_reg) {
case 0: case 0:
if (valxor & 0x0c) if (valxor & 0x0c)
w83877f_lpt_handler(dev); w83877f_lpt_handler(dev);
break; break;
case 1: case 1:
if (valxor & 0x80) if (valxor & 0x80)
fdc_set_swap(dev->fdc, (dev->regs[1] & 0x80) ? 1 : 0); fdc_set_swap(dev->fdc, (dev->regs[1] & 0x80) ? 1 : 0);
break; break;
case 3: case 3:
if (valxor & 0x02) if (valxor & 0x02)
w83877f_serial_handler(dev, 0); w83877f_serial_handler(dev, 0);
if (valxor & 0x01) if (valxor & 0x01)
w83877f_serial_handler(dev, 1); w83877f_serial_handler(dev, 1);
break; break;
case 4: case 4:
if (valxor & 0x10) if (valxor & 0x10)
w83877f_serial_handler(dev, 1); w83877f_serial_handler(dev, 1);
if (valxor & 0x20) if (valxor & 0x20)
w83877f_serial_handler(dev, 0); w83877f_serial_handler(dev, 0);
if (valxor & 0x80) if (valxor & 0x80)
w83877f_lpt_handler(dev); w83877f_lpt_handler(dev);
break; break;
case 6: case 6:
if (valxor & 0x08) if (valxor & 0x08)
w83877f_fdc_handler(dev); w83877f_fdc_handler(dev);
break; break;
case 7: case 7:
if (valxor & 0x03) if (valxor & 0x03)
fdc_update_rwc(dev->fdc, 0, FDDA_TYPE); fdc_update_rwc(dev->fdc, 0, FDDA_TYPE);
if (valxor & 0x0c) if (valxor & 0x0c)
fdc_update_rwc(dev->fdc, 1, FDDB_TYPE); fdc_update_rwc(dev->fdc, 1, FDDB_TYPE);
if (valxor & 0x30) if (valxor & 0x30)
fdc_update_rwc(dev->fdc, 2, FDDC_TYPE); fdc_update_rwc(dev->fdc, 2, FDDC_TYPE);
if (valxor & 0xc0) if (valxor & 0xc0)
fdc_update_rwc(dev->fdc, 3, FDDD_TYPE); fdc_update_rwc(dev->fdc, 3, FDDD_TYPE);
break; break;
case 8: case 8:
if (valxor & 0x03) if (valxor & 0x03)
fdc_update_boot_drive(dev->fdc, FD_BOOT); fdc_update_boot_drive(dev->fdc, FD_BOOT);
if (valxor & 0x10) if (valxor & 0x10)
fdc_set_swwp(dev->fdc, SWWP ? 1 : 0); fdc_set_swwp(dev->fdc, SWWP ? 1 : 0);
if (valxor & 0x20) if (valxor & 0x20)
fdc_set_diswr(dev->fdc, DISFDDWR ? 1 : 0); fdc_set_diswr(dev->fdc, DISFDDWR ? 1 : 0);
break; break;
case 9: case 9:
if (valxor & 0x20) if (valxor & 0x20)
fdc_update_enh_mode(dev->fdc, EN3MODE ? 1 : 0); fdc_update_enh_mode(dev->fdc, EN3MODE ? 1 : 0);
if (valxor & 0x40) if (valxor & 0x40)
dev->rw_locked = (val & 0x40) ? 1 : 0; dev->rw_locked = (val & 0x40) ? 1 : 0;
if (valxor & 0x80) if (valxor & 0x80)
w83877f_lpt_handler(dev); w83877f_lpt_handler(dev);
break; break;
case 0xB: case 0xB:
if (valxor & 1) if (valxor & 1)
fdc_update_drv2en(dev->fdc, DRV2EN_NEG ? 0 : 1); fdc_update_drv2en(dev->fdc, DRV2EN_NEG ? 0 : 1);
if (valxor & 2) if (valxor & 2)
fdc_update_densel_polarity(dev->fdc, INVERTZ ? 1 : 0); fdc_update_densel_polarity(dev->fdc, INVERTZ ? 1 : 0);
break; break;
case 0xC: case 0xC:
if (valxor & 0x20) if (valxor & 0x20)
w83877f_remap(dev); w83877f_remap(dev);
break; break;
case 0x16: case 0x16:
if (valxor & 1) if (valxor & 1)
w83877f_remap(dev); w83877f_remap(dev);
break; break;
case 0x19: case 0x19:
if (valxor & 0x02) if (valxor & 0x02)
w83877f_serial_handler(dev, 0); w83877f_serial_handler(dev, 0);
if (valxor & 0x01) if (valxor & 0x01)
w83877f_serial_handler(dev, 1); w83877f_serial_handler(dev, 1);
break; break;
case 0x20: case 0x20:
if (valxor) if (valxor)
w83877f_fdc_handler(dev); w83877f_fdc_handler(dev);
break; break;
case 0x23: case 0x23:
if (valxor) if (valxor)
w83877f_lpt_handler(dev); w83877f_lpt_handler(dev);
break; break;
case 0x24: case 0x24:
if (valxor & 0xfe) if (valxor & 0xfe)
w83877f_serial_handler(dev, 0); w83877f_serial_handler(dev, 0);
break; break;
case 0x25: case 0x25:
if (valxor & 0xfe) if (valxor & 0xfe)
w83877f_serial_handler(dev, 1); w83877f_serial_handler(dev, 1);
break; break;
case 0x27: case 0x27:
if (valxor & 0xef) if (valxor & 0xef)
w83877f_lpt_handler(dev); w83877f_lpt_handler(dev);
break; break;
case 0x28: case 0x28:
if (valxor & 0xf) { if (valxor & 0xf) {
if ((dev->regs[0x28] & 0x0f) == 0) if ((dev->regs[0x28] & 0x0f) == 0)
dev->regs[0x28] |= 0x03; dev->regs[0x28] |= 0x03;
w83877f_serial_handler(dev, 1); w83877f_serial_handler(dev, 1);
} }
if (valxor & 0xf0) { if (valxor & 0xf0) {
if ((dev->regs[0x28] & 0xf0) == 0) if ((dev->regs[0x28] & 0xf0) == 0)
dev->regs[0x28] |= 0x40; dev->regs[0x28] |= 0x40;
w83877f_serial_handler(dev, 0); w83877f_serial_handler(dev, 0);
} }
break; break;
} }
} }
static uint8_t static uint8_t
w83877f_read(uint16_t port, void *priv) w83877f_read(uint16_t port, void *priv)
{ {
w83877f_t *dev = (w83877f_t *) priv; w83877f_t *dev = (w83877f_t *) priv;
uint8_t ret = 0xff; uint8_t ret = 0xff;
if (dev->locked) { if (dev->locked) {
if ((port == FDC_PRIMARY_ADDR) || (port == 0x251)) if ((port == FDC_PRIMARY_ADDR) || (port == 0x251))
ret = dev->cur_reg; ret = dev->cur_reg;
else if ((port == 0x3f1) || (port == 0x252)) { else if ((port == 0x3f1) || (port == 0x252)) {
if (dev->cur_reg == 7) if (dev->cur_reg == 7)
ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6)); ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6));
else if ((dev->cur_reg >= 0x18) || !dev->rw_locked) else if ((dev->cur_reg >= 0x18) || !dev->rw_locked)
ret = dev->regs[dev->cur_reg]; ret = dev->regs[dev->cur_reg];
} }
} }
return ret; return ret;
} }
static void static void
w83877f_reset(w83877f_t *dev) w83877f_reset(w83877f_t *dev)
{ {
@@ -422,16 +414,15 @@ w83877f_reset(w83877f_t *dev)
w83877f_serial_handler(dev, 1); w83877f_serial_handler(dev, 1);
dev->base_address = FDC_PRIMARY_ADDR; dev->base_address = FDC_PRIMARY_ADDR;
dev->key = 0x89; dev->key = 0x89;
dev->key_times = 1; dev->key_times = 1;
w83877f_remap(dev); w83877f_remap(dev);
dev->locked = 0; dev->locked = 0;
dev->rw_locked = 0; dev->rw_locked = 0;
} }
static void static void
w83877f_close(void *priv) w83877f_close(void *priv)
{ {
@@ -440,7 +431,6 @@ w83877f_close(void *priv)
free(dev); free(dev);
} }
static void * static void *
w83877f_init(const device_t *info) w83877f_init(const device_t *info)
{ {
@@ -460,57 +450,57 @@ w83877f_init(const device_t *info)
} }
const device_t w83877f_device = { const device_t w83877f_device = {
.name = "Winbond W83877F Super I/O", .name = "Winbond W83877F Super I/O",
.internal_name = "w83877f", .internal_name = "w83877f",
.flags = 0, .flags = 0,
.local = 0x0a05, .local = 0x0a05,
.init = w83877f_init, .init = w83877f_init,
.close = w83877f_close, .close = w83877f_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t w83877f_president_device = { const device_t w83877f_president_device = {
.name = "Winbond W83877F Super I/O (President)", .name = "Winbond W83877F Super I/O (President)",
.internal_name = "w83877f_president", .internal_name = "w83877f_president",
.flags = 0, .flags = 0,
.local = 0x0a04, .local = 0x0a04,
.init = w83877f_init, .init = w83877f_init,
.close = w83877f_close, .close = w83877f_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t w83877tf_device = { const device_t w83877tf_device = {
.name = "Winbond W83877TF Super I/O", .name = "Winbond W83877TF Super I/O",
.internal_name = "w83877tf", .internal_name = "w83877tf",
.flags = 0, .flags = 0,
.local = 0x0c04, .local = 0x0c04,
.init = w83877f_init, .init = w83877f_init,
.close = w83877f_close, .close = w83877f_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t w83877tf_acorp_device = { const device_t w83877tf_acorp_device = {
.name = "Winbond W83877TF Super I/O", .name = "Winbond W83877TF Super I/O",
.internal_name = "w83877tf_acorp", .internal_name = "w83877tf_acorp",
.flags = 0, .flags = 0,
.local = 0x0c05, .local = 0x0c05,
.init = w83877f_init, .init = w83877f_init,
.close = w83877f_close, .close = w83877f_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };

View File

@@ -34,333 +34,331 @@
#include <86box/fdc.h> #include <86box/fdc.h>
#include <86box/sio.h> #include <86box/sio.h>
#define HEFRAS (dev->regs[0x26] & 0x40)
#define HEFRAS (dev->regs[0x26] & 0x40)
typedef struct { typedef struct {
uint8_t id, tries, uint8_t id, tries,
regs[48], regs[48],
dev_regs[256][208]; dev_regs[256][208];
int locked, rw_locked, int locked, rw_locked,
cur_reg, base_address, cur_reg, base_address,
type, hefras; type, hefras;
fdc_t *fdc; fdc_t *fdc;
serial_t *uart[2]; serial_t *uart[2];
} w83977f_t; } w83977f_t;
static int next_id = 0;
static int next_id = 0; static void w83977f_write(uint16_t port, uint8_t val, void *priv);
static uint8_t w83977f_read(uint16_t port, void *priv);
static void w83977f_write(uint16_t port, uint8_t val, void *priv);
static uint8_t w83977f_read(uint16_t port, void *priv);
static void static void
w83977f_remap(w83977f_t *dev) w83977f_remap(w83977f_t *dev)
{ {
io_removehandler(FDC_PRIMARY_ADDR, 0x0002, io_removehandler(FDC_PRIMARY_ADDR, 0x0002,
w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev); w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev);
io_removehandler(FDC_SECONDARY_ADDR, 0x0002, io_removehandler(FDC_SECONDARY_ADDR, 0x0002,
w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev); w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev);
dev->base_address = (HEFRAS ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); dev->base_address = (HEFRAS ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
io_sethandler(dev->base_address, 0x0002, io_sethandler(dev->base_address, 0x0002,
w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev); w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev);
} }
static uint8_t static uint8_t
get_lpt_length(w83977f_t *dev) get_lpt_length(w83977f_t *dev)
{ {
uint8_t length = 4; uint8_t length = 4;
if (((dev->dev_regs[1][0xc0] & 0x07) != 0x00) && ((dev->dev_regs[1][0xc0] & 0x07) != 0x02) && if (((dev->dev_regs[1][0xc0] & 0x07) != 0x00) && ((dev->dev_regs[1][0xc0] & 0x07) != 0x02) && ((dev->dev_regs[1][0xc0] & 0x07) != 0x04))
((dev->dev_regs[1][0xc0] & 0x07) != 0x04)) length = 8;
length = 8;
return length; return length;
} }
static void static void
w83977f_fdc_handler(w83977f_t *dev) w83977f_fdc_handler(w83977f_t *dev)
{ {
uint16_t io_base = (dev->dev_regs[0][0x30] << 8) | dev->dev_regs[0][0x31]; uint16_t io_base = (dev->dev_regs[0][0x30] << 8) | dev->dev_regs[0][0x31];
if (dev->id == 1) if (dev->id == 1)
return; return;
fdc_remove(dev->fdc); fdc_remove(dev->fdc);
if ((dev->dev_regs[0][0x00] & 0x01) && (dev->regs[0x22] & 0x01) && (io_base >= 0x100) && (io_base <= 0xff8)) if ((dev->dev_regs[0][0x00] & 0x01) && (dev->regs[0x22] & 0x01) && (io_base >= 0x100) && (io_base <= 0xff8))
fdc_set_base(dev->fdc, io_base); fdc_set_base(dev->fdc, io_base);
fdc_set_irq(dev->fdc, dev->dev_regs[0][0x40] & 0x0f); fdc_set_irq(dev->fdc, dev->dev_regs[0][0x40] & 0x0f);
} }
static void static void
w83977f_lpt_handler(w83977f_t *dev) w83977f_lpt_handler(w83977f_t *dev)
{ {
uint16_t io_mask, io_base = (dev->dev_regs[1][0x30] << 8) | dev->dev_regs[1][0x31]; uint16_t io_mask, io_base = (dev->dev_regs[1][0x30] << 8) | dev->dev_regs[1][0x31];
int io_len = get_lpt_length(dev); int io_len = get_lpt_length(dev);
io_base &= (0xff8 | io_len); io_base &= (0xff8 | io_len);
io_mask = 0xffc; io_mask = 0xffc;
if (io_len == 8) if (io_len == 8)
io_mask = 0xff8; io_mask = 0xff8;
if (dev->id == 1) { if (dev->id == 1) {
lpt2_remove(); lpt2_remove();
if ((dev->dev_regs[1][0x00] & 0x01) && (dev->regs[0x22] & 0x08) && (io_base >= 0x100) && (io_base <= io_mask)) if ((dev->dev_regs[1][0x00] & 0x01) && (dev->regs[0x22] & 0x08) && (io_base >= 0x100) && (io_base <= io_mask))
lpt2_init(io_base); lpt2_init(io_base);
lpt2_irq(dev->dev_regs[1][0x40] & 0x0f); lpt2_irq(dev->dev_regs[1][0x40] & 0x0f);
} else { } else {
lpt1_remove(); lpt1_remove();
if ((dev->dev_regs[1][0x00] & 0x01) && (dev->regs[0x22] & 0x08) && (io_base >= 0x100) && (io_base <= io_mask)) if ((dev->dev_regs[1][0x00] & 0x01) && (dev->regs[0x22] & 0x08) && (io_base >= 0x100) && (io_base <= io_mask))
lpt1_init(io_base); lpt1_init(io_base);
lpt1_irq(dev->dev_regs[1][0x40] & 0x0f); lpt1_irq(dev->dev_regs[1][0x40] & 0x0f);
} }
} }
static void static void
w83977f_serial_handler(w83977f_t *dev, int uart) w83977f_serial_handler(w83977f_t *dev, int uart)
{ {
uint16_t io_base = (dev->dev_regs[2 + uart][0x30] << 8) | dev->dev_regs[2 + uart][0x31]; uint16_t io_base = (dev->dev_regs[2 + uart][0x30] << 8) | dev->dev_regs[2 + uart][0x31];
double clock_src = 24000000.0 / 13.0; double clock_src = 24000000.0 / 13.0;
serial_remove(dev->uart[uart]); serial_remove(dev->uart[uart]);
if ((dev->dev_regs[2 + uart][0x00] & 0x01) && (dev->regs[0x22] & (0x10 << uart)) && (io_base >= 0x100) && (io_base <= 0xff8)) if ((dev->dev_regs[2 + uart][0x00] & 0x01) && (dev->regs[0x22] & (0x10 << uart)) && (io_base >= 0x100) && (io_base <= 0xff8))
serial_setup(dev->uart[uart], io_base, dev->dev_regs[2 + uart][0x40] & 0x0f); serial_setup(dev->uart[uart], io_base, dev->dev_regs[2 + uart][0x40] & 0x0f);
switch (dev->dev_regs[2 + uart][0xc0] & 0x03) { switch (dev->dev_regs[2 + uart][0xc0] & 0x03) {
case 0x00: case 0x00:
clock_src = 24000000.0 / 13.0; clock_src = 24000000.0 / 13.0;
break; break;
case 0x01: case 0x01:
clock_src = 24000000.0 / 12.0; clock_src = 24000000.0 / 12.0;
break; break;
case 0x02: case 0x02:
clock_src = 24000000.0 / 1.0; clock_src = 24000000.0 / 1.0;
break; break;
case 0x03: case 0x03:
clock_src = 24000000.0 / 1.625; clock_src = 24000000.0 / 1.625;
break; break;
} }
serial_set_clock_src(dev->uart[uart], clock_src); serial_set_clock_src(dev->uart[uart], clock_src);
} }
static void static void
w83977f_write(uint16_t port, uint8_t val, void *priv) w83977f_write(uint16_t port, uint8_t val, void *priv)
{ {
w83977f_t *dev = (w83977f_t *) priv; w83977f_t *dev = (w83977f_t *) priv;
uint8_t index = (port & 1) ? 0 : 1; uint8_t index = (port & 1) ? 0 : 1;
uint8_t valxor = 0; uint8_t valxor = 0;
uint8_t ld = dev->regs[7]; uint8_t ld = dev->regs[7];
if (index) { if (index) {
if ((val == 0x87) && !dev->locked) { if ((val == 0x87) && !dev->locked) {
if (dev->tries) { if (dev->tries) {
dev->locked = 1; dev->locked = 1;
dev->tries = 0; dev->tries = 0;
} else } else
dev->tries++; dev->tries++;
} else { } else {
if (dev->locked) { if (dev->locked) {
if (val == 0xaa) if (val == 0xaa)
dev->locked = 0; dev->locked = 0;
else else
dev->cur_reg = val; dev->cur_reg = val;
} else { } else {
if (dev->tries) if (dev->tries)
dev->tries = 0; dev->tries = 0;
} }
} }
return; return;
} else { } else {
if (dev->locked) { if (dev->locked) {
if (dev->rw_locked) if (dev->rw_locked)
return; return;
if (dev->cur_reg >= 0x30) { if (dev->cur_reg >= 0x30) {
valxor = val ^ dev->dev_regs[ld][dev->cur_reg - 0x30]; valxor = val ^ dev->dev_regs[ld][dev->cur_reg - 0x30];
dev->dev_regs[ld][dev->cur_reg - 0x30] = val; dev->dev_regs[ld][dev->cur_reg - 0x30] = val;
} else { } else {
valxor = val ^ dev->regs[dev->cur_reg]; valxor = val ^ dev->regs[dev->cur_reg];
dev->regs[dev->cur_reg] = val; dev->regs[dev->cur_reg] = val;
} }
} else } else
return; return;
} }
switch (dev->cur_reg) { switch (dev->cur_reg) {
case 0x02: case 0x02:
/* if (valxor & 0x02) /* if (valxor & 0x02)
softresetx86(); */ softresetx86(); */
break; break;
case 0x22: case 0x22:
if (valxor & 0x20) if (valxor & 0x20)
w83977f_serial_handler(dev, 1); w83977f_serial_handler(dev, 1);
if (valxor & 0x10) if (valxor & 0x10)
w83977f_serial_handler(dev, 0); w83977f_serial_handler(dev, 0);
if (valxor & 0x08) if (valxor & 0x08)
w83977f_lpt_handler(dev); w83977f_lpt_handler(dev);
if (valxor & 0x01) if (valxor & 0x01)
w83977f_fdc_handler(dev); w83977f_fdc_handler(dev);
break; break;
case 0x26: case 0x26:
if (valxor & 0x40) if (valxor & 0x40)
w83977f_remap(dev); w83977f_remap(dev);
if (valxor & 0x20) if (valxor & 0x20)
dev->rw_locked = (val & 0x20) ? 1 : 0; dev->rw_locked = (val & 0x20) ? 1 : 0;
break; break;
case 0x30: case 0x30:
if (valxor & 0x01) switch (ld) { if (valxor & 0x01)
case 0x00: switch (ld) {
w83977f_fdc_handler(dev); case 0x00:
break; w83977f_fdc_handler(dev);
case 0x01: break;
w83977f_lpt_handler(dev); case 0x01:
break; w83977f_lpt_handler(dev);
case 0x02: case 0x03: break;
w83977f_serial_handler(dev, ld - 2); case 0x02:
break; case 0x03:
} w83977f_serial_handler(dev, ld - 2);
break; break;
case 0x60: case 0x61: }
if (valxor & 0xff) switch (ld) { break;
case 0x00: case 0x60:
w83977f_fdc_handler(dev); case 0x61:
break; if (valxor & 0xff)
case 0x01: switch (ld) {
w83977f_lpt_handler(dev); case 0x00:
break; w83977f_fdc_handler(dev);
case 0x02: case 0x03: break;
w83977f_serial_handler(dev, ld - 2); case 0x01:
break; w83977f_lpt_handler(dev);
} break;
break; case 0x02:
case 0x70: case 0x03:
if (valxor & 0x0f) switch (ld) { w83977f_serial_handler(dev, ld - 2);
case 0x00: break;
w83977f_fdc_handler(dev); }
break; break;
case 0x01: case 0x70:
w83977f_lpt_handler(dev); if (valxor & 0x0f)
break; switch (ld) {
case 0x02: case 0x03: case 0x00:
w83977f_serial_handler(dev, ld - 2); w83977f_fdc_handler(dev);
break; break;
} case 0x01:
break; w83977f_lpt_handler(dev);
case 0xf0: break;
switch (ld) { case 0x02:
case 0x00: case 0x03:
if (dev->id == 1) w83977f_serial_handler(dev, ld - 2);
break; break;
}
break;
case 0xf0:
switch (ld) {
case 0x00:
if (dev->id == 1)
break;
if (!dev->id && (valxor & 0x20)) if (!dev->id && (valxor & 0x20))
fdc_update_drv2en(dev->fdc, (val & 0x20) ? 0 : 1); fdc_update_drv2en(dev->fdc, (val & 0x20) ? 0 : 1);
if (!dev->id && (valxor & 0x10)) if (!dev->id && (valxor & 0x10))
fdc_set_swap(dev->fdc, (val & 0x10) ? 1 : 0); fdc_set_swap(dev->fdc, (val & 0x10) ? 1 : 0);
if (!dev->id && (valxor & 0x01)) if (!dev->id && (valxor & 0x01))
fdc_update_enh_mode(dev->fdc, (val & 0x01) ? 1 : 0); fdc_update_enh_mode(dev->fdc, (val & 0x01) ? 1 : 0);
break; break;
case 0x01: case 0x01:
if (valxor & 0x07) if (valxor & 0x07)
w83977f_lpt_handler(dev); w83977f_lpt_handler(dev);
break; break;
case 0x02: case 0x03: case 0x02:
if (valxor & 0x03) case 0x03:
w83977f_serial_handler(dev, ld - 2); if (valxor & 0x03)
break; w83977f_serial_handler(dev, ld - 2);
} break;
break; }
case 0xf1: break;
switch (ld) { case 0xf1:
case 0x00: switch (ld) {
if (dev->id == 1) case 0x00:
break; if (dev->id == 1)
break;
if (!dev->id && (valxor & 0xc0)) if (!dev->id && (valxor & 0xc0))
fdc_update_boot_drive(dev->fdc, (val & 0xc0) >> 6); fdc_update_boot_drive(dev->fdc, (val & 0xc0) >> 6);
if (!dev->id && (valxor & 0x0c)) if (!dev->id && (valxor & 0x0c))
fdc_update_densel_force(dev->fdc, (val & 0x0c) >> 2); fdc_update_densel_force(dev->fdc, (val & 0x0c) >> 2);
if (!dev->id && (valxor & 0x02)) if (!dev->id && (valxor & 0x02))
fdc_set_diswr(dev->fdc, (val & 0x02) ? 1 : 0); fdc_set_diswr(dev->fdc, (val & 0x02) ? 1 : 0);
if (!dev->id && (valxor & 0x01)) if (!dev->id && (valxor & 0x01))
fdc_set_swwp(dev->fdc, (val & 0x01) ? 1 : 0); fdc_set_swwp(dev->fdc, (val & 0x01) ? 1 : 0);
break; break;
} }
break; break;
case 0xf2: case 0xf2:
switch (ld) { switch (ld) {
case 0x00: case 0x00:
if (dev->id == 1) if (dev->id == 1)
break; break;
if (!dev->id && (valxor & 0xc0)) if (!dev->id && (valxor & 0xc0))
fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6); fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6);
if (!dev->id && (valxor & 0x30)) if (!dev->id && (valxor & 0x30))
fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4); fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4);
if (!dev->id && (valxor & 0x0c)) if (!dev->id && (valxor & 0x0c))
fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2); fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2);
if (!dev->id && (valxor & 0x03)) if (!dev->id && (valxor & 0x03))
fdc_update_rwc(dev->fdc, 0, val & 0x03); fdc_update_rwc(dev->fdc, 0, val & 0x03);
break; break;
} }
break; break;
case 0xf4: case 0xf5: case 0xf6: case 0xf7: case 0xf4:
switch (ld) { case 0xf5:
case 0x00: case 0xf6:
if (dev->id == 1) case 0xf7:
break; switch (ld) {
case 0x00:
if (dev->id == 1)
break;
if (!dev->id && (valxor & 0x18)) if (!dev->id && (valxor & 0x18))
fdc_update_drvrate(dev->fdc, dev->cur_reg & 0x03, (val & 0x18) >> 3); fdc_update_drvrate(dev->fdc, dev->cur_reg & 0x03, (val & 0x18) >> 3);
break; break;
} }
break; break;
} }
} }
static uint8_t static uint8_t
w83977f_read(uint16_t port, void *priv) w83977f_read(uint16_t port, void *priv)
{ {
w83977f_t *dev = (w83977f_t *) priv; w83977f_t *dev = (w83977f_t *) priv;
uint8_t ret = 0xff; uint8_t ret = 0xff;
uint8_t index = (port & 1) ? 0 : 1; uint8_t index = (port & 1) ? 0 : 1;
uint8_t ld = dev->regs[7]; uint8_t ld = dev->regs[7];
if (dev->locked) { if (dev->locked) {
if (index) if (index)
ret = dev->cur_reg; ret = dev->cur_reg;
else { else {
if (!dev->rw_locked) { if (!dev->rw_locked) {
if (!dev->id && ((dev->cur_reg == 0xf2) && (ld == 0x00))) if (!dev->id && ((dev->cur_reg == 0xf2) && (ld == 0x00)))
ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6)); ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6));
else if (dev->cur_reg >= 0x30) else if (dev->cur_reg >= 0x30)
ret = dev->dev_regs[ld][dev->cur_reg - 0x30]; ret = dev->dev_regs[ld][dev->cur_reg - 0x30];
else else
ret = dev->regs[dev->cur_reg]; ret = dev->regs[dev->cur_reg];
} }
} }
} }
return ret; return ret;
} }
static void static void
w83977f_reset(w83977f_t *dev) w83977f_reset(w83977f_t *dev)
{ {
@@ -368,14 +366,14 @@ w83977f_reset(w83977f_t *dev)
memset(dev->regs, 0, 48); memset(dev->regs, 0, 48);
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
memset(dev->dev_regs[i], 0, 208); memset(dev->dev_regs[i], 0, 208);
if (dev->type < 2) { if (dev->type < 2) {
dev->regs[0x20] = 0x97; dev->regs[0x20] = 0x97;
dev->regs[0x21] = dev->type ? 0x73 : 0x71; dev->regs[0x21] = dev->type ? 0x73 : 0x71;
} else { } else {
dev->regs[0x20] = 0x52; dev->regs[0x20] = 0x52;
dev->regs[0x21] = 0xf0; dev->regs[0x21] = 0xf0;
} }
dev->regs[0x22] = 0xff; dev->regs[0x22] = 0xff;
dev->regs[0x24] = dev->type ? 0x84 : 0xa4; dev->regs[0x24] = dev->type ? 0x84 : 0xa4;
@@ -385,137 +383,159 @@ w83977f_reset(w83977f_t *dev)
/* Logical Device 0 (FDC) */ /* Logical Device 0 (FDC) */
dev->dev_regs[0][0x00] = 0x01; dev->dev_regs[0][0x00] = 0x01;
if (!dev->type) if (!dev->type)
dev->dev_regs[0][0x01] = 0x02; dev->dev_regs[0][0x01] = 0x02;
if (next_id == 1) { if (next_id == 1) {
dev->dev_regs[0][0x30] = 0x03; dev->dev_regs[0][0x31] = 0x70; dev->dev_regs[0][0x30] = 0x03;
dev->dev_regs[0][0x31] = 0x70;
} else { } else {
dev->dev_regs[0][0x30] = 0x03; dev->dev_regs[0][0x31] = 0xf0; dev->dev_regs[0][0x30] = 0x03;
dev->dev_regs[0][0x31] = 0xf0;
} }
dev->dev_regs[0][0x40] = 0x06; dev->dev_regs[0][0x40] = 0x06;
if (!dev->type) if (!dev->type)
dev->dev_regs[0][0x41] = 0x02; /* Read-only */ dev->dev_regs[0][0x41] = 0x02; /* Read-only */
dev->dev_regs[0][0x44] = 0x02; dev->dev_regs[0][0x44] = 0x02;
dev->dev_regs[0][0xc0] = 0x0e; dev->dev_regs[0][0xc0] = 0x0e;
/* Logical Device 1 (Parallel Port) */ /* Logical Device 1 (Parallel Port) */
dev->dev_regs[1][0x00] = 0x01; dev->dev_regs[1][0x00] = 0x01;
if (!dev->type) if (!dev->type)
dev->dev_regs[1][0x01] = 0x02; dev->dev_regs[1][0x01] = 0x02;
if (next_id == 1) { if (next_id == 1) {
dev->dev_regs[1][0x30] = 0x02; dev->dev_regs[1][0x31] = 0x78; dev->dev_regs[1][0x30] = 0x02;
dev->dev_regs[1][0x40] = 0x05; dev->dev_regs[1][0x31] = 0x78;
dev->dev_regs[1][0x40] = 0x05;
} else { } else {
dev->dev_regs[1][0x30] = 0x03; dev->dev_regs[1][0x31] = 0x78; dev->dev_regs[1][0x30] = 0x03;
dev->dev_regs[1][0x40] = 0x07; dev->dev_regs[1][0x31] = 0x78;
dev->dev_regs[1][0x40] = 0x07;
} }
if (!dev->type) if (!dev->type)
dev->dev_regs[1][0x41] = 0x01 /*0x02*/; /* Read-only */ dev->dev_regs[1][0x41] = 0x01 /*0x02*/; /* Read-only */
dev->dev_regs[1][0x44] = 0x04; dev->dev_regs[1][0x44] = 0x04;
dev->dev_regs[1][0xc0] = 0x3c; /* The datasheet says default is 3f, but also default is printer mode. */ dev->dev_regs[1][0xc0] = 0x3c; /* The datasheet says default is 3f, but also default is printer mode. */
/* Logical Device 2 (UART A) */ /* Logical Device 2 (UART A) */
dev->dev_regs[2][0x00] = 0x01; dev->dev_regs[2][0x00] = 0x01;
if (!dev->type) if (!dev->type)
dev->dev_regs[2][0x01] = 0x02; dev->dev_regs[2][0x01] = 0x02;
if (next_id == 1) { if (next_id == 1) {
dev->dev_regs[2][0x30] = 0x03; dev->dev_regs[2][0x31] = 0xe8; dev->dev_regs[2][0x30] = 0x03;
dev->dev_regs[2][0x31] = 0xe8;
} else { } else {
dev->dev_regs[2][0x30] = 0x03; dev->dev_regs[2][0x31] = 0xf8; dev->dev_regs[2][0x30] = 0x03;
dev->dev_regs[2][0x31] = 0xf8;
} }
dev->dev_regs[2][0x40] = 0x04; dev->dev_regs[2][0x40] = 0x04;
if (!dev->type) if (!dev->type)
dev->dev_regs[2][0x41] = 0x02; /* Read-only */ dev->dev_regs[2][0x41] = 0x02; /* Read-only */
/* Logical Device 3 (UART B) */ /* Logical Device 3 (UART B) */
dev->dev_regs[3][0x00] = 0x01; dev->dev_regs[3][0x00] = 0x01;
if (!dev->type) if (!dev->type)
dev->dev_regs[3][0x01] = 0x02; dev->dev_regs[3][0x01] = 0x02;
if (next_id == 1) { if (next_id == 1) {
dev->dev_regs[3][0x30] = 0x02; dev->dev_regs[3][0x31] = 0xe8; dev->dev_regs[3][0x30] = 0x02;
dev->dev_regs[3][0x31] = 0xe8;
} else { } else {
dev->dev_regs[3][0x30] = 0x02; dev->dev_regs[3][0x31] = 0xf8; dev->dev_regs[3][0x30] = 0x02;
dev->dev_regs[3][0x31] = 0xf8;
} }
dev->dev_regs[3][0x40] = 0x03; dev->dev_regs[3][0x40] = 0x03;
if (!dev->type) if (!dev->type)
dev->dev_regs[3][0x41] = 0x02; /* Read-only */ dev->dev_regs[3][0x41] = 0x02; /* Read-only */
/* Logical Device 4 (RTC) */ /* Logical Device 4 (RTC) */
if (!dev->type) { if (!dev->type) {
dev->dev_regs[4][0x00] = 0x01; dev->dev_regs[4][0x00] = 0x01;
dev->dev_regs[4][0x01] = 0x02; dev->dev_regs[4][0x01] = 0x02;
dev->dev_regs[4][0x30] = 0x00; dev->dev_regs[4][0x31] = 0x70; dev->dev_regs[4][0x30] = 0x00;
dev->dev_regs[4][0x40] = 0x08; dev->dev_regs[4][0x31] = 0x70;
dev->dev_regs[4][0x41] = 0x02; /* Read-only */ dev->dev_regs[4][0x40] = 0x08;
dev->dev_regs[4][0x41] = 0x02; /* Read-only */
} }
/* Logical Device 5 (KBC) */ /* Logical Device 5 (KBC) */
dev->dev_regs[5][0x00] = 0x01; dev->dev_regs[5][0x00] = 0x01;
if (!dev->type) if (!dev->type)
dev->dev_regs[5][0x01] = 0x02; dev->dev_regs[5][0x01] = 0x02;
dev->dev_regs[5][0x30] = 0x00; dev->dev_regs[5][0x31] = 0x60; dev->dev_regs[5][0x30] = 0x00;
dev->dev_regs[5][0x32] = 0x00; dev->dev_regs[5][0x33] = 0x64; dev->dev_regs[5][0x31] = 0x60;
dev->dev_regs[5][0x32] = 0x00;
dev->dev_regs[5][0x33] = 0x64;
dev->dev_regs[5][0x40] = 0x01; dev->dev_regs[5][0x40] = 0x01;
if (!dev->type) if (!dev->type)
dev->dev_regs[5][0x41] = 0x02; /* Read-only */ dev->dev_regs[5][0x41] = 0x02; /* Read-only */
dev->dev_regs[5][0x42] = 0x0c; dev->dev_regs[5][0x42] = 0x0c;
if (!dev->type) if (!dev->type)
dev->dev_regs[5][0x43] = 0x02; /* Read-only? */ dev->dev_regs[5][0x43] = 0x02; /* Read-only? */
dev->dev_regs[5][0xc0] = dev->type ? 0x83 : 0x40; dev->dev_regs[5][0xc0] = dev->type ? 0x83 : 0x40;
/* Logical Device 6 (IR) = UART C */ /* Logical Device 6 (IR) = UART C */
if (!dev->type) { if (!dev->type) {
dev->dev_regs[6][0x01] = 0x02; dev->dev_regs[6][0x01] = 0x02;
dev->dev_regs[6][0x41] = 0x02; /* Read-only */ dev->dev_regs[6][0x41] = 0x02; /* Read-only */
dev->dev_regs[6][0x44] = 0x04; dev->dev_regs[6][0x44] = 0x04;
dev->dev_regs[6][0x45] = 0x04; dev->dev_regs[6][0x45] = 0x04;
} }
/* Logical Device 7 (Auxiliary I/O Part I) */ /* Logical Device 7 (Auxiliary I/O Part I) */
if (!dev->type) if (!dev->type)
dev->dev_regs[7][0x01] = 0x02; dev->dev_regs[7][0x01] = 0x02;
if (!dev->type) if (!dev->type)
dev->dev_regs[7][0x41] = 0x02; /* Read-only */ dev->dev_regs[7][0x41] = 0x02; /* Read-only */
if (!dev->type) if (!dev->type)
dev->dev_regs[7][0x43] = 0x02; /* Read-only? */ dev->dev_regs[7][0x43] = 0x02; /* Read-only? */
dev->dev_regs[7][0xb0] = 0x01; dev->dev_regs[7][0xb1] = 0x01; dev->dev_regs[7][0xb0] = 0x01;
dev->dev_regs[7][0xb2] = 0x01; dev->dev_regs[7][0xb3] = 0x01; dev->dev_regs[7][0xb1] = 0x01;
dev->dev_regs[7][0xb4] = 0x01; dev->dev_regs[7][0xb5] = 0x01; dev->dev_regs[7][0xb2] = 0x01;
dev->dev_regs[7][0xb3] = 0x01;
dev->dev_regs[7][0xb4] = 0x01;
dev->dev_regs[7][0xb5] = 0x01;
dev->dev_regs[7][0xb6] = 0x01; dev->dev_regs[7][0xb6] = 0x01;
if (dev->type) if (dev->type)
dev->dev_regs[7][0xb7] = 0x01; dev->dev_regs[7][0xb7] = 0x01;
/* Logical Device 8 (Auxiliary I/O Part II) */ /* Logical Device 8 (Auxiliary I/O Part II) */
if (!dev->type) if (!dev->type)
dev->dev_regs[8][0x01] = 0x02; dev->dev_regs[8][0x01] = 0x02;
if (!dev->type) if (!dev->type)
dev->dev_regs[8][0x41] = 0x02; /* Read-only */ dev->dev_regs[8][0x41] = 0x02; /* Read-only */
if (!dev->type) if (!dev->type)
dev->dev_regs[8][0x43] = 0x02; /* Read-only? */ dev->dev_regs[8][0x43] = 0x02; /* Read-only? */
dev->dev_regs[8][0xb8] = 0x01; dev->dev_regs[8][0xb9] = 0x01; dev->dev_regs[8][0xb8] = 0x01;
dev->dev_regs[8][0xba] = 0x01; dev->dev_regs[8][0xbb] = 0x01; dev->dev_regs[8][0xb9] = 0x01;
dev->dev_regs[8][0xbc] = 0x01; dev->dev_regs[8][0xbd] = 0x01; dev->dev_regs[8][0xba] = 0x01;
dev->dev_regs[8][0xbe] = 0x01; dev->dev_regs[8][0xbf] = 0x01; dev->dev_regs[8][0xbb] = 0x01;
dev->dev_regs[8][0xbc] = 0x01;
dev->dev_regs[8][0xbd] = 0x01;
dev->dev_regs[8][0xbe] = 0x01;
dev->dev_regs[8][0xbf] = 0x01;
/* Logical Device 9 (Auxiliary I/O Part III) */ /* Logical Device 9 (Auxiliary I/O Part III) */
if (dev->type) { if (dev->type) {
dev->dev_regs[9][0xb0] = 0x01; dev->dev_regs[9][0xb1] = 0x01; dev->dev_regs[9][0xb0] = 0x01;
dev->dev_regs[9][0xb2] = 0x01; dev->dev_regs[9][0xb3] = 0x01; dev->dev_regs[9][0xb1] = 0x01;
dev->dev_regs[9][0xb4] = 0x01; dev->dev_regs[9][0xb5] = 0x01; dev->dev_regs[9][0xb2] = 0x01;
dev->dev_regs[9][0xb6] = 0x01; dev->dev_regs[9][0xb7] = 0x01; dev->dev_regs[9][0xb3] = 0x01;
dev->dev_regs[9][0xb4] = 0x01;
dev->dev_regs[9][0xb5] = 0x01;
dev->dev_regs[9][0xb6] = 0x01;
dev->dev_regs[9][0xb7] = 0x01;
dev->dev_regs[10][0xc0] = 0x8f; dev->dev_regs[10][0xc0] = 0x8f;
} }
if (dev->id == 1) { if (dev->id == 1) {
serial_setup(dev->uart[0], COM3_ADDR, COM3_IRQ); serial_setup(dev->uart[0], COM3_ADDR, COM3_IRQ);
serial_setup(dev->uart[1], COM4_ADDR, COM4_IRQ); serial_setup(dev->uart[1], COM4_ADDR, COM4_IRQ);
} else { } else {
fdc_reset(dev->fdc); fdc_reset(dev->fdc);
serial_setup(dev->uart[0], COM1_ADDR, COM1_IRQ); serial_setup(dev->uart[0], COM1_ADDR, COM1_IRQ);
serial_setup(dev->uart[1], COM2_ADDR, COM2_IRQ); serial_setup(dev->uart[1], COM2_ADDR, COM2_IRQ);
w83977f_fdc_handler(dev); w83977f_fdc_handler(dev);
} }
w83977f_lpt_handler(dev); w83977f_lpt_handler(dev);
@@ -524,11 +544,10 @@ w83977f_reset(w83977f_t *dev)
w83977f_remap(dev); w83977f_remap(dev);
dev->locked = 0; dev->locked = 0;
dev->rw_locked = 0; dev->rw_locked = 0;
} }
static void static void
w83977f_close(void *priv) w83977f_close(void *priv)
{ {
@@ -539,22 +558,21 @@ w83977f_close(void *priv)
free(dev); free(dev);
} }
static void * static void *
w83977f_init(const device_t *info) w83977f_init(const device_t *info)
{ {
w83977f_t *dev = (w83977f_t *) malloc(sizeof(w83977f_t)); w83977f_t *dev = (w83977f_t *) malloc(sizeof(w83977f_t));
memset(dev, 0, sizeof(w83977f_t)); memset(dev, 0, sizeof(w83977f_t));
dev->type = info->local & 0x0f; dev->type = info->local & 0x0f;
dev->hefras = info->local & 0x40; dev->hefras = info->local & 0x40;
dev->id = next_id; dev->id = next_id;
if (next_id == 1) if (next_id == 1)
dev->hefras ^= 0x40; dev->hefras ^= 0x40;
else else
dev->fdc = device_add(&fdc_at_smc_device); dev->fdc = device_add(&fdc_at_smc_device);
dev->uart[0] = device_add_inst(&ns16550_device, (next_id << 1) + 1); dev->uart[0] = device_add_inst(&ns16550_device, (next_id << 1) + 1);
dev->uart[1] = device_add_inst(&ns16550_device, (next_id << 1) + 2); dev->uart[1] = device_add_inst(&ns16550_device, (next_id << 1) + 2);
@@ -567,71 +585,71 @@ w83977f_init(const device_t *info)
} }
const device_t w83977f_device = { const device_t w83977f_device = {
.name = "Winbond W83977F Super I/O", .name = "Winbond W83977F Super I/O",
.internal_name = "w83977f", .internal_name = "w83977f",
.flags = 0, .flags = 0,
.local = 0, .local = 0,
.init = w83977f_init, .init = w83977f_init,
.close = w83977f_close, .close = w83977f_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t w83977f_370_device = { const device_t w83977f_370_device = {
.name = "Winbond W83977F Super I/O (Port 370h)", .name = "Winbond W83977F Super I/O (Port 370h)",
.internal_name = "w83977f_370", .internal_name = "w83977f_370",
.flags = 0, .flags = 0,
.local = 0x40, .local = 0x40,
.init = w83977f_init, .init = w83977f_init,
.close = w83977f_close, .close = w83977f_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t w83977tf_device = { const device_t w83977tf_device = {
.name = "Winbond W83977TF Super I/O", .name = "Winbond W83977TF Super I/O",
.internal_name = "w83977tf", .internal_name = "w83977tf",
.flags = 0, .flags = 0,
.local = 1, .local = 1,
.init = w83977f_init, .init = w83977f_init,
.close = w83977f_close, .close = w83977f_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t w83977ef_device = { const device_t w83977ef_device = {
.name = "Winbond W83977TF Super I/O", .name = "Winbond W83977TF Super I/O",
.internal_name = "w83977ef", .internal_name = "w83977ef",
.flags = 0, .flags = 0,
.local = 2, .local = 2,
.init = w83977f_init, .init = w83977f_init,
.close = w83977f_close, .close = w83977f_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };
const device_t w83977ef_370_device = { const device_t w83977ef_370_device = {
.name = "Winbond W83977TF Super I/O (Port 370h)", .name = "Winbond W83977TF Super I/O (Port 370h)",
.internal_name = "w83977ef_370", .internal_name = "w83977ef_370",
.flags = 0, .flags = 0,
.local = 0x42, .local = 0x42,
.init = w83977f_init, .init = w83977f_init,
.close = w83977f_close, .close = w83977f_close,
.reset = NULL, .reset = NULL,
{ .available = NULL }, { .available = NULL },
.speed_changed = NULL, .speed_changed = NULL,
.force_redraw = NULL, .force_redraw = NULL,
.config = NULL .config = NULL
}; };