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

View File

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

View File

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

View File

@@ -27,12 +27,10 @@
#include <86box/fdc.h>
#include <86box/sio.h>
typedef struct {
uint8_t regs[2];
} sio_detect_t;
static void
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;
}
static uint8_t
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]*/;
}
static void
sio_detect_close(void *priv)
{
@@ -65,7 +61,6 @@ sio_detect_close(void *priv)
free(dev);
}
static void *
sio_detect_init(const device_t *info)
{
@@ -75,48 +70,47 @@ sio_detect_init(const device_t *info)
device_add(&fdc_at_smc_device);
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
return dev;
}
const device_t sio_detect_device = {
.name = "Super I/O Detection Helper",
.name = "Super I/O Detection Helper",
.internal_name = "sio_detect",
.flags = 0,
.local = 0,
.init = sio_detect_init,
.close = sio_detect_close,
.reset = NULL,
.flags = 0,
.local = 0,
.init = sio_detect_init,
.close = sio_detect_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};

View File

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

View File

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

View File

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

View File

@@ -35,207 +35,197 @@
#include <86box/fdc.h>
#include <86box/sio.h>
typedef struct {
uint8_t max_reg, chip_id,
tries, has_ide,
regs[16];
tries, has_ide,
regs[16];
int cur_reg,
com3_addr, com4_addr;
fdc_t *fdc;
com3_addr, com4_addr;
fdc_t *fdc;
serial_t *uart[2];
} fdc37c6xx_t;
static void
set_com34_addr(fdc37c6xx_t *dev)
{
switch (dev->regs[1] & 0x60) {
case 0x00:
dev->com3_addr = 0x338;
dev->com4_addr = 0x238;
break;
case 0x20:
dev->com3_addr = COM3_ADDR;
dev->com4_addr = COM4_ADDR;
break;
case 0x40:
dev->com3_addr = COM3_ADDR;
dev->com4_addr = 0x2e0;
break;
case 0x60:
dev->com3_addr = 0x220;
dev->com4_addr = 0x228;
break;
case 0x00:
dev->com3_addr = 0x338;
dev->com4_addr = 0x238;
break;
case 0x20:
dev->com3_addr = COM3_ADDR;
dev->com4_addr = COM4_ADDR;
break;
case 0x40:
dev->com3_addr = COM3_ADDR;
dev->com4_addr = 0x2e0;
break;
case 0x60:
dev->com3_addr = 0x220;
dev->com4_addr = 0x228;
break;
}
}
static void
set_serial_addr(fdc37c6xx_t *dev, int port)
{
uint8_t shift = (port << 2);
double clock_src = 24000000.0 / 13.0;
uint8_t shift = (port << 2);
double clock_src = 24000000.0 / 13.0;
if (dev->regs[4] & (1 << (4 + port)))
clock_src = 24000000.0 / 12.0;
clock_src = 24000000.0 / 12.0;
serial_remove(dev->uart[port]);
if (dev->regs[2] & (4 << shift)) {
switch ((dev->regs[2] >> shift) & 3) {
case 0:
serial_setup(dev->uart[port], COM1_ADDR, COM1_IRQ);
break;
case 1:
serial_setup(dev->uart[port], COM2_ADDR, COM2_IRQ);
break;
case 2:
serial_setup(dev->uart[port], dev->com3_addr, COM3_IRQ);
break;
case 3:
serial_setup(dev->uart[port], dev->com4_addr, COM4_IRQ);
break;
}
switch ((dev->regs[2] >> shift) & 3) {
case 0:
serial_setup(dev->uart[port], COM1_ADDR, COM1_IRQ);
break;
case 1:
serial_setup(dev->uart[port], COM2_ADDR, COM2_IRQ);
break;
case 2:
serial_setup(dev->uart[port], dev->com3_addr, COM3_IRQ);
break;
case 3:
serial_setup(dev->uart[port], dev->com4_addr, COM4_IRQ);
break;
}
}
serial_set_clock_src(dev->uart[port], clock_src);
}
static void
lpt1_handler(fdc37c6xx_t *dev)
{
lpt1_remove();
switch (dev->regs[1] & 3) {
case 1:
lpt1_init(LPT_MDA_ADDR);
lpt1_irq(7);
break;
case 2:
lpt1_init(LPT1_ADDR);
lpt1_irq(7 /*5*/);
break;
case 3:
lpt1_init(LPT2_ADDR);
lpt1_irq(7 /*5*/);
break;
case 1:
lpt1_init(LPT_MDA_ADDR);
lpt1_irq(7);
break;
case 2:
lpt1_init(LPT1_ADDR);
lpt1_irq(7 /*5*/);
break;
case 3:
lpt1_init(LPT2_ADDR);
lpt1_irq(7 /*5*/);
break;
}
}
static void
fdc_handler(fdc37c6xx_t *dev)
{
fdc_remove(dev->fdc);
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
ide_handler(fdc37c6xx_t *dev)
{
/* TODO: Make an ide_disable(channel) and ide_enable(channel) so we can simplify this. */
if (dev->has_ide == 2) {
ide_sec_disable();
ide_set_base(1, (dev->regs[0x05] & 0x02) ? 0x170 : 0x1f0);
ide_set_side(1, (dev->regs[0x05] & 0x02) ? 0x376 : 0x3f6);
if (dev->regs[0x00] & 0x01)
ide_sec_enable();
ide_sec_disable();
ide_set_base(1, (dev->regs[0x05] & 0x02) ? 0x170 : 0x1f0);
ide_set_side(1, (dev->regs[0x05] & 0x02) ? 0x376 : 0x3f6);
if (dev->regs[0x00] & 0x01)
ide_sec_enable();
} else if (dev->has_ide == 1) {
ide_pri_disable();
ide_set_base(0, (dev->regs[0x05] & 0x02) ? 0x170 : 0x1f0);
ide_set_side(0, (dev->regs[0x05] & 0x02) ? 0x376 : 0x3f6);
if (dev->regs[0x00] & 0x01)
ide_pri_enable();
ide_pri_disable();
ide_set_base(0, (dev->regs[0x05] & 0x02) ? 0x170 : 0x1f0);
ide_set_side(0, (dev->regs[0x05] & 0x02) ? 0x376 : 0x3f6);
if (dev->regs[0x00] & 0x01)
ide_pri_enable();
}
}
static void
fdc37c6xx_write(uint16_t port, uint8_t val, void *priv)
{
fdc37c6xx_t *dev = (fdc37c6xx_t *) priv;
uint8_t valxor = 0;
fdc37c6xx_t *dev = (fdc37c6xx_t *) priv;
uint8_t valxor = 0;
if (dev->tries == 2) {
if (port == FDC_PRIMARY_ADDR) {
if (val == 0xaa)
dev->tries = 0;
else
dev->cur_reg = val;
} else {
if (dev->cur_reg > dev->max_reg)
return;
if (port == FDC_PRIMARY_ADDR) {
if (val == 0xaa)
dev->tries = 0;
else
dev->cur_reg = val;
} else {
if (dev->cur_reg > dev->max_reg)
return;
valxor = val ^ dev->regs[dev->cur_reg];
dev->regs[dev->cur_reg] = val;
valxor = val ^ dev->regs[dev->cur_reg];
dev->regs[dev->cur_reg] = val;
switch(dev->cur_reg) {
case 0:
if (dev->has_ide && (valxor & 0x01))
ide_handler(dev);
if (valxor & 0x10)
fdc_handler(dev);
break;
case 1:
if (valxor & 3)
lpt1_handler(dev);
if (valxor & 0x60) {
set_com34_addr(dev);
set_serial_addr(dev, 0);
set_serial_addr(dev, 1);
}
break;
case 2:
if (valxor & 7)
set_serial_addr(dev, 0);
if (valxor & 0x70)
set_serial_addr(dev, 1);
break;
case 3:
if (valxor & 2)
fdc_update_enh_mode(dev->fdc, (dev->regs[3] & 2) ? 1 : 0);
break;
case 4:
if (valxor & 0x10)
set_serial_addr(dev, 0);
if (valxor & 0x20)
set_serial_addr(dev, 1);
break;
case 5:
if (valxor & 0x01)
fdc_handler(dev);
if (dev->has_ide && (valxor & 0x02))
ide_handler(dev);
if (valxor & 0x18)
fdc_update_densel_force(dev->fdc, (dev->regs[5] & 0x18) >> 3);
if (valxor & 0x20)
fdc_set_swap(dev->fdc, (dev->regs[5] & 0x20) >> 5);
break;
}
}
switch (dev->cur_reg) {
case 0:
if (dev->has_ide && (valxor & 0x01))
ide_handler(dev);
if (valxor & 0x10)
fdc_handler(dev);
break;
case 1:
if (valxor & 3)
lpt1_handler(dev);
if (valxor & 0x60) {
set_com34_addr(dev);
set_serial_addr(dev, 0);
set_serial_addr(dev, 1);
}
break;
case 2:
if (valxor & 7)
set_serial_addr(dev, 0);
if (valxor & 0x70)
set_serial_addr(dev, 1);
break;
case 3:
if (valxor & 2)
fdc_update_enh_mode(dev->fdc, (dev->regs[3] & 2) ? 1 : 0);
break;
case 4:
if (valxor & 0x10)
set_serial_addr(dev, 0);
if (valxor & 0x20)
set_serial_addr(dev, 1);
break;
case 5:
if (valxor & 0x01)
fdc_handler(dev);
if (dev->has_ide && (valxor & 0x02))
ide_handler(dev);
if (valxor & 0x18)
fdc_update_densel_force(dev->fdc, (dev->regs[5] & 0x18) >> 3);
if (valxor & 0x20)
fdc_set_swap(dev->fdc, (dev->regs[5] & 0x20) >> 5);
break;
}
}
} else if ((port == FDC_PRIMARY_ADDR) && (val == 0x55))
dev->tries++;
dev->tries++;
}
static uint8_t
fdc37c6xx_read(uint16_t port, void *priv)
{
fdc37c6xx_t *dev = (fdc37c6xx_t *) priv;
uint8_t ret = 0x00;
uint8_t ret = 0x00;
if (dev->tries == 2) {
if (port == 0x3f1)
ret = dev->regs[dev->cur_reg];
if (port == 0x3f1)
ret = dev->regs[dev->cur_reg];
}
return ret;
}
static void
fdc37c6xx_reset(fdc37c6xx_t *dev)
{
@@ -258,18 +248,20 @@ fdc37c6xx_reset(fdc37c6xx_t *dev)
memset(dev->regs, 0, 16);
switch (dev->chip_id) {
case 0x63: case 0x65:
dev->max_reg = 0x0f;
dev->regs[0x0] = 0x3b;
break;
case 0x64: case 0x66:
dev->max_reg = 0x0f;
dev->regs[0x0] = 0x2b;
break;
default:
dev->max_reg = (dev->chip_id >= 0x61) ? 0x03 : 0x02;
dev->regs[0x0] = 0x3f;
break;
case 0x63:
case 0x65:
dev->max_reg = 0x0f;
dev->regs[0x0] = 0x3b;
break;
case 0x64:
case 0x66:
dev->max_reg = 0x0f;
dev->regs[0x0] = 0x2b;
break;
default:
dev->max_reg = (dev->chip_id >= 0x61) ? 0x03 : 0x02;
dev->regs[0x0] = 0x3f;
break;
}
dev->regs[0x1] = 0x9f;
@@ -277,12 +269,12 @@ fdc37c6xx_reset(fdc37c6xx_t *dev)
dev->regs[0x3] = 0x78;
if (dev->chip_id >= 0x63) {
dev->regs[0x6] = 0xff;
dev->regs[0xd] = dev->chip_id;
if (dev->chip_id >= 0x65)
dev->regs[0xe] = 0x02;
else
dev->regs[0xe] = 0x01;
dev->regs[0x6] = 0xff;
dev->regs[0xd] = dev->chip_id;
if (dev->chip_id >= 0x65)
dev->regs[0xe] = 0x02;
else
dev->regs[0xe] = 0x01;
}
set_serial_addr(dev, 0);
@@ -293,10 +285,9 @@ fdc37c6xx_reset(fdc37c6xx_t *dev)
fdc_handler(dev);
if (dev->has_ide)
ide_handler(dev);
ide_handler(dev);
}
static void
fdc37c6xx_close(void *priv)
{
@@ -305,7 +296,6 @@ fdc37c6xx_close(void *priv)
free(dev);
}
static void *
fdc37c6xx_init(const device_t *info)
{
@@ -318,15 +308,15 @@ fdc37c6xx_init(const device_t *info)
dev->has_ide = (info->local >> 8) & 0xff;
if (dev->chip_id >= 0x63) {
dev->uart[0] = device_add_inst(&ns16550_device, 1);
dev->uart[1] = device_add_inst(&ns16550_device, 2);
dev->uart[0] = device_add_inst(&ns16550_device, 1);
dev->uart[1] = device_add_inst(&ns16550_device, 2);
} else {
dev->uart[0] = device_add_inst(&ns16450_device, 1);
dev->uart[1] = device_add_inst(&ns16450_device, 2);
dev->uart[0] = device_add_inst(&ns16450_device, 1);
dev->uart[1] = device_add_inst(&ns16450_device, 2);
}
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);
@@ -336,127 +326,127 @@ fdc37c6xx_init(const device_t *info)
/* The three appear to differ only in the chip ID, if I
understood their datasheets correctly. */
const device_t fdc37c651_device = {
.name = "SMC FDC37C651 Super I/O",
.name = "SMC FDC37C651 Super I/O",
.internal_name = "fdc37c651",
.flags = 0,
.local = 0x51,
.init = fdc37c6xx_init,
.close = fdc37c6xx_close,
.reset = NULL,
.flags = 0,
.local = 0x51,
.init = fdc37c6xx_init,
.close = fdc37c6xx_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
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",
.flags = 0,
.local = 0x151,
.init = fdc37c6xx_init,
.close = fdc37c6xx_close,
.reset = NULL,
.flags = 0,
.local = 0x151,
.init = fdc37c6xx_init,
.close = fdc37c6xx_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
const device_t fdc37c661_device = {
.name = "SMC FDC37C661 Super I/O",
.name = "SMC FDC37C661 Super I/O",
.internal_name = "fdc37c661",
.flags = 0,
.local = 0x61,
.init = fdc37c6xx_init,
.close = fdc37c6xx_close,
.reset = NULL,
.flags = 0,
.local = 0x61,
.init = fdc37c6xx_init,
.close = fdc37c6xx_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
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",
.flags = 0,
.local = 0x161,
.init = fdc37c6xx_init,
.close = fdc37c6xx_close,
.reset = NULL,
.flags = 0,
.local = 0x161,
.init = fdc37c6xx_init,
.close = fdc37c6xx_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
const device_t fdc37c663_device = {
.name = "SMC FDC37C663 Super I/O",
.name = "SMC FDC37C663 Super I/O",
.internal_name = "fdc37c663",
.flags = 0,
.local = 0x63,
.init = fdc37c6xx_init,
.close = fdc37c6xx_close,
.reset = NULL,
.flags = 0,
.local = 0x63,
.init = fdc37c6xx_init,
.close = fdc37c6xx_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
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",
.flags = 0,
.local = 0x163,
.init = fdc37c6xx_init,
.close = fdc37c6xx_close,
.reset = NULL,
.flags = 0,
.local = 0x163,
.init = fdc37c6xx_init,
.close = fdc37c6xx_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
const device_t fdc37c665_device = {
.name = "SMC FDC37C665 Super I/O",
.name = "SMC FDC37C665 Super I/O",
.internal_name = "fdc37c665",
.flags = 0,
.local = 0x65,
.init = fdc37c6xx_init,
.close = fdc37c6xx_close,
.reset = NULL,
.flags = 0,
.local = 0x65,
.init = fdc37c6xx_init,
.close = fdc37c6xx_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
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",
.flags = 0,
.local = 0x265,
.init = fdc37c6xx_init,
.close = fdc37c6xx_close,
.reset = NULL,
.flags = 0,
.local = 0x265,
.init = fdc37c6xx_init,
.close = fdc37c6xx_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
const device_t fdc37c666_device = {
.name = "SMC FDC37C666 Super I/O",
.name = "SMC FDC37C666 Super I/O",
.internal_name = "fdc37c666",
.flags = 0,
.local = 0x66,
.init = fdc37c6xx_init,
.close = fdc37c6xx_close,
.reset = NULL,
.flags = 0,
.local = 0x66,
.init = fdc37c6xx_init,
.close = fdc37c6xx_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = 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/sio.h>
#define SIO_INDEX_PORT dev->sio_index_port
#define INDEX dev->index
#define SIO_INDEX_PORT dev->sio_index_port
#define INDEX dev->index
/* Current Logical Device Number */
#define CURRENT_LOGICAL_DEVICE dev->regs[0x07]
#define CURRENT_LOGICAL_DEVICE dev->regs[0x07]
/* Global Device Configuration */
#define ENABLED(ld) dev->device_regs[ld][0x30]
#define BASE_ADDRESS(ld) ((dev->device_regs[ld][0x60] << 8) | \
(dev->device_regs[ld][0x61]))
#define IRQ(ld) dev->device_regs[ld][0x70]
#define DMA(ld) dev->device_regs[ld][0x74]
#define ENABLED(ld) dev->device_regs[ld][0x30]
#define BASE_ADDRESS(ld) ((dev->device_regs[ld][0x60] << 8) | (dev->device_regs[ld][0x61]))
#define IRQ(ld) dev->device_regs[ld][0x70]
#define DMA(ld) dev->device_regs[ld][0x74]
/* Miscellaneous Chip Functionality */
#define SOFT_RESET (val & 0x01)
#define POWER_CONTROL dev->regs[0x22]
#define SOFT_RESET (val & 0x01)
#define POWER_CONTROL dev->regs[0x22]
#ifdef ENABLE_FDC37M60X_LOG
int fdc37m60x_do_log = ENABLE_FDC37M60X_LOG;
@@ -57,117 +55,120 @@ fdc37m60x_log(const char *fmt, ...)
{
va_list ap;
if (fdc37m60x_do_log)
{
if (fdc37m60x_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define fdc37m60x_log(fmt, ...)
# define fdc37m60x_log(fmt, ...)
#endif
typedef struct
{
uint8_t index, regs[256], device_regs[10][256], cfg_lock, ide_function;
uint16_t sio_index_port;
uint8_t index, regs[256], device_regs[10][256], cfg_lock, ide_function;
uint16_t sio_index_port;
fdc_t * fdc;
serial_t * uart[2];
fdc_t *fdc;
serial_t *uart[2];
} fdc37m60x_t;
static void fdc37m60x_fdc_handler(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_logical_device_handler(fdc37m60x_t *dev);
static void fdc37m60x_reset(void *priv);
static void fdc37m60x_fdc_handler(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_logical_device_handler(fdc37m60x_t *dev);
static void fdc37m60x_reset(void *priv);
static void
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 (!dev->cfg_lock) {
switch (INDEX) {
/* Global Configuration */
case 0x02:
dev->regs[INDEX] = val;
if (SOFT_RESET)
fdc37m60x_reset(dev);
break;
if (!dev->cfg_lock) {
switch (INDEX) {
/* Global Configuration */
case 0x02:
dev->regs[INDEX] = val;
if (SOFT_RESET)
fdc37m60x_reset(dev);
break;
case 0x07:
CURRENT_LOGICAL_DEVICE = val;
break;
case 0x07:
CURRENT_LOGICAL_DEVICE = val;
break;
case 0x22:
POWER_CONTROL = val & 0x3f;
break;
case 0x22:
POWER_CONTROL = val & 0x3f;
break;
case 0x23:
dev->regs[INDEX] = val & 0x3f;
break;
case 0x23:
dev->regs[INDEX] = val & 0x3f;
break;
case 0x24:
dev->regs[INDEX] = val & 0x4e;
break;
case 0x24:
dev->regs[INDEX] = val & 0x4e;
break;
case 0x2b: case 0x2c: case 0x2d: case 0x2e:
case 0x2f:
dev->regs[INDEX] = val;
break;
case 0x2b:
case 0x2c:
case 0x2d:
case 0x2e:
case 0x2f:
dev->regs[INDEX] = val;
break;
/* Device Configuration */
case 0x30:
case 0x60: case 0x61:
case 0x70:
case 0x74:
case 0xf0: case 0xf1: case 0xf2: case 0xf3:
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;
}
/* Device Configuration */
case 0x30:
case 0x60:
case 0x61:
case 0x70:
case 0x74:
case 0xf0:
case 0xf1:
case 0xf2:
case 0xf3:
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 {
/* Enter/Escape Configuration Mode */
if (val == 0x55)
dev->cfg_lock = 0;
else if (!dev->cfg_lock && (val == 0xaa))
dev->cfg_lock = 1;
else if (!dev->cfg_lock)
INDEX = val;
/* Enter/Escape Configuration Mode */
if (val == 0x55)
dev->cfg_lock = 0;
else if (!dev->cfg_lock && (val == 0xaa))
dev->cfg_lock = 1;
else if (!dev->cfg_lock)
INDEX = val;
}
}
static uint8_t
fdc37m60x_read(uint16_t addr, void *priv)
{
fdc37m60x_t *dev = (fdc37m60x_t *)priv;
uint8_t ret = 0xff;
fdc37m60x_t *dev = (fdc37m60x_t *) priv;
uint8_t ret = 0xff;
if (addr & 1)
ret = (INDEX >= 0x30) ? dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] : dev->regs[INDEX];
ret = (INDEX >= 0x30) ? dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] : dev->regs[INDEX];
return ret;
}
static void
fdc37m60x_fdc_handler(fdc37m60x_t *dev)
{
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_irq(dev->fdc, IRQ(0) & 0xf);
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);
}
static void
fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev)
{
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);
fdc37m60x_log("SMC60x-UART%d: BASE %04x IRQ %d\n", num & 1, BASE_ADDRESS(4 + (num & 1)), IRQ(4 + (num & 1)) & 0xf);
}
}
void fdc37m60x_lpt_handler(fdc37m60x_t *dev)
void
fdc37m60x_lpt_handler(fdc37m60x_t *dev)
{
lpt1_remove();
if (ENABLED(3) || (POWER_CONTROL & 0x08)) {
lpt1_init(BASE_ADDRESS(3));
lpt1_irq(IRQ(3) & 0xf);
fdc37m60x_log("SMC60x-LPT: BASE %04x IRQ %d\n", BASE_ADDRESS(3), IRQ(3) & 0xf);
lpt1_init(BASE_ADDRESS(3));
lpt1_irq(IRQ(3) & 0xf);
fdc37m60x_log("SMC60x-LPT: BASE %04x IRQ %d\n", BASE_ADDRESS(3), IRQ(3) & 0xf);
}
}
void fdc37m60x_logical_device_handler(fdc37m60x_t *dev)
void
fdc37m60x_logical_device_handler(fdc37m60x_t *dev)
{
/* Register 07h:
Device 0: FDC
Device 3: LPT
Device 4: UART1
Device 5: UART2
Device 0: FDC
Device 3: LPT
Device 4: UART1
Device 5: UART2
*/
switch (CURRENT_LOGICAL_DEVICE) {
case 0x00:
fdc37m60x_fdc_handler(dev);
break;
case 0x00:
fdc37m60x_fdc_handler(dev);
break;
case 0x03:
fdc37m60x_lpt_handler(dev);
break;
case 0x03:
fdc37m60x_lpt_handler(dev);
break;
case 0x04:
fdc37m60x_uart_handler(0, dev);
break;
case 0x04:
fdc37m60x_uart_handler(0, dev);
break;
case 0x05:
fdc37m60x_uart_handler(1, dev);
break;
case 0x05:
fdc37m60x_uart_handler(1, dev);
break;
}
}
static void
fdc37m60x_reset(void *priv)
{
fdc37m60x_t *dev = (fdc37m60x_t *) priv;
uint8_t i;
uint8_t i;
memset(dev->regs, 0, sizeof(dev->regs));
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[0x24] = 0x04;
@@ -286,24 +284,22 @@ fdc37m60x_reset(void *priv)
fdc37m60x_lpt_handler(dev);
}
static void
fdc37m60x_close(void *priv)
{
fdc37m60x_t *dev = (fdc37m60x_t *)priv;
fdc37m60x_t *dev = (fdc37m60x_t *) priv;
free(dev);
}
static void *
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));
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[1] = device_add_inst(&ns16550_device, 2);
@@ -315,29 +311,29 @@ fdc37m60x_init(const device_t *info)
}
const device_t fdc37m60x_device = {
.name = "SMSC FDC37M60X",
.name = "SMSC FDC37M60X",
.internal_name = "fdc37m60x",
.flags = 0,
.local = FDC_PRIMARY_ADDR,
.init = fdc37m60x_init,
.close = fdc37m60x_close,
.reset = NULL,
.flags = 0,
.local = FDC_PRIMARY_ADDR,
.init = fdc37m60x_init,
.close = fdc37m60x_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
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",
.flags = 0,
.local = FDC_SECONDARY_ADDR,
.init = fdc37m60x_init,
.close = fdc37m60x_close,
.reset = NULL,
.flags = 0,
.local = FDC_SECONDARY_ADDR,
.init = fdc37m60x_init,
.close = fdc37m60x_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};

View File

@@ -33,250 +33,237 @@
#include <86box/fdd_common.h>
#include <86box/sio.h>
#define LDN dev->regs[7]
typedef struct
{
fdc_t *fdc_controller;
fdc_t *fdc_controller;
serial_t *uart[2];
uint8_t index, regs[256], device_regs[6][256];
int unlocked, enumerator;
int unlocked, enumerator;
} it8661f_t;
static uint8_t mb_pnp_key[32] = { 0x6a, 0xb5, 0xda, 0xed, 0xf6, 0xfb, 0x7d, 0xbe, 0xdf, 0x6f, 0x37, 0x1b, 0x0d, 0x86, 0xc3, 0x61, 0xb0, 0x58, 0x2c, 0x16, 0x8b, 0x45, 0xa2, 0xd1, 0xe8, 0x74, 0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39 };
static 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
int it8661_do_log = ENABLE_IT8661_LOG;
void
it8661_log(const char *fmt, ...)
{
va_list ap;
if (it8661_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define it8661_log(fmt, ...)
# define it8661_log(fmt, ...)
#endif
static void
it8661_fdc(uint16_t addr, uint8_t val, it8661f_t *dev)
{
fdc_remove(dev->fdc_controller);
if (((addr == 0x30) && (val & 1)) || (dev->device_regs[0][0x30] & 1)) {
switch (addr) {
case 0x30:
dev->device_regs[0][addr] = val & 1;
break;
switch (addr) {
case 0x30:
dev->device_regs[0][addr] = val & 1;
break;
case 0x31:
dev->device_regs[0][addr] = val & 3;
if (val & 1)
dev->device_regs[0][addr] |= 0x55;
break;
case 0x31:
dev->device_regs[0][addr] = val & 3;
if (val & 1)
dev->device_regs[0][addr] |= 0x55;
break;
case 0x60:
case 0x61:
dev->device_regs[0][addr] = val & ((addr == 0x61) ? 0xff : 0xf8);
break;
case 0x60:
case 0x61:
dev->device_regs[0][addr] = val & ((addr == 0x61) ? 0xff : 0xf8);
break;
case 0x70:
dev->device_regs[0][addr] = val & 0x0f;
break;
case 0x70:
dev->device_regs[0][addr] = val & 0x0f;
break;
case 0x74:
dev->device_regs[0][addr] = val & 7;
break;
case 0x74:
dev->device_regs[0][addr] = val & 7;
break;
case 0xf0:
dev->device_regs[0][addr] = val & 0x0f;
break;
}
case 0xf0:
dev->device_regs[0][addr] = val & 0x0f;
break;
}
fdc_set_base(dev->fdc_controller, (dev->device_regs[0][0x60] << 8) | (dev->device_regs[0][0x61]));
fdc_set_irq(dev->fdc_controller, dev->device_regs[0][0x70] & 0x0f);
fdc_set_dma_ch(dev->fdc_controller, dev->device_regs[0][0x74] & 7);
fdc_set_base(dev->fdc_controller, (dev->device_regs[0][0x60] << 8) | (dev->device_regs[0][0x61]));
fdc_set_irq(dev->fdc_controller, dev->device_regs[0][0x70] & 0x0f);
fdc_set_dma_ch(dev->fdc_controller, dev->device_regs[0][0x74] & 7);
if (dev->device_regs[0][0xf0] & 1)
fdc_writeprotect(dev->fdc_controller);
if (dev->device_regs[0][0xf0] & 1)
fdc_writeprotect(dev->fdc_controller);
it8661_log("ITE 8661-FDC: BASE %04x IRQ %02x\n", (dev->device_regs[0][0x60] << 8) | (dev->device_regs[0][0x61]),
dev->device_regs[0][0x70] & 0x0f);
dev->device_regs[0][0x70] & 0x0f);
}
}
static void
it8661_serial(int uart, uint16_t addr, uint8_t val, it8661f_t *dev)
{
serial_remove(dev->uart[uart]);
if (((addr == 0x30) && (val & 1)) || (dev->device_regs[1 + uart][0x30] & 1)) {
switch (addr) {
case 0x30:
dev->device_regs[1 + uart][addr] = val & 1;
break;
switch (addr) {
case 0x30:
dev->device_regs[1 + uart][addr] = val & 1;
break;
case 0x60:
case 0x61:
dev->device_regs[1 + uart][addr] = val & ((addr == 0x61) ? 0xff : 0xf8);
break;
case 0x60:
case 0x61:
dev->device_regs[1 + uart][addr] = val & ((addr == 0x61) ? 0xff : 0xf8);
break;
case 0x70:
dev->device_regs[1 + uart][addr] = val & 0x0f;
break;
case 0x70:
dev->device_regs[1 + uart][addr] = val & 0x0f;
break;
case 0x74:
dev->device_regs[1 + uart][addr] = val & 7;
break;
case 0x74:
dev->device_regs[1 + uart][addr] = val & 7;
break;
case 0xf0:
dev->device_regs[1 + uart][addr] = val & 3;
break;
}
case 0xf0:
dev->device_regs[1 + uart][addr] = val & 3;
break;
}
serial_setup(dev->uart[uart], (dev->device_regs[1 + uart][0x60] << 8) | (dev->device_regs[1 + uart][0x61]), dev->device_regs[1 + uart][0x70] & 0x0f);
serial_setup(dev->uart[uart], (dev->device_regs[1 + uart][0x60] << 8) | (dev->device_regs[1 + uart][0x61]), dev->device_regs[1 + uart][0x70] & 0x0f);
it8661_log("ITE 8661-UART%01x: BASE %04x IRQ %02x\n", 1 + (LDN % 1),
(dev->device_regs[1 + uart][0x60] << 8) | (dev->device_regs[1 + uart][0x61]),
dev->device_regs[1 + uart][0x70] & 0x0f);
it8661_log("ITE 8661-UART%01x: BASE %04x IRQ %02x\n", 1 + (LDN % 1),
(dev->device_regs[1 + uart][0x60] << 8) | (dev->device_regs[1 + uart][0x61]),
dev->device_regs[1 + uart][0x70] & 0x0f);
}
}
void
it8661_lpt(uint16_t addr, uint8_t val, it8661f_t *dev)
{
lpt1_remove();
if (((addr == 0x30) && (val & 1)) || (dev->device_regs[3][0x30] & 1)) {
switch (addr) {
case 0x30:
dev->device_regs[3][addr] = val & 1;
break;
switch (addr) {
case 0x30:
dev->device_regs[3][addr] = val & 1;
break;
case 0x60:
case 0x61:
dev->device_regs[3][addr] = val & ((addr == 0x61) ? 0xff : 0xf8);
break;
case 0x60:
case 0x61:
dev->device_regs[3][addr] = val & ((addr == 0x61) ? 0xff : 0xf8);
break;
case 0x70:
dev->device_regs[3][addr] = val & 0x0f;
break;
case 0x70:
dev->device_regs[3][addr] = val & 0x0f;
break;
case 0x74:
dev->device_regs[3][addr] = val & 7;
break;
case 0x74:
dev->device_regs[3][addr] = val & 7;
break;
case 0xf0:
dev->device_regs[3][addr] = val & 3;
break;
}
case 0xf0:
dev->device_regs[3][addr] = val & 3;
break;
}
lpt1_init((dev->device_regs[3][0x60] << 8) | (dev->device_regs[3][0x61]));
lpt1_irq(dev->device_regs[3][0x70] & 0x0f);
lpt1_init((dev->device_regs[3][0x60] << 8) | (dev->device_regs[3][0x61]));
lpt1_irq(dev->device_regs[3][0x70] & 0x0f);
it8661_log("ITE 8661-LPT: BASE %04x IRQ %02x\n", (dev->device_regs[3][0x60] << 8) | (dev->device_regs[3][0x61]),
dev->device_regs[3][0x70] & 0x0f);
it8661_log("ITE 8661-LPT: BASE %04x IRQ %02x\n", (dev->device_regs[3][0x60] << 8) | (dev->device_regs[3][0x61]),
dev->device_regs[3][0x70] & 0x0f);
}
}
void
it8661_ldn(uint16_t addr, uint8_t val, it8661f_t *dev)
{
switch (LDN) {
case 0:
it8661_fdc(addr, val, dev);
break;
case 1:
case 2:
it8661_serial(LDN & 2, addr, val, dev);
break;
case 3:
it8661_lpt(addr, val, dev);
break;
case 0:
it8661_fdc(addr, val, dev);
break;
case 1:
case 2:
it8661_serial(LDN & 2, addr, val, dev);
break;
case 3:
it8661_lpt(addr, val, dev);
break;
}
}
static void
it8661f_write(uint16_t addr, uint8_t val, void *priv)
{
it8661f_t *dev = (it8661f_t *)priv;
it8661f_t *dev = (it8661f_t *) priv;
switch (addr) {
case FDC_SECONDARY_ADDR:
if (!dev->unlocked) {
(val == mb_pnp_key[dev->enumerator]) ? dev->enumerator++ : (dev->enumerator = 0);
if (dev->enumerator == 31) {
dev->unlocked = 1;
it8661_log("ITE8661F: Unlocked!\n");
}
} else
dev->index = val;
break;
case FDC_SECONDARY_ADDR:
if (!dev->unlocked) {
(val == mb_pnp_key[dev->enumerator]) ? dev->enumerator++ : (dev->enumerator = 0);
if (dev->enumerator == 31) {
dev->unlocked = 1;
it8661_log("ITE8661F: Unlocked!\n");
}
} else
dev->index = val;
break;
case 0x371:
if (dev->unlocked) {
switch (dev->index) {
case 0x02:
dev->regs[dev->index] = val;
if (val & 1)
it8661f_reset(dev);
if (val & 2)
dev->unlocked = 0;
break;
case 0x07:
dev->regs[dev->index] = val;
break;
case 0x22:
dev->regs[dev->index] = val & 0x30;
break;
case 0x23:
dev->regs[dev->index] = val & 0x1f;
break;
default:
it8661_ldn(dev->index, val, dev);
break;
}
}
break;
case 0x371:
if (dev->unlocked) {
switch (dev->index) {
case 0x02:
dev->regs[dev->index] = val;
if (val & 1)
it8661f_reset(dev);
if (val & 2)
dev->unlocked = 0;
break;
case 0x07:
dev->regs[dev->index] = val;
break;
case 0x22:
dev->regs[dev->index] = val & 0x30;
break;
case 0x23:
dev->regs[dev->index] = val & 0x1f;
break;
default:
it8661_ldn(dev->index, val, dev);
break;
}
}
break;
}
return;
}
static uint8_t
it8661f_read(uint16_t addr, void *priv)
{
it8661f_t *dev = (it8661f_t *)priv;
it8661f_t *dev = (it8661f_t *) priv;
it8661_log("IT8661F:\n", addr, dev->regs[dev->index]);
return (addr == 0xa79) ? dev->regs[dev->index] : 0xff;
}
static void
it8661f_reset(void *priv)
{
it8661f_t *dev = (it8661f_t *)priv;
it8661f_t *dev = (it8661f_t *) priv;
dev->regs[0x20] = 0x86;
dev->regs[0x21] = 0x61;
@@ -304,20 +291,18 @@ it8661f_reset(void *priv)
dev->device_regs[3][0xf0] = 3;
}
static void
it8661f_close(void *priv)
{
it8661f_t *dev = (it8661f_t *)priv;
it8661f_t *dev = (it8661f_t *) priv;
free(dev);
}
static void *
it8661f_init(const device_t *info)
{
it8661f_t *dev = (it8661f_t *)malloc(sizeof(it8661f_t));
it8661f_t *dev = (it8661f_t *) malloc(sizeof(it8661f_t));
memset(dev, 0, sizeof(it8661f_t));
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);
dev->enumerator = 0;
dev->unlocked = 0;
dev->unlocked = 0;
it8661f_reset(dev);
return dev;
}
const device_t it8661f_device = {
.name = "ITE IT8661F",
.name = "ITE IT8661F",
.internal_name = "it8661f",
.flags = 0,
.local = 0,
.init = it8661f_init,
.close = it8661f_close,
.reset = NULL,
.flags = 0,
.local = 0,
.init = it8661f_init,
.close = it8661f_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -30,9 +30,9 @@
#include <86box/fdc.h>
#include <86box/sio.h>
#define FSR dev->regs[0xa0]
#define ASR dev->regs[0xa1]
#define PDR dev->regs[0xa2]
#define FSR dev->regs[0xa0]
#define ASR dev->regs[0xa1]
#define PDR dev->regs[0xa2]
#define HAS_IDE_FUNCTIONALITY dev->ide_function
#ifdef ENABLE_PRIME3B_LOG
@@ -42,23 +42,22 @@ prime3b_log(const char *fmt, ...)
{
va_list ap;
if (prime3b_do_log)
{
if (prime3b_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define prime3b_log(fmt, ...)
# define prime3b_log(fmt, ...)
#endif
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;
fdc_t *fdc_controller;
fdc_t *fdc_controller;
serial_t *uart[2];
} prime3b_t;
@@ -73,10 +72,9 @@ void prime3b_powerdown(prime3b_t *dev);
static void
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;
/* Enter/Escape Configuration Mode */
@@ -84,50 +82,46 @@ prime3b_write(uint16_t addr, uint8_t val, void *priv)
dev->cfg_lock = 0;
else if (val == 0xcc)
dev->cfg_lock = 1;
}
else if ((addr == 0x399) && !dev->cfg_lock)
{
switch (dev->index)
{
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;
} else if ((addr == 0x399) && !dev->cfg_lock) {
switch (dev->index) {
case 0xa0: /* Function Selection Register (FSR) */
FSR = val;
prime3b_enable(dev);
break;
case 1:
dev->com3_addr = 0x338;
dev->com4_addr = 0x238;
case 0xa1: /* Address Selection Register (ASR) */
ASR = val;
prime3b_enable(dev);
break;
case 2:
dev->com3_addr = COM4_ADDR;
dev->com4_addr = 0x2e0;
case 0xa2: /* Power Down Register (PDR) */
dev->regs[0xa2] = val;
break;
case 3:
dev->com3_addr = 0x220;
dev->com4_addr = 0x228;
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;
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;
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
prime3b_read(uint16_t addr, void *priv)
{
prime3b_t *dev = (prime3b_t *)priv;
prime3b_t *dev = (prime3b_t *) priv;
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;
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);
}
void prime3b_uart_handler(uint8_t num, prime3b_t *dev)
void
prime3b_uart_handler(uint8_t num, prime3b_t *dev)
{
uint16_t uart_base;
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);
}
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);
lpt1_remove();
@@ -170,7 +167,8 @@ void prime3b_lpt_handler(prime3b_t *dev)
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();
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);
}
void prime3b_enable(prime3b_t *dev)
void
prime3b_enable(prime3b_t *dev)
{
/*
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();
}
void prime3b_powerdown(prime3b_t *dev)
void
prime3b_powerdown(prime3b_t *dev)
{
/* Note: It can be done more efficiently for sure */
uint8_t old_base = PDR;
@@ -235,7 +235,7 @@ void prime3b_powerdown(prime3b_t *dev)
static void
prime3b_close(void *priv)
{
prime3b_t *dev = (prime3b_t *)priv;
prime3b_t *dev = (prime3b_t *) priv;
free(dev);
}
@@ -243,7 +243,7 @@ prime3b_close(void *priv)
static void *
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));
/* 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->fdc_controller = device_add(&fdc_at_device);
dev->uart[0] = device_add_inst(&ns16550_device, 1);
dev->uart[1] = device_add_inst(&ns16550_device, 2);
dev->uart[0] = device_add_inst(&ns16550_device, 1);
dev->uart[1] = device_add_inst(&ns16550_device, 2);
if (HAS_IDE_FUNCTIONALITY)
device_add(&ide_isa_device);
@@ -269,29 +269,29 @@ prime3b_init(const device_t *info)
}
const device_t prime3b_device = {
.name = "Goldstar Prime3B",
.name = "Goldstar Prime3B",
.internal_name = "prime3b",
.flags = 0,
.local = 0,
.init = prime3b_init,
.close = prime3b_close,
.reset = NULL,
.flags = 0,
.local = 0,
.init = prime3b_init,
.close = prime3b_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
const device_t prime3b_ide_device = {
.name = "Goldstar Prime3B with IDE functionality",
.name = "Goldstar Prime3B with IDE functionality",
.internal_name = "prime3b_ide",
.flags = 0,
.local = 1,
.init = prime3b_init,
.close = prime3b_close,
.reset = NULL,
.flags = 0,
.local = 1,
.init = prime3b_init,
.close = prime3b_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};

View File

@@ -37,25 +37,24 @@ prime3c_log(const char *fmt, ...)
{
va_list ap;
if (prime3c_do_log)
{
if (prime3c_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define prime3c_log(fmt, ...)
# define prime3c_log(fmt, ...)
#endif
/* Function Select(Note on prime3c_enable) */
#define FUNCTION_SELECT dev->regs[0xc2]
/* Base Address Registers */
#define FDC_BASE_ADDRESS dev->regs[0xc3]
#define IDE_BASE_ADDRESS dev->regs[0xc4]
#define IDE_SIDE_ADDRESS dev->regs[0xc5]
#define LPT_BASE_ADDRESS dev->regs[0xc6]
#define FDC_BASE_ADDRESS dev->regs[0xc3]
#define IDE_BASE_ADDRESS dev->regs[0xc4]
#define IDE_SIDE_ADDRESS dev->regs[0xc5]
#define LPT_BASE_ADDRESS dev->regs[0xc6]
#define UART1_BASE_ADDRESS dev->regs[0xc7]
#define UART2_BASE_ADDRESS dev->regs[0xc8]
@@ -76,7 +75,7 @@ typedef struct
{
uint8_t index, regs[256], cfg_lock, ide_function;
fdc_t *fdc_controller;
fdc_t *fdc_controller;
serial_t *uart[2];
} prime3c_t;
@@ -90,124 +89,121 @@ void prime3c_enable(prime3c_t *dev);
static void
prime3c_write(uint16_t addr, uint8_t val, void *priv)
{
prime3c_t *dev = (prime3c_t *)priv;
prime3c_t *dev = (prime3c_t *) priv;
switch (addr)
{
case 0x398:
dev->index = val;
switch (addr) {
case 0x398:
dev->index = val;
/* Enter/Escape Configuration Mode */
if (val == 0x33)
dev->cfg_lock = 0;
else if (val == 0x55)
dev->cfg_lock = 1;
break;
/* Enter/Escape Configuration Mode */
if (val == 0x33)
dev->cfg_lock = 0;
else if (val == 0x55)
dev->cfg_lock = 1;
break;
case 0x399:
if (!dev->cfg_lock)
{
switch (dev->index)
{
case 0xc2:
FUNCTION_SELECT = val & 0xbf;
prime3c_enable(dev);
break;
case 0x399:
if (!dev->cfg_lock) {
switch (dev->index) {
case 0xc2:
FUNCTION_SELECT = val & 0xbf;
prime3c_enable(dev);
break;
case 0xc3:
FDC_BASE_ADDRESS = val & 0xfc;
prime3c_fdc_handler(dev);
break;
case 0xc3:
FDC_BASE_ADDRESS = val & 0xfc;
prime3c_fdc_handler(dev);
break;
case 0xc4:
IDE_BASE_ADDRESS = val & 0xfc;
if (HAS_IDE_FUNCTIONALITY)
prime3c_ide_handler(dev);
break;
case 0xc4:
IDE_BASE_ADDRESS = val & 0xfc;
if (HAS_IDE_FUNCTIONALITY)
prime3c_ide_handler(dev);
break;
case 0xc5:
IDE_SIDE_ADDRESS = (val & 0xfc) | 0x02;
if (HAS_IDE_FUNCTIONALITY)
prime3c_ide_handler(dev);
break;
case 0xc5:
IDE_SIDE_ADDRESS = (val & 0xfc) | 0x02;
if (HAS_IDE_FUNCTIONALITY)
prime3c_ide_handler(dev);
break;
case 0xc6:
LPT_BASE_ADDRESS = val;
break;
case 0xc6:
LPT_BASE_ADDRESS = val;
break;
case 0xc7:
UART1_BASE_ADDRESS = val & 0xfe;
prime3c_uart_handler(0, dev);
break;
case 0xc7:
UART1_BASE_ADDRESS = val & 0xfe;
prime3c_uart_handler(0, dev);
break;
case 0xc8:
UART2_BASE_ADDRESS = val & 0xfe;
prime3c_uart_handler(1, dev);
break;
case 0xc8:
UART2_BASE_ADDRESS = val & 0xfe;
prime3c_uart_handler(1, dev);
break;
case 0xc9:
FDC_LPT_DMA = val;
prime3c_fdc_handler(dev);
break;
case 0xc9:
FDC_LPT_DMA = val;
prime3c_fdc_handler(dev);
break;
case 0xca:
FDC_LPT_IRQ = val;
prime3c_fdc_handler(dev);
prime3c_lpt_handler(dev);
break;
case 0xca:
FDC_LPT_IRQ = val;
prime3c_fdc_handler(dev);
prime3c_lpt_handler(dev);
break;
case 0xcb:
UART_IRQ = val;
prime3c_uart_handler(0, dev);
prime3c_uart_handler(1, dev);
break;
case 0xcb:
UART_IRQ = val;
prime3c_uart_handler(0, dev);
prime3c_uart_handler(1, dev);
break;
case 0xcd:
case 0xce:
dev->regs[dev->index] = val;
break;
case 0xcd:
case 0xce:
dev->regs[dev->index] = val;
break;
case 0xcf:
dev->regs[dev->index] = val & 0x3f;
break;
case 0xcf:
dev->regs[dev->index] = val & 0x3f;
break;
case 0xd0:
dev->regs[dev->index] = val & 0xfc;
break;
case 0xd0:
dev->regs[dev->index] = val & 0xfc;
break;
case 0xd1:
dev->regs[dev->index] = val & 0x3f;
break;
case 0xd1:
dev->regs[dev->index] = val & 0x3f;
break;
case 0xd3:
dev->regs[dev->index] = val & 0x7c;
break;
case 0xd3:
dev->regs[dev->index] = val & 0x7c;
break;
case 0xd5:
case 0xd6:
case 0xd7:
case 0xd8:
dev->regs[dev->index] = val;
break;
case 0xd5:
case 0xd6:
case 0xd7:
case 0xd8:
dev->regs[dev->index] = val;
break;
}
}
}
break;
break;
}
}
static uint8_t
prime3c_read(uint16_t addr, void *priv)
{
prime3c_t *dev = (prime3c_t *)priv;
prime3c_t *dev = (prime3c_t *) priv;
return dev->regs[dev->index];
}
void prime3c_fdc_handler(prime3c_t *dev)
void
prime3c_fdc_handler(prime3c_t *dev)
{
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_irq(dev->fdc_controller, (FDC_LPT_IRQ >> 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]);
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);
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();
if (!(FUNCTION_SELECT & 0x03))
{
if (!(FUNCTION_SELECT & 0x03)) {
lpt1_init(LPT_BASE_ADDRESS << 2);
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();
if (FUNCTION_SELECT & 0x20)
{
if (FUNCTION_SELECT & 0x20) {
ide_set_base(0, IDE_BASE_ADDRESS << 2);
ide_set_side(0, IDE_SIDE_ADDRESS << 2);
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
Bit 7: Gameport
Bit 6: Reserved
Bit 5: IDE
Bit 4: FDC
Bit 3: UART 2
Bit 2: UART 1
Bit 1/0: PIO (0/0 Unidirectional , 0/1 ECP, 1/0 EPP, 1/1 Disabled)
Register C2: Function Select
Bit 7: Gameport
Bit 6: Reserved
Bit 5: IDE
Bit 4: FDC
Bit 3: UART 2
Bit 2: UART 1
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 & 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 & 0x10) ? prime3c_fdc_handler(dev) : fdc_remove(dev->fdc_controller);
if (HAS_IDE_FUNCTIONALITY)
(FUNCTION_SELECT & 0x20) ? prime3c_ide_handler(dev) : ide_pri_disable();
!(FUNCTION_SELECT & 0x03) ? prime3c_lpt_handler(dev) : lpt1_remove();
(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 & 0x10) ? prime3c_fdc_handler(dev) : fdc_remove(dev->fdc_controller);
if (HAS_IDE_FUNCTIONALITY)
(FUNCTION_SELECT & 0x20) ? prime3c_ide_handler(dev) : ide_pri_disable();
}
static void
prime3c_close(void *priv)
{
prime3c_t *dev = (prime3c_t *)priv;
prime3c_t *dev = (prime3c_t *) priv;
free(dev);
}
@@ -286,7 +283,7 @@ prime3c_close(void *priv)
static void *
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));
/* 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->fdc_controller = device_add(&fdc_at_device);
dev->uart[0] = device_add_inst(&ns16550_device, 1);
dev->uart[1] = device_add_inst(&ns16550_device, 2);
dev->uart[0] = device_add_inst(&ns16550_device, 1);
dev->uart[1] = device_add_inst(&ns16550_device, 2);
if (HAS_IDE_FUNCTIONALITY)
device_add(&ide_isa_device);
@@ -318,29 +315,29 @@ prime3c_init(const device_t *info)
}
const device_t prime3c_device = {
.name = "Goldstar Prime3C",
.name = "Goldstar Prime3C",
.internal_name = "prime3c",
.flags = 0,
.local = 0,
.init = prime3c_init,
.close = prime3c_close,
.reset = NULL,
.flags = 0,
.local = 0,
.init = prime3c_init,
.close = prime3c_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
const device_t prime3c_ide_device = {
.name = "Goldstar Prime3C with IDE functionality",
.name = "Goldstar Prime3C with IDE functionality",
.internal_name = "prime3c_ide",
.flags = 0,
.local = 1,
.init = prime3c_init,
.close = prime3c_close,
.reset = NULL,
.flags = 0,
.local = 1,
.init = prime3c_init,
.close = prime3c_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};

View File

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

View File

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

View File

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

View File

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

View File

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