clang-format in src/sio/
This commit is contained in:
@@ -34,25 +34,22 @@
|
|||||||
#include <86box/fdc.h>
|
#include <86box/fdc.h>
|
||||||
#include <86box/sio.h>
|
#include <86box/sio.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t cur_reg, has_ide,
|
uint8_t cur_reg, has_ide,
|
||||||
regs[81];
|
regs[81];
|
||||||
uint16_t base_address;
|
uint16_t base_address;
|
||||||
fdc_t * fdc;
|
fdc_t *fdc;
|
||||||
serial_t * uart[2];
|
serial_t *uart[2];
|
||||||
} i82091aa_t;
|
} i82091aa_t;
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc_handler(i82091aa_t *dev)
|
fdc_handler(i82091aa_t *dev)
|
||||||
{
|
{
|
||||||
fdc_remove(dev->fdc);
|
fdc_remove(dev->fdc);
|
||||||
if (dev->regs[0x10] & 0x01)
|
if (dev->regs[0x10] & 0x01)
|
||||||
fdc_set_base(dev->fdc, (dev->regs[0x10] & 0x02) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
|
fdc_set_base(dev->fdc, (dev->regs[0x10] & 0x02) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lpt1_handler(i82091aa_t *dev)
|
lpt1_handler(i82091aa_t *dev)
|
||||||
{
|
{
|
||||||
@@ -61,67 +58,65 @@ lpt1_handler(i82091aa_t *dev)
|
|||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
|
|
||||||
switch ((dev->regs[0x20] >> 1) & 0x03) {
|
switch ((dev->regs[0x20] >> 1) & 0x03) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
lpt_port = LPT1_ADDR;
|
lpt_port = LPT1_ADDR;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
lpt_port = LPT2_ADDR;
|
lpt_port = LPT2_ADDR;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
lpt_port = LPT_MDA_ADDR;
|
lpt_port = LPT_MDA_ADDR;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
lpt_port = 0x000;
|
lpt_port = 0x000;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dev->regs[0x20] & 0x01) && lpt_port)
|
if ((dev->regs[0x20] & 0x01) && lpt_port)
|
||||||
lpt1_init(lpt_port);
|
lpt1_init(lpt_port);
|
||||||
|
|
||||||
lpt1_irq((dev->regs[0x20] & 0x08) ? LPT1_IRQ : LPT2_IRQ);
|
lpt1_irq((dev->regs[0x20] & 0x08) ? LPT1_IRQ : LPT2_IRQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
serial_handler(i82091aa_t *dev, int uart)
|
serial_handler(i82091aa_t *dev, int uart)
|
||||||
{
|
{
|
||||||
int reg = (0x30 + (uart << 4));
|
int reg = (0x30 + (uart << 4));
|
||||||
uint16_t uart_port = COM1_ADDR;
|
uint16_t uart_port = COM1_ADDR;
|
||||||
|
|
||||||
serial_remove(dev->uart[uart]);
|
serial_remove(dev->uart[uart]);
|
||||||
|
|
||||||
switch ((dev->regs[reg] >> 1) & 0x07) {
|
switch ((dev->regs[reg] >> 1) & 0x07) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
uart_port = COM1_ADDR;
|
uart_port = COM1_ADDR;
|
||||||
break;
|
break;
|
||||||
case 0x01:
|
case 0x01:
|
||||||
uart_port = COM2_ADDR;
|
uart_port = COM2_ADDR;
|
||||||
break;
|
break;
|
||||||
case 0x02:
|
case 0x02:
|
||||||
uart_port = 0x220;
|
uart_port = 0x220;
|
||||||
break;
|
break;
|
||||||
case 0x03:
|
case 0x03:
|
||||||
uart_port = 0x228;
|
uart_port = 0x228;
|
||||||
break;
|
break;
|
||||||
case 0x04:
|
case 0x04:
|
||||||
uart_port = 0x238;
|
uart_port = 0x238;
|
||||||
break;
|
break;
|
||||||
case 0x05:
|
case 0x05:
|
||||||
uart_port = COM4_ADDR;
|
uart_port = COM4_ADDR;
|
||||||
break;
|
break;
|
||||||
case 0x06:
|
case 0x06:
|
||||||
uart_port = 0x338;
|
uart_port = 0x338;
|
||||||
break;
|
break;
|
||||||
case 0x07:
|
case 0x07:
|
||||||
uart_port = COM3_ADDR;
|
uart_port = COM3_ADDR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->regs[reg] & 0x01)
|
if (dev->regs[reg] & 0x01)
|
||||||
serial_setup(dev->uart[uart], uart_port, (dev->regs[reg] & 0x10) ? COM1_IRQ : COM2_IRQ);
|
serial_setup(dev->uart[uart], uart_port, (dev->regs[reg] & 0x10) ? COM1_IRQ : COM2_IRQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ide_handler(i82091aa_t *dev)
|
ide_handler(i82091aa_t *dev)
|
||||||
{
|
{
|
||||||
@@ -131,91 +126,90 @@ ide_handler(i82091aa_t *dev)
|
|||||||
ide_set_base(board, (dev->regs[0x50] & 0x02) ? 0x170 : 0x1f0);
|
ide_set_base(board, (dev->regs[0x50] & 0x02) ? 0x170 : 0x1f0);
|
||||||
ide_set_side(board, (dev->regs[0x50] & 0x02) ? 0x376 : 0x3f6);
|
ide_set_side(board, (dev->regs[0x50] & 0x02) ? 0x376 : 0x3f6);
|
||||||
if (dev->regs[0x50] & 0x01)
|
if (dev->regs[0x50] & 0x01)
|
||||||
ide_set_handlers(board);
|
ide_set_handlers(board);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
i82091aa_write(uint16_t port, uint8_t val, void *priv)
|
i82091aa_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
i82091aa_t *dev = (i82091aa_t *) priv;
|
i82091aa_t *dev = (i82091aa_t *) priv;
|
||||||
uint8_t index, valxor;
|
uint8_t index, valxor;
|
||||||
uint8_t uart = (dev->cur_reg >> 4) - 0x03;
|
uint8_t uart = (dev->cur_reg >> 4) - 0x03;
|
||||||
uint8_t *reg = &(dev->regs[dev->cur_reg]);
|
uint8_t *reg = &(dev->regs[dev->cur_reg]);
|
||||||
|
|
||||||
index = (port & 1) ? 0 : 1;
|
index = (port & 1) ? 0 : 1;
|
||||||
|
|
||||||
if (index) {
|
if (index) {
|
||||||
dev->cur_reg = val;
|
dev->cur_reg = val;
|
||||||
return;
|
return;
|
||||||
} else if (dev->cur_reg < 0x51)
|
} else if (dev->cur_reg < 0x51)
|
||||||
valxor = val ^ *reg;
|
valxor = val ^ *reg;
|
||||||
else if (dev->cur_reg >= 0x51)
|
else if (dev->cur_reg >= 0x51)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch(dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0x02:
|
case 0x02:
|
||||||
*reg = (*reg & 0x78) | (val & 0x01);
|
*reg = (*reg & 0x78) | (val & 0x01);
|
||||||
break;
|
break;
|
||||||
case 0x03:
|
case 0x03:
|
||||||
*reg = (val & 0xf8);
|
*reg = (val & 0xf8);
|
||||||
break;
|
break;
|
||||||
case 0x10:
|
case 0x10:
|
||||||
*reg = (val & 0x83);
|
*reg = (val & 0x83);
|
||||||
if (valxor & 0x03)
|
if (valxor & 0x03)
|
||||||
fdc_handler(dev);
|
fdc_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 0x11:
|
case 0x11:
|
||||||
*reg = (val & 0x0f);
|
*reg = (val & 0x0f);
|
||||||
if ((valxor & 0x04) && (val & 0x04))
|
if ((valxor & 0x04) && (val & 0x04))
|
||||||
fdc_reset(dev->fdc);
|
fdc_reset(dev->fdc);
|
||||||
break;
|
break;
|
||||||
case 0x20:
|
case 0x20:
|
||||||
*reg = (val & 0xef);
|
*reg = (val & 0xef);
|
||||||
if (valxor & 0x07)
|
if (valxor & 0x07)
|
||||||
lpt1_handler(dev);
|
lpt1_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 0x21:
|
case 0x21:
|
||||||
*reg = (val & 0x2f);
|
*reg = (val & 0x2f);
|
||||||
break;
|
break;
|
||||||
case 0x30: case 0x40:
|
case 0x30:
|
||||||
*reg = (val & 0x9f);
|
case 0x40:
|
||||||
if (valxor & 0x1f)
|
*reg = (val & 0x9f);
|
||||||
serial_handler(dev, uart);
|
if (valxor & 0x1f)
|
||||||
if (valxor & 0x80)
|
serial_handler(dev, uart);
|
||||||
serial_set_clock_src(dev->uart[uart], (val & 0x80) ? 2000000.0 : (24000000.0 / 13.0));
|
if (valxor & 0x80)
|
||||||
break;
|
serial_set_clock_src(dev->uart[uart], (val & 0x80) ? 2000000.0 : (24000000.0 / 13.0));
|
||||||
case 0x31: case 0x41:
|
break;
|
||||||
*reg = (val & 0x1f);
|
case 0x31:
|
||||||
if ((valxor & 0x04) && (val & 0x04))
|
case 0x41:
|
||||||
serial_reset_port(dev->uart[uart]);
|
*reg = (val & 0x1f);
|
||||||
break;
|
if ((valxor & 0x04) && (val & 0x04))
|
||||||
case 0x50:
|
serial_reset_port(dev->uart[uart]);
|
||||||
*reg = (val & 0x07);
|
break;
|
||||||
if (dev->has_ide && (valxor & 0x03))
|
case 0x50:
|
||||||
ide_handler(dev);
|
*reg = (val & 0x07);
|
||||||
break;
|
if (dev->has_ide && (valxor & 0x03))
|
||||||
|
ide_handler(dev);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
i82091aa_read(uint16_t port, void *priv)
|
i82091aa_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
i82091aa_t *dev = (i82091aa_t *) priv;
|
i82091aa_t *dev = (i82091aa_t *) priv;
|
||||||
uint8_t ret = 0xff, index;
|
uint8_t ret = 0xff, index;
|
||||||
|
|
||||||
index = (port & 1) ? 0 : 1;
|
index = (port & 1) ? 0 : 1;
|
||||||
|
|
||||||
if (index)
|
if (index)
|
||||||
ret = dev->cur_reg;
|
ret = dev->cur_reg;
|
||||||
else if (dev->cur_reg < 0x51)
|
else if (dev->cur_reg < 0x51)
|
||||||
ret = dev->regs[dev->cur_reg];
|
ret = dev->regs[dev->cur_reg];
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
i82091aa_reset(i82091aa_t *dev)
|
i82091aa_reset(i82091aa_t *dev)
|
||||||
{
|
{
|
||||||
@@ -224,7 +218,7 @@ i82091aa_reset(i82091aa_t *dev)
|
|||||||
dev->regs[0x00] = 0xa0;
|
dev->regs[0x00] = 0xa0;
|
||||||
dev->regs[0x10] = 0x01;
|
dev->regs[0x10] = 0x01;
|
||||||
dev->regs[0x31] = dev->regs[0x41] = 0x02;
|
dev->regs[0x31] = dev->regs[0x41] = 0x02;
|
||||||
dev->regs[0x50] = 0x01;
|
dev->regs[0x50] = 0x01;
|
||||||
|
|
||||||
fdc_reset(dev->fdc);
|
fdc_reset(dev->fdc);
|
||||||
|
|
||||||
@@ -236,10 +230,9 @@ i82091aa_reset(i82091aa_t *dev)
|
|||||||
serial_set_clock_src(dev->uart[1], (24000000.0 / 13.0));
|
serial_set_clock_src(dev->uart[1], (24000000.0 / 13.0));
|
||||||
|
|
||||||
if (dev->has_ide)
|
if (dev->has_ide)
|
||||||
ide_handler(dev);
|
ide_handler(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
i82091aa_close(void *priv)
|
i82091aa_close(void *priv)
|
||||||
{
|
{
|
||||||
@@ -248,7 +241,6 @@ i82091aa_close(void *priv)
|
|||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
i82091aa_init(const device_t *info)
|
i82091aa_init(const device_t *info)
|
||||||
{
|
{
|
||||||
@@ -267,68 +259,68 @@ i82091aa_init(const device_t *info)
|
|||||||
dev->regs[0x02] = info->local & 0xff;
|
dev->regs[0x02] = info->local & 0xff;
|
||||||
|
|
||||||
if (info->local & 0x08)
|
if (info->local & 0x08)
|
||||||
dev->base_address = (info->local & 0x100) ? 0x0398 : 0x0024;
|
dev->base_address = (info->local & 0x100) ? 0x0398 : 0x0024;
|
||||||
else
|
else
|
||||||
dev->base_address = (info->local & 0x100) ? 0x026e : 0x0022;
|
dev->base_address = (info->local & 0x100) ? 0x026e : 0x0022;
|
||||||
|
|
||||||
io_sethandler(dev->base_address, 0x0002,
|
io_sethandler(dev->base_address, 0x0002,
|
||||||
i82091aa_read, NULL, NULL, i82091aa_write, NULL, NULL, dev);
|
i82091aa_read, NULL, NULL, i82091aa_write, NULL, NULL, dev);
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
const device_t i82091aa_device = {
|
const device_t i82091aa_device = {
|
||||||
.name = "Intel 82091AA Super I/O",
|
.name = "Intel 82091AA Super I/O",
|
||||||
.internal_name = "i82091aa",
|
.internal_name = "i82091aa",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x40,
|
.local = 0x40,
|
||||||
.init = i82091aa_init,
|
.init = i82091aa_init,
|
||||||
.close = i82091aa_close,
|
.close = i82091aa_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t i82091aa_398_device = {
|
const device_t i82091aa_398_device = {
|
||||||
.name = "Intel 82091AA Super I/O (Port 398h)",
|
.name = "Intel 82091AA Super I/O (Port 398h)",
|
||||||
.internal_name = "i82091aa_398",
|
.internal_name = "i82091aa_398",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x148,
|
.local = 0x148,
|
||||||
.init = i82091aa_init,
|
.init = i82091aa_init,
|
||||||
.close = i82091aa_close,
|
.close = i82091aa_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t i82091aa_ide_pri_device = {
|
const device_t i82091aa_ide_pri_device = {
|
||||||
.name = "Intel 82091AA Super I/O (With Primary IDE)",
|
.name = "Intel 82091AA Super I/O (With Primary IDE)",
|
||||||
.internal_name = "i82091aa_ide",
|
.internal_name = "i82091aa_ide",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x240,
|
.local = 0x240,
|
||||||
.init = i82091aa_init,
|
.init = i82091aa_init,
|
||||||
.close = i82091aa_close,
|
.close = i82091aa_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t i82091aa_ide_device = {
|
const device_t i82091aa_ide_device = {
|
||||||
.name = "Intel 82091AA Super I/O (With IDE)",
|
.name = "Intel 82091AA Super I/O (With IDE)",
|
||||||
.internal_name = "i82091aa_ide",
|
.internal_name = "i82091aa_ide",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x440,
|
.local = 0x440,
|
||||||
.init = i82091aa_init,
|
.init = i82091aa_init,
|
||||||
.close = i82091aa_close,
|
.close = i82091aa_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -32,86 +32,84 @@
|
|||||||
#include <86box/fdc.h>
|
#include <86box/fdc.h>
|
||||||
#include <86box/sio.h>
|
#include <86box/sio.h>
|
||||||
|
|
||||||
typedef struct acc3221_t
|
typedef struct acc3221_t {
|
||||||
{
|
int reg_idx;
|
||||||
int reg_idx;
|
uint8_t regs[256];
|
||||||
uint8_t regs[256];
|
fdc_t *fdc;
|
||||||
fdc_t * fdc;
|
serial_t *uart[2];
|
||||||
serial_t * uart[2];
|
|
||||||
} acc3221_t;
|
} acc3221_t;
|
||||||
|
|
||||||
|
|
||||||
/* Configuration Register Index, BE (R/W):
|
/* Configuration Register Index, BE (R/W):
|
||||||
Bit Function
|
Bit Function
|
||||||
7 PIRQ 5 polarity.
|
7 PIRQ 5 polarity.
|
||||||
1 = active high, default
|
1 = active high, default
|
||||||
0 = active low
|
0 = active low
|
||||||
6 PIRQ 7 polarity.
|
6 PIRQ 7 polarity.
|
||||||
1 = active high, default
|
1 = active high, default
|
||||||
0 = active low
|
0 = active low
|
||||||
5 Primary Parallel Port Extended Mode
|
5 Primary Parallel Port Extended Mode
|
||||||
0 = Compatible mode, default
|
0 = Compatible mode, default
|
||||||
1 = Extended/Bidirectional mode.
|
1 = Extended/Bidirectional mode.
|
||||||
4 Primary Parallel Port Disable
|
4 Primary Parallel Port Disable
|
||||||
1 = Disable, 0 = Enable
|
1 = Disable, 0 = Enable
|
||||||
Power Up Default is set by pin 120
|
Power Up Default is set by pin 120
|
||||||
(3221-DP)/pin 96 (3221-SP)
|
(3221-DP)/pin 96 (3221-SP)
|
||||||
3 Primary Parallel Port Power Down
|
3 Primary Parallel Port Power Down
|
||||||
1 = Power Down, default = 0
|
1 = Power Down, default = 0
|
||||||
2** Secondary Parallel Port Extended
|
2** Secondary Parallel Port Extended
|
||||||
Mode
|
Mode
|
||||||
0 = Compatible mode, default
|
0 = Compatible mode, default
|
||||||
1 = Extended/Bidirectional mode.
|
1 = Extended/Bidirectional mode.
|
||||||
1** Secondary Parallel Port Disable
|
1** Secondary Parallel Port Disable
|
||||||
1 = Disable, 0 = Enable
|
1 = Disable, 0 = Enable
|
||||||
Power Up Default is set by pin 77
|
Power Up Default is set by pin 77
|
||||||
(3221-DP)
|
(3221-DP)
|
||||||
0** Secondary Parallel Port Power Down
|
0** Secondary Parallel Port Power Down
|
||||||
1 = Power Down
|
1 = Power Down
|
||||||
0 = Enable, default
|
0 = Enable, default
|
||||||
Note: Power Up not applicable to 3221-EP. */
|
Note: Power Up not applicable to 3221-EP. */
|
||||||
#define REG_BE_LPT1_DISABLE (3 << 3)
|
#define REG_BE_LPT1_DISABLE (3 << 3)
|
||||||
#define REG_BE_LPT2_DISABLE (3 << 0) /* 3221-DP/EP only */
|
#define REG_BE_LPT2_DISABLE (3 << 0) /* 3221-DP/EP only */
|
||||||
|
|
||||||
/* Configuration Register Index, BF (R/W):
|
/* Configuration Register Index, BF (R/W):
|
||||||
Bit Function
|
Bit Function
|
||||||
7-0 The 8 most significant address bits of
|
7-0 The 8 most significant address bits of
|
||||||
the primary parallel port (A9-2)
|
the primary parallel port (A9-2)
|
||||||
Default 9E (LPT2, at 278-27B) */
|
Default 9E (LPT2, at 278-27B) */
|
||||||
|
|
||||||
/* Configuration Register Index, DA (R/W)**:
|
/* Configuration Register Index, DA (R/W)**:
|
||||||
Bit Function
|
Bit Function
|
||||||
7-0 The 8 most significant address bits of
|
7-0 The 8 most significant address bits of
|
||||||
the secondary parallel port (A9-2)
|
the secondary parallel port (A9-2)
|
||||||
Default DE (LPT1, at 378-37B) */
|
Default DE (LPT1, at 378-37B) */
|
||||||
|
|
||||||
/* Configuration Register Index, DB (R/W):
|
/* Configuration Register Index, DB (R/W):
|
||||||
Bit Function
|
Bit Function
|
||||||
7 SIRQ4 polarity.
|
7 SIRQ4 polarity.
|
||||||
1 = active high; default
|
1 = active high; default
|
||||||
0 = active low
|
0 = active low
|
||||||
6 SIRQ3 polarity.
|
6 SIRQ3 polarity.
|
||||||
1 = active high; default
|
1 = active high; default
|
||||||
0 = active low
|
0 = active low
|
||||||
5 SXTAL clock off. 1 = SCLK off,
|
5 SXTAL clock off. 1 = SCLK off,
|
||||||
0 = SCKL on, default
|
0 = SCKL on, default
|
||||||
4 Primary serial port disable
|
4 Primary serial port disable
|
||||||
1 = Disable, 0 = Enable
|
1 = Disable, 0 = Enable
|
||||||
Power Up default is set by pin 116
|
Power Up default is set by pin 116
|
||||||
(3221-DP)/pin 93 (3221-SP)
|
(3221-DP)/pin 93 (3221-SP)
|
||||||
3 Primary serial port power down
|
3 Primary serial port power down
|
||||||
1 = Power down, 0 = Enable
|
1 = Power down, 0 = Enable
|
||||||
Power Up default is set by pin 116
|
Power Up default is set by pin 116
|
||||||
(3221-DP)/pin 93 (3221-SP)
|
(3221-DP)/pin 93 (3221-SP)
|
||||||
2 Reserved
|
2 Reserved
|
||||||
1 Secondary serial port disable
|
1 Secondary serial port disable
|
||||||
1 = Disable, 0 = Enable
|
1 = Disable, 0 = Enable
|
||||||
Power Up default is set by pin 121
|
Power Up default is set by pin 121
|
||||||
(3221-DP)/pin 97 (3221-SP)
|
(3221-DP)/pin 97 (3221-SP)
|
||||||
0 Secondary serial port power down
|
0 Secondary serial port power down
|
||||||
1 = Power down, 0 = Enable
|
1 = Power down, 0 = Enable
|
||||||
Power Up default is set by pin 121
|
Power Up default is set by pin 121
|
||||||
(3221-DP)/pin 97 (3221-SP)
|
(3221-DP)/pin 97 (3221-SP)
|
||||||
Note: Power Up not applicable to 3221-EP. */
|
Note: Power Up not applicable to 3221-EP. */
|
||||||
#define REG_DB_SERIAL1_DISABLE (3 << 3)
|
#define REG_DB_SERIAL1_DISABLE (3 << 3)
|
||||||
#define REG_DB_SERIAL2_DISABLE (3 << 0)
|
#define REG_DB_SERIAL2_DISABLE (3 << 0)
|
||||||
@@ -119,56 +117,56 @@ typedef struct acc3221_t
|
|||||||
/* Configuration Register Index, DC (R/W):
|
/* Configuration Register Index, DC (R/W):
|
||||||
Bit Function
|
Bit Function
|
||||||
7-1 The MSB of the Primary Serial Port
|
7-1 The MSB of the Primary Serial Port
|
||||||
Address (bits A9-3).
|
Address (bits A9-3).
|
||||||
Default = 7F (COM1, at 3F8-3FF).
|
Default = 7F (COM1, at 3F8-3FF).
|
||||||
0 When this bit is set to 1, bit A2 of
|
0 When this bit is set to 1, bit A2 of
|
||||||
primary parallel port is decoded.
|
primary parallel port is decoded.
|
||||||
Default is 0. */
|
Default is 0. */
|
||||||
|
|
||||||
/* Configuration Register Index, DD (R/W):
|
/* Configuration Register Index, DD (R/W):
|
||||||
Bit Function
|
Bit Function
|
||||||
7-1 The MSB of the Secondary Serial Port
|
7-1 The MSB of the Secondary Serial Port
|
||||||
Address (bits A9-3).
|
Address (bits A9-3).
|
||||||
Default = 5F (COM2, at 2F8-2FF).
|
Default = 5F (COM2, at 2F8-2FF).
|
||||||
0** When this bit is set to 1, bit A2 of
|
0** When this bit is set to 1, bit A2 of
|
||||||
secondary parallel port is decoded.
|
secondary parallel port is decoded.
|
||||||
Default is 0. */
|
Default is 0. */
|
||||||
|
|
||||||
/* Configuration Register Index, DE (R/W):
|
/* Configuration Register Index, DE (R/W):
|
||||||
Bit Function
|
Bit Function
|
||||||
7-6 SIRQ3 source
|
7-6 SIRQ3 source
|
||||||
b7 b6
|
b7 b6
|
||||||
0 0 Disabled, tri-stated
|
0 0 Disabled, tri-stated
|
||||||
0 1 Disabled, tri-stated**
|
0 1 Disabled, tri-stated**
|
||||||
1 0 Primary serial port
|
1 0 Primary serial port
|
||||||
1 1 Secondary serial port,
|
1 1 Secondary serial port,
|
||||||
default
|
default
|
||||||
5-4 SIRQ4 source
|
5-4 SIRQ4 source
|
||||||
b5 b4
|
b5 b4
|
||||||
0 0 Disabled, tri-stated
|
0 0 Disabled, tri-stated
|
||||||
0 1 Disabled, tri-stated**
|
0 1 Disabled, tri-stated**
|
||||||
1 0 Primary serial port,
|
1 0 Primary serial port,
|
||||||
default
|
default
|
||||||
1 1 Secondary serial port
|
1 1 Secondary serial port
|
||||||
|
|
||||||
3-2** PIRQ7 source
|
3-2** PIRQ7 source
|
||||||
b3 b2
|
b3 b2
|
||||||
0 0 Diabled, tri-stated,
|
0 0 Diabled, tri-stated,
|
||||||
default
|
default
|
||||||
0 1 Primary serial port
|
0 1 Primary serial port
|
||||||
1 0 Primary parallel port
|
1 0 Primary parallel port
|
||||||
1 1 Secondary parallel
|
1 1 Secondary parallel
|
||||||
port
|
port
|
||||||
Note: Bits 3-2 are reserved in 3221-SP.
|
Note: Bits 3-2 are reserved in 3221-SP.
|
||||||
|
|
||||||
1-0 PIRQ5 source
|
1-0 PIRQ5 source
|
||||||
b1 b0
|
b1 b0
|
||||||
0 0 Disabled, tri-stated
|
0 0 Disabled, tri-stated
|
||||||
0 1 Secondary serial port
|
0 1 Secondary serial port
|
||||||
1 0 Primary parallel port,
|
1 0 Primary parallel port,
|
||||||
default
|
default
|
||||||
1 1 Secondary parallel
|
1 1 Secondary parallel
|
||||||
port** */
|
port** */
|
||||||
#define REG_DE_SIRQ3_SOURCE (3 << 6)
|
#define REG_DE_SIRQ3_SOURCE (3 << 6)
|
||||||
#define REG_DE_SIRQ3_SERIAL1 (1 << 6)
|
#define REG_DE_SIRQ3_SERIAL1 (1 << 6)
|
||||||
#define REG_DE_SIRQ3_SERIAL2 (3 << 6)
|
#define REG_DE_SIRQ3_SERIAL2 (3 << 6)
|
||||||
@@ -188,29 +186,29 @@ typedef struct acc3221_t
|
|||||||
Bit Function
|
Bit Function
|
||||||
7-6 Reserved
|
7-6 Reserved
|
||||||
5 RTC interface disable
|
5 RTC interface disable
|
||||||
1 = /RTCCS disabled
|
1 = /RTCCS disabled
|
||||||
0 = /RTCCS enabled, default
|
0 = /RTCCS enabled, default
|
||||||
4 Disable Modem Select
|
4 Disable Modem Select
|
||||||
1 = Moden CS disabled, default
|
1 = Moden CS disabled, default
|
||||||
0 = Modem CS enabled
|
0 = Modem CS enabled
|
||||||
|
|
||||||
3-2
|
3-2
|
||||||
b3 b2
|
b3 b2
|
||||||
1 1 Reserved
|
1 1 Reserved
|
||||||
1 0 Modem port address
|
1 0 Modem port address
|
||||||
= 3E8-3EF (default)
|
= 3E8-3EF (default)
|
||||||
0 1 Modem port address:
|
0 1 Modem port address:
|
||||||
2F8-2FF
|
2F8-2FF
|
||||||
0 0 Modem port address:
|
0 0 Modem port address:
|
||||||
3F8-3FF
|
3F8-3FF
|
||||||
|
|
||||||
1-0
|
1-0
|
||||||
b1 b0
|
b1 b0
|
||||||
1 1 Reserved
|
1 1 Reserved
|
||||||
1 0 Mode 2, EISA Mode
|
1 0 Mode 2, EISA Mode
|
||||||
0 1 Mode 1, AT BUS,
|
0 1 Mode 1, AT BUS,
|
||||||
0 0 Mode 0, Two parallel
|
0 0 Mode 0, Two parallel
|
||||||
ports, default */
|
ports, default */
|
||||||
|
|
||||||
/* Configuration Register Index, FA (R/W)**:
|
/* Configuration Register Index, FA (R/W)**:
|
||||||
Bit Function
|
Bit Function
|
||||||
@@ -227,90 +225,88 @@ typedef struct acc3221_t
|
|||||||
Bit Function
|
Bit Function
|
||||||
7 Reserved
|
7 Reserved
|
||||||
6** 0/2 EXG (Read Only)
|
6** 0/2 EXG (Read Only)
|
||||||
In mode 1 and mode 2
|
In mode 1 and mode 2
|
||||||
operation, when the third
|
operation, when the third
|
||||||
floppy drive is installed, pin
|
floppy drive is installed, pin
|
||||||
EXTFDD should be pulled
|
EXTFDD should be pulled
|
||||||
high to enable the third floppy
|
high to enable the third floppy
|
||||||
drive or be pulled low to
|
drive or be pulled low to
|
||||||
disable the third floppy drive.
|
disable the third floppy drive.
|
||||||
1 = Third floppy drive enabled
|
1 = Third floppy drive enabled
|
||||||
0 = Third floppy drive disabled
|
0 = Third floppy drive disabled
|
||||||
5** EXTFDD (Read Only)
|
5** EXTFDD (Read Only)
|
||||||
In mode 1 and mode 2
|
In mode 1 and mode 2
|
||||||
operation, when the third
|
operation, when the third
|
||||||
floppy drive is installed and
|
floppy drive is installed and
|
||||||
pin 0/2 EXG is pulled high,
|
pin 0/2 EXG is pulled high,
|
||||||
the third floppy drive becomes
|
the third floppy drive becomes
|
||||||
the bootable drive (drive 0).
|
the bootable drive (drive 0).
|
||||||
When pi 0/2 EXG is pulled low,
|
When pi 0/2 EXG is pulled low,
|
||||||
the third floppy drive acts as
|
the third floppy drive acts as
|
||||||
drive 2.
|
drive 2.
|
||||||
1 = Third floppy drive as drive 0 (bootable)
|
1 = Third floppy drive as drive 0 (bootable)
|
||||||
0 = Third floppy drive as drive 2
|
0 = Third floppy drive as drive 2
|
||||||
4** MS
|
4** MS
|
||||||
In mode 1 and mode 2, t his bit is to
|
In mode 1 and mode 2, t his bit is to
|
||||||
control the output pin MS to support a
|
control the output pin MS to support a
|
||||||
special 3 1/2", 1.2M drive. When this
|
special 3 1/2", 1.2M drive. When this
|
||||||
bit is set to high (1), the MS pin sends
|
bit is set to high (1), the MS pin sends
|
||||||
a low signal. When this bit is set to
|
a low signal. When this bit is set to
|
||||||
low (0), the MS pin sends a high
|
low (0), the MS pin sends a high
|
||||||
signal to support a 3 1/2", 1.2M drive.
|
signal to support a 3 1/2", 1.2M drive.
|
||||||
3 FDC, Clock disable
|
3 FDC, Clock disable
|
||||||
0 = enable, default
|
0 = enable, default
|
||||||
1 = disable
|
1 = disable
|
||||||
2 Reserved
|
2 Reserved
|
||||||
1 FDC disable
|
1 FDC disable
|
||||||
0 = enable, 1= disable
|
0 = enable, 1= disable
|
||||||
Power Upd efault set by pin 117 (3221-
|
Power Upd efault set by pin 117 (3221-
|
||||||
DP)/pin 94 (3221-SP)
|
DP)/pin 94 (3221-SP)
|
||||||
0 FDC address
|
0 FDC address
|
||||||
0 = Primary, default
|
0 = Primary, default
|
||||||
1 = Secondary
|
1 = Secondary
|
||||||
Note: Bits 6-4 are reserved in 3221-SP. */
|
Note: Bits 6-4 are reserved in 3221-SP. */
|
||||||
#define REG_FB_FDC_DISABLE (1 << 1)
|
#define REG_FB_FDC_DISABLE (1 << 1)
|
||||||
|
|
||||||
/* Configuration Register Index, FB (R/W)**:
|
/* Configuration Register Index, FB (R/W)**:
|
||||||
Bit Function
|
Bit Function
|
||||||
7** Disable general chip select 1
|
7** Disable general chip select 1
|
||||||
1 = disable, default
|
1 = disable, default
|
||||||
0 = enable
|
0 = enable
|
||||||
6** Disable general chip select 2
|
6** Disable general chip select 2
|
||||||
1 = disable, default
|
1 = disable, default
|
||||||
0 = enable
|
0 = enable
|
||||||
5** Enable SA2 decoding for general chip
|
5** Enable SA2 decoding for general chip
|
||||||
select 1
|
select 1
|
||||||
1 = enable
|
1 = enable
|
||||||
0 = disable, default
|
0 = disable, default
|
||||||
4** Enable SA2 decoding for general chip
|
4** Enable SA2 decoding for general chip
|
||||||
select 2
|
select 2
|
||||||
1 = enable
|
1 = enable
|
||||||
0 = disable, default
|
0 = disable, default
|
||||||
3 Reserved
|
3 Reserved
|
||||||
2 IDE XT selected
|
2 IDE XT selected
|
||||||
0 = IDE AT interface, default
|
0 = IDE AT interface, default
|
||||||
1 = IDE XT interface
|
1 = IDE XT interface
|
||||||
1 IDE disable, 1 = IDE disable
|
1 IDE disable, 1 = IDE disable
|
||||||
0 = IDE enable
|
0 = IDE enable
|
||||||
Power Up default set by pin 13 (3221-
|
Power Up default set by pin 13 (3221-
|
||||||
DP)/pin 13 (3221-SP)
|
DP)/pin 13 (3221-SP)
|
||||||
0 Secondary IDE
|
0 Secondary IDE
|
||||||
1 = secondary
|
1 = secondary
|
||||||
0 = primary, default
|
0 = primary, default
|
||||||
Note: Bits 6-4 are reserved in 3221-SP. */
|
Note: Bits 6-4 are reserved in 3221-SP. */
|
||||||
#define REG_FE_IDE_DISABLE (1 << 1)
|
#define REG_FE_IDE_DISABLE (1 << 1)
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
acc3221_lpt_handle(acc3221_t *dev)
|
acc3221_lpt_handle(acc3221_t *dev)
|
||||||
{
|
{
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
|
|
||||||
if (!(dev->regs[0xbe] & REG_BE_LPT1_DISABLE))
|
if (!(dev->regs[0xbe] & REG_BE_LPT1_DISABLE))
|
||||||
lpt1_init(dev->regs[0xbf] << 2);
|
lpt1_init(dev->regs[0xbf] << 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
acc3221_serial1_handler(acc3221_t *dev)
|
acc3221_serial1_handler(acc3221_t *dev)
|
||||||
{
|
{
|
||||||
@@ -319,16 +315,15 @@ acc3221_serial1_handler(acc3221_t *dev)
|
|||||||
serial_remove(dev->uart[0]);
|
serial_remove(dev->uart[0]);
|
||||||
|
|
||||||
if (!(dev->regs[0xdb] & REG_DB_SERIAL1_DISABLE)) {
|
if (!(dev->regs[0xdb] & REG_DB_SERIAL1_DISABLE)) {
|
||||||
com_addr = ((dev->regs[0xdc] & 0xfe) << 2);
|
com_addr = ((dev->regs[0xdc] & 0xfe) << 2);
|
||||||
|
|
||||||
if ((dev->regs[0xde] & REG_DE_SIRQ3_SOURCE) == REG_DE_SIRQ3_SERIAL1)
|
if ((dev->regs[0xde] & REG_DE_SIRQ3_SOURCE) == REG_DE_SIRQ3_SERIAL1)
|
||||||
serial_setup(dev->uart[0], com_addr, 3);
|
serial_setup(dev->uart[0], com_addr, 3);
|
||||||
else if ((dev->regs[0xde] & REG_DE_SIRQ4_SOURCE) == REG_DE_SIRQ4_SERIAL1)
|
else if ((dev->regs[0xde] & REG_DE_SIRQ4_SOURCE) == REG_DE_SIRQ4_SERIAL1)
|
||||||
serial_setup(dev->uart[0], com_addr, 4);
|
serial_setup(dev->uart[0], com_addr, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
acc3221_serial2_handler(acc3221_t *dev)
|
acc3221_serial2_handler(acc3221_t *dev)
|
||||||
{
|
{
|
||||||
@@ -337,100 +332,97 @@ acc3221_serial2_handler(acc3221_t *dev)
|
|||||||
serial_remove(dev->uart[1]);
|
serial_remove(dev->uart[1]);
|
||||||
|
|
||||||
if (!(dev->regs[0xdb] & REG_DB_SERIAL2_DISABLE)) {
|
if (!(dev->regs[0xdb] & REG_DB_SERIAL2_DISABLE)) {
|
||||||
com_addr = ((dev->regs[0xdd] & 0xfe) << 2);
|
com_addr = ((dev->regs[0xdd] & 0xfe) << 2);
|
||||||
|
|
||||||
if ((dev->regs[0xde] & REG_DE_SIRQ3_SOURCE) == REG_DE_SIRQ3_SERIAL2)
|
if ((dev->regs[0xde] & REG_DE_SIRQ3_SOURCE) == REG_DE_SIRQ3_SERIAL2)
|
||||||
serial_setup(dev->uart[1], com_addr, 3);
|
serial_setup(dev->uart[1], com_addr, 3);
|
||||||
else if ((dev->regs[0xde] & REG_DE_SIRQ4_SOURCE) == REG_DE_SIRQ4_SERIAL2)
|
else if ((dev->regs[0xde] & REG_DE_SIRQ4_SOURCE) == REG_DE_SIRQ4_SERIAL2)
|
||||||
serial_setup(dev->uart[1], com_addr, 4);
|
serial_setup(dev->uart[1], com_addr, 4);
|
||||||
else if ((dev->regs[0xde] & REG_DE_PIRQ5_SOURCE) == REG_DE_PIRQ5_SERIAL2)
|
else if ((dev->regs[0xde] & REG_DE_PIRQ5_SOURCE) == REG_DE_PIRQ5_SERIAL2)
|
||||||
serial_setup(dev->uart[1], com_addr, 5);
|
serial_setup(dev->uart[1], com_addr, 5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
acc3221_write(uint16_t addr, uint8_t val, void *p)
|
acc3221_write(uint16_t addr, uint8_t val, void *p)
|
||||||
{
|
{
|
||||||
acc3221_t *dev = (acc3221_t *)p;
|
acc3221_t *dev = (acc3221_t *) p;
|
||||||
uint8_t old;
|
uint8_t old;
|
||||||
|
|
||||||
if (!(addr & 1))
|
if (!(addr & 1))
|
||||||
dev->reg_idx = val;
|
dev->reg_idx = val;
|
||||||
else {
|
else {
|
||||||
old = dev->regs[dev->reg_idx];
|
old = dev->regs[dev->reg_idx];
|
||||||
dev->regs[dev->reg_idx] = val;
|
dev->regs[dev->reg_idx] = val;
|
||||||
|
|
||||||
switch (dev->reg_idx) {
|
switch (dev->reg_idx) {
|
||||||
case 0xbe:
|
case 0xbe:
|
||||||
if ((old ^ val) & REG_BE_LPT1_DISABLE)
|
if ((old ^ val) & REG_BE_LPT1_DISABLE)
|
||||||
acc3221_lpt_handle(dev);
|
acc3221_lpt_handle(dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xbf:
|
case 0xbf:
|
||||||
if (old != val)
|
if (old != val)
|
||||||
acc3221_lpt_handle(dev);
|
acc3221_lpt_handle(dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xdb:
|
case 0xdb:
|
||||||
if ((old ^ val) & REG_DB_SERIAL2_DISABLE)
|
if ((old ^ val) & REG_DB_SERIAL2_DISABLE)
|
||||||
acc3221_serial2_handler(dev);
|
acc3221_serial2_handler(dev);
|
||||||
if ((old ^ val) & REG_DB_SERIAL1_DISABLE)
|
if ((old ^ val) & REG_DB_SERIAL1_DISABLE)
|
||||||
acc3221_serial1_handler(dev);
|
acc3221_serial1_handler(dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xdc:
|
case 0xdc:
|
||||||
if (old != val)
|
if (old != val)
|
||||||
acc3221_serial1_handler(dev);
|
acc3221_serial1_handler(dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xdd:
|
case 0xdd:
|
||||||
if (old != val)
|
if (old != val)
|
||||||
acc3221_serial2_handler(dev);
|
acc3221_serial2_handler(dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xde:
|
case 0xde:
|
||||||
if ((old ^ val) & (REG_DE_SIRQ3_SOURCE | REG_DE_SIRQ4_SOURCE)) {
|
if ((old ^ val) & (REG_DE_SIRQ3_SOURCE | REG_DE_SIRQ4_SOURCE)) {
|
||||||
acc3221_serial2_handler(dev);
|
acc3221_serial2_handler(dev);
|
||||||
acc3221_serial1_handler(dev);
|
acc3221_serial1_handler(dev);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xfb:
|
case 0xfb:
|
||||||
if ((old ^ val) & REG_FB_FDC_DISABLE) {
|
if ((old ^ val) & REG_FB_FDC_DISABLE) {
|
||||||
fdc_remove(dev->fdc);
|
fdc_remove(dev->fdc);
|
||||||
if (!(dev->regs[0xfb] & REG_FB_FDC_DISABLE))
|
if (!(dev->regs[0xfb] & REG_FB_FDC_DISABLE))
|
||||||
fdc_set_base(dev->fdc, FDC_PRIMARY_ADDR);
|
fdc_set_base(dev->fdc, FDC_PRIMARY_ADDR);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xfe:
|
case 0xfe:
|
||||||
if ((old ^ val) & REG_FE_IDE_DISABLE) {
|
if ((old ^ val) & REG_FE_IDE_DISABLE) {
|
||||||
ide_pri_disable();
|
ide_pri_disable();
|
||||||
if (!(dev->regs[0xfe] & REG_FE_IDE_DISABLE))
|
if (!(dev->regs[0xfe] & REG_FE_IDE_DISABLE))
|
||||||
ide_pri_enable();
|
ide_pri_enable();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
acc3221_read(uint16_t addr, void *p)
|
acc3221_read(uint16_t addr, void *p)
|
||||||
{
|
{
|
||||||
acc3221_t *dev = (acc3221_t *)p;
|
acc3221_t *dev = (acc3221_t *) p;
|
||||||
|
|
||||||
if (!(addr & 1))
|
if (!(addr & 1))
|
||||||
return dev->reg_idx;
|
return dev->reg_idx;
|
||||||
|
|
||||||
if (dev->reg_idx < 0xbc)
|
if (dev->reg_idx < 0xbc)
|
||||||
return 0xff;
|
return 0xff;
|
||||||
|
|
||||||
return dev->regs[dev->reg_idx];
|
return dev->regs[dev->reg_idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
acc3221_reset(acc3221_t *dev)
|
acc3221_reset(acc3221_t *dev)
|
||||||
{
|
{
|
||||||
@@ -455,7 +447,6 @@ acc3221_close(void *priv)
|
|||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
acc3221_init(const device_t *info)
|
acc3221_init(const device_t *info)
|
||||||
{
|
{
|
||||||
@@ -467,24 +458,23 @@ acc3221_init(const device_t *info)
|
|||||||
dev->uart[0] = device_add_inst(&ns16450_device, 1);
|
dev->uart[0] = device_add_inst(&ns16450_device, 1);
|
||||||
dev->uart[1] = device_add_inst(&ns16450_device, 2);
|
dev->uart[1] = device_add_inst(&ns16450_device, 2);
|
||||||
|
|
||||||
io_sethandler(0x00f2, 0x0002, acc3221_read, NULL, NULL, acc3221_write, NULL, NULL, dev);
|
io_sethandler(0x00f2, 0x0002, acc3221_read, NULL, NULL, acc3221_write, NULL, NULL, dev);
|
||||||
|
|
||||||
acc3221_reset(dev);
|
acc3221_reset(dev);
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const device_t acc3221_device = {
|
const device_t acc3221_device = {
|
||||||
.name = "ACC 3221-SP Super I/O",
|
.name = "ACC 3221-SP Super I/O",
|
||||||
.internal_name = "acc3221",
|
.internal_name = "acc3221",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0,
|
.local = 0,
|
||||||
.init = acc3221_init,
|
.init = acc3221_init,
|
||||||
.close = acc3221_close,
|
.close = acc3221_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,25 +34,21 @@
|
|||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include <86box/sio.h>
|
#include <86box/sio.h>
|
||||||
|
|
||||||
|
#define AB_RST 0x80
|
||||||
#define AB_RST 0x80
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t chip_id, is_apm,
|
uint8_t chip_id, is_apm,
|
||||||
tries,
|
tries,
|
||||||
regs[48],
|
regs[48],
|
||||||
ld_regs[13][256];
|
ld_regs[13][256];
|
||||||
int locked,
|
int locked,
|
||||||
cur_reg;
|
cur_reg;
|
||||||
fdc_t *fdc;
|
fdc_t *fdc;
|
||||||
serial_t *uart[3];
|
serial_t *uart[3];
|
||||||
} ali5123_t;
|
} ali5123_t;
|
||||||
|
|
||||||
|
static void ali5123_write(uint16_t port, uint8_t val, void *priv);
|
||||||
static void ali5123_write(uint16_t port, uint8_t val, void *priv);
|
static uint8_t ali5123_read(uint16_t port, void *priv);
|
||||||
static uint8_t ali5123_read(uint16_t port, void *priv);
|
|
||||||
|
|
||||||
|
|
||||||
static uint16_t
|
static uint16_t
|
||||||
make_port(ali5123_t *dev, uint8_t ld)
|
make_port(ali5123_t *dev, uint8_t ld)
|
||||||
@@ -65,74 +61,71 @@ make_port(ali5123_t *dev, uint8_t ld)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ali5123_fdc_handler(ali5123_t *dev)
|
ali5123_fdc_handler(ali5123_t *dev)
|
||||||
{
|
{
|
||||||
uint16_t ld_port = 0;
|
uint16_t ld_port = 0;
|
||||||
uint8_t global_enable = !!(dev->regs[0x22] & (1 << 0));
|
uint8_t global_enable = !!(dev->regs[0x22] & (1 << 0));
|
||||||
uint8_t local_enable = !!dev->ld_regs[0][0x30];
|
uint8_t local_enable = !!dev->ld_regs[0][0x30];
|
||||||
|
|
||||||
fdc_remove(dev->fdc);
|
fdc_remove(dev->fdc);
|
||||||
if (global_enable && local_enable) {
|
if (global_enable && local_enable) {
|
||||||
ld_port = make_port(dev, 0) & 0xFFF8;
|
ld_port = make_port(dev, 0) & 0xFFF8;
|
||||||
if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8))
|
if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8))
|
||||||
fdc_set_base(dev->fdc, ld_port);
|
fdc_set_base(dev->fdc, ld_port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ali5123_lpt_handler(ali5123_t *dev)
|
ali5123_lpt_handler(ali5123_t *dev)
|
||||||
{
|
{
|
||||||
uint16_t ld_port = 0;
|
uint16_t ld_port = 0;
|
||||||
uint8_t global_enable = !!(dev->regs[0x22] & (1 << 3));
|
uint8_t global_enable = !!(dev->regs[0x22] & (1 << 3));
|
||||||
uint8_t local_enable = !!dev->ld_regs[3][0x30];
|
uint8_t local_enable = !!dev->ld_regs[3][0x30];
|
||||||
uint8_t lpt_irq = dev->ld_regs[3][0x70];
|
uint8_t lpt_irq = dev->ld_regs[3][0x70];
|
||||||
|
|
||||||
if (lpt_irq > 15)
|
if (lpt_irq > 15)
|
||||||
lpt_irq = 0xff;
|
lpt_irq = 0xff;
|
||||||
|
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
if (global_enable && local_enable) {
|
if (global_enable && local_enable) {
|
||||||
ld_port = make_port(dev, 3) & 0xFFFC;
|
ld_port = make_port(dev, 3) & 0xFFFC;
|
||||||
if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC))
|
if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC))
|
||||||
lpt1_init(ld_port);
|
lpt1_init(ld_port);
|
||||||
}
|
}
|
||||||
lpt1_irq(lpt_irq);
|
lpt1_irq(lpt_irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ali5123_serial_handler(ali5123_t *dev, int uart)
|
ali5123_serial_handler(ali5123_t *dev, int uart)
|
||||||
{
|
{
|
||||||
uint16_t ld_port = 0;
|
uint16_t ld_port = 0;
|
||||||
uint8_t uart_no = (uart == 2) ? 0x0b : (4 + uart);
|
uint8_t uart_no = (uart == 2) ? 0x0b : (4 + uart);
|
||||||
uint8_t global_enable = !!(dev->regs[0x22] & (1 << uart_no));
|
uint8_t global_enable = !!(dev->regs[0x22] & (1 << uart_no));
|
||||||
uint8_t local_enable = !!dev->ld_regs[uart_no][0x30];
|
uint8_t local_enable = !!dev->ld_regs[uart_no][0x30];
|
||||||
uint8_t mask = (uart == 1) ? 0x04 : 0x05;
|
uint8_t mask = (uart == 1) ? 0x04 : 0x05;
|
||||||
|
|
||||||
serial_remove(dev->uart[uart]);
|
serial_remove(dev->uart[uart]);
|
||||||
if (global_enable && local_enable) {
|
if (global_enable && local_enable) {
|
||||||
ld_port = make_port(dev, uart_no) & 0xFFF8;
|
ld_port = make_port(dev, uart_no) & 0xFFF8;
|
||||||
if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8))
|
if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8))
|
||||||
serial_setup(dev->uart[uart], ld_port, dev->ld_regs[uart_no][0x70]);
|
serial_setup(dev->uart[uart], ld_port, dev->ld_regs[uart_no][0x70]);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (dev->ld_regs[uart_no][0xf0] & mask) {
|
switch (dev->ld_regs[uart_no][0xf0] & mask) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
serial_set_clock_src(dev->uart[uart], 1843200.0);
|
serial_set_clock_src(dev->uart[uart], 1843200.0);
|
||||||
break;
|
break;
|
||||||
case 0x04:
|
case 0x04:
|
||||||
serial_set_clock_src(dev->uart[uart], 8000000.0);
|
serial_set_clock_src(dev->uart[uart], 8000000.0);
|
||||||
break;
|
break;
|
||||||
case 0x01: case 0x05:
|
case 0x01:
|
||||||
serial_set_clock_src(dev->uart[uart], 2000000.0);
|
case 0x05:
|
||||||
break;
|
serial_set_clock_src(dev->uart[uart], 2000000.0);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ali5123_reset(ali5123_t *dev)
|
ali5123_reset(ali5123_t *dev)
|
||||||
{
|
{
|
||||||
@@ -145,7 +138,7 @@ ali5123_reset(ali5123_t *dev)
|
|||||||
dev->regs[0x2d] = 0x20;
|
dev->regs[0x2d] = 0x20;
|
||||||
|
|
||||||
for (i = 0; i < 13; i++)
|
for (i = 0; i < 13; i++)
|
||||||
memset(dev->ld_regs[i], 0, 256);
|
memset(dev->ld_regs[i], 0, 256);
|
||||||
|
|
||||||
/* Logical device 0: FDD */
|
/* Logical device 0: FDD */
|
||||||
dev->ld_regs[0][0x60] = 3;
|
dev->ld_regs[0][0x60] = 3;
|
||||||
@@ -208,227 +201,228 @@ ali5123_reset(ali5123_t *dev)
|
|||||||
dev->locked = 0;
|
dev->locked = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ali5123_write(uint16_t port, uint8_t val, void *priv)
|
ali5123_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
ali5123_t *dev = (ali5123_t *) priv;
|
ali5123_t *dev = (ali5123_t *) priv;
|
||||||
uint8_t index = (port & 1) ? 0 : 1;
|
uint8_t index = (port & 1) ? 0 : 1;
|
||||||
uint8_t valxor = 0x00, keep = 0x00;
|
uint8_t valxor = 0x00, keep = 0x00;
|
||||||
uint8_t cur_ld;
|
uint8_t cur_ld;
|
||||||
|
|
||||||
if (index) {
|
if (index) {
|
||||||
if (((val == 0x51) && (!dev->tries) && (!dev->locked)) ||
|
if (((val == 0x51) && (!dev->tries) && (!dev->locked)) || ((val == 0x23) && (dev->tries) && (!dev->locked))) {
|
||||||
((val == 0x23) && (dev->tries) && (!dev->locked))) {
|
if (dev->tries) {
|
||||||
if (dev->tries) {
|
dev->locked = 1;
|
||||||
dev->locked = 1;
|
fdc_3f1_enable(dev->fdc, 0);
|
||||||
fdc_3f1_enable(dev->fdc, 0);
|
dev->tries = 0;
|
||||||
dev->tries = 0;
|
} else
|
||||||
} else
|
dev->tries++;
|
||||||
dev->tries++;
|
} else {
|
||||||
} else {
|
if (dev->locked) {
|
||||||
if (dev->locked) {
|
if (val == 0xbb) {
|
||||||
if (val == 0xbb) {
|
dev->locked = 0;
|
||||||
dev->locked = 0;
|
fdc_3f1_enable(dev->fdc, 1);
|
||||||
fdc_3f1_enable(dev->fdc, 1);
|
return;
|
||||||
return;
|
}
|
||||||
}
|
dev->cur_reg = val;
|
||||||
dev->cur_reg = val;
|
} else {
|
||||||
} else {
|
if (dev->tries)
|
||||||
if (dev->tries)
|
dev->tries = 0;
|
||||||
dev->tries = 0;
|
}
|
||||||
}
|
}
|
||||||
}
|
return;
|
||||||
return;
|
|
||||||
} else {
|
} else {
|
||||||
if (dev->locked) {
|
if (dev->locked) {
|
||||||
if (dev->cur_reg < 48) {
|
if (dev->cur_reg < 48) {
|
||||||
valxor = val ^ dev->regs[dev->cur_reg];
|
valxor = val ^ dev->regs[dev->cur_reg];
|
||||||
if ((val == 0x1f) || (val == 0x20) || (val == 0x21))
|
if ((val == 0x1f) || (val == 0x20) || (val == 0x21))
|
||||||
return;
|
return;
|
||||||
dev->regs[dev->cur_reg] = val;
|
dev->regs[dev->cur_reg] = val;
|
||||||
} else {
|
} else {
|
||||||
valxor = val ^ dev->ld_regs[dev->regs[7]][dev->cur_reg];
|
valxor = val ^ dev->ld_regs[dev->regs[7]][dev->cur_reg];
|
||||||
if (((dev->cur_reg & 0xf0) == 0x70) && (dev->regs[7] < 4))
|
if (((dev->cur_reg & 0xf0) == 0x70) && (dev->regs[7] < 4))
|
||||||
return;
|
return;
|
||||||
/* Block writes to some logical devices. */
|
/* Block writes to some logical devices. */
|
||||||
if (dev->regs[7] > 0x0c)
|
if (dev->regs[7] > 0x0c)
|
||||||
return;
|
return;
|
||||||
else switch (dev->regs[7]) {
|
else
|
||||||
case 0x01: case 0x02: case 0x06: case 0x08:
|
switch (dev->regs[7]) {
|
||||||
case 0x09: case 0x0a:
|
case 0x01:
|
||||||
return;
|
case 0x02:
|
||||||
}
|
case 0x06:
|
||||||
dev->ld_regs[dev->regs[7]][dev->cur_reg] = val | keep;
|
case 0x08:
|
||||||
}
|
case 0x09:
|
||||||
} else
|
case 0x0a:
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
dev->ld_regs[dev->regs[7]][dev->cur_reg] = val | keep;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->cur_reg < 48) {
|
if (dev->cur_reg < 48) {
|
||||||
switch(dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0x02:
|
case 0x02:
|
||||||
if (val & 0x01)
|
if (val & 0x01)
|
||||||
ali5123_reset(dev);
|
ali5123_reset(dev);
|
||||||
dev->regs[0x02] = 0x00;
|
dev->regs[0x02] = 0x00;
|
||||||
break;
|
break;
|
||||||
case 0x22:
|
case 0x22:
|
||||||
if (valxor & 0x01)
|
if (valxor & 0x01)
|
||||||
ali5123_fdc_handler(dev);
|
ali5123_fdc_handler(dev);
|
||||||
if (valxor & 0x08)
|
if (valxor & 0x08)
|
||||||
ali5123_lpt_handler(dev);
|
ali5123_lpt_handler(dev);
|
||||||
if (valxor & 0x10)
|
if (valxor & 0x10)
|
||||||
ali5123_serial_handler(dev, 0);
|
ali5123_serial_handler(dev, 0);
|
||||||
if (valxor & 0x20)
|
if (valxor & 0x20)
|
||||||
ali5123_serial_handler(dev, 1);
|
ali5123_serial_handler(dev, 1);
|
||||||
if (valxor & 0x40)
|
if (valxor & 0x40)
|
||||||
ali5123_serial_handler(dev, 2);
|
ali5123_serial_handler(dev, 2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_ld = dev->regs[7];
|
cur_ld = dev->regs[7];
|
||||||
if ((dev->regs[7] == 5) && (dev->regs[0x2d] & 0x20))
|
if ((dev->regs[7] == 5) && (dev->regs[0x2d] & 0x20))
|
||||||
cur_ld = 0x0b;
|
cur_ld = 0x0b;
|
||||||
else if ((dev->regs[7] == 0x0b) && (dev->regs[0x2d] & 0x20))
|
else if ((dev->regs[7] == 0x0b) && (dev->regs[0x2d] & 0x20))
|
||||||
cur_ld = 5;
|
cur_ld = 5;
|
||||||
switch(cur_ld) {
|
switch (cur_ld) {
|
||||||
case 0:
|
case 0:
|
||||||
/* FDD */
|
/* FDD */
|
||||||
switch(dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0x30:
|
case 0x30:
|
||||||
case 0x60:
|
case 0x60:
|
||||||
case 0x61:
|
case 0x61:
|
||||||
if ((dev->cur_reg == 0x30) && (val & 0x01))
|
if ((dev->cur_reg == 0x30) && (val & 0x01))
|
||||||
dev->regs[0x22] |= 0x01;
|
dev->regs[0x22] |= 0x01;
|
||||||
if (valxor)
|
if (valxor)
|
||||||
ali5123_fdc_handler(dev);
|
ali5123_fdc_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 0xf0:
|
case 0xf0:
|
||||||
if (valxor & 0x08)
|
if (valxor & 0x08)
|
||||||
fdc_update_enh_mode(dev->fdc, !(val & 0x08));
|
fdc_update_enh_mode(dev->fdc, !(val & 0x08));
|
||||||
if (valxor & 0x10)
|
if (valxor & 0x10)
|
||||||
fdc_set_swap(dev->fdc, (val & 0x10) >> 4);
|
fdc_set_swap(dev->fdc, (val & 0x10) >> 4);
|
||||||
break;
|
break;
|
||||||
case 0xf1:
|
case 0xf1:
|
||||||
if (valxor & 0xc)
|
if (valxor & 0xc)
|
||||||
fdc_update_densel_force(dev->fdc, (val & 0xc) >> 2);
|
fdc_update_densel_force(dev->fdc, (val & 0xc) >> 2);
|
||||||
break;
|
break;
|
||||||
case 0xf4:
|
case 0xf4:
|
||||||
if (valxor & 0x08)
|
if (valxor & 0x08)
|
||||||
fdc_update_drvrate(dev->fdc, 0, (val & 0x08) >> 3);
|
fdc_update_drvrate(dev->fdc, 0, (val & 0x08) >> 3);
|
||||||
break;
|
break;
|
||||||
case 0xf5:
|
case 0xf5:
|
||||||
if (valxor & 0x08)
|
if (valxor & 0x08)
|
||||||
fdc_update_drvrate(dev->fdc, 1, (val & 0x08) >> 3);
|
fdc_update_drvrate(dev->fdc, 1, (val & 0x08) >> 3);
|
||||||
break;
|
break;
|
||||||
case 0xf6:
|
case 0xf6:
|
||||||
if (valxor & 0x08)
|
if (valxor & 0x08)
|
||||||
fdc_update_drvrate(dev->fdc, 2, (val & 0x08) >> 3);
|
fdc_update_drvrate(dev->fdc, 2, (val & 0x08) >> 3);
|
||||||
break;
|
break;
|
||||||
case 0xf7:
|
case 0xf7:
|
||||||
if (valxor & 0x08)
|
if (valxor & 0x08)
|
||||||
fdc_update_drvrate(dev->fdc, 3, (val & 0x08) >> 3);
|
fdc_update_drvrate(dev->fdc, 3, (val & 0x08) >> 3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
/* Parallel port */
|
/* Parallel port */
|
||||||
switch(dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0x30:
|
case 0x30:
|
||||||
case 0x60:
|
case 0x60:
|
||||||
case 0x61:
|
case 0x61:
|
||||||
case 0x70:
|
case 0x70:
|
||||||
if ((dev->cur_reg == 0x30) && (val & 0x01))
|
if ((dev->cur_reg == 0x30) && (val & 0x01))
|
||||||
dev->regs[0x22] |= 0x08;
|
dev->regs[0x22] |= 0x08;
|
||||||
if (valxor)
|
if (valxor)
|
||||||
ali5123_lpt_handler(dev);
|
ali5123_lpt_handler(dev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
/* Serial port 1 */
|
/* Serial port 1 */
|
||||||
switch(dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0x30:
|
case 0x30:
|
||||||
case 0x60:
|
case 0x60:
|
||||||
case 0x61:
|
case 0x61:
|
||||||
case 0x70:
|
case 0x70:
|
||||||
case 0xf0:
|
case 0xf0:
|
||||||
if ((dev->cur_reg == 0x30) && (val & 0x01))
|
if ((dev->cur_reg == 0x30) && (val & 0x01))
|
||||||
dev->regs[0x22] |= 0x10;
|
dev->regs[0x22] |= 0x10;
|
||||||
if (valxor)
|
if (valxor)
|
||||||
ali5123_serial_handler(dev, 0);
|
ali5123_serial_handler(dev, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
/* Serial port 2 - HP like module */
|
/* Serial port 2 - HP like module */
|
||||||
switch(dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0x30:
|
case 0x30:
|
||||||
case 0x60:
|
case 0x60:
|
||||||
case 0x61:
|
case 0x61:
|
||||||
case 0x70:
|
case 0x70:
|
||||||
case 0xf0:
|
case 0xf0:
|
||||||
if ((dev->cur_reg == 0x30) && (val & 0x01))
|
if ((dev->cur_reg == 0x30) && (val & 0x01))
|
||||||
dev->regs[0x22] |= 0x20;
|
dev->regs[0x22] |= 0x20;
|
||||||
if (valxor)
|
if (valxor)
|
||||||
ali5123_serial_handler(dev, 1);
|
ali5123_serial_handler(dev, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x0b:
|
case 0x0b:
|
||||||
/* Serial port 3 */
|
/* Serial port 3 */
|
||||||
switch(dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0x30:
|
case 0x30:
|
||||||
case 0x60:
|
case 0x60:
|
||||||
case 0x61:
|
case 0x61:
|
||||||
case 0x70:
|
case 0x70:
|
||||||
case 0xf0:
|
case 0xf0:
|
||||||
if ((dev->cur_reg == 0x30) && (val & 0x01))
|
if ((dev->cur_reg == 0x30) && (val & 0x01))
|
||||||
dev->regs[0x22] |= 0x40;
|
dev->regs[0x22] |= 0x40;
|
||||||
if (valxor)
|
if (valxor)
|
||||||
ali5123_serial_handler(dev, 2);
|
ali5123_serial_handler(dev, 2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
ali5123_read(uint16_t port, void *priv)
|
ali5123_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
ali5123_t *dev = (ali5123_t *) priv;
|
ali5123_t *dev = (ali5123_t *) priv;
|
||||||
uint8_t index = (port & 1) ? 0 : 1;
|
uint8_t index = (port & 1) ? 0 : 1;
|
||||||
uint8_t ret = 0xff, cur_ld;
|
uint8_t ret = 0xff, cur_ld;
|
||||||
|
|
||||||
if (dev->locked) {
|
if (dev->locked) {
|
||||||
if (index)
|
if (index)
|
||||||
ret = dev->cur_reg;
|
ret = dev->cur_reg;
|
||||||
else {
|
else {
|
||||||
if (dev->cur_reg < 0x30) {
|
if (dev->cur_reg < 0x30) {
|
||||||
if (dev->cur_reg == 0x20)
|
if (dev->cur_reg == 0x20)
|
||||||
ret = dev->chip_id;
|
ret = dev->chip_id;
|
||||||
else
|
else
|
||||||
ret = dev->regs[dev->cur_reg];
|
ret = dev->regs[dev->cur_reg];
|
||||||
} else {
|
} else {
|
||||||
cur_ld = dev->regs[7];
|
cur_ld = dev->regs[7];
|
||||||
if ((dev->regs[7] == 5) && (dev->regs[0x2d] & 0x20))
|
if ((dev->regs[7] == 5) && (dev->regs[0x2d] & 0x20))
|
||||||
cur_ld = 0x0b;
|
cur_ld = 0x0b;
|
||||||
else if ((dev->regs[7] == 0x0b) && (dev->regs[0x2d] & 0x20))
|
else if ((dev->regs[7] == 0x0b) && (dev->regs[0x2d] & 0x20))
|
||||||
cur_ld = 5;
|
cur_ld = 5;
|
||||||
|
|
||||||
ret = dev->ld_regs[cur_ld][dev->cur_reg];
|
ret = dev->ld_regs[cur_ld][dev->cur_reg];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ali5123_close(void *priv)
|
ali5123_close(void *priv)
|
||||||
{
|
{
|
||||||
@@ -437,7 +431,6 @@ ali5123_close(void *priv)
|
|||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
ali5123_init(const device_t *info)
|
ali5123_init(const device_t *info)
|
||||||
{
|
{
|
||||||
@@ -455,24 +448,23 @@ ali5123_init(const device_t *info)
|
|||||||
ali5123_reset(dev);
|
ali5123_reset(dev);
|
||||||
|
|
||||||
io_sethandler(FDC_PRIMARY_ADDR, 0x0002,
|
io_sethandler(FDC_PRIMARY_ADDR, 0x0002,
|
||||||
ali5123_read, NULL, NULL, ali5123_write, NULL, NULL, dev);
|
ali5123_read, NULL, NULL, ali5123_write, NULL, NULL, dev);
|
||||||
|
|
||||||
device_add(&keyboard_ps2_ali_pci_device);
|
device_add(&keyboard_ps2_ali_pci_device);
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const device_t ali5123_device = {
|
const device_t ali5123_device = {
|
||||||
.name = "ALi M5123/M1543C Super I/O",
|
.name = "ALi M5123/M1543C Super I/O",
|
||||||
.internal_name = "ali5123",
|
.internal_name = "ali5123",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x40,
|
.local = 0x40,
|
||||||
.init = ali5123_init,
|
.init = ali5123_init,
|
||||||
.close = ali5123_close,
|
.close = ali5123_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,12 +27,10 @@
|
|||||||
#include <86box/fdc.h>
|
#include <86box/fdc.h>
|
||||||
#include <86box/sio.h>
|
#include <86box/sio.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t regs[2];
|
uint8_t regs[2];
|
||||||
} sio_detect_t;
|
} sio_detect_t;
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sio_detect_write(uint16_t port, uint8_t val, void *priv)
|
sio_detect_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
@@ -45,7 +43,6 @@ sio_detect_write(uint16_t port, uint8_t val, void *priv)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
sio_detect_read(uint16_t port, void *priv)
|
sio_detect_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
@@ -56,7 +53,6 @@ sio_detect_read(uint16_t port, void *priv)
|
|||||||
return 0xff /*dev->regs[port & 1]*/;
|
return 0xff /*dev->regs[port & 1]*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sio_detect_close(void *priv)
|
sio_detect_close(void *priv)
|
||||||
{
|
{
|
||||||
@@ -65,7 +61,6 @@ sio_detect_close(void *priv)
|
|||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
sio_detect_init(const device_t *info)
|
sio_detect_init(const device_t *info)
|
||||||
{
|
{
|
||||||
@@ -75,48 +70,47 @@ sio_detect_init(const device_t *info)
|
|||||||
device_add(&fdc_at_smc_device);
|
device_add(&fdc_at_smc_device);
|
||||||
|
|
||||||
io_sethandler(0x0022, 0x0006,
|
io_sethandler(0x0022, 0x0006,
|
||||||
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
||||||
io_sethandler(0x002e, 0x0002,
|
io_sethandler(0x002e, 0x0002,
|
||||||
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
||||||
io_sethandler(0x0044, 0x0004,
|
io_sethandler(0x0044, 0x0004,
|
||||||
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
||||||
io_sethandler(0x004e, 0x0002,
|
io_sethandler(0x004e, 0x0002,
|
||||||
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
||||||
io_sethandler(0x0108, 0x0002,
|
io_sethandler(0x0108, 0x0002,
|
||||||
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
||||||
io_sethandler(0x015c, 0x0002,
|
io_sethandler(0x015c, 0x0002,
|
||||||
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
||||||
io_sethandler(0x0250, 0x0003,
|
io_sethandler(0x0250, 0x0003,
|
||||||
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
||||||
io_sethandler(0x026e, 0x0002,
|
io_sethandler(0x026e, 0x0002,
|
||||||
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
||||||
io_sethandler(0x0279, 0x0001,
|
io_sethandler(0x0279, 0x0001,
|
||||||
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
||||||
io_sethandler(FDC_SECONDARY_ADDR, 0x0002,
|
io_sethandler(FDC_SECONDARY_ADDR, 0x0002,
|
||||||
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
||||||
io_sethandler(0x0398, 0x0002,
|
io_sethandler(0x0398, 0x0002,
|
||||||
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
||||||
io_sethandler(0x03e3, 0x0001,
|
io_sethandler(0x03e3, 0x0001,
|
||||||
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
||||||
io_sethandler(FDC_PRIMARY_ADDR, 0x0002,
|
io_sethandler(FDC_PRIMARY_ADDR, 0x0002,
|
||||||
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
||||||
io_sethandler(0x0a79, 0x0001,
|
io_sethandler(0x0a79, 0x0001,
|
||||||
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const device_t sio_detect_device = {
|
const device_t sio_detect_device = {
|
||||||
.name = "Super I/O Detection Helper",
|
.name = "Super I/O Detection Helper",
|
||||||
.internal_name = "sio_detect",
|
.internal_name = "sio_detect",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0,
|
.local = 0,
|
||||||
.init = sio_detect_init,
|
.init = sio_detect_init,
|
||||||
.close = sio_detect_close,
|
.close = sio_detect_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -43,26 +43,23 @@
|
|||||||
#include <86box/nvr.h>
|
#include <86box/nvr.h>
|
||||||
#include <86box/sio.h>
|
#include <86box/sio.h>
|
||||||
|
|
||||||
|
typedef struct upc_t {
|
||||||
typedef struct upc_t
|
uint32_t local;
|
||||||
{
|
int configuration_state; /* state of algorithm to enter configuration mode */
|
||||||
uint32_t local;
|
int configuration_mode;
|
||||||
int configuration_state; /* state of algorithm to enter configuration mode */
|
uint16_t cri_addr; /* cri = configuration index register, addr is even */
|
||||||
int configuration_mode;
|
uint16_t cap_addr; /* cap = configuration access port, addr is odd and is cri_addr + 1 */
|
||||||
uint16_t cri_addr; /* cri = configuration index register, addr is even */
|
uint8_t cri; /* currently indexed register */
|
||||||
uint16_t cap_addr; /* cap = configuration access port, addr is odd and is cri_addr + 1 */
|
uint8_t last_write;
|
||||||
uint8_t cri; /* currently indexed register */
|
|
||||||
uint8_t last_write;
|
|
||||||
|
|
||||||
/* these regs are not affected by reset */
|
/* these regs are not affected by reset */
|
||||||
uint8_t regs[15]; /* there are 16 indexes, but there is no need to store the last one which is: R = cri_addr / 4, W = exit config mode */
|
uint8_t regs[15]; /* there are 16 indexes, but there is no need to store the last one which is: R = cri_addr / 4, W = exit config mode */
|
||||||
fdc_t * fdc;
|
fdc_t *fdc;
|
||||||
nvr_t * nvr;
|
nvr_t *nvr;
|
||||||
void * gameport;
|
void *gameport;
|
||||||
serial_t * uart[2];
|
serial_t *uart[2];
|
||||||
} upc_t;
|
} upc_t;
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
f82c710_update_ports(upc_t *dev, int set)
|
f82c710_update_ports(upc_t *dev, int set)
|
||||||
{
|
{
|
||||||
@@ -77,40 +74,39 @@ f82c710_update_ports(upc_t *dev, int set)
|
|||||||
ide_pri_disable();
|
ide_pri_disable();
|
||||||
|
|
||||||
if (!set)
|
if (!set)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (dev->regs[0] & 4) {
|
if (dev->regs[0] & 4) {
|
||||||
com_addr = dev->regs[4] * 4;
|
com_addr = dev->regs[4] * 4;
|
||||||
if (com_addr == COM1_ADDR)
|
if (com_addr == COM1_ADDR)
|
||||||
serial_setup(dev->uart[0], com_addr, COM1_IRQ);
|
serial_setup(dev->uart[0], com_addr, COM1_IRQ);
|
||||||
else if (com_addr == COM2_ADDR)
|
else if (com_addr == COM2_ADDR)
|
||||||
serial_setup(dev->uart[1], com_addr, COM2_IRQ);
|
serial_setup(dev->uart[1], com_addr, COM2_IRQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->regs[0] & 8) {
|
if (dev->regs[0] & 8) {
|
||||||
lpt_addr = dev->regs[6] * 4;
|
lpt_addr = dev->regs[6] * 4;
|
||||||
lpt1_init(lpt_addr);
|
lpt1_init(lpt_addr);
|
||||||
if ((lpt_addr == LPT1_ADDR) || (lpt_addr == LPT_MDA_ADDR))
|
if ((lpt_addr == LPT1_ADDR) || (lpt_addr == LPT_MDA_ADDR))
|
||||||
lpt1_irq(LPT1_IRQ);
|
lpt1_irq(LPT1_IRQ);
|
||||||
else if (lpt_addr == LPT2_ADDR)
|
else if (lpt_addr == LPT2_ADDR)
|
||||||
lpt1_irq(LPT2_IRQ);
|
lpt1_irq(LPT2_IRQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->regs[12] & 0x80)
|
if (dev->regs[12] & 0x80)
|
||||||
ide_pri_enable();
|
ide_pri_enable();
|
||||||
|
|
||||||
if (dev->regs[12] & 0x20)
|
if (dev->regs[12] & 0x20)
|
||||||
fdc_set_base(dev->fdc, FDC_PRIMARY_ADDR);
|
fdc_set_base(dev->fdc, FDC_PRIMARY_ADDR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
f82c606_update_ports(upc_t *dev, int set)
|
f82c606_update_ports(upc_t *dev, int set)
|
||||||
{
|
{
|
||||||
uint8_t uart1_int = 0xff;
|
uint8_t uart1_int = 0xff;
|
||||||
uint8_t uart2_int = 0xff;
|
uint8_t uart2_int = 0xff;
|
||||||
uint8_t lpt1_int = 0xff;
|
uint8_t lpt1_int = 0xff;
|
||||||
int nvr_int = -1;
|
int nvr_int = -1;
|
||||||
|
|
||||||
serial_remove(dev->uart[0]);
|
serial_remove(dev->uart[0]);
|
||||||
serial_remove(dev->uart[1]);
|
serial_remove(dev->uart[1]);
|
||||||
@@ -123,51 +119,75 @@ f82c606_update_ports(upc_t *dev, int set)
|
|||||||
gameport_remap(dev->gameport, 0);
|
gameport_remap(dev->gameport, 0);
|
||||||
|
|
||||||
if (!set)
|
if (!set)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (dev->regs[8] & 0xc0) {
|
switch (dev->regs[8] & 0xc0) {
|
||||||
case 0x40: nvr_int = 3; break;
|
case 0x40:
|
||||||
case 0x80: uart1_int = COM2_IRQ; break;
|
nvr_int = 3;
|
||||||
case 0xc0: uart2_int = COM2_IRQ; break;
|
break;
|
||||||
|
case 0x80:
|
||||||
|
uart1_int = COM2_IRQ;
|
||||||
|
break;
|
||||||
|
case 0xc0:
|
||||||
|
uart2_int = COM2_IRQ;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (dev->regs[8] & 0x30) {
|
switch (dev->regs[8] & 0x30) {
|
||||||
case 0x10: nvr_int = 4; break;
|
case 0x10:
|
||||||
case 0x20: uart1_int = COM1_IRQ; break;
|
nvr_int = 4;
|
||||||
case 0x30: uart2_int = COM1_IRQ; break;
|
break;
|
||||||
|
case 0x20:
|
||||||
|
uart1_int = COM1_IRQ;
|
||||||
|
break;
|
||||||
|
case 0x30:
|
||||||
|
uart2_int = COM1_IRQ;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (dev->regs[8] & 0x0c) {
|
switch (dev->regs[8] & 0x0c) {
|
||||||
case 0x04: nvr_int = 5; break;
|
case 0x04:
|
||||||
case 0x08: uart1_int = 5; break;
|
nvr_int = 5;
|
||||||
case 0x0c: lpt1_int = LPT2_IRQ; break;
|
break;
|
||||||
|
case 0x08:
|
||||||
|
uart1_int = 5;
|
||||||
|
break;
|
||||||
|
case 0x0c:
|
||||||
|
lpt1_int = LPT2_IRQ;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (dev->regs[8] & 0x03) {
|
switch (dev->regs[8] & 0x03) {
|
||||||
case 0x01: nvr_int = 7; break;
|
case 0x01:
|
||||||
case 0x02: uart2_int = 7; break;
|
nvr_int = 7;
|
||||||
case 0x03: lpt1_int = LPT1_IRQ; break;
|
break;
|
||||||
|
case 0x02:
|
||||||
|
uart2_int = 7;
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
lpt1_int = LPT1_IRQ;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->regs[0] & 1) {
|
if (dev->regs[0] & 1) {
|
||||||
gameport_remap(dev->gameport, ((uint16_t) dev->regs[7]) << 2);
|
gameport_remap(dev->gameport, ((uint16_t) dev->regs[7]) << 2);
|
||||||
pclog("Game port at %04X\n", ((uint16_t) dev->regs[7]) << 2);
|
pclog("Game port at %04X\n", ((uint16_t) dev->regs[7]) << 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->regs[0] & 2) {
|
if (dev->regs[0] & 2) {
|
||||||
serial_setup(dev->uart[0], ((uint16_t) dev->regs[4]) << 2, uart1_int);
|
serial_setup(dev->uart[0], ((uint16_t) dev->regs[4]) << 2, uart1_int);
|
||||||
pclog("UART 1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[4]) << 2, uart1_int);
|
pclog("UART 1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[4]) << 2, uart1_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->regs[0] & 4) {
|
if (dev->regs[0] & 4) {
|
||||||
serial_setup(dev->uart[1], ((uint16_t) dev->regs[5]) << 2, uart2_int);
|
serial_setup(dev->uart[1], ((uint16_t) dev->regs[5]) << 2, uart2_int);
|
||||||
pclog("UART 2 at %04X, IRQ %i\n", ((uint16_t) dev->regs[5]) << 2, uart2_int);
|
pclog("UART 2 at %04X, IRQ %i\n", ((uint16_t) dev->regs[5]) << 2, uart2_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->regs[0] & 8) {
|
if (dev->regs[0] & 8) {
|
||||||
lpt1_init(((uint16_t) dev->regs[6]) << 2);
|
lpt1_init(((uint16_t) dev->regs[6]) << 2);
|
||||||
lpt1_irq(lpt1_int);
|
lpt1_irq(lpt1_int);
|
||||||
pclog("LPT1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[6]) << 2, lpt1_int);
|
pclog("LPT1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[6]) << 2, lpt1_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
nvr_at_handler(1, ((uint16_t) dev->regs[3]) << 2, dev->nvr);
|
nvr_at_handler(1, ((uint16_t) dev->regs[3]) << 2, dev->nvr);
|
||||||
@@ -175,97 +195,94 @@ f82c606_update_ports(upc_t *dev, int set)
|
|||||||
pclog("RTC at %04X, IRQ %i\n", ((uint16_t) dev->regs[3]) << 2, nvr_int);
|
pclog("RTC at %04X, IRQ %i\n", ((uint16_t) dev->regs[3]) << 2, nvr_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
f82c710_config_read(uint16_t port, void *priv)
|
f82c710_config_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
upc_t *dev = (upc_t *) priv;
|
upc_t *dev = (upc_t *) priv;
|
||||||
uint8_t temp = 0xff;
|
uint8_t temp = 0xff;
|
||||||
|
|
||||||
if (dev->configuration_mode) {
|
if (dev->configuration_mode) {
|
||||||
if (port == dev->cri_addr) {
|
if (port == dev->cri_addr) {
|
||||||
temp = dev->cri;
|
temp = dev->cri;
|
||||||
} else if (port == dev->cap_addr) {
|
} else if (port == dev->cap_addr) {
|
||||||
if (dev->cri == 0xf)
|
if (dev->cri == 0xf)
|
||||||
temp = dev->cri_addr / 4;
|
temp = dev->cri_addr / 4;
|
||||||
else
|
else
|
||||||
temp = dev->regs[dev->cri];
|
temp = dev->regs[dev->cri];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
f82c710_config_write(uint16_t port, uint8_t val, void *priv)
|
f82c710_config_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
upc_t *dev = (upc_t *) priv;
|
upc_t *dev = (upc_t *) priv;
|
||||||
int configuration_state_event = 0;
|
int configuration_state_event = 0;
|
||||||
|
|
||||||
switch (port) {
|
switch (port) {
|
||||||
case 0x2fa:
|
case 0x2fa:
|
||||||
if ((dev->configuration_state == 0) && (val != 0x00) && (val != 0xff) && (dev->local == 606)) {
|
if ((dev->configuration_state == 0) && (val != 0x00) && (val != 0xff) && (dev->local == 606)) {
|
||||||
configuration_state_event = 1;
|
configuration_state_event = 1;
|
||||||
dev->last_write = val;
|
dev->last_write = val;
|
||||||
} else if ((dev->configuration_state == 0) && (val == 0x55) && (dev->local == 710))
|
} else if ((dev->configuration_state == 0) && (val == 0x55) && (dev->local == 710))
|
||||||
configuration_state_event = 1;
|
configuration_state_event = 1;
|
||||||
else if (dev->configuration_state == 4) {
|
else if (dev->configuration_state == 4) {
|
||||||
if ((val | dev->last_write) == 0xff) {
|
if ((val | dev->last_write) == 0xff) {
|
||||||
dev->cri_addr = ((uint16_t) dev->last_write) << 2;
|
dev->cri_addr = ((uint16_t) dev->last_write) << 2;
|
||||||
dev->cap_addr = dev->cri_addr + 1;
|
dev->cap_addr = dev->cri_addr + 1;
|
||||||
dev->configuration_mode = 1;
|
dev->configuration_mode = 1;
|
||||||
if (dev->local == 606)
|
if (dev->local == 606)
|
||||||
f82c606_update_ports(dev, 0);
|
f82c606_update_ports(dev, 0);
|
||||||
else if (dev->local == 710)
|
else if (dev->local == 710)
|
||||||
f82c710_update_ports(dev, 0);
|
f82c710_update_ports(dev, 0);
|
||||||
/* TODO: is the value of cri reset here or when exiting configuration mode? */
|
/* TODO: is the value of cri reset here or when exiting configuration mode? */
|
||||||
io_sethandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev);
|
io_sethandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev);
|
||||||
} else
|
} else
|
||||||
dev->configuration_mode = 0;
|
dev->configuration_mode = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x3fa:
|
case 0x3fa:
|
||||||
if ((dev->configuration_state == 1) && ((val | dev->last_write) == 0xff) && (dev->local == 606))
|
if ((dev->configuration_state == 1) && ((val | dev->last_write) == 0xff) && (dev->local == 606))
|
||||||
configuration_state_event = 1;
|
configuration_state_event = 1;
|
||||||
else if ((dev->configuration_state == 1) && (val == 0xaa) && (dev->local == 710))
|
else if ((dev->configuration_state == 1) && (val == 0xaa) && (dev->local == 710))
|
||||||
configuration_state_event = 1;
|
configuration_state_event = 1;
|
||||||
else if ((dev->configuration_state == 2) && (val == 0x36))
|
else if ((dev->configuration_state == 2) && (val == 0x36))
|
||||||
configuration_state_event = 1;
|
configuration_state_event = 1;
|
||||||
else if (dev->configuration_state == 3) {
|
else if (dev->configuration_state == 3) {
|
||||||
dev->last_write = val;
|
dev->last_write = val;
|
||||||
configuration_state_event = 1;
|
configuration_state_event = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->configuration_mode) {
|
if (dev->configuration_mode) {
|
||||||
if (port == dev->cri_addr) {
|
if (port == dev->cri_addr) {
|
||||||
dev->cri = val & 0xf;
|
dev->cri = val & 0xf;
|
||||||
} else if (port == dev->cap_addr) {
|
} else if (port == dev->cap_addr) {
|
||||||
if (dev->cri == 0xf) {
|
if (dev->cri == 0xf) {
|
||||||
dev->configuration_mode = 0;
|
dev->configuration_mode = 0;
|
||||||
io_removehandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev);
|
io_removehandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev);
|
||||||
/* TODO: any benefit in updating at each register write instead of when exiting config mode? */
|
/* TODO: any benefit in updating at each register write instead of when exiting config mode? */
|
||||||
if (dev->local == 606)
|
if (dev->local == 606)
|
||||||
f82c606_update_ports(dev, 1);
|
f82c606_update_ports(dev, 1);
|
||||||
else if (dev->local == 710)
|
else if (dev->local == 710)
|
||||||
f82c710_update_ports(dev, 1);
|
f82c710_update_ports(dev, 1);
|
||||||
} else
|
} else
|
||||||
dev->regs[dev->cri] = val;
|
dev->regs[dev->cri] = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: is the state only reset when accessing 0x2fa and 0x3fa wrongly? */
|
/* TODO: is the state only reset when accessing 0x2fa and 0x3fa wrongly? */
|
||||||
if ((port == 0x2fa || port == 0x3fa) && configuration_state_event)
|
if ((port == 0x2fa || port == 0x3fa) && configuration_state_event)
|
||||||
dev->configuration_state++;
|
dev->configuration_state++;
|
||||||
else
|
else
|
||||||
dev->configuration_state = 0;
|
dev->configuration_state = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
f82c710_reset(void *priv)
|
f82c710_reset(void *priv)
|
||||||
{
|
{
|
||||||
@@ -273,40 +290,39 @@ f82c710_reset(void *priv)
|
|||||||
|
|
||||||
/* Set power-on defaults. */
|
/* Set power-on defaults. */
|
||||||
if (dev->local == 606) {
|
if (dev->local == 606) {
|
||||||
dev->regs[0] = 0x00; /* Enable */
|
dev->regs[0] = 0x00; /* Enable */
|
||||||
dev->regs[1] = 0x00; /* Configuration Register */
|
dev->regs[1] = 0x00; /* Configuration Register */
|
||||||
dev->regs[2] = 0x00; /* Ext Baud Rate Select */
|
dev->regs[2] = 0x00; /* Ext Baud Rate Select */
|
||||||
dev->regs[3] = 0xb0; /* RTC Base */
|
dev->regs[3] = 0xb0; /* RTC Base */
|
||||||
dev->regs[4] = 0xfe; /* UART1 Base */
|
dev->regs[4] = 0xfe; /* UART1 Base */
|
||||||
dev->regs[5] = 0xbe; /* UART2 Base */
|
dev->regs[5] = 0xbe; /* UART2 Base */
|
||||||
dev->regs[6] = 0x9e; /* Parallel Base */
|
dev->regs[6] = 0x9e; /* Parallel Base */
|
||||||
dev->regs[7] = 0x80; /* Game Base */
|
dev->regs[7] = 0x80; /* Game Base */
|
||||||
dev->regs[8] = 0xec; /* Interrupt Select */
|
dev->regs[8] = 0xec; /* Interrupt Select */
|
||||||
} else if (dev->local == 710) {
|
} else if (dev->local == 710) {
|
||||||
dev->regs[0] = 0x0c;
|
dev->regs[0] = 0x0c;
|
||||||
dev->regs[1] = 0x00;
|
dev->regs[1] = 0x00;
|
||||||
dev->regs[2] = 0x00;
|
dev->regs[2] = 0x00;
|
||||||
dev->regs[3] = 0x00;
|
dev->regs[3] = 0x00;
|
||||||
dev->regs[4] = 0xfe;
|
dev->regs[4] = 0xfe;
|
||||||
dev->regs[5] = 0x00;
|
dev->regs[5] = 0x00;
|
||||||
dev->regs[6] = 0x9e;
|
dev->regs[6] = 0x9e;
|
||||||
dev->regs[7] = 0x00;
|
dev->regs[7] = 0x00;
|
||||||
dev->regs[8] = 0x00;
|
dev->regs[8] = 0x00;
|
||||||
dev->regs[9] = 0xb0;
|
dev->regs[9] = 0xb0;
|
||||||
dev->regs[10] = 0x00;
|
dev->regs[10] = 0x00;
|
||||||
dev->regs[11] = 0x00;
|
dev->regs[11] = 0x00;
|
||||||
dev->regs[12] = 0xa0;
|
dev->regs[12] = 0xa0;
|
||||||
dev->regs[13] = 0x00;
|
dev->regs[13] = 0x00;
|
||||||
dev->regs[14] = 0x00;
|
dev->regs[14] = 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->local == 606)
|
if (dev->local == 606)
|
||||||
f82c606_update_ports(dev, 1);
|
f82c606_update_ports(dev, 1);
|
||||||
else if (dev->local == 710)
|
else if (dev->local == 710)
|
||||||
f82c710_update_ports(dev, 1);
|
f82c710_update_ports(dev, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
f82c710_close(void *priv)
|
f82c710_close(void *priv)
|
||||||
{
|
{
|
||||||
@@ -315,7 +331,6 @@ f82c710_close(void *priv)
|
|||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
f82c710_init(const device_t *info)
|
f82c710_init(const device_t *info)
|
||||||
{
|
{
|
||||||
@@ -324,10 +339,10 @@ f82c710_init(const device_t *info)
|
|||||||
dev->local = info->local;
|
dev->local = info->local;
|
||||||
|
|
||||||
if (dev->local == 606) {
|
if (dev->local == 606) {
|
||||||
dev->nvr = device_add(&at_nvr_old_device);
|
dev->nvr = device_add(&at_nvr_old_device);
|
||||||
dev->gameport = gameport_add(&gameport_sio_device);
|
dev->gameport = gameport_add(&gameport_sio_device);
|
||||||
} else if (dev->local == 710)
|
} else if (dev->local == 710)
|
||||||
dev->fdc = device_add(&fdc_at_device);
|
dev->fdc = device_add(&fdc_at_device);
|
||||||
|
|
||||||
dev->uart[0] = device_add_inst(&ns16450_device, 1);
|
dev->uart[0] = device_add_inst(&ns16450_device, 1);
|
||||||
dev->uart[1] = device_add_inst(&ns16450_device, 2);
|
dev->uart[1] = device_add_inst(&ns16450_device, 2);
|
||||||
@@ -341,29 +356,29 @@ f82c710_init(const device_t *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const device_t f82c606_device = {
|
const device_t f82c606_device = {
|
||||||
.name = "82C606 CHIPSpak Multifunction Controller",
|
.name = "82C606 CHIPSpak Multifunction Controller",
|
||||||
.internal_name = "f82c606",
|
.internal_name = "f82c606",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 606,
|
.local = 606,
|
||||||
.init = f82c710_init,
|
.init = f82c710_init,
|
||||||
.close = f82c710_close,
|
.close = f82c710_close,
|
||||||
.reset = f82c710_reset,
|
.reset = f82c710_reset,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t f82c710_device = {
|
const device_t f82c710_device = {
|
||||||
.name = "F82C710 UPC Super I/O",
|
.name = "F82C710 UPC Super I/O",
|
||||||
.internal_name = "f82c710",
|
.internal_name = "f82c710",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 710,
|
.local = 710,
|
||||||
.init = f82c710_init,
|
.init = f82c710_init,
|
||||||
.close = f82c710_close,
|
.close = f82c710_close,
|
||||||
.reset = f82c710_reset,
|
.reset = f82c710_reset,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -31,217 +31,211 @@
|
|||||||
#include <86box/fdc.h>
|
#include <86box/fdc.h>
|
||||||
#include <86box/sio.h>
|
#include <86box/sio.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t id, tries,
|
uint8_t id, tries,
|
||||||
regs[42];
|
regs[42];
|
||||||
int locked, rw_locked,
|
int locked, rw_locked,
|
||||||
cur_reg;
|
cur_reg;
|
||||||
fdc_t *fdc;
|
fdc_t *fdc;
|
||||||
serial_t *uart[2];
|
serial_t *uart[2];
|
||||||
} fdc37c669_t;
|
} fdc37c669_t;
|
||||||
|
|
||||||
|
static int next_id = 0;
|
||||||
static int next_id = 0;
|
|
||||||
|
|
||||||
|
|
||||||
static uint16_t
|
static uint16_t
|
||||||
make_port(fdc37c669_t *dev, uint8_t reg)
|
make_port(fdc37c669_t *dev, uint8_t reg)
|
||||||
{
|
{
|
||||||
uint16_t p = 0;
|
uint16_t p = 0;
|
||||||
uint16_t mask = 0;
|
uint16_t mask = 0;
|
||||||
|
|
||||||
switch(reg) {
|
switch (reg) {
|
||||||
case 0x20:
|
case 0x20:
|
||||||
case 0x21:
|
case 0x21:
|
||||||
case 0x22:
|
case 0x22:
|
||||||
mask = 0xfc;
|
mask = 0xfc;
|
||||||
break;
|
break;
|
||||||
case 0x23:
|
case 0x23:
|
||||||
mask = 0xff;
|
mask = 0xff;
|
||||||
break;
|
break;
|
||||||
case 0x24:
|
case 0x24:
|
||||||
case 0x25:
|
case 0x25:
|
||||||
mask = 0xfe;
|
mask = 0xfe;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = ((uint16_t) (dev->regs[reg] & mask)) << 2;
|
p = ((uint16_t) (dev->regs[reg] & mask)) << 2;
|
||||||
if (reg == 0x22)
|
if (reg == 0x22)
|
||||||
p |= 6;
|
p |= 6;
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37c669_write(uint16_t port, uint8_t val, void *priv)
|
fdc37c669_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
fdc37c669_t *dev = (fdc37c669_t *) priv;
|
fdc37c669_t *dev = (fdc37c669_t *) priv;
|
||||||
uint8_t index = (port & 1) ? 0 : 1;
|
uint8_t index = (port & 1) ? 0 : 1;
|
||||||
uint8_t valxor = 0;
|
uint8_t valxor = 0;
|
||||||
uint8_t max = 42;
|
uint8_t max = 42;
|
||||||
|
|
||||||
if (index) {
|
if (index) {
|
||||||
if ((val == 0x55) && !dev->locked) {
|
if ((val == 0x55) && !dev->locked) {
|
||||||
if (dev->tries) {
|
if (dev->tries) {
|
||||||
dev->locked = 1;
|
dev->locked = 1;
|
||||||
dev->tries = 0;
|
dev->tries = 0;
|
||||||
} else
|
} else
|
||||||
dev->tries++;
|
dev->tries++;
|
||||||
} else {
|
} else {
|
||||||
if (dev->locked) {
|
if (dev->locked) {
|
||||||
if (val < max)
|
if (val < max)
|
||||||
dev->cur_reg = val;
|
dev->cur_reg = val;
|
||||||
if (val == 0xaa)
|
if (val == 0xaa)
|
||||||
dev->locked = 0;
|
dev->locked = 0;
|
||||||
} else {
|
} else {
|
||||||
if (dev->tries)
|
if (dev->tries)
|
||||||
dev->tries = 0;
|
dev->tries = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (dev->locked) {
|
if (dev->locked) {
|
||||||
if ((dev->cur_reg < 0x18) && (dev->rw_locked))
|
if ((dev->cur_reg < 0x18) && (dev->rw_locked))
|
||||||
return;
|
return;
|
||||||
if ((dev->cur_reg >= 0x26) && (dev->cur_reg <= 0x27))
|
if ((dev->cur_reg >= 0x26) && (dev->cur_reg <= 0x27))
|
||||||
return;
|
return;
|
||||||
if (dev->cur_reg == 0x29)
|
if (dev->cur_reg == 0x29)
|
||||||
return;
|
return;
|
||||||
valxor = val ^ dev->regs[dev->cur_reg];
|
valxor = val ^ dev->regs[dev->cur_reg];
|
||||||
dev->regs[dev->cur_reg] = val;
|
dev->regs[dev->cur_reg] = val;
|
||||||
} else
|
} else
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0:
|
case 0:
|
||||||
if (!dev->id && (valxor & 8)) {
|
if (!dev->id && (valxor & 8)) {
|
||||||
fdc_remove(dev->fdc);
|
fdc_remove(dev->fdc);
|
||||||
if ((dev->regs[0] & 8) && (dev->regs[0x20] & 0xc0))
|
if ((dev->regs[0] & 8) && (dev->regs[0x20] & 0xc0))
|
||||||
fdc_set_base(dev->fdc, make_port(dev, 0x20));
|
fdc_set_base(dev->fdc, make_port(dev, 0x20));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (valxor & 4) {
|
if (valxor & 4) {
|
||||||
if (dev->id) {
|
if (dev->id) {
|
||||||
lpt2_remove();
|
lpt2_remove();
|
||||||
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
|
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
|
||||||
lpt2_init(make_port(dev, 0x23));
|
lpt2_init(make_port(dev, 0x23));
|
||||||
} else {
|
} else {
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
|
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
|
||||||
lpt1_init(make_port(dev, 0x23));
|
lpt1_init(make_port(dev, 0x23));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (valxor & 7)
|
if (valxor & 7)
|
||||||
dev->rw_locked = (val & 8) ? 0 : 1;
|
dev->rw_locked = (val & 8) ? 0 : 1;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (valxor & 8) {
|
if (valxor & 8) {
|
||||||
serial_remove(dev->uart[0]);
|
serial_remove(dev->uart[0]);
|
||||||
if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40))
|
if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40))
|
||||||
serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4);
|
serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4);
|
||||||
}
|
}
|
||||||
if (valxor & 0x80) {
|
if (valxor & 0x80) {
|
||||||
serial_remove(dev->uart[1]);
|
serial_remove(dev->uart[1]);
|
||||||
if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40))
|
if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40))
|
||||||
serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f);
|
serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (!dev->id && (valxor & 2))
|
if (!dev->id && (valxor & 2))
|
||||||
fdc_update_enh_mode(dev->fdc, (val & 2) ? 1 : 0);
|
fdc_update_enh_mode(dev->fdc, (val & 2) ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
if (!dev->id && (valxor & 0x18))
|
if (!dev->id && (valxor & 0x18))
|
||||||
fdc_update_densel_force(dev->fdc, (val & 0x18) >> 3);
|
fdc_update_densel_force(dev->fdc, (val & 0x18) >> 3);
|
||||||
if (!dev->id && (valxor & 0x20))
|
if (!dev->id && (valxor & 0x20))
|
||||||
fdc_set_swap(dev->fdc, (val & 0x20) >> 5);
|
fdc_set_swap(dev->fdc, (val & 0x20) >> 5);
|
||||||
break;
|
break;
|
||||||
case 0xB:
|
case 0xB:
|
||||||
if (!dev->id && (valxor & 3))
|
if (!dev->id && (valxor & 3))
|
||||||
fdc_update_rwc(dev->fdc, 0, val & 3);
|
fdc_update_rwc(dev->fdc, 0, val & 3);
|
||||||
if (!dev->id && (valxor & 0xC))
|
if (!dev->id && (valxor & 0xC))
|
||||||
fdc_update_rwc(dev->fdc, 1, (val & 0xC) >> 2);
|
fdc_update_rwc(dev->fdc, 1, (val & 0xC) >> 2);
|
||||||
break;
|
break;
|
||||||
case 0x20:
|
case 0x20:
|
||||||
if (!dev->id && (valxor & 0xfc)) {
|
if (!dev->id && (valxor & 0xfc)) {
|
||||||
fdc_remove(dev->fdc);
|
fdc_remove(dev->fdc);
|
||||||
if ((dev->regs[0] & 8) && (dev->regs[0x20] & 0xc0))
|
if ((dev->regs[0] & 8) && (dev->regs[0x20] & 0xc0))
|
||||||
fdc_set_base(dev->fdc, make_port(dev, 0x20));
|
fdc_set_base(dev->fdc, make_port(dev, 0x20));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x23:
|
case 0x23:
|
||||||
if (valxor) {
|
if (valxor) {
|
||||||
if (dev->id) {
|
if (dev->id) {
|
||||||
lpt2_remove();
|
lpt2_remove();
|
||||||
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
|
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
|
||||||
lpt2_init(make_port(dev, 0x23));
|
lpt2_init(make_port(dev, 0x23));
|
||||||
} else {
|
} else {
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
|
if ((dev->regs[1] & 4) && (dev->regs[0x23] >= 0x40))
|
||||||
lpt1_init(make_port(dev, 0x23));
|
lpt1_init(make_port(dev, 0x23));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x24:
|
case 0x24:
|
||||||
if (valxor & 0xfe) {
|
if (valxor & 0xfe) {
|
||||||
serial_remove(dev->uart[0]);
|
serial_remove(dev->uart[0]);
|
||||||
if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40))
|
if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40))
|
||||||
serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4);
|
serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x25:
|
case 0x25:
|
||||||
if (valxor & 0xfe) {
|
if (valxor & 0xfe) {
|
||||||
serial_remove(dev->uart[1]);
|
serial_remove(dev->uart[1]);
|
||||||
if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40))
|
if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40))
|
||||||
serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f);
|
serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x27:
|
case 0x27:
|
||||||
if (valxor & 0xf) {
|
if (valxor & 0xf) {
|
||||||
if (dev->id)
|
if (dev->id)
|
||||||
lpt2_irq(val & 0xf);
|
lpt2_irq(val & 0xf);
|
||||||
else
|
else
|
||||||
lpt1_irq(val & 0xf);
|
lpt1_irq(val & 0xf);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x28:
|
case 0x28:
|
||||||
if (valxor & 0xf) {
|
if (valxor & 0xf) {
|
||||||
serial_remove(dev->uart[1]);
|
serial_remove(dev->uart[1]);
|
||||||
if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40))
|
if ((dev->regs[2] & 0x80) && (dev->regs[0x25] >= 0x40))
|
||||||
serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f);
|
serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f);
|
||||||
}
|
}
|
||||||
if (valxor & 0xf0) {
|
if (valxor & 0xf0) {
|
||||||
serial_remove(dev->uart[0]);
|
serial_remove(dev->uart[0]);
|
||||||
if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40))
|
if ((dev->regs[2] & 8) && (dev->regs[0x24] >= 0x40))
|
||||||
serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4);
|
serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
fdc37c669_read(uint16_t port, void *priv)
|
fdc37c669_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
fdc37c669_t *dev = (fdc37c669_t *) priv;
|
fdc37c669_t *dev = (fdc37c669_t *) priv;
|
||||||
uint8_t index = (port & 1) ? 0 : 1;
|
uint8_t index = (port & 1) ? 0 : 1;
|
||||||
uint8_t ret = 0xff;
|
uint8_t ret = 0xff;
|
||||||
|
|
||||||
if (dev->locked) {
|
if (dev->locked) {
|
||||||
if (index)
|
if (index)
|
||||||
ret = dev->cur_reg;
|
ret = dev->cur_reg;
|
||||||
else if ((dev->cur_reg >= 0x18) || !dev->rw_locked)
|
else if ((dev->cur_reg >= 0x18) || !dev->rw_locked)
|
||||||
ret = dev->regs[dev->cur_reg];
|
ret = dev->regs[dev->cur_reg];
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37c669_reset(fdc37c669_t *dev)
|
fdc37c669_reset(fdc37c669_t *dev)
|
||||||
{
|
{
|
||||||
@@ -259,38 +253,37 @@ fdc37c669_reset(fdc37c669_t *dev)
|
|||||||
dev->regs[0x06] = 0xff;
|
dev->regs[0x06] = 0xff;
|
||||||
dev->regs[0x0d] = 0x03;
|
dev->regs[0x0d] = 0x03;
|
||||||
dev->regs[0x0e] = 0x02;
|
dev->regs[0x0e] = 0x02;
|
||||||
dev->regs[0x1e] = 0x80; /* Gameport controller. */
|
dev->regs[0x1e] = 0x80; /* Gameport controller. */
|
||||||
dev->regs[0x20] = (FDC_PRIMARY_ADDR >> 2) & 0xfc;
|
dev->regs[0x20] = (FDC_PRIMARY_ADDR >> 2) & 0xfc;
|
||||||
dev->regs[0x21] = (0x1f0 >> 2) & 0xfc;
|
dev->regs[0x21] = (0x1f0 >> 2) & 0xfc;
|
||||||
dev->regs[0x22] = ((0x3f6 >> 2) & 0xfc) | 1;
|
dev->regs[0x22] = ((0x3f6 >> 2) & 0xfc) | 1;
|
||||||
if (dev->id == 1) {
|
if (dev->id == 1) {
|
||||||
dev->regs[0x23] = (LPT2_ADDR >> 2);
|
dev->regs[0x23] = (LPT2_ADDR >> 2);
|
||||||
|
|
||||||
lpt2_remove();
|
lpt2_remove();
|
||||||
lpt2_init(LPT2_ADDR);
|
lpt2_init(LPT2_ADDR);
|
||||||
|
|
||||||
dev->regs[0x24] = (COM3_ADDR >> 2) & 0xfe;
|
dev->regs[0x24] = (COM3_ADDR >> 2) & 0xfe;
|
||||||
dev->regs[0x25] = (COM4_ADDR >> 2) & 0xfe;
|
dev->regs[0x25] = (COM4_ADDR >> 2) & 0xfe;
|
||||||
} else {
|
} else {
|
||||||
fdc_reset(dev->fdc);
|
fdc_reset(dev->fdc);
|
||||||
|
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
lpt1_init(LPT1_ADDR);
|
lpt1_init(LPT1_ADDR);
|
||||||
|
|
||||||
dev->regs[0x23] = (LPT1_ADDR >> 2);
|
dev->regs[0x23] = (LPT1_ADDR >> 2);
|
||||||
|
|
||||||
dev->regs[0x24] = (COM1_ADDR >> 2) & 0xfe;
|
dev->regs[0x24] = (COM1_ADDR >> 2) & 0xfe;
|
||||||
dev->regs[0x25] = (COM2_ADDR >> 2) & 0xfe;
|
dev->regs[0x25] = (COM2_ADDR >> 2) & 0xfe;
|
||||||
}
|
}
|
||||||
dev->regs[0x26] = (2 << 4) | 3;
|
dev->regs[0x26] = (2 << 4) | 3;
|
||||||
dev->regs[0x27] = (6 << 4) | (dev->id ? 5 : 7);
|
dev->regs[0x27] = (6 << 4) | (dev->id ? 5 : 7);
|
||||||
dev->regs[0x28] = (4 << 4) | 3;
|
dev->regs[0x28] = (4 << 4) | 3;
|
||||||
|
|
||||||
dev->locked = 0;
|
dev->locked = 0;
|
||||||
dev->rw_locked = 0;
|
dev->rw_locked = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37c669_close(void *priv)
|
fdc37c669_close(void *priv)
|
||||||
{
|
{
|
||||||
@@ -301,7 +294,6 @@ fdc37c669_close(void *priv)
|
|||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
fdc37c669_init(const device_t *info)
|
fdc37c669_init(const device_t *info)
|
||||||
{
|
{
|
||||||
@@ -311,13 +303,13 @@ fdc37c669_init(const device_t *info)
|
|||||||
dev->id = next_id;
|
dev->id = next_id;
|
||||||
|
|
||||||
if (next_id != 1)
|
if (next_id != 1)
|
||||||
dev->fdc = device_add(&fdc_at_smc_device);
|
dev->fdc = device_add(&fdc_at_smc_device);
|
||||||
|
|
||||||
dev->uart[0] = device_add_inst(&ns16550_device, (next_id << 1) + 1);
|
dev->uart[0] = device_add_inst(&ns16550_device, (next_id << 1) + 1);
|
||||||
dev->uart[1] = device_add_inst(&ns16550_device, (next_id << 1) + 2);
|
dev->uart[1] = device_add_inst(&ns16550_device, (next_id << 1) + 2);
|
||||||
|
|
||||||
io_sethandler(info->local ? FDC_SECONDARY_ADDR : (next_id ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR), 0x0002,
|
io_sethandler(info->local ? FDC_SECONDARY_ADDR : (next_id ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR), 0x0002,
|
||||||
fdc37c669_read, NULL, NULL, fdc37c669_write, NULL, NULL, dev);
|
fdc37c669_read, NULL, NULL, fdc37c669_write, NULL, NULL, dev);
|
||||||
|
|
||||||
fdc37c669_reset(dev);
|
fdc37c669_reset(dev);
|
||||||
|
|
||||||
@@ -327,30 +319,29 @@ fdc37c669_init(const device_t *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const device_t fdc37c669_device = {
|
const device_t fdc37c669_device = {
|
||||||
.name = "SMC FDC37C669 Super I/O",
|
.name = "SMC FDC37C669 Super I/O",
|
||||||
.internal_name = "fdc37c669",
|
.internal_name = "fdc37c669",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0,
|
.local = 0,
|
||||||
.init = fdc37c669_init,
|
.init = fdc37c669_init,
|
||||||
.close = fdc37c669_close,
|
.close = fdc37c669_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const device_t fdc37c669_370_device = {
|
const device_t fdc37c669_370_device = {
|
||||||
.name = "SMC FDC37C669 Super I/O (Port 370h)",
|
.name = "SMC FDC37C669 Super I/O (Port 370h)",
|
||||||
.internal_name = "fdc37c669_370",
|
.internal_name = "fdc37c669_370",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 1,
|
.local = 1,
|
||||||
fdc37c669_init,
|
fdc37c669_init,
|
||||||
fdc37c669_close,
|
fdc37c669_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -33,28 +33,24 @@
|
|||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include <86box/sio.h>
|
#include <86box/sio.h>
|
||||||
|
|
||||||
|
#define AB_RST 0x80
|
||||||
#define AB_RST 0x80
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t chip_id, is_apm,
|
uint8_t chip_id, is_apm,
|
||||||
tries,
|
tries,
|
||||||
gpio_regs[2], auxio_reg,
|
gpio_regs[2], auxio_reg,
|
||||||
regs[48],
|
regs[48],
|
||||||
ld_regs[11][256];
|
ld_regs[11][256];
|
||||||
uint16_t gpio_base, /* Set to EA */
|
uint16_t gpio_base, /* Set to EA */
|
||||||
auxio_base, sio_base;
|
auxio_base, sio_base;
|
||||||
int locked,
|
int locked,
|
||||||
cur_reg;
|
cur_reg;
|
||||||
fdc_t *fdc;
|
fdc_t *fdc;
|
||||||
serial_t *uart[2];
|
serial_t *uart[2];
|
||||||
} fdc37c67x_t;
|
} fdc37c67x_t;
|
||||||
|
|
||||||
|
static void fdc37c67x_write(uint16_t port, uint8_t val, void *priv);
|
||||||
static void fdc37c67x_write(uint16_t port, uint8_t val, void *priv);
|
static uint8_t fdc37c67x_read(uint16_t port, void *priv);
|
||||||
static uint8_t fdc37c67x_read(uint16_t port, void *priv);
|
|
||||||
|
|
||||||
|
|
||||||
static uint16_t
|
static uint16_t
|
||||||
make_port(fdc37c67x_t *dev, uint8_t ld)
|
make_port(fdc37c67x_t *dev, uint8_t ld)
|
||||||
@@ -67,7 +63,6 @@ make_port(fdc37c67x_t *dev, uint8_t ld)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
fdc37c67x_auxio_read(uint16_t port, void *priv)
|
fdc37c67x_auxio_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
@@ -76,7 +71,6 @@ fdc37c67x_auxio_read(uint16_t port, void *priv)
|
|||||||
return dev->auxio_reg;
|
return dev->auxio_reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37c67x_auxio_write(uint16_t port, uint8_t val, void *priv)
|
fdc37c67x_auxio_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
@@ -85,100 +79,93 @@ fdc37c67x_auxio_write(uint16_t port, uint8_t val, void *priv)
|
|||||||
dev->auxio_reg = val;
|
dev->auxio_reg = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
fdc37c67x_gpio_read(uint16_t port, void *priv)
|
fdc37c67x_gpio_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
fdc37c67x_t *dev = (fdc37c67x_t *) priv;
|
fdc37c67x_t *dev = (fdc37c67x_t *) priv;
|
||||||
uint8_t ret = 0xff;
|
uint8_t ret = 0xff;
|
||||||
|
|
||||||
ret = dev->gpio_regs[port & 1];
|
ret = dev->gpio_regs[port & 1];
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37c67x_gpio_write(uint16_t port, uint8_t val, void *priv)
|
fdc37c67x_gpio_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
fdc37c67x_t *dev = (fdc37c67x_t *) priv;
|
fdc37c67x_t *dev = (fdc37c67x_t *) priv;
|
||||||
|
|
||||||
if (!(port & 1))
|
if (!(port & 1))
|
||||||
dev->gpio_regs[0] = (dev->gpio_regs[0] & 0xfc) | (val & 0x03);
|
dev->gpio_regs[0] = (dev->gpio_regs[0] & 0xfc) | (val & 0x03);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37c67x_fdc_handler(fdc37c67x_t *dev)
|
fdc37c67x_fdc_handler(fdc37c67x_t *dev)
|
||||||
{
|
{
|
||||||
uint16_t ld_port = 0;
|
uint16_t ld_port = 0;
|
||||||
uint8_t global_enable = !!(dev->regs[0x22] & (1 << 0));
|
uint8_t global_enable = !!(dev->regs[0x22] & (1 << 0));
|
||||||
uint8_t local_enable = !!dev->ld_regs[0][0x30];
|
uint8_t local_enable = !!dev->ld_regs[0][0x30];
|
||||||
|
|
||||||
fdc_remove(dev->fdc);
|
fdc_remove(dev->fdc);
|
||||||
if (global_enable && local_enable) {
|
if (global_enable && local_enable) {
|
||||||
ld_port = make_port(dev, 0) & 0xFFF8;
|
ld_port = make_port(dev, 0) & 0xFFF8;
|
||||||
if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8))
|
if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8))
|
||||||
fdc_set_base(dev->fdc, ld_port);
|
fdc_set_base(dev->fdc, ld_port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37c67x_lpt_handler(fdc37c67x_t *dev)
|
fdc37c67x_lpt_handler(fdc37c67x_t *dev)
|
||||||
{
|
{
|
||||||
uint16_t ld_port = 0;
|
uint16_t ld_port = 0;
|
||||||
uint8_t global_enable = !!(dev->regs[0x22] & (1 << 3));
|
uint8_t global_enable = !!(dev->regs[0x22] & (1 << 3));
|
||||||
uint8_t local_enable = !!dev->ld_regs[3][0x30];
|
uint8_t local_enable = !!dev->ld_regs[3][0x30];
|
||||||
uint8_t lpt_irq = dev->ld_regs[3][0x70];
|
uint8_t lpt_irq = dev->ld_regs[3][0x70];
|
||||||
|
|
||||||
if (lpt_irq > 15)
|
if (lpt_irq > 15)
|
||||||
lpt_irq = 0xff;
|
lpt_irq = 0xff;
|
||||||
|
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
if (global_enable && local_enable) {
|
if (global_enable && local_enable) {
|
||||||
ld_port = make_port(dev, 3) & 0xFFFC;
|
ld_port = make_port(dev, 3) & 0xFFFC;
|
||||||
if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC))
|
if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC))
|
||||||
lpt1_init(ld_port);
|
lpt1_init(ld_port);
|
||||||
}
|
}
|
||||||
lpt1_irq(lpt_irq);
|
lpt1_irq(lpt_irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37c67x_serial_handler(fdc37c67x_t *dev, int uart)
|
fdc37c67x_serial_handler(fdc37c67x_t *dev, int uart)
|
||||||
{
|
{
|
||||||
uint16_t ld_port = 0;
|
uint16_t ld_port = 0;
|
||||||
uint8_t uart_no = 4 + uart;
|
uint8_t uart_no = 4 + uart;
|
||||||
uint8_t global_enable = !!(dev->regs[0x22] & (1 << uart_no));
|
uint8_t global_enable = !!(dev->regs[0x22] & (1 << uart_no));
|
||||||
uint8_t local_enable = !!dev->ld_regs[uart_no][0x30];
|
uint8_t local_enable = !!dev->ld_regs[uart_no][0x30];
|
||||||
|
|
||||||
serial_remove(dev->uart[uart]);
|
serial_remove(dev->uart[uart]);
|
||||||
if (global_enable && local_enable) {
|
if (global_enable && local_enable) {
|
||||||
ld_port = make_port(dev, uart_no) & 0xFFF8;
|
ld_port = make_port(dev, uart_no) & 0xFFF8;
|
||||||
if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8))
|
if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8))
|
||||||
serial_setup(dev->uart[uart], ld_port, dev->ld_regs[uart_no][0x70]);
|
serial_setup(dev->uart[uart], ld_port, dev->ld_regs[uart_no][0x70]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37c67x_auxio_handler(fdc37c67x_t *dev)
|
fdc37c67x_auxio_handler(fdc37c67x_t *dev)
|
||||||
{
|
{
|
||||||
uint16_t ld_port = 0;
|
uint16_t ld_port = 0;
|
||||||
uint8_t local_enable = !!dev->ld_regs[8][0x30];
|
uint8_t local_enable = !!dev->ld_regs[8][0x30];
|
||||||
|
|
||||||
io_removehandler(dev->auxio_base, 0x0001,
|
io_removehandler(dev->auxio_base, 0x0001,
|
||||||
fdc37c67x_auxio_read, NULL, NULL, fdc37c67x_auxio_write, NULL, NULL, dev);
|
fdc37c67x_auxio_read, NULL, NULL, fdc37c67x_auxio_write, NULL, NULL, dev);
|
||||||
if (local_enable) {
|
if (local_enable) {
|
||||||
dev->auxio_base = ld_port = make_port(dev, 8);
|
dev->auxio_base = ld_port = make_port(dev, 8);
|
||||||
if ((ld_port >= 0x0100) && (ld_port <= 0x0FFF))
|
if ((ld_port >= 0x0100) && (ld_port <= 0x0FFF))
|
||||||
io_sethandler(dev->auxio_base, 0x0001,
|
io_sethandler(dev->auxio_base, 0x0001,
|
||||||
fdc37c67x_auxio_read, NULL, NULL, fdc37c67x_auxio_write, NULL, NULL, dev);
|
fdc37c67x_auxio_read, NULL, NULL, fdc37c67x_auxio_write, NULL, NULL, dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37c67x_sio_handler(fdc37c67x_t *dev)
|
fdc37c67x_sio_handler(fdc37c67x_t *dev)
|
||||||
{
|
{
|
||||||
@@ -195,40 +182,38 @@ fdc37c67x_sio_handler(fdc37c67x_t *dev)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37c67x_gpio_handler(fdc37c67x_t *dev)
|
fdc37c67x_gpio_handler(fdc37c67x_t *dev)
|
||||||
{
|
{
|
||||||
uint16_t ld_port = 0;
|
uint16_t ld_port = 0;
|
||||||
uint8_t local_enable;
|
uint8_t local_enable;
|
||||||
|
|
||||||
local_enable = !!(dev->regs[0x03] & 0x80);
|
local_enable = !!(dev->regs[0x03] & 0x80);
|
||||||
|
|
||||||
io_removehandler(dev->gpio_base, 0x0002,
|
io_removehandler(dev->gpio_base, 0x0002,
|
||||||
fdc37c67x_gpio_read, NULL, NULL, fdc37c67x_gpio_write, NULL, NULL, dev);
|
fdc37c67x_gpio_read, NULL, NULL, fdc37c67x_gpio_write, NULL, NULL, dev);
|
||||||
if (local_enable) {
|
if (local_enable) {
|
||||||
switch (dev->regs[0x03] & 0x03) {
|
switch (dev->regs[0x03] & 0x03) {
|
||||||
case 0:
|
case 0:
|
||||||
ld_port = 0xe0;
|
ld_port = 0xe0;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
ld_port = 0xe2;
|
ld_port = 0xe2;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
ld_port = 0xe4;
|
ld_port = 0xe4;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
ld_port = 0xea; /* Default */
|
ld_port = 0xea; /* Default */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dev->gpio_base = ld_port;
|
dev->gpio_base = ld_port;
|
||||||
if (ld_port > 0x0000)
|
if (ld_port > 0x0000)
|
||||||
io_sethandler(dev->gpio_base, 0x0002,
|
io_sethandler(dev->gpio_base, 0x0002,
|
||||||
fdc37c67x_gpio_read, NULL, NULL, fdc37c67x_gpio_write, NULL, NULL, dev);
|
fdc37c67x_gpio_read, NULL, NULL, fdc37c67x_gpio_write, NULL, NULL, dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37c67x_smi_handler(fdc37c67x_t *dev)
|
fdc37c67x_smi_handler(fdc37c67x_t *dev)
|
||||||
{
|
{
|
||||||
@@ -243,253 +228,251 @@ fdc37c67x_smi_handler(fdc37c67x_t *dev)
|
|||||||
pic_set_smi_irq_mask(10, dev->ld_regs[8][0xb5] & 0x80);
|
pic_set_smi_irq_mask(10, dev->ld_regs[8][0xb5] & 0x80);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37c67x_write(uint16_t port, uint8_t val, void *priv)
|
fdc37c67x_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
fdc37c67x_t *dev = (fdc37c67x_t *) priv;
|
fdc37c67x_t *dev = (fdc37c67x_t *) priv;
|
||||||
uint8_t index = (port & 1) ? 0 : 1;
|
uint8_t index = (port & 1) ? 0 : 1;
|
||||||
uint8_t valxor = 0x00, keep = 0x00;
|
uint8_t valxor = 0x00, keep = 0x00;
|
||||||
|
|
||||||
if (index) {
|
if (index) {
|
||||||
if ((val == 0x55) && !dev->locked) {
|
if ((val == 0x55) && !dev->locked) {
|
||||||
if (dev->tries) {
|
if (dev->tries) {
|
||||||
dev->locked = 1;
|
dev->locked = 1;
|
||||||
fdc_3f1_enable(dev->fdc, 0);
|
fdc_3f1_enable(dev->fdc, 0);
|
||||||
dev->tries = 0;
|
dev->tries = 0;
|
||||||
} else
|
} else
|
||||||
dev->tries++;
|
dev->tries++;
|
||||||
} else {
|
} else {
|
||||||
if (dev->locked) {
|
if (dev->locked) {
|
||||||
if (val == 0xaa) {
|
if (val == 0xaa) {
|
||||||
dev->locked = 0;
|
dev->locked = 0;
|
||||||
fdc_3f1_enable(dev->fdc, 1);
|
fdc_3f1_enable(dev->fdc, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dev->cur_reg = val;
|
dev->cur_reg = val;
|
||||||
} else {
|
} else {
|
||||||
if (dev->tries)
|
if (dev->tries)
|
||||||
dev->tries = 0;
|
dev->tries = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (dev->locked) {
|
if (dev->locked) {
|
||||||
if (dev->cur_reg < 48) {
|
if (dev->cur_reg < 48) {
|
||||||
valxor = val ^ dev->regs[dev->cur_reg];
|
valxor = val ^ dev->regs[dev->cur_reg];
|
||||||
if ((val == 0x20) || (val == 0x21))
|
if ((val == 0x20) || (val == 0x21))
|
||||||
return;
|
return;
|
||||||
dev->regs[dev->cur_reg] = val;
|
dev->regs[dev->cur_reg] = val;
|
||||||
} else {
|
} else {
|
||||||
valxor = val ^ dev->ld_regs[dev->regs[7]][dev->cur_reg];
|
valxor = val ^ dev->ld_regs[dev->regs[7]][dev->cur_reg];
|
||||||
if (((dev->cur_reg & 0xF0) == 0x70) && (dev->regs[7] < 4))
|
if (((dev->cur_reg & 0xF0) == 0x70) && (dev->regs[7] < 4))
|
||||||
return;
|
return;
|
||||||
/* Block writes to some logical devices. */
|
/* Block writes to some logical devices. */
|
||||||
if (dev->regs[7] > 0x0a)
|
if (dev->regs[7] > 0x0a)
|
||||||
return;
|
return;
|
||||||
else switch (dev->regs[7]) {
|
else
|
||||||
case 0x01:
|
switch (dev->regs[7]) {
|
||||||
case 0x02:
|
case 0x01:
|
||||||
case 0x07:
|
case 0x02:
|
||||||
return;
|
case 0x07:
|
||||||
}
|
return;
|
||||||
dev->ld_regs[dev->regs[7]][dev->cur_reg] = val | keep;
|
}
|
||||||
}
|
dev->ld_regs[dev->regs[7]][dev->cur_reg] = val | keep;
|
||||||
} else
|
}
|
||||||
return;
|
} else
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->cur_reg < 48) {
|
if (dev->cur_reg < 48) {
|
||||||
switch(dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0x03:
|
case 0x03:
|
||||||
if (valxor & 0x83)
|
if (valxor & 0x83)
|
||||||
fdc37c67x_gpio_handler(dev);
|
fdc37c67x_gpio_handler(dev);
|
||||||
dev->regs[0x03] &= 0x83;
|
dev->regs[0x03] &= 0x83;
|
||||||
break;
|
break;
|
||||||
case 0x22:
|
case 0x22:
|
||||||
if (valxor & 0x01)
|
if (valxor & 0x01)
|
||||||
fdc37c67x_fdc_handler(dev);
|
fdc37c67x_fdc_handler(dev);
|
||||||
if (valxor & 0x08)
|
if (valxor & 0x08)
|
||||||
fdc37c67x_lpt_handler(dev);
|
fdc37c67x_lpt_handler(dev);
|
||||||
if (valxor & 0x10)
|
if (valxor & 0x10)
|
||||||
fdc37c67x_serial_handler(dev, 0);
|
fdc37c67x_serial_handler(dev, 0);
|
||||||
if (valxor & 0x20)
|
if (valxor & 0x20)
|
||||||
fdc37c67x_serial_handler(dev, 1);
|
fdc37c67x_serial_handler(dev, 1);
|
||||||
break;
|
break;
|
||||||
case 0x26: case 0x27:
|
case 0x26:
|
||||||
fdc37c67x_sio_handler(dev);
|
case 0x27:
|
||||||
}
|
fdc37c67x_sio_handler(dev);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(dev->regs[7]) {
|
switch (dev->regs[7]) {
|
||||||
case 0:
|
case 0:
|
||||||
/* FDD */
|
/* FDD */
|
||||||
switch(dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0x30:
|
case 0x30:
|
||||||
case 0x60:
|
case 0x60:
|
||||||
case 0x61:
|
case 0x61:
|
||||||
if ((dev->cur_reg == 0x30) && (val & 0x01))
|
if ((dev->cur_reg == 0x30) && (val & 0x01))
|
||||||
dev->regs[0x22] |= 0x01;
|
dev->regs[0x22] |= 0x01;
|
||||||
if (valxor)
|
if (valxor)
|
||||||
fdc37c67x_fdc_handler(dev);
|
fdc37c67x_fdc_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 0xF0:
|
case 0xF0:
|
||||||
if (valxor & 0x01)
|
if (valxor & 0x01)
|
||||||
fdc_update_enh_mode(dev->fdc, val & 0x01);
|
fdc_update_enh_mode(dev->fdc, val & 0x01);
|
||||||
if (valxor & 0x10)
|
if (valxor & 0x10)
|
||||||
fdc_set_swap(dev->fdc, (val & 0x10) >> 4);
|
fdc_set_swap(dev->fdc, (val & 0x10) >> 4);
|
||||||
break;
|
break;
|
||||||
case 0xF1:
|
case 0xF1:
|
||||||
if (valxor & 0xC)
|
if (valxor & 0xC)
|
||||||
fdc_update_densel_force(dev->fdc, (val & 0xc) >> 2);
|
fdc_update_densel_force(dev->fdc, (val & 0xc) >> 2);
|
||||||
break;
|
break;
|
||||||
case 0xF2:
|
case 0xF2:
|
||||||
if (valxor & 0xC0)
|
if (valxor & 0xC0)
|
||||||
fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6);
|
fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6);
|
||||||
if (valxor & 0x30)
|
if (valxor & 0x30)
|
||||||
fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4);
|
fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4);
|
||||||
if (valxor & 0x0C)
|
if (valxor & 0x0C)
|
||||||
fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2);
|
fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2);
|
||||||
if (valxor & 0x03)
|
if (valxor & 0x03)
|
||||||
fdc_update_rwc(dev->fdc, 0, (val & 0x03));
|
fdc_update_rwc(dev->fdc, 0, (val & 0x03));
|
||||||
break;
|
break;
|
||||||
case 0xF4:
|
case 0xF4:
|
||||||
if (valxor & 0x18)
|
if (valxor & 0x18)
|
||||||
fdc_update_drvrate(dev->fdc, 0, (val & 0x18) >> 3);
|
fdc_update_drvrate(dev->fdc, 0, (val & 0x18) >> 3);
|
||||||
break;
|
break;
|
||||||
case 0xF5:
|
case 0xF5:
|
||||||
if (valxor & 0x18)
|
if (valxor & 0x18)
|
||||||
fdc_update_drvrate(dev->fdc, 1, (val & 0x18) >> 3);
|
fdc_update_drvrate(dev->fdc, 1, (val & 0x18) >> 3);
|
||||||
break;
|
break;
|
||||||
case 0xF6:
|
case 0xF6:
|
||||||
if (valxor & 0x18)
|
if (valxor & 0x18)
|
||||||
fdc_update_drvrate(dev->fdc, 2, (val & 0x18) >> 3);
|
fdc_update_drvrate(dev->fdc, 2, (val & 0x18) >> 3);
|
||||||
break;
|
break;
|
||||||
case 0xF7:
|
case 0xF7:
|
||||||
if (valxor & 0x18)
|
if (valxor & 0x18)
|
||||||
fdc_update_drvrate(dev->fdc, 3, (val & 0x18) >> 3);
|
fdc_update_drvrate(dev->fdc, 3, (val & 0x18) >> 3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
/* Parallel port */
|
/* Parallel port */
|
||||||
switch(dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0x30:
|
case 0x30:
|
||||||
case 0x60:
|
case 0x60:
|
||||||
case 0x61:
|
case 0x61:
|
||||||
case 0x70:
|
case 0x70:
|
||||||
if ((dev->cur_reg == 0x30) && (val & 0x01))
|
if ((dev->cur_reg == 0x30) && (val & 0x01))
|
||||||
dev->regs[0x22] |= 0x08;
|
dev->regs[0x22] |= 0x08;
|
||||||
if (valxor)
|
if (valxor)
|
||||||
fdc37c67x_lpt_handler(dev);
|
fdc37c67x_lpt_handler(dev);
|
||||||
if (dev->cur_reg == 0x70)
|
if (dev->cur_reg == 0x70)
|
||||||
fdc37c67x_smi_handler(dev);
|
fdc37c67x_smi_handler(dev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
/* Serial port 1 */
|
/* Serial port 1 */
|
||||||
switch(dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0x30:
|
case 0x30:
|
||||||
case 0x60:
|
case 0x60:
|
||||||
case 0x61:
|
case 0x61:
|
||||||
case 0x70:
|
case 0x70:
|
||||||
if ((dev->cur_reg == 0x30) && (val & 0x01))
|
if ((dev->cur_reg == 0x30) && (val & 0x01))
|
||||||
dev->regs[0x22] |= 0x10;
|
dev->regs[0x22] |= 0x10;
|
||||||
if (valxor)
|
if (valxor)
|
||||||
fdc37c67x_serial_handler(dev, 0);
|
fdc37c67x_serial_handler(dev, 0);
|
||||||
if (dev->cur_reg == 0x70)
|
if (dev->cur_reg == 0x70)
|
||||||
fdc37c67x_smi_handler(dev);
|
fdc37c67x_smi_handler(dev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
/* Serial port 2 */
|
/* Serial port 2 */
|
||||||
switch(dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0x30:
|
case 0x30:
|
||||||
case 0x60:
|
case 0x60:
|
||||||
case 0x61:
|
case 0x61:
|
||||||
case 0x70:
|
case 0x70:
|
||||||
if ((dev->cur_reg == 0x30) && (val & 0x01))
|
if ((dev->cur_reg == 0x30) && (val & 0x01))
|
||||||
dev->regs[0x22] |= 0x20;
|
dev->regs[0x22] |= 0x20;
|
||||||
if (valxor)
|
if (valxor)
|
||||||
fdc37c67x_serial_handler(dev, 1);
|
fdc37c67x_serial_handler(dev, 1);
|
||||||
if (dev->cur_reg == 0x70)
|
if (dev->cur_reg == 0x70)
|
||||||
fdc37c67x_smi_handler(dev);
|
fdc37c67x_smi_handler(dev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
/* Auxiliary I/O */
|
/* Auxiliary I/O */
|
||||||
switch(dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0x30:
|
case 0x30:
|
||||||
case 0x60:
|
case 0x60:
|
||||||
case 0x61:
|
case 0x61:
|
||||||
case 0x70:
|
case 0x70:
|
||||||
if (valxor)
|
if (valxor)
|
||||||
fdc37c67x_auxio_handler(dev);
|
fdc37c67x_auxio_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 0xb4:
|
case 0xb4:
|
||||||
case 0xb5:
|
case 0xb5:
|
||||||
fdc37c67x_smi_handler(dev);
|
fdc37c67x_smi_handler(dev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
fdc37c67x_read(uint16_t port, void *priv)
|
fdc37c67x_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
fdc37c67x_t *dev = (fdc37c67x_t *) priv;
|
fdc37c67x_t *dev = (fdc37c67x_t *) priv;
|
||||||
uint8_t index = (port & 1) ? 0 : 1;
|
uint8_t index = (port & 1) ? 0 : 1;
|
||||||
uint8_t ret = 0xff;
|
uint8_t ret = 0xff;
|
||||||
uint16_t smi_stat = pic_get_smi_irq_status();
|
uint16_t smi_stat = pic_get_smi_irq_status();
|
||||||
int f_irq = dev->ld_regs[0][0x70];
|
int f_irq = dev->ld_regs[0][0x70];
|
||||||
int p_irq = dev->ld_regs[3][0x70];
|
int p_irq = dev->ld_regs[3][0x70];
|
||||||
int s1_irq = dev->ld_regs[4][0x70];
|
int s1_irq = dev->ld_regs[4][0x70];
|
||||||
int s2_irq = dev->ld_regs[5][0x70];
|
int s2_irq = dev->ld_regs[5][0x70];
|
||||||
|
|
||||||
if (dev->locked) {
|
if (dev->locked) {
|
||||||
if (index)
|
if (index)
|
||||||
ret = dev->cur_reg;
|
ret = dev->cur_reg;
|
||||||
else {
|
else {
|
||||||
if (dev->cur_reg < 0x30) {
|
if (dev->cur_reg < 0x30) {
|
||||||
if (dev->cur_reg == 0x20)
|
if (dev->cur_reg == 0x20)
|
||||||
ret = dev->chip_id;
|
ret = dev->chip_id;
|
||||||
else
|
else
|
||||||
ret = dev->regs[dev->cur_reg];
|
ret = dev->regs[dev->cur_reg];
|
||||||
} else {
|
} else {
|
||||||
if ((dev->regs[7] == 0) && (dev->cur_reg == 0xF2)) {
|
if ((dev->regs[7] == 0) && (dev->cur_reg == 0xF2)) {
|
||||||
ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) |
|
ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6));
|
||||||
(fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6));
|
} else
|
||||||
} else
|
ret = dev->ld_regs[dev->regs[7]][dev->cur_reg];
|
||||||
ret = dev->ld_regs[dev->regs[7]][dev->cur_reg];
|
|
||||||
|
|
||||||
/* TODO: 8042 P1.2 SMI#. */
|
/* TODO: 8042 P1.2 SMI#. */
|
||||||
if ((dev->regs[7] == 8) && (dev->cur_reg == 0xb6)) {
|
if ((dev->regs[7] == 8) && (dev->cur_reg == 0xb6)) {
|
||||||
ret = dev->ld_regs[dev->regs[7]][dev->cur_reg] & 0xe1;
|
ret = dev->ld_regs[dev->regs[7]][dev->cur_reg] & 0xe1;
|
||||||
ret |= ((!!(smi_stat & (1 << p_irq))) << 1);
|
ret |= ((!!(smi_stat & (1 << p_irq))) << 1);
|
||||||
ret |= ((!!(smi_stat & (1 << s2_irq))) << 2);
|
ret |= ((!!(smi_stat & (1 << s2_irq))) << 2);
|
||||||
ret |= ((!!(smi_stat & (1 << s1_irq))) << 3);
|
ret |= ((!!(smi_stat & (1 << s1_irq))) << 3);
|
||||||
ret |= ((!!(smi_stat & (1 << f_irq))) << 4);
|
ret |= ((!!(smi_stat & (1 << f_irq))) << 4);
|
||||||
} else if ((dev->regs[7] == 8) && (dev->cur_reg == 0xb7)) {
|
} else if ((dev->regs[7] == 8) && (dev->cur_reg == 0xb7)) {
|
||||||
ret = dev->ld_regs[dev->regs[7]][dev->cur_reg] & 0xec;
|
ret = dev->ld_regs[dev->regs[7]][dev->cur_reg] & 0xec;
|
||||||
ret |= ((!!(smi_stat & (1 << 12))) << 0);
|
ret |= ((!!(smi_stat & (1 << 12))) << 0);
|
||||||
ret |= ((!!(smi_stat & (1 << 1))) << 1);
|
ret |= ((!!(smi_stat & (1 << 1))) << 1);
|
||||||
ret |= ((!!(smi_stat & (1 << 10))) << 4);
|
ret |= ((!!(smi_stat & (1 << 10))) << 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37c67x_reset(fdc37c67x_t *dev)
|
fdc37c67x_reset(fdc37c67x_t *dev)
|
||||||
{
|
{
|
||||||
@@ -505,7 +488,7 @@ fdc37c67x_reset(fdc37c67x_t *dev)
|
|||||||
dev->regs[0x27] = 0x03;
|
dev->regs[0x27] = 0x03;
|
||||||
|
|
||||||
for (i = 0; i < 11; i++)
|
for (i = 0; i < 11; i++)
|
||||||
memset(dev->ld_regs[i], 0, 256);
|
memset(dev->ld_regs[i], 0, 256);
|
||||||
|
|
||||||
/* Logical device 0: FDD */
|
/* Logical device 0: FDD */
|
||||||
dev->ld_regs[0][0x30] = 1;
|
dev->ld_regs[0][0x30] = 1;
|
||||||
@@ -565,7 +548,6 @@ fdc37c67x_reset(fdc37c67x_t *dev)
|
|||||||
dev->locked = 0;
|
dev->locked = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37c67x_close(void *priv)
|
fdc37c67x_close(void *priv)
|
||||||
{
|
{
|
||||||
@@ -574,7 +556,6 @@ fdc37c67x_close(void *priv)
|
|||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
fdc37c67x_init(const device_t *info)
|
fdc37c67x_init(const device_t *info)
|
||||||
{
|
{
|
||||||
@@ -595,24 +576,23 @@ fdc37c67x_init(const device_t *info)
|
|||||||
fdc37c67x_reset(dev);
|
fdc37c67x_reset(dev);
|
||||||
|
|
||||||
io_sethandler(FDC_SECONDARY_ADDR, 0x0002,
|
io_sethandler(FDC_SECONDARY_ADDR, 0x0002,
|
||||||
fdc37c67x_read, NULL, NULL, fdc37c67x_write, NULL, NULL, dev);
|
fdc37c67x_read, NULL, NULL, fdc37c67x_write, NULL, NULL, dev);
|
||||||
io_sethandler(FDC_PRIMARY_ADDR, 0x0002,
|
io_sethandler(FDC_PRIMARY_ADDR, 0x0002,
|
||||||
fdc37c67x_read, NULL, NULL, fdc37c67x_write, NULL, NULL, dev);
|
fdc37c67x_read, NULL, NULL, fdc37c67x_write, NULL, NULL, dev);
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const device_t fdc37c67x_device = {
|
const device_t fdc37c67x_device = {
|
||||||
.name = "SMC FDC37C67X Super I/O",
|
.name = "SMC FDC37C67X Super I/O",
|
||||||
.internal_name = "fdc37c67x",
|
.internal_name = "fdc37c67x",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x40,
|
.local = 0x40,
|
||||||
.init = fdc37c67x_init,
|
.init = fdc37c67x_init,
|
||||||
.close = fdc37c67x_close,
|
.close = fdc37c67x_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,207 +35,197 @@
|
|||||||
#include <86box/fdc.h>
|
#include <86box/fdc.h>
|
||||||
#include <86box/sio.h>
|
#include <86box/sio.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t max_reg, chip_id,
|
uint8_t max_reg, chip_id,
|
||||||
tries, has_ide,
|
tries, has_ide,
|
||||||
regs[16];
|
regs[16];
|
||||||
int cur_reg,
|
int cur_reg,
|
||||||
com3_addr, com4_addr;
|
com3_addr, com4_addr;
|
||||||
fdc_t *fdc;
|
fdc_t *fdc;
|
||||||
serial_t *uart[2];
|
serial_t *uart[2];
|
||||||
} fdc37c6xx_t;
|
} fdc37c6xx_t;
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_com34_addr(fdc37c6xx_t *dev)
|
set_com34_addr(fdc37c6xx_t *dev)
|
||||||
{
|
{
|
||||||
switch (dev->regs[1] & 0x60) {
|
switch (dev->regs[1] & 0x60) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
dev->com3_addr = 0x338;
|
dev->com3_addr = 0x338;
|
||||||
dev->com4_addr = 0x238;
|
dev->com4_addr = 0x238;
|
||||||
break;
|
break;
|
||||||
case 0x20:
|
case 0x20:
|
||||||
dev->com3_addr = COM3_ADDR;
|
dev->com3_addr = COM3_ADDR;
|
||||||
dev->com4_addr = COM4_ADDR;
|
dev->com4_addr = COM4_ADDR;
|
||||||
break;
|
break;
|
||||||
case 0x40:
|
case 0x40:
|
||||||
dev->com3_addr = COM3_ADDR;
|
dev->com3_addr = COM3_ADDR;
|
||||||
dev->com4_addr = 0x2e0;
|
dev->com4_addr = 0x2e0;
|
||||||
break;
|
break;
|
||||||
case 0x60:
|
case 0x60:
|
||||||
dev->com3_addr = 0x220;
|
dev->com3_addr = 0x220;
|
||||||
dev->com4_addr = 0x228;
|
dev->com4_addr = 0x228;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_serial_addr(fdc37c6xx_t *dev, int port)
|
set_serial_addr(fdc37c6xx_t *dev, int port)
|
||||||
{
|
{
|
||||||
uint8_t shift = (port << 2);
|
uint8_t shift = (port << 2);
|
||||||
double clock_src = 24000000.0 / 13.0;
|
double clock_src = 24000000.0 / 13.0;
|
||||||
|
|
||||||
if (dev->regs[4] & (1 << (4 + port)))
|
if (dev->regs[4] & (1 << (4 + port)))
|
||||||
clock_src = 24000000.0 / 12.0;
|
clock_src = 24000000.0 / 12.0;
|
||||||
|
|
||||||
serial_remove(dev->uart[port]);
|
serial_remove(dev->uart[port]);
|
||||||
if (dev->regs[2] & (4 << shift)) {
|
if (dev->regs[2] & (4 << shift)) {
|
||||||
switch ((dev->regs[2] >> shift) & 3) {
|
switch ((dev->regs[2] >> shift) & 3) {
|
||||||
case 0:
|
case 0:
|
||||||
serial_setup(dev->uart[port], COM1_ADDR, COM1_IRQ);
|
serial_setup(dev->uart[port], COM1_ADDR, COM1_IRQ);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
serial_setup(dev->uart[port], COM2_ADDR, COM2_IRQ);
|
serial_setup(dev->uart[port], COM2_ADDR, COM2_IRQ);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
serial_setup(dev->uart[port], dev->com3_addr, COM3_IRQ);
|
serial_setup(dev->uart[port], dev->com3_addr, COM3_IRQ);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
serial_setup(dev->uart[port], dev->com4_addr, COM4_IRQ);
|
serial_setup(dev->uart[port], dev->com4_addr, COM4_IRQ);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
serial_set_clock_src(dev->uart[port], clock_src);
|
serial_set_clock_src(dev->uart[port], clock_src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lpt1_handler(fdc37c6xx_t *dev)
|
lpt1_handler(fdc37c6xx_t *dev)
|
||||||
{
|
{
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
switch (dev->regs[1] & 3) {
|
switch (dev->regs[1] & 3) {
|
||||||
case 1:
|
case 1:
|
||||||
lpt1_init(LPT_MDA_ADDR);
|
lpt1_init(LPT_MDA_ADDR);
|
||||||
lpt1_irq(7);
|
lpt1_irq(7);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
lpt1_init(LPT1_ADDR);
|
lpt1_init(LPT1_ADDR);
|
||||||
lpt1_irq(7 /*5*/);
|
lpt1_irq(7 /*5*/);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
lpt1_init(LPT2_ADDR);
|
lpt1_init(LPT2_ADDR);
|
||||||
lpt1_irq(7 /*5*/);
|
lpt1_irq(7 /*5*/);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc_handler(fdc37c6xx_t *dev)
|
fdc_handler(fdc37c6xx_t *dev)
|
||||||
{
|
{
|
||||||
fdc_remove(dev->fdc);
|
fdc_remove(dev->fdc);
|
||||||
if (dev->regs[0] & 0x10)
|
if (dev->regs[0] & 0x10)
|
||||||
fdc_set_base(dev->fdc, (dev->regs[5] & 0x01) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
|
fdc_set_base(dev->fdc, (dev->regs[5] & 0x01) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ide_handler(fdc37c6xx_t *dev)
|
ide_handler(fdc37c6xx_t *dev)
|
||||||
{
|
{
|
||||||
/* TODO: Make an ide_disable(channel) and ide_enable(channel) so we can simplify this. */
|
/* TODO: Make an ide_disable(channel) and ide_enable(channel) so we can simplify this. */
|
||||||
if (dev->has_ide == 2) {
|
if (dev->has_ide == 2) {
|
||||||
ide_sec_disable();
|
ide_sec_disable();
|
||||||
ide_set_base(1, (dev->regs[0x05] & 0x02) ? 0x170 : 0x1f0);
|
ide_set_base(1, (dev->regs[0x05] & 0x02) ? 0x170 : 0x1f0);
|
||||||
ide_set_side(1, (dev->regs[0x05] & 0x02) ? 0x376 : 0x3f6);
|
ide_set_side(1, (dev->regs[0x05] & 0x02) ? 0x376 : 0x3f6);
|
||||||
if (dev->regs[0x00] & 0x01)
|
if (dev->regs[0x00] & 0x01)
|
||||||
ide_sec_enable();
|
ide_sec_enable();
|
||||||
} else if (dev->has_ide == 1) {
|
} else if (dev->has_ide == 1) {
|
||||||
ide_pri_disable();
|
ide_pri_disable();
|
||||||
ide_set_base(0, (dev->regs[0x05] & 0x02) ? 0x170 : 0x1f0);
|
ide_set_base(0, (dev->regs[0x05] & 0x02) ? 0x170 : 0x1f0);
|
||||||
ide_set_side(0, (dev->regs[0x05] & 0x02) ? 0x376 : 0x3f6);
|
ide_set_side(0, (dev->regs[0x05] & 0x02) ? 0x376 : 0x3f6);
|
||||||
if (dev->regs[0x00] & 0x01)
|
if (dev->regs[0x00] & 0x01)
|
||||||
ide_pri_enable();
|
ide_pri_enable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37c6xx_write(uint16_t port, uint8_t val, void *priv)
|
fdc37c6xx_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
fdc37c6xx_t *dev = (fdc37c6xx_t *) priv;
|
fdc37c6xx_t *dev = (fdc37c6xx_t *) priv;
|
||||||
uint8_t valxor = 0;
|
uint8_t valxor = 0;
|
||||||
|
|
||||||
if (dev->tries == 2) {
|
if (dev->tries == 2) {
|
||||||
if (port == FDC_PRIMARY_ADDR) {
|
if (port == FDC_PRIMARY_ADDR) {
|
||||||
if (val == 0xaa)
|
if (val == 0xaa)
|
||||||
dev->tries = 0;
|
dev->tries = 0;
|
||||||
else
|
else
|
||||||
dev->cur_reg = val;
|
dev->cur_reg = val;
|
||||||
} else {
|
} else {
|
||||||
if (dev->cur_reg > dev->max_reg)
|
if (dev->cur_reg > dev->max_reg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
valxor = val ^ dev->regs[dev->cur_reg];
|
valxor = val ^ dev->regs[dev->cur_reg];
|
||||||
dev->regs[dev->cur_reg] = val;
|
dev->regs[dev->cur_reg] = val;
|
||||||
|
|
||||||
switch(dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0:
|
case 0:
|
||||||
if (dev->has_ide && (valxor & 0x01))
|
if (dev->has_ide && (valxor & 0x01))
|
||||||
ide_handler(dev);
|
ide_handler(dev);
|
||||||
if (valxor & 0x10)
|
if (valxor & 0x10)
|
||||||
fdc_handler(dev);
|
fdc_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (valxor & 3)
|
if (valxor & 3)
|
||||||
lpt1_handler(dev);
|
lpt1_handler(dev);
|
||||||
if (valxor & 0x60) {
|
if (valxor & 0x60) {
|
||||||
set_com34_addr(dev);
|
set_com34_addr(dev);
|
||||||
set_serial_addr(dev, 0);
|
set_serial_addr(dev, 0);
|
||||||
set_serial_addr(dev, 1);
|
set_serial_addr(dev, 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (valxor & 7)
|
if (valxor & 7)
|
||||||
set_serial_addr(dev, 0);
|
set_serial_addr(dev, 0);
|
||||||
if (valxor & 0x70)
|
if (valxor & 0x70)
|
||||||
set_serial_addr(dev, 1);
|
set_serial_addr(dev, 1);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (valxor & 2)
|
if (valxor & 2)
|
||||||
fdc_update_enh_mode(dev->fdc, (dev->regs[3] & 2) ? 1 : 0);
|
fdc_update_enh_mode(dev->fdc, (dev->regs[3] & 2) ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if (valxor & 0x10)
|
if (valxor & 0x10)
|
||||||
set_serial_addr(dev, 0);
|
set_serial_addr(dev, 0);
|
||||||
if (valxor & 0x20)
|
if (valxor & 0x20)
|
||||||
set_serial_addr(dev, 1);
|
set_serial_addr(dev, 1);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
if (valxor & 0x01)
|
if (valxor & 0x01)
|
||||||
fdc_handler(dev);
|
fdc_handler(dev);
|
||||||
if (dev->has_ide && (valxor & 0x02))
|
if (dev->has_ide && (valxor & 0x02))
|
||||||
ide_handler(dev);
|
ide_handler(dev);
|
||||||
if (valxor & 0x18)
|
if (valxor & 0x18)
|
||||||
fdc_update_densel_force(dev->fdc, (dev->regs[5] & 0x18) >> 3);
|
fdc_update_densel_force(dev->fdc, (dev->regs[5] & 0x18) >> 3);
|
||||||
if (valxor & 0x20)
|
if (valxor & 0x20)
|
||||||
fdc_set_swap(dev->fdc, (dev->regs[5] & 0x20) >> 5);
|
fdc_set_swap(dev->fdc, (dev->regs[5] & 0x20) >> 5);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ((port == FDC_PRIMARY_ADDR) && (val == 0x55))
|
} else if ((port == FDC_PRIMARY_ADDR) && (val == 0x55))
|
||||||
dev->tries++;
|
dev->tries++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
fdc37c6xx_read(uint16_t port, void *priv)
|
fdc37c6xx_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
fdc37c6xx_t *dev = (fdc37c6xx_t *) priv;
|
fdc37c6xx_t *dev = (fdc37c6xx_t *) priv;
|
||||||
uint8_t ret = 0x00;
|
uint8_t ret = 0x00;
|
||||||
|
|
||||||
if (dev->tries == 2) {
|
if (dev->tries == 2) {
|
||||||
if (port == 0x3f1)
|
if (port == 0x3f1)
|
||||||
ret = dev->regs[dev->cur_reg];
|
ret = dev->regs[dev->cur_reg];
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37c6xx_reset(fdc37c6xx_t *dev)
|
fdc37c6xx_reset(fdc37c6xx_t *dev)
|
||||||
{
|
{
|
||||||
@@ -258,18 +248,20 @@ fdc37c6xx_reset(fdc37c6xx_t *dev)
|
|||||||
memset(dev->regs, 0, 16);
|
memset(dev->regs, 0, 16);
|
||||||
|
|
||||||
switch (dev->chip_id) {
|
switch (dev->chip_id) {
|
||||||
case 0x63: case 0x65:
|
case 0x63:
|
||||||
dev->max_reg = 0x0f;
|
case 0x65:
|
||||||
dev->regs[0x0] = 0x3b;
|
dev->max_reg = 0x0f;
|
||||||
break;
|
dev->regs[0x0] = 0x3b;
|
||||||
case 0x64: case 0x66:
|
break;
|
||||||
dev->max_reg = 0x0f;
|
case 0x64:
|
||||||
dev->regs[0x0] = 0x2b;
|
case 0x66:
|
||||||
break;
|
dev->max_reg = 0x0f;
|
||||||
default:
|
dev->regs[0x0] = 0x2b;
|
||||||
dev->max_reg = (dev->chip_id >= 0x61) ? 0x03 : 0x02;
|
break;
|
||||||
dev->regs[0x0] = 0x3f;
|
default:
|
||||||
break;
|
dev->max_reg = (dev->chip_id >= 0x61) ? 0x03 : 0x02;
|
||||||
|
dev->regs[0x0] = 0x3f;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->regs[0x1] = 0x9f;
|
dev->regs[0x1] = 0x9f;
|
||||||
@@ -277,12 +269,12 @@ fdc37c6xx_reset(fdc37c6xx_t *dev)
|
|||||||
dev->regs[0x3] = 0x78;
|
dev->regs[0x3] = 0x78;
|
||||||
|
|
||||||
if (dev->chip_id >= 0x63) {
|
if (dev->chip_id >= 0x63) {
|
||||||
dev->regs[0x6] = 0xff;
|
dev->regs[0x6] = 0xff;
|
||||||
dev->regs[0xd] = dev->chip_id;
|
dev->regs[0xd] = dev->chip_id;
|
||||||
if (dev->chip_id >= 0x65)
|
if (dev->chip_id >= 0x65)
|
||||||
dev->regs[0xe] = 0x02;
|
dev->regs[0xe] = 0x02;
|
||||||
else
|
else
|
||||||
dev->regs[0xe] = 0x01;
|
dev->regs[0xe] = 0x01;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_serial_addr(dev, 0);
|
set_serial_addr(dev, 0);
|
||||||
@@ -293,10 +285,9 @@ fdc37c6xx_reset(fdc37c6xx_t *dev)
|
|||||||
fdc_handler(dev);
|
fdc_handler(dev);
|
||||||
|
|
||||||
if (dev->has_ide)
|
if (dev->has_ide)
|
||||||
ide_handler(dev);
|
ide_handler(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37c6xx_close(void *priv)
|
fdc37c6xx_close(void *priv)
|
||||||
{
|
{
|
||||||
@@ -305,7 +296,6 @@ fdc37c6xx_close(void *priv)
|
|||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
fdc37c6xx_init(const device_t *info)
|
fdc37c6xx_init(const device_t *info)
|
||||||
{
|
{
|
||||||
@@ -318,15 +308,15 @@ fdc37c6xx_init(const device_t *info)
|
|||||||
dev->has_ide = (info->local >> 8) & 0xff;
|
dev->has_ide = (info->local >> 8) & 0xff;
|
||||||
|
|
||||||
if (dev->chip_id >= 0x63) {
|
if (dev->chip_id >= 0x63) {
|
||||||
dev->uart[0] = device_add_inst(&ns16550_device, 1);
|
dev->uart[0] = device_add_inst(&ns16550_device, 1);
|
||||||
dev->uart[1] = device_add_inst(&ns16550_device, 2);
|
dev->uart[1] = device_add_inst(&ns16550_device, 2);
|
||||||
} else {
|
} else {
|
||||||
dev->uart[0] = device_add_inst(&ns16450_device, 1);
|
dev->uart[0] = device_add_inst(&ns16450_device, 1);
|
||||||
dev->uart[1] = device_add_inst(&ns16450_device, 2);
|
dev->uart[1] = device_add_inst(&ns16450_device, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
io_sethandler(FDC_PRIMARY_ADDR, 0x0002,
|
io_sethandler(FDC_PRIMARY_ADDR, 0x0002,
|
||||||
fdc37c6xx_read, NULL, NULL, fdc37c6xx_write, NULL, NULL, dev);
|
fdc37c6xx_read, NULL, NULL, fdc37c6xx_write, NULL, NULL, dev);
|
||||||
|
|
||||||
fdc37c6xx_reset(dev);
|
fdc37c6xx_reset(dev);
|
||||||
|
|
||||||
@@ -336,127 +326,127 @@ fdc37c6xx_init(const device_t *info)
|
|||||||
/* The three appear to differ only in the chip ID, if I
|
/* The three appear to differ only in the chip ID, if I
|
||||||
understood their datasheets correctly. */
|
understood their datasheets correctly. */
|
||||||
const device_t fdc37c651_device = {
|
const device_t fdc37c651_device = {
|
||||||
.name = "SMC FDC37C651 Super I/O",
|
.name = "SMC FDC37C651 Super I/O",
|
||||||
.internal_name = "fdc37c651",
|
.internal_name = "fdc37c651",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x51,
|
.local = 0x51,
|
||||||
.init = fdc37c6xx_init,
|
.init = fdc37c6xx_init,
|
||||||
.close = fdc37c6xx_close,
|
.close = fdc37c6xx_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t fdc37c651_ide_device = {
|
const device_t fdc37c651_ide_device = {
|
||||||
.name = "SMC FDC37C651 Super I/O (With IDE)",
|
.name = "SMC FDC37C651 Super I/O (With IDE)",
|
||||||
.internal_name = "fdc37c651_ide",
|
.internal_name = "fdc37c651_ide",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x151,
|
.local = 0x151,
|
||||||
.init = fdc37c6xx_init,
|
.init = fdc37c6xx_init,
|
||||||
.close = fdc37c6xx_close,
|
.close = fdc37c6xx_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t fdc37c661_device = {
|
const device_t fdc37c661_device = {
|
||||||
.name = "SMC FDC37C661 Super I/O",
|
.name = "SMC FDC37C661 Super I/O",
|
||||||
.internal_name = "fdc37c661",
|
.internal_name = "fdc37c661",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x61,
|
.local = 0x61,
|
||||||
.init = fdc37c6xx_init,
|
.init = fdc37c6xx_init,
|
||||||
.close = fdc37c6xx_close,
|
.close = fdc37c6xx_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t fdc37c661_ide_device = {
|
const device_t fdc37c661_ide_device = {
|
||||||
.name = "SMC FDC37C661 Super I/O (With IDE)",
|
.name = "SMC FDC37C661 Super I/O (With IDE)",
|
||||||
.internal_name = "fdc37c661_ide",
|
.internal_name = "fdc37c661_ide",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x161,
|
.local = 0x161,
|
||||||
.init = fdc37c6xx_init,
|
.init = fdc37c6xx_init,
|
||||||
.close = fdc37c6xx_close,
|
.close = fdc37c6xx_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t fdc37c663_device = {
|
const device_t fdc37c663_device = {
|
||||||
.name = "SMC FDC37C663 Super I/O",
|
.name = "SMC FDC37C663 Super I/O",
|
||||||
.internal_name = "fdc37c663",
|
.internal_name = "fdc37c663",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x63,
|
.local = 0x63,
|
||||||
.init = fdc37c6xx_init,
|
.init = fdc37c6xx_init,
|
||||||
.close = fdc37c6xx_close,
|
.close = fdc37c6xx_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t fdc37c663_ide_device = {
|
const device_t fdc37c663_ide_device = {
|
||||||
.name = "SMC FDC37C663 Super I/O (With IDE)",
|
.name = "SMC FDC37C663 Super I/O (With IDE)",
|
||||||
.internal_name = "fdc37c663_ide",
|
.internal_name = "fdc37c663_ide",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x163,
|
.local = 0x163,
|
||||||
.init = fdc37c6xx_init,
|
.init = fdc37c6xx_init,
|
||||||
.close = fdc37c6xx_close,
|
.close = fdc37c6xx_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t fdc37c665_device = {
|
const device_t fdc37c665_device = {
|
||||||
.name = "SMC FDC37C665 Super I/O",
|
.name = "SMC FDC37C665 Super I/O",
|
||||||
.internal_name = "fdc37c665",
|
.internal_name = "fdc37c665",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x65,
|
.local = 0x65,
|
||||||
.init = fdc37c6xx_init,
|
.init = fdc37c6xx_init,
|
||||||
.close = fdc37c6xx_close,
|
.close = fdc37c6xx_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t fdc37c665_ide_device = {
|
const device_t fdc37c665_ide_device = {
|
||||||
.name = "SMC FDC37C665 Super I/O (With IDE)",
|
.name = "SMC FDC37C665 Super I/O (With IDE)",
|
||||||
.internal_name = "fdc37c665_ide",
|
.internal_name = "fdc37c665_ide",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x265,
|
.local = 0x265,
|
||||||
.init = fdc37c6xx_init,
|
.init = fdc37c6xx_init,
|
||||||
.close = fdc37c6xx_close,
|
.close = fdc37c6xx_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t fdc37c666_device = {
|
const device_t fdc37c666_device = {
|
||||||
.name = "SMC FDC37C666 Super I/O",
|
.name = "SMC FDC37C666 Super I/O",
|
||||||
.internal_name = "fdc37c666",
|
.internal_name = "fdc37c666",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x66,
|
.local = 0x66,
|
||||||
.init = fdc37c6xx_init,
|
.init = fdc37c6xx_init,
|
||||||
.close = fdc37c6xx_close,
|
.close = fdc37c6xx_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -31,23 +31,21 @@
|
|||||||
#include <86box/fdc.h>
|
#include <86box/fdc.h>
|
||||||
#include <86box/sio.h>
|
#include <86box/sio.h>
|
||||||
|
|
||||||
#define SIO_INDEX_PORT dev->sio_index_port
|
#define SIO_INDEX_PORT dev->sio_index_port
|
||||||
#define INDEX dev->index
|
#define INDEX dev->index
|
||||||
|
|
||||||
/* Current Logical Device Number */
|
/* Current Logical Device Number */
|
||||||
#define CURRENT_LOGICAL_DEVICE dev->regs[0x07]
|
#define CURRENT_LOGICAL_DEVICE dev->regs[0x07]
|
||||||
|
|
||||||
/* Global Device Configuration */
|
/* Global Device Configuration */
|
||||||
#define ENABLED(ld) dev->device_regs[ld][0x30]
|
#define ENABLED(ld) dev->device_regs[ld][0x30]
|
||||||
#define BASE_ADDRESS(ld) ((dev->device_regs[ld][0x60] << 8) | \
|
#define BASE_ADDRESS(ld) ((dev->device_regs[ld][0x60] << 8) | (dev->device_regs[ld][0x61]))
|
||||||
(dev->device_regs[ld][0x61]))
|
#define IRQ(ld) dev->device_regs[ld][0x70]
|
||||||
#define IRQ(ld) dev->device_regs[ld][0x70]
|
#define DMA(ld) dev->device_regs[ld][0x74]
|
||||||
#define DMA(ld) dev->device_regs[ld][0x74]
|
|
||||||
|
|
||||||
/* Miscellaneous Chip Functionality */
|
/* Miscellaneous Chip Functionality */
|
||||||
#define SOFT_RESET (val & 0x01)
|
#define SOFT_RESET (val & 0x01)
|
||||||
#define POWER_CONTROL dev->regs[0x22]
|
#define POWER_CONTROL dev->regs[0x22]
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_FDC37M60X_LOG
|
#ifdef ENABLE_FDC37M60X_LOG
|
||||||
int fdc37m60x_do_log = ENABLE_FDC37M60X_LOG;
|
int fdc37m60x_do_log = ENABLE_FDC37M60X_LOG;
|
||||||
@@ -57,117 +55,120 @@ fdc37m60x_log(const char *fmt, ...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (fdc37m60x_do_log)
|
if (fdc37m60x_do_log) {
|
||||||
{
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
pclog_ex(fmt, ap);
|
pclog_ex(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define fdc37m60x_log(fmt, ...)
|
# define fdc37m60x_log(fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint8_t index, regs[256], device_regs[10][256], cfg_lock, ide_function;
|
uint8_t index, regs[256], device_regs[10][256], cfg_lock, ide_function;
|
||||||
uint16_t sio_index_port;
|
uint16_t sio_index_port;
|
||||||
|
|
||||||
fdc_t * fdc;
|
fdc_t *fdc;
|
||||||
serial_t * uart[2];
|
serial_t *uart[2];
|
||||||
|
|
||||||
} fdc37m60x_t;
|
} fdc37m60x_t;
|
||||||
|
|
||||||
|
static void fdc37m60x_fdc_handler(fdc37m60x_t *dev);
|
||||||
static void fdc37m60x_fdc_handler(fdc37m60x_t *dev);
|
static void fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev);
|
||||||
static void fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev);
|
static void fdc37m60x_lpt_handler(fdc37m60x_t *dev);
|
||||||
static void fdc37m60x_lpt_handler(fdc37m60x_t *dev);
|
static void fdc37m60x_logical_device_handler(fdc37m60x_t *dev);
|
||||||
static void fdc37m60x_logical_device_handler(fdc37m60x_t *dev);
|
static void fdc37m60x_reset(void *priv);
|
||||||
static void fdc37m60x_reset(void *priv);
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37m60x_write(uint16_t addr, uint8_t val, void *priv)
|
fdc37m60x_write(uint16_t addr, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
fdc37m60x_t *dev = (fdc37m60x_t *)priv;
|
fdc37m60x_t *dev = (fdc37m60x_t *) priv;
|
||||||
|
|
||||||
if (addr & 1) {
|
if (addr & 1) {
|
||||||
if (!dev->cfg_lock) {
|
if (!dev->cfg_lock) {
|
||||||
switch (INDEX) {
|
switch (INDEX) {
|
||||||
/* Global Configuration */
|
/* Global Configuration */
|
||||||
case 0x02:
|
case 0x02:
|
||||||
dev->regs[INDEX] = val;
|
dev->regs[INDEX] = val;
|
||||||
if (SOFT_RESET)
|
if (SOFT_RESET)
|
||||||
fdc37m60x_reset(dev);
|
fdc37m60x_reset(dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x07:
|
case 0x07:
|
||||||
CURRENT_LOGICAL_DEVICE = val;
|
CURRENT_LOGICAL_DEVICE = val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x22:
|
case 0x22:
|
||||||
POWER_CONTROL = val & 0x3f;
|
POWER_CONTROL = val & 0x3f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x23:
|
case 0x23:
|
||||||
dev->regs[INDEX] = val & 0x3f;
|
dev->regs[INDEX] = val & 0x3f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x24:
|
case 0x24:
|
||||||
dev->regs[INDEX] = val & 0x4e;
|
dev->regs[INDEX] = val & 0x4e;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x2b: case 0x2c: case 0x2d: case 0x2e:
|
case 0x2b:
|
||||||
case 0x2f:
|
case 0x2c:
|
||||||
dev->regs[INDEX] = val;
|
case 0x2d:
|
||||||
break;
|
case 0x2e:
|
||||||
|
case 0x2f:
|
||||||
|
dev->regs[INDEX] = val;
|
||||||
|
break;
|
||||||
|
|
||||||
/* Device Configuration */
|
/* Device Configuration */
|
||||||
case 0x30:
|
case 0x30:
|
||||||
case 0x60: case 0x61:
|
case 0x60:
|
||||||
case 0x70:
|
case 0x61:
|
||||||
case 0x74:
|
case 0x70:
|
||||||
case 0xf0: case 0xf1: case 0xf2: case 0xf3:
|
case 0x74:
|
||||||
case 0xf4: case 0xf5: case 0xf6: case 0xf7:
|
case 0xf0:
|
||||||
if (CURRENT_LOGICAL_DEVICE <= 0x81) /* Avoid Overflow */
|
case 0xf1:
|
||||||
dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] = (INDEX == 0x30) ? (val & 1) : val;
|
case 0xf2:
|
||||||
fdc37m60x_logical_device_handler(dev);
|
case 0xf3:
|
||||||
break;
|
case 0xf4:
|
||||||
}
|
case 0xf5:
|
||||||
|
case 0xf6:
|
||||||
|
case 0xf7:
|
||||||
|
if (CURRENT_LOGICAL_DEVICE <= 0x81) /* Avoid Overflow */
|
||||||
|
dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] = (INDEX == 0x30) ? (val & 1) : val;
|
||||||
|
fdc37m60x_logical_device_handler(dev);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Enter/Escape Configuration Mode */
|
/* Enter/Escape Configuration Mode */
|
||||||
if (val == 0x55)
|
if (val == 0x55)
|
||||||
dev->cfg_lock = 0;
|
dev->cfg_lock = 0;
|
||||||
else if (!dev->cfg_lock && (val == 0xaa))
|
else if (!dev->cfg_lock && (val == 0xaa))
|
||||||
dev->cfg_lock = 1;
|
dev->cfg_lock = 1;
|
||||||
else if (!dev->cfg_lock)
|
else if (!dev->cfg_lock)
|
||||||
INDEX = val;
|
INDEX = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
fdc37m60x_read(uint16_t addr, void *priv)
|
fdc37m60x_read(uint16_t addr, void *priv)
|
||||||
{
|
{
|
||||||
fdc37m60x_t *dev = (fdc37m60x_t *)priv;
|
fdc37m60x_t *dev = (fdc37m60x_t *) priv;
|
||||||
uint8_t ret = 0xff;
|
uint8_t ret = 0xff;
|
||||||
|
|
||||||
if (addr & 1)
|
if (addr & 1)
|
||||||
ret = (INDEX >= 0x30) ? dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] : dev->regs[INDEX];
|
ret = (INDEX >= 0x30) ? dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] : dev->regs[INDEX];
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37m60x_fdc_handler(fdc37m60x_t *dev)
|
fdc37m60x_fdc_handler(fdc37m60x_t *dev)
|
||||||
{
|
{
|
||||||
fdc_remove(dev->fdc);
|
fdc_remove(dev->fdc);
|
||||||
|
|
||||||
if (ENABLED(0) || (POWER_CONTROL & 0x01))
|
if (ENABLED(0) || (POWER_CONTROL & 0x01)) {
|
||||||
{
|
|
||||||
fdc_set_base(dev->fdc, BASE_ADDRESS(0));
|
fdc_set_base(dev->fdc, BASE_ADDRESS(0));
|
||||||
fdc_set_irq(dev->fdc, IRQ(0) & 0xf);
|
fdc_set_irq(dev->fdc, IRQ(0) & 0xf);
|
||||||
fdc_set_dma_ch(dev->fdc, DMA(0) & 0x07);
|
fdc_set_dma_ch(dev->fdc, DMA(0) & 0x07);
|
||||||
@@ -189,70 +190,67 @@ fdc37m60x_fdc_handler(fdc37m60x_t *dev)
|
|||||||
fdc_update_drvrate(dev->fdc, 3, (dev->device_regs[0][0xf7] & 0x18) >> 3);
|
fdc_update_drvrate(dev->fdc, 3, (dev->device_regs[0][0xf7] & 0x18) >> 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev)
|
fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev)
|
||||||
{
|
{
|
||||||
serial_remove(dev->uart[num & 1]);
|
serial_remove(dev->uart[num & 1]);
|
||||||
|
|
||||||
if (ENABLED(4 + (num & 1)) || (POWER_CONTROL & (1 << (4 + (num & 1)))))
|
if (ENABLED(4 + (num & 1)) || (POWER_CONTROL & (1 << (4 + (num & 1))))) {
|
||||||
{
|
|
||||||
serial_setup(dev->uart[num & 1], BASE_ADDRESS(4 + (num & 1)), IRQ(4 + (num & 1)) & 0xf);
|
serial_setup(dev->uart[num & 1], BASE_ADDRESS(4 + (num & 1)), IRQ(4 + (num & 1)) & 0xf);
|
||||||
fdc37m60x_log("SMC60x-UART%d: BASE %04x IRQ %d\n", num & 1, BASE_ADDRESS(4 + (num & 1)), IRQ(4 + (num & 1)) & 0xf);
|
fdc37m60x_log("SMC60x-UART%d: BASE %04x IRQ %d\n", num & 1, BASE_ADDRESS(4 + (num & 1)), IRQ(4 + (num & 1)) & 0xf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
void fdc37m60x_lpt_handler(fdc37m60x_t *dev)
|
fdc37m60x_lpt_handler(fdc37m60x_t *dev)
|
||||||
{
|
{
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
|
|
||||||
if (ENABLED(3) || (POWER_CONTROL & 0x08)) {
|
if (ENABLED(3) || (POWER_CONTROL & 0x08)) {
|
||||||
lpt1_init(BASE_ADDRESS(3));
|
lpt1_init(BASE_ADDRESS(3));
|
||||||
lpt1_irq(IRQ(3) & 0xf);
|
lpt1_irq(IRQ(3) & 0xf);
|
||||||
fdc37m60x_log("SMC60x-LPT: BASE %04x IRQ %d\n", BASE_ADDRESS(3), IRQ(3) & 0xf);
|
fdc37m60x_log("SMC60x-LPT: BASE %04x IRQ %d\n", BASE_ADDRESS(3), IRQ(3) & 0xf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
void fdc37m60x_logical_device_handler(fdc37m60x_t *dev)
|
fdc37m60x_logical_device_handler(fdc37m60x_t *dev)
|
||||||
{
|
{
|
||||||
/* Register 07h:
|
/* Register 07h:
|
||||||
Device 0: FDC
|
Device 0: FDC
|
||||||
Device 3: LPT
|
Device 3: LPT
|
||||||
Device 4: UART1
|
Device 4: UART1
|
||||||
Device 5: UART2
|
Device 5: UART2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
switch (CURRENT_LOGICAL_DEVICE) {
|
switch (CURRENT_LOGICAL_DEVICE) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
fdc37m60x_fdc_handler(dev);
|
fdc37m60x_fdc_handler(dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03:
|
case 0x03:
|
||||||
fdc37m60x_lpt_handler(dev);
|
fdc37m60x_lpt_handler(dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x04:
|
case 0x04:
|
||||||
fdc37m60x_uart_handler(0, dev);
|
fdc37m60x_uart_handler(0, dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x05:
|
case 0x05:
|
||||||
fdc37m60x_uart_handler(1, dev);
|
fdc37m60x_uart_handler(1, dev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37m60x_reset(void *priv)
|
fdc37m60x_reset(void *priv)
|
||||||
{
|
{
|
||||||
fdc37m60x_t *dev = (fdc37m60x_t *) priv;
|
fdc37m60x_t *dev = (fdc37m60x_t *) priv;
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
|
|
||||||
memset(dev->regs, 0, sizeof(dev->regs));
|
memset(dev->regs, 0, sizeof(dev->regs));
|
||||||
for (i = 0; i < 10; i++)
|
for (i = 0; i < 10; i++)
|
||||||
memset(dev->device_regs[i], 0, sizeof(dev->device_regs[i]));
|
memset(dev->device_regs[i], 0, sizeof(dev->device_regs[i]));
|
||||||
|
|
||||||
dev->regs[0x20] = 0x47;
|
dev->regs[0x20] = 0x47;
|
||||||
dev->regs[0x24] = 0x04;
|
dev->regs[0x24] = 0x04;
|
||||||
@@ -286,24 +284,22 @@ fdc37m60x_reset(void *priv)
|
|||||||
fdc37m60x_lpt_handler(dev);
|
fdc37m60x_lpt_handler(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc37m60x_close(void *priv)
|
fdc37m60x_close(void *priv)
|
||||||
{
|
{
|
||||||
fdc37m60x_t *dev = (fdc37m60x_t *)priv;
|
fdc37m60x_t *dev = (fdc37m60x_t *) priv;
|
||||||
|
|
||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
fdc37m60x_init(const device_t *info)
|
fdc37m60x_init(const device_t *info)
|
||||||
{
|
{
|
||||||
fdc37m60x_t *dev = (fdc37m60x_t *)malloc(sizeof(fdc37m60x_t));
|
fdc37m60x_t *dev = (fdc37m60x_t *) malloc(sizeof(fdc37m60x_t));
|
||||||
memset(dev, 0, sizeof(fdc37m60x_t));
|
memset(dev, 0, sizeof(fdc37m60x_t));
|
||||||
SIO_INDEX_PORT = info->local;
|
SIO_INDEX_PORT = info->local;
|
||||||
|
|
||||||
dev->fdc = device_add(&fdc_at_smc_device);
|
dev->fdc = device_add(&fdc_at_smc_device);
|
||||||
dev->uart[0] = device_add_inst(&ns16550_device, 1);
|
dev->uart[0] = device_add_inst(&ns16550_device, 1);
|
||||||
dev->uart[1] = device_add_inst(&ns16550_device, 2);
|
dev->uart[1] = device_add_inst(&ns16550_device, 2);
|
||||||
|
|
||||||
@@ -315,29 +311,29 @@ fdc37m60x_init(const device_t *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const device_t fdc37m60x_device = {
|
const device_t fdc37m60x_device = {
|
||||||
.name = "SMSC FDC37M60X",
|
.name = "SMSC FDC37M60X",
|
||||||
.internal_name = "fdc37m60x",
|
.internal_name = "fdc37m60x",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = FDC_PRIMARY_ADDR,
|
.local = FDC_PRIMARY_ADDR,
|
||||||
.init = fdc37m60x_init,
|
.init = fdc37m60x_init,
|
||||||
.close = fdc37m60x_close,
|
.close = fdc37m60x_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t fdc37m60x_370_device = {
|
const device_t fdc37m60x_370_device = {
|
||||||
.name = "SMSC FDC37M60X with 10K Pull Up Resistor",
|
.name = "SMSC FDC37M60X with 10K Pull Up Resistor",
|
||||||
.internal_name = "fdc37m60x_370",
|
.internal_name = "fdc37m60x_370",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = FDC_SECONDARY_ADDR,
|
.local = FDC_SECONDARY_ADDR,
|
||||||
.init = fdc37m60x_init,
|
.init = fdc37m60x_init,
|
||||||
.close = fdc37m60x_close,
|
.close = fdc37m60x_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -33,250 +33,237 @@
|
|||||||
#include <86box/fdd_common.h>
|
#include <86box/fdd_common.h>
|
||||||
#include <86box/sio.h>
|
#include <86box/sio.h>
|
||||||
|
|
||||||
|
|
||||||
#define LDN dev->regs[7]
|
#define LDN dev->regs[7]
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
fdc_t *fdc_controller;
|
fdc_t *fdc_controller;
|
||||||
serial_t *uart[2];
|
serial_t *uart[2];
|
||||||
|
|
||||||
uint8_t index, regs[256], device_regs[6][256];
|
uint8_t index, regs[256], device_regs[6][256];
|
||||||
int unlocked, enumerator;
|
int unlocked, enumerator;
|
||||||
} it8661f_t;
|
} it8661f_t;
|
||||||
|
|
||||||
|
static uint8_t mb_pnp_key[32] = { 0x6a, 0xb5, 0xda, 0xed, 0xf6, 0xfb, 0x7d, 0xbe, 0xdf, 0x6f, 0x37, 0x1b, 0x0d, 0x86, 0xc3, 0x61, 0xb0, 0x58, 0x2c, 0x16, 0x8b, 0x45, 0xa2, 0xd1, 0xe8, 0x74, 0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39 };
|
||||||
|
|
||||||
static uint8_t mb_pnp_key[32] = {0x6a, 0xb5, 0xda, 0xed, 0xf6, 0xfb, 0x7d, 0xbe, 0xdf, 0x6f, 0x37, 0x1b, 0x0d, 0x86, 0xc3, 0x61, 0xb0, 0x58, 0x2c, 0x16, 0x8b, 0x45, 0xa2, 0xd1, 0xe8, 0x74, 0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39};
|
static void it8661f_reset(void *priv);
|
||||||
|
|
||||||
|
|
||||||
static void it8661f_reset(void *priv);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_IT8661_LOG
|
#ifdef ENABLE_IT8661_LOG
|
||||||
int it8661_do_log = ENABLE_IT8661_LOG;
|
int it8661_do_log = ENABLE_IT8661_LOG;
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
it8661_log(const char *fmt, ...)
|
it8661_log(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (it8661_do_log) {
|
if (it8661_do_log) {
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
pclog_ex(fmt, ap);
|
pclog_ex(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define it8661_log(fmt, ...)
|
# define it8661_log(fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
it8661_fdc(uint16_t addr, uint8_t val, it8661f_t *dev)
|
it8661_fdc(uint16_t addr, uint8_t val, it8661f_t *dev)
|
||||||
{
|
{
|
||||||
fdc_remove(dev->fdc_controller);
|
fdc_remove(dev->fdc_controller);
|
||||||
|
|
||||||
if (((addr == 0x30) && (val & 1)) || (dev->device_regs[0][0x30] & 1)) {
|
if (((addr == 0x30) && (val & 1)) || (dev->device_regs[0][0x30] & 1)) {
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case 0x30:
|
case 0x30:
|
||||||
dev->device_regs[0][addr] = val & 1;
|
dev->device_regs[0][addr] = val & 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x31:
|
case 0x31:
|
||||||
dev->device_regs[0][addr] = val & 3;
|
dev->device_regs[0][addr] = val & 3;
|
||||||
if (val & 1)
|
if (val & 1)
|
||||||
dev->device_regs[0][addr] |= 0x55;
|
dev->device_regs[0][addr] |= 0x55;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x60:
|
case 0x60:
|
||||||
case 0x61:
|
case 0x61:
|
||||||
dev->device_regs[0][addr] = val & ((addr == 0x61) ? 0xff : 0xf8);
|
dev->device_regs[0][addr] = val & ((addr == 0x61) ? 0xff : 0xf8);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x70:
|
case 0x70:
|
||||||
dev->device_regs[0][addr] = val & 0x0f;
|
dev->device_regs[0][addr] = val & 0x0f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x74:
|
case 0x74:
|
||||||
dev->device_regs[0][addr] = val & 7;
|
dev->device_regs[0][addr] = val & 7;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xf0:
|
case 0xf0:
|
||||||
dev->device_regs[0][addr] = val & 0x0f;
|
dev->device_regs[0][addr] = val & 0x0f;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fdc_set_base(dev->fdc_controller, (dev->device_regs[0][0x60] << 8) | (dev->device_regs[0][0x61]));
|
fdc_set_base(dev->fdc_controller, (dev->device_regs[0][0x60] << 8) | (dev->device_regs[0][0x61]));
|
||||||
fdc_set_irq(dev->fdc_controller, dev->device_regs[0][0x70] & 0x0f);
|
fdc_set_irq(dev->fdc_controller, dev->device_regs[0][0x70] & 0x0f);
|
||||||
fdc_set_dma_ch(dev->fdc_controller, dev->device_regs[0][0x74] & 7);
|
fdc_set_dma_ch(dev->fdc_controller, dev->device_regs[0][0x74] & 7);
|
||||||
|
|
||||||
if (dev->device_regs[0][0xf0] & 1)
|
if (dev->device_regs[0][0xf0] & 1)
|
||||||
fdc_writeprotect(dev->fdc_controller);
|
fdc_writeprotect(dev->fdc_controller);
|
||||||
|
|
||||||
it8661_log("ITE 8661-FDC: BASE %04x IRQ %02x\n", (dev->device_regs[0][0x60] << 8) | (dev->device_regs[0][0x61]),
|
it8661_log("ITE 8661-FDC: BASE %04x IRQ %02x\n", (dev->device_regs[0][0x60] << 8) | (dev->device_regs[0][0x61]),
|
||||||
dev->device_regs[0][0x70] & 0x0f);
|
dev->device_regs[0][0x70] & 0x0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
it8661_serial(int uart, uint16_t addr, uint8_t val, it8661f_t *dev)
|
it8661_serial(int uart, uint16_t addr, uint8_t val, it8661f_t *dev)
|
||||||
{
|
{
|
||||||
serial_remove(dev->uart[uart]);
|
serial_remove(dev->uart[uart]);
|
||||||
|
|
||||||
if (((addr == 0x30) && (val & 1)) || (dev->device_regs[1 + uart][0x30] & 1)) {
|
if (((addr == 0x30) && (val & 1)) || (dev->device_regs[1 + uart][0x30] & 1)) {
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case 0x30:
|
case 0x30:
|
||||||
dev->device_regs[1 + uart][addr] = val & 1;
|
dev->device_regs[1 + uart][addr] = val & 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x60:
|
case 0x60:
|
||||||
case 0x61:
|
case 0x61:
|
||||||
dev->device_regs[1 + uart][addr] = val & ((addr == 0x61) ? 0xff : 0xf8);
|
dev->device_regs[1 + uart][addr] = val & ((addr == 0x61) ? 0xff : 0xf8);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x70:
|
case 0x70:
|
||||||
dev->device_regs[1 + uart][addr] = val & 0x0f;
|
dev->device_regs[1 + uart][addr] = val & 0x0f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x74:
|
case 0x74:
|
||||||
dev->device_regs[1 + uart][addr] = val & 7;
|
dev->device_regs[1 + uart][addr] = val & 7;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xf0:
|
case 0xf0:
|
||||||
dev->device_regs[1 + uart][addr] = val & 3;
|
dev->device_regs[1 + uart][addr] = val & 3;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
serial_setup(dev->uart[uart], (dev->device_regs[1 + uart][0x60] << 8) | (dev->device_regs[1 + uart][0x61]), dev->device_regs[1 + uart][0x70] & 0x0f);
|
serial_setup(dev->uart[uart], (dev->device_regs[1 + uart][0x60] << 8) | (dev->device_regs[1 + uart][0x61]), dev->device_regs[1 + uart][0x70] & 0x0f);
|
||||||
|
|
||||||
it8661_log("ITE 8661-UART%01x: BASE %04x IRQ %02x\n", 1 + (LDN % 1),
|
it8661_log("ITE 8661-UART%01x: BASE %04x IRQ %02x\n", 1 + (LDN % 1),
|
||||||
(dev->device_regs[1 + uart][0x60] << 8) | (dev->device_regs[1 + uart][0x61]),
|
(dev->device_regs[1 + uart][0x60] << 8) | (dev->device_regs[1 + uart][0x61]),
|
||||||
dev->device_regs[1 + uart][0x70] & 0x0f);
|
dev->device_regs[1 + uart][0x70] & 0x0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
it8661_lpt(uint16_t addr, uint8_t val, it8661f_t *dev)
|
it8661_lpt(uint16_t addr, uint8_t val, it8661f_t *dev)
|
||||||
{
|
{
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
|
|
||||||
if (((addr == 0x30) && (val & 1)) || (dev->device_regs[3][0x30] & 1)) {
|
if (((addr == 0x30) && (val & 1)) || (dev->device_regs[3][0x30] & 1)) {
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case 0x30:
|
case 0x30:
|
||||||
dev->device_regs[3][addr] = val & 1;
|
dev->device_regs[3][addr] = val & 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x60:
|
case 0x60:
|
||||||
case 0x61:
|
case 0x61:
|
||||||
dev->device_regs[3][addr] = val & ((addr == 0x61) ? 0xff : 0xf8);
|
dev->device_regs[3][addr] = val & ((addr == 0x61) ? 0xff : 0xf8);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x70:
|
case 0x70:
|
||||||
dev->device_regs[3][addr] = val & 0x0f;
|
dev->device_regs[3][addr] = val & 0x0f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x74:
|
case 0x74:
|
||||||
dev->device_regs[3][addr] = val & 7;
|
dev->device_regs[3][addr] = val & 7;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xf0:
|
case 0xf0:
|
||||||
dev->device_regs[3][addr] = val & 3;
|
dev->device_regs[3][addr] = val & 3;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
lpt1_init((dev->device_regs[3][0x60] << 8) | (dev->device_regs[3][0x61]));
|
lpt1_init((dev->device_regs[3][0x60] << 8) | (dev->device_regs[3][0x61]));
|
||||||
lpt1_irq(dev->device_regs[3][0x70] & 0x0f);
|
lpt1_irq(dev->device_regs[3][0x70] & 0x0f);
|
||||||
|
|
||||||
it8661_log("ITE 8661-LPT: BASE %04x IRQ %02x\n", (dev->device_regs[3][0x60] << 8) | (dev->device_regs[3][0x61]),
|
it8661_log("ITE 8661-LPT: BASE %04x IRQ %02x\n", (dev->device_regs[3][0x60] << 8) | (dev->device_regs[3][0x61]),
|
||||||
dev->device_regs[3][0x70] & 0x0f);
|
dev->device_regs[3][0x70] & 0x0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
it8661_ldn(uint16_t addr, uint8_t val, it8661f_t *dev)
|
it8661_ldn(uint16_t addr, uint8_t val, it8661f_t *dev)
|
||||||
{
|
{
|
||||||
switch (LDN) {
|
switch (LDN) {
|
||||||
case 0:
|
case 0:
|
||||||
it8661_fdc(addr, val, dev);
|
it8661_fdc(addr, val, dev);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
it8661_serial(LDN & 2, addr, val, dev);
|
it8661_serial(LDN & 2, addr, val, dev);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
it8661_lpt(addr, val, dev);
|
it8661_lpt(addr, val, dev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
it8661f_write(uint16_t addr, uint8_t val, void *priv)
|
it8661f_write(uint16_t addr, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
it8661f_t *dev = (it8661f_t *)priv;
|
it8661f_t *dev = (it8661f_t *) priv;
|
||||||
|
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case FDC_SECONDARY_ADDR:
|
case FDC_SECONDARY_ADDR:
|
||||||
if (!dev->unlocked) {
|
if (!dev->unlocked) {
|
||||||
(val == mb_pnp_key[dev->enumerator]) ? dev->enumerator++ : (dev->enumerator = 0);
|
(val == mb_pnp_key[dev->enumerator]) ? dev->enumerator++ : (dev->enumerator = 0);
|
||||||
if (dev->enumerator == 31) {
|
if (dev->enumerator == 31) {
|
||||||
dev->unlocked = 1;
|
dev->unlocked = 1;
|
||||||
it8661_log("ITE8661F: Unlocked!\n");
|
it8661_log("ITE8661F: Unlocked!\n");
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
dev->index = val;
|
dev->index = val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x371:
|
case 0x371:
|
||||||
if (dev->unlocked) {
|
if (dev->unlocked) {
|
||||||
switch (dev->index) {
|
switch (dev->index) {
|
||||||
case 0x02:
|
case 0x02:
|
||||||
dev->regs[dev->index] = val;
|
dev->regs[dev->index] = val;
|
||||||
if (val & 1)
|
if (val & 1)
|
||||||
it8661f_reset(dev);
|
it8661f_reset(dev);
|
||||||
if (val & 2)
|
if (val & 2)
|
||||||
dev->unlocked = 0;
|
dev->unlocked = 0;
|
||||||
break;
|
break;
|
||||||
case 0x07:
|
case 0x07:
|
||||||
dev->regs[dev->index] = val;
|
dev->regs[dev->index] = val;
|
||||||
break;
|
break;
|
||||||
case 0x22:
|
case 0x22:
|
||||||
dev->regs[dev->index] = val & 0x30;
|
dev->regs[dev->index] = val & 0x30;
|
||||||
break;
|
break;
|
||||||
case 0x23:
|
case 0x23:
|
||||||
dev->regs[dev->index] = val & 0x1f;
|
dev->regs[dev->index] = val & 0x1f;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
it8661_ldn(dev->index, val, dev);
|
it8661_ldn(dev->index, val, dev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
it8661f_read(uint16_t addr, void *priv)
|
it8661f_read(uint16_t addr, void *priv)
|
||||||
{
|
{
|
||||||
it8661f_t *dev = (it8661f_t *)priv;
|
it8661f_t *dev = (it8661f_t *) priv;
|
||||||
|
|
||||||
it8661_log("IT8661F:\n", addr, dev->regs[dev->index]);
|
it8661_log("IT8661F:\n", addr, dev->regs[dev->index]);
|
||||||
return (addr == 0xa79) ? dev->regs[dev->index] : 0xff;
|
return (addr == 0xa79) ? dev->regs[dev->index] : 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
it8661f_reset(void *priv)
|
it8661f_reset(void *priv)
|
||||||
{
|
{
|
||||||
it8661f_t *dev = (it8661f_t *)priv;
|
it8661f_t *dev = (it8661f_t *) priv;
|
||||||
dev->regs[0x20] = 0x86;
|
dev->regs[0x20] = 0x86;
|
||||||
dev->regs[0x21] = 0x61;
|
dev->regs[0x21] = 0x61;
|
||||||
|
|
||||||
@@ -304,20 +291,18 @@ it8661f_reset(void *priv)
|
|||||||
dev->device_regs[3][0xf0] = 3;
|
dev->device_regs[3][0xf0] = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
it8661f_close(void *priv)
|
it8661f_close(void *priv)
|
||||||
{
|
{
|
||||||
it8661f_t *dev = (it8661f_t *)priv;
|
it8661f_t *dev = (it8661f_t *) priv;
|
||||||
|
|
||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
it8661f_init(const device_t *info)
|
it8661f_init(const device_t *info)
|
||||||
{
|
{
|
||||||
it8661f_t *dev = (it8661f_t *)malloc(sizeof(it8661f_t));
|
it8661f_t *dev = (it8661f_t *) malloc(sizeof(it8661f_t));
|
||||||
memset(dev, 0, sizeof(it8661f_t));
|
memset(dev, 0, sizeof(it8661f_t));
|
||||||
|
|
||||||
dev->fdc_controller = device_add(&fdc_at_smc_device);
|
dev->fdc_controller = device_add(&fdc_at_smc_device);
|
||||||
@@ -329,22 +314,22 @@ it8661f_init(const device_t *info)
|
|||||||
io_sethandler(FDC_SECONDARY_ADDR, 0x0002, it8661f_read, NULL, NULL, it8661f_write, NULL, NULL, dev);
|
io_sethandler(FDC_SECONDARY_ADDR, 0x0002, it8661f_read, NULL, NULL, it8661f_write, NULL, NULL, dev);
|
||||||
|
|
||||||
dev->enumerator = 0;
|
dev->enumerator = 0;
|
||||||
dev->unlocked = 0;
|
dev->unlocked = 0;
|
||||||
|
|
||||||
it8661f_reset(dev);
|
it8661f_reset(dev);
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
const device_t it8661f_device = {
|
const device_t it8661f_device = {
|
||||||
.name = "ITE IT8661F",
|
.name = "ITE IT8661F",
|
||||||
.internal_name = "it8661f",
|
.internal_name = "it8661f",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0,
|
.local = 0,
|
||||||
.init = it8661f_init,
|
.init = it8661f_init,
|
||||||
.close = it8661f_close,
|
.close = it8661f_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,17 +34,15 @@
|
|||||||
#include <86box/fdc.h>
|
#include <86box/fdc.h>
|
||||||
#include <86box/sio.h>
|
#include <86box/sio.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t tries,
|
uint8_t tries,
|
||||||
regs[29], gpio[2];
|
regs[29], gpio[2];
|
||||||
int cur_reg;
|
int cur_reg;
|
||||||
fdc_t *fdc;
|
fdc_t *fdc;
|
||||||
serial_t *uart[2];
|
serial_t *uart[2];
|
||||||
nvr_t *nvr;
|
nvr_t *nvr;
|
||||||
} pc87306_t;
|
} pc87306_t;
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87306_gpio_write(uint16_t port, uint8_t val, void *priv)
|
pc87306_gpio_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
@@ -53,7 +51,6 @@ pc87306_gpio_write(uint16_t port, uint8_t val, void *priv)
|
|||||||
dev->gpio[port & 1] = val;
|
dev->gpio[port & 1] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
pc87306_gpio_read(uint16_t port, void *priv)
|
pc87306_gpio_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
@@ -62,298 +59,291 @@ pc87306_gpio_read(uint16_t port, void *priv)
|
|||||||
return dev->gpio[port & 1];
|
return dev->gpio[port & 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87306_gpio_remove(pc87306_t *dev)
|
pc87306_gpio_remove(pc87306_t *dev)
|
||||||
{
|
{
|
||||||
io_removehandler(dev->regs[0x0f] << 2, 0x0001,
|
io_removehandler(dev->regs[0x0f] << 2, 0x0001,
|
||||||
pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev);
|
pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev);
|
||||||
io_removehandler((dev->regs[0x0f] << 2) + 1, 0x0001,
|
io_removehandler((dev->regs[0x0f] << 2) + 1, 0x0001,
|
||||||
pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev);
|
pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87306_gpio_init(pc87306_t *dev)
|
pc87306_gpio_init(pc87306_t *dev)
|
||||||
{
|
{
|
||||||
if ((dev->regs[0x12]) & 0x10)
|
if ((dev->regs[0x12]) & 0x10)
|
||||||
io_sethandler(dev->regs[0x0f] << 2, 0x0001,
|
io_sethandler(dev->regs[0x0f] << 2, 0x0001,
|
||||||
pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev);
|
pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev);
|
||||||
|
|
||||||
if ((dev->regs[0x12]) & 0x20)
|
if ((dev->regs[0x12]) & 0x20)
|
||||||
io_sethandler((dev->regs[0x0f] << 2) + 1, 0x0001,
|
io_sethandler((dev->regs[0x0f] << 2) + 1, 0x0001,
|
||||||
pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev);
|
pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lpt1_handler(pc87306_t *dev)
|
lpt1_handler(pc87306_t *dev)
|
||||||
{
|
{
|
||||||
int temp;
|
int temp;
|
||||||
uint16_t lptba, lpt_port = LPT1_ADDR;
|
uint16_t lptba, lpt_port = LPT1_ADDR;
|
||||||
uint8_t lpt_irq = LPT2_IRQ;
|
uint8_t lpt_irq = LPT2_IRQ;
|
||||||
|
|
||||||
temp = dev->regs[0x01] & 3;
|
temp = dev->regs[0x01] & 3;
|
||||||
lptba = ((uint16_t) dev->regs[0x19]) << 2;
|
lptba = ((uint16_t) dev->regs[0x19]) << 2;
|
||||||
|
|
||||||
switch (temp) {
|
switch (temp) {
|
||||||
case 0:
|
case 0:
|
||||||
lpt_port = LPT1_ADDR;
|
lpt_port = LPT1_ADDR;
|
||||||
lpt_irq = (dev->regs[0x02] & 0x08) ? LPT1_IRQ : LPT2_IRQ;
|
lpt_irq = (dev->regs[0x02] & 0x08) ? LPT1_IRQ : LPT2_IRQ;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (dev->regs[0x1b] & 0x40)
|
if (dev->regs[0x1b] & 0x40)
|
||||||
lpt_port = lptba;
|
lpt_port = lptba;
|
||||||
else
|
else
|
||||||
lpt_port = LPT_MDA_ADDR;
|
lpt_port = LPT_MDA_ADDR;
|
||||||
lpt_irq = LPT_MDA_IRQ;
|
lpt_irq = LPT_MDA_IRQ;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
lpt_port = LPT2_ADDR;
|
lpt_port = LPT2_ADDR;
|
||||||
lpt_irq = LPT2_IRQ;
|
lpt_irq = LPT2_IRQ;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
lpt_port = 0x000;
|
lpt_port = 0x000;
|
||||||
lpt_irq = 0xff;
|
lpt_irq = 0xff;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->regs[0x1b] & 0x10)
|
if (dev->regs[0x1b] & 0x10)
|
||||||
lpt_irq = (dev->regs[0x1b] & 0x20) ? 7 : 5;
|
lpt_irq = (dev->regs[0x1b] & 0x20) ? 7 : 5;
|
||||||
|
|
||||||
if (lpt_port)
|
if (lpt_port)
|
||||||
lpt1_init(lpt_port);
|
lpt1_init(lpt_port);
|
||||||
|
|
||||||
lpt1_irq(lpt_irq);
|
lpt1_irq(lpt_irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
serial_handler(pc87306_t *dev, int uart)
|
serial_handler(pc87306_t *dev, int uart)
|
||||||
{
|
{
|
||||||
int temp;
|
int temp;
|
||||||
uint8_t fer_irq, pnp1_irq;
|
uint8_t fer_irq, pnp1_irq;
|
||||||
uint8_t fer_shift, pnp_shift;
|
uint8_t fer_shift, pnp_shift;
|
||||||
uint8_t irq;
|
uint8_t irq;
|
||||||
|
|
||||||
temp = (dev->regs[1] >> (2 << uart)) & 3;
|
temp = (dev->regs[1] >> (2 << uart)) & 3;
|
||||||
|
|
||||||
fer_shift = 2 << uart; /* 2 for UART 1, 4 for UART 2 */
|
fer_shift = 2 << uart; /* 2 for UART 1, 4 for UART 2 */
|
||||||
pnp_shift = 2 + (uart << 2); /* 2 for UART 1, 6 for UART 2 */
|
pnp_shift = 2 + (uart << 2); /* 2 for UART 1, 6 for UART 2 */
|
||||||
|
|
||||||
/* 0 = COM1 (IRQ 4), 1 = COM2 (IRQ 3), 2 = COM3 (IRQ 4), 3 = COM4 (IRQ 3) */
|
/* 0 = COM1 (IRQ 4), 1 = COM2 (IRQ 3), 2 = COM3 (IRQ 4), 3 = COM4 (IRQ 3) */
|
||||||
fer_irq = ((dev->regs[1] >> fer_shift) & 1) ? 3 : 4;
|
fer_irq = ((dev->regs[1] >> fer_shift) & 1) ? 3 : 4;
|
||||||
pnp1_irq = ((dev->regs[0x1c] >> pnp_shift) & 1) ? 4 : 3;
|
pnp1_irq = ((dev->regs[0x1c] >> pnp_shift) & 1) ? 4 : 3;
|
||||||
|
|
||||||
irq = (dev->regs[0x1c] & 1) ? pnp1_irq : fer_irq;
|
irq = (dev->regs[0x1c] & 1) ? pnp1_irq : fer_irq;
|
||||||
|
|
||||||
switch (temp) {
|
switch (temp) {
|
||||||
case 0:
|
case 0:
|
||||||
serial_setup(dev->uart[uart], COM1_ADDR, irq);
|
serial_setup(dev->uart[uart], COM1_ADDR, irq);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
serial_setup(dev->uart[uart], COM2_ADDR, irq);
|
serial_setup(dev->uart[uart], COM2_ADDR, irq);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
switch ((dev->regs[1] >> 6) & 3) {
|
switch ((dev->regs[1] >> 6) & 3) {
|
||||||
case 0:
|
case 0:
|
||||||
serial_setup(dev->uart[uart], COM3_ADDR, irq);
|
serial_setup(dev->uart[uart], COM3_ADDR, irq);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
serial_setup(dev->uart[uart], 0x338, irq);
|
serial_setup(dev->uart[uart], 0x338, irq);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
serial_setup(dev->uart[uart], COM4_ADDR, irq);
|
serial_setup(dev->uart[uart], COM4_ADDR, irq);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
serial_setup(dev->uart[uart], 0x220, irq);
|
serial_setup(dev->uart[uart], 0x220, irq);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
switch ((dev->regs[1] >> 6) & 3) {
|
switch ((dev->regs[1] >> 6) & 3) {
|
||||||
case 0:
|
case 0:
|
||||||
serial_setup(dev->uart[uart], COM4_ADDR, irq);
|
serial_setup(dev->uart[uart], COM4_ADDR, irq);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
serial_setup(dev->uart[uart], 0x238, irq);
|
serial_setup(dev->uart[uart], 0x238, irq);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
serial_setup(dev->uart[uart], 0x2e0, irq);
|
serial_setup(dev->uart[uart], 0x2e0, irq);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
serial_setup(dev->uart[uart], 0x228, irq);
|
serial_setup(dev->uart[uart], 0x228, irq);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87306_write(uint16_t port, uint8_t val, void *priv)
|
pc87306_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
pc87306_t *dev = (pc87306_t *) priv;
|
pc87306_t *dev = (pc87306_t *) priv;
|
||||||
uint8_t index, valxor;
|
uint8_t index, valxor;
|
||||||
|
|
||||||
index = (port & 1) ? 0 : 1;
|
index = (port & 1) ? 0 : 1;
|
||||||
|
|
||||||
if (index) {
|
if (index) {
|
||||||
dev->cur_reg = val & 0x1f;
|
dev->cur_reg = val & 0x1f;
|
||||||
dev->tries = 0;
|
dev->tries = 0;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (dev->tries) {
|
if (dev->tries) {
|
||||||
if ((dev->cur_reg == 0) && (val == 8))
|
if ((dev->cur_reg == 0) && (val == 8))
|
||||||
val = 0x4b;
|
val = 0x4b;
|
||||||
valxor = val ^ dev->regs[dev->cur_reg];
|
valxor = val ^ dev->regs[dev->cur_reg];
|
||||||
dev->tries = 0;
|
dev->tries = 0;
|
||||||
if ((dev->cur_reg <= 28) && (dev->cur_reg != 8)) {
|
if ((dev->cur_reg <= 28) && (dev->cur_reg != 8)) {
|
||||||
if (dev->cur_reg == 0)
|
if (dev->cur_reg == 0)
|
||||||
val &= 0x5f;
|
val &= 0x5f;
|
||||||
if (((dev->cur_reg == 0x0F) || (dev->cur_reg == 0x12)) && valxor)
|
if (((dev->cur_reg == 0x0F) || (dev->cur_reg == 0x12)) && valxor)
|
||||||
pc87306_gpio_remove(dev);
|
pc87306_gpio_remove(dev);
|
||||||
dev->regs[dev->cur_reg] = val;
|
dev->regs[dev->cur_reg] = val;
|
||||||
} else
|
} else
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
dev->tries++;
|
dev->tries++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0:
|
case 0:
|
||||||
if (valxor & 1) {
|
if (valxor & 1) {
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
if ((val & 1) && !(dev->regs[2] & 1))
|
if ((val & 1) && !(dev->regs[2] & 1))
|
||||||
lpt1_handler(dev);
|
lpt1_handler(dev);
|
||||||
}
|
}
|
||||||
if (valxor & 2) {
|
if (valxor & 2) {
|
||||||
serial_remove(dev->uart[0]);
|
serial_remove(dev->uart[0]);
|
||||||
if ((val & 2) && !(dev->regs[2] & 1))
|
if ((val & 2) && !(dev->regs[2] & 1))
|
||||||
serial_handler(dev, 0);
|
serial_handler(dev, 0);
|
||||||
}
|
}
|
||||||
if (valxor & 4) {
|
if (valxor & 4) {
|
||||||
serial_remove(dev->uart[1]);
|
serial_remove(dev->uart[1]);
|
||||||
if ((val & 4) && !(dev->regs[2] & 1))
|
if ((val & 4) && !(dev->regs[2] & 1))
|
||||||
serial_handler(dev, 1);
|
serial_handler(dev, 1);
|
||||||
}
|
}
|
||||||
if (valxor & 0x28) {
|
if (valxor & 0x28) {
|
||||||
fdc_remove(dev->fdc);
|
fdc_remove(dev->fdc);
|
||||||
if ((val & 8) && !(dev->regs[2] & 1))
|
if ((val & 8) && !(dev->regs[2] & 1))
|
||||||
fdc_set_base(dev->fdc, (val & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
|
fdc_set_base(dev->fdc, (val & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (valxor & 3) {
|
if (valxor & 3) {
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
if ((dev->regs[0] & 1) && !(dev->regs[2] & 1))
|
if ((dev->regs[0] & 1) && !(dev->regs[2] & 1))
|
||||||
lpt1_handler(dev);
|
lpt1_handler(dev);
|
||||||
}
|
}
|
||||||
if (valxor & 0xcc) {
|
if (valxor & 0xcc) {
|
||||||
serial_remove(dev->uart[0]);
|
serial_remove(dev->uart[0]);
|
||||||
if ((dev->regs[0] & 2) && !(dev->regs[2] & 1))
|
if ((dev->regs[0] & 2) && !(dev->regs[2] & 1))
|
||||||
serial_handler(dev, 0);
|
serial_handler(dev, 0);
|
||||||
}
|
}
|
||||||
if (valxor & 0xf0) {
|
if (valxor & 0xf0) {
|
||||||
serial_remove(dev->uart[1]);
|
serial_remove(dev->uart[1]);
|
||||||
if ((dev->regs[0] & 4) && !(dev->regs[2] & 1))
|
if ((dev->regs[0] & 4) && !(dev->regs[2] & 1))
|
||||||
serial_handler(dev, 1);
|
serial_handler(dev, 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (valxor & 1) {
|
if (valxor & 1) {
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
serial_remove(dev->uart[0]);
|
serial_remove(dev->uart[0]);
|
||||||
serial_remove(dev->uart[1]);
|
serial_remove(dev->uart[1]);
|
||||||
fdc_remove(dev->fdc);
|
fdc_remove(dev->fdc);
|
||||||
|
|
||||||
if (!(val & 1)) {
|
if (!(val & 1)) {
|
||||||
if (dev->regs[0] & 1)
|
if (dev->regs[0] & 1)
|
||||||
lpt1_handler(dev);
|
lpt1_handler(dev);
|
||||||
if (dev->regs[0] & 2)
|
if (dev->regs[0] & 2)
|
||||||
serial_handler(dev, 0);
|
serial_handler(dev, 0);
|
||||||
if (dev->regs[0] & 4)
|
if (dev->regs[0] & 4)
|
||||||
serial_handler(dev, 1);
|
serial_handler(dev, 1);
|
||||||
if (dev->regs[0] & 8)
|
if (dev->regs[0] & 8)
|
||||||
fdc_set_base(dev->fdc, (dev->regs[0] & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
|
fdc_set_base(dev->fdc, (dev->regs[0] & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (valxor & 8) {
|
if (valxor & 8) {
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
if ((dev->regs[0] & 1) && !(dev->regs[2] & 1))
|
if ((dev->regs[0] & 1) && !(dev->regs[2] & 1))
|
||||||
lpt1_handler(dev);
|
lpt1_handler(dev);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
if (valxor & 0x44) {
|
if (valxor & 0x44) {
|
||||||
fdc_update_enh_mode(dev->fdc, (val & 4) ? 1 : 0);
|
fdc_update_enh_mode(dev->fdc, (val & 4) ? 1 : 0);
|
||||||
fdc_update_densel_polarity(dev->fdc, (val & 0x40) ? 1 : 0);
|
fdc_update_densel_polarity(dev->fdc, (val & 0x40) ? 1 : 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xF:
|
case 0xF:
|
||||||
if (valxor)
|
if (valxor)
|
||||||
pc87306_gpio_init(dev);
|
pc87306_gpio_init(dev);
|
||||||
break;
|
break;
|
||||||
case 0x12:
|
case 0x12:
|
||||||
if (valxor & 0x30)
|
if (valxor & 0x30)
|
||||||
pc87306_gpio_init(dev);
|
pc87306_gpio_init(dev);
|
||||||
break;
|
break;
|
||||||
case 0x19:
|
case 0x19:
|
||||||
if (valxor) {
|
if (valxor) {
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
if ((dev->regs[0] & 1) && !(dev->regs[2] & 1))
|
if ((dev->regs[0] & 1) && !(dev->regs[2] & 1))
|
||||||
lpt1_handler(dev);
|
lpt1_handler(dev);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x1B:
|
case 0x1B:
|
||||||
if (valxor & 0x70) {
|
if (valxor & 0x70) {
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
if (!(val & 0x40))
|
if (!(val & 0x40))
|
||||||
dev->regs[0x19] = 0xEF;
|
dev->regs[0x19] = 0xEF;
|
||||||
if ((dev->regs[0] & 1) && !(dev->regs[2] & 1))
|
if ((dev->regs[0] & 1) && !(dev->regs[2] & 1))
|
||||||
lpt1_handler(dev);
|
lpt1_handler(dev);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x1C:
|
case 0x1C:
|
||||||
if (valxor) {
|
if (valxor) {
|
||||||
serial_remove(dev->uart[0]);
|
serial_remove(dev->uart[0]);
|
||||||
serial_remove(dev->uart[1]);
|
serial_remove(dev->uart[1]);
|
||||||
|
|
||||||
if ((dev->regs[0] & 2) && !(dev->regs[2] & 1))
|
if ((dev->regs[0] & 2) && !(dev->regs[2] & 1))
|
||||||
serial_handler(dev, 0);
|
serial_handler(dev, 0);
|
||||||
if ((dev->regs[0] & 4) && !(dev->regs[2] & 1))
|
if ((dev->regs[0] & 4) && !(dev->regs[2] & 1))
|
||||||
serial_handler(dev, 1);
|
serial_handler(dev, 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
pc87306_read(uint16_t port, void *priv)
|
pc87306_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
pc87306_t *dev = (pc87306_t *) priv;
|
pc87306_t *dev = (pc87306_t *) priv;
|
||||||
uint8_t ret = 0xff, index;
|
uint8_t ret = 0xff, index;
|
||||||
|
|
||||||
index = (port & 1) ? 0 : 1;
|
index = (port & 1) ? 0 : 1;
|
||||||
|
|
||||||
dev->tries = 0;
|
dev->tries = 0;
|
||||||
|
|
||||||
if (index)
|
if (index)
|
||||||
ret = dev->cur_reg & 0x1f;
|
ret = dev->cur_reg & 0x1f;
|
||||||
else {
|
else {
|
||||||
if (dev->cur_reg == 8)
|
if (dev->cur_reg == 8)
|
||||||
ret = 0x70;
|
ret = 0x70;
|
||||||
else if (dev->cur_reg < 28)
|
else if (dev->cur_reg < 28)
|
||||||
ret = dev->regs[dev->cur_reg];
|
ret = dev->regs[dev->cur_reg];
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
pc87306_reset(pc87306_t *dev)
|
pc87306_reset(pc87306_t *dev)
|
||||||
{
|
{
|
||||||
@@ -374,8 +364,8 @@ pc87306_reset(pc87306_t *dev)
|
|||||||
dev->gpio[1] = 0xfb;
|
dev->gpio[1] = 0xfb;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
0 = 360 rpm @ 500 kbps for 3.5"
|
0 = 360 rpm @ 500 kbps for 3.5"
|
||||||
1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5"
|
1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5"
|
||||||
*/
|
*/
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
lpt1_handler(dev);
|
lpt1_handler(dev);
|
||||||
@@ -387,7 +377,6 @@ pc87306_reset(pc87306_t *dev)
|
|||||||
pc87306_gpio_init(dev);
|
pc87306_gpio_init(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87306_close(void *priv)
|
pc87306_close(void *priv)
|
||||||
{
|
{
|
||||||
@@ -396,7 +385,6 @@ pc87306_close(void *priv)
|
|||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
pc87306_init(const device_t *info)
|
pc87306_init(const device_t *info)
|
||||||
{
|
{
|
||||||
@@ -413,21 +401,21 @@ pc87306_init(const device_t *info)
|
|||||||
pc87306_reset(dev);
|
pc87306_reset(dev);
|
||||||
|
|
||||||
io_sethandler(0x02e, 0x0002,
|
io_sethandler(0x02e, 0x0002,
|
||||||
pc87306_read, NULL, NULL, pc87306_write, NULL, NULL, dev);
|
pc87306_read, NULL, NULL, pc87306_write, NULL, NULL, dev);
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
const device_t pc87306_device = {
|
const device_t pc87306_device = {
|
||||||
.name = "National Semiconductor PC87306 Super I/O",
|
.name = "National Semiconductor PC87306 Super I/O",
|
||||||
.internal_name = "pc87306",
|
.internal_name = "pc87306",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0,
|
.local = 0,
|
||||||
.init = pc87306_init,
|
.init = pc87306_init,
|
||||||
.close = pc87306_close,
|
.close = pc87306_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,70 +34,64 @@
|
|||||||
#include <86box/fdc.h>
|
#include <86box/fdc.h>
|
||||||
#include <86box/sio.h>
|
#include <86box/sio.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t id, pm_idx,
|
uint8_t id, pm_idx,
|
||||||
regs[48], ld_regs[256][208],
|
regs[48], ld_regs[256][208],
|
||||||
pcregs[16], gpio[2][4],
|
pcregs[16], gpio[2][4],
|
||||||
pm[8];
|
pm[8];
|
||||||
uint16_t gpio_base, gpio_base2,
|
uint16_t gpio_base, gpio_base2,
|
||||||
pm_base;
|
pm_base;
|
||||||
int cur_reg;
|
int cur_reg;
|
||||||
fdc_t *fdc;
|
fdc_t *fdc;
|
||||||
serial_t *uart[2];
|
serial_t *uart[2];
|
||||||
} pc87307_t;
|
} pc87307_t;
|
||||||
|
|
||||||
|
static void fdc_handler(pc87307_t *dev);
|
||||||
static void fdc_handler(pc87307_t *dev);
|
static void lpt1_handler(pc87307_t *dev);
|
||||||
static void lpt1_handler(pc87307_t *dev);
|
static void serial_handler(pc87307_t *dev, int uart);
|
||||||
static void serial_handler(pc87307_t *dev, int uart);
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87307_gpio_write(uint16_t port, uint8_t val, void *priv)
|
pc87307_gpio_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
pc87307_t *dev = (pc87307_t *) priv;
|
pc87307_t *dev = (pc87307_t *) priv;
|
||||||
uint8_t bank = ((port & 0xfffc) == dev->gpio_base2);
|
uint8_t bank = ((port & 0xfffc) == dev->gpio_base2);
|
||||||
|
|
||||||
dev->gpio[bank][port & 3] = val;
|
dev->gpio[bank][port & 3] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
pc87307_gpio_read(uint16_t port, void *priv)
|
pc87307_gpio_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
pc87307_t *dev = (pc87307_t *) priv;
|
pc87307_t *dev = (pc87307_t *) priv;
|
||||||
uint8_t pins = 0xff, bank = ((port & 0xfffc) == dev->gpio_base2);
|
uint8_t pins = 0xff, bank = ((port & 0xfffc) == dev->gpio_base2);
|
||||||
uint8_t mask, ret = dev->gpio[bank][port & 0x0003];
|
uint8_t mask, ret = dev->gpio[bank][port & 0x0003];
|
||||||
|
|
||||||
switch (port & 0x0003) {
|
switch (port & 0x0003) {
|
||||||
case 0x0000:
|
case 0x0000:
|
||||||
mask = dev->gpio[bank][0x0001];
|
mask = dev->gpio[bank][0x0001];
|
||||||
ret = (ret & mask) | (pins & ~mask);
|
ret = (ret & mask) | (pins & ~mask);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87307_gpio_remove(pc87307_t *dev)
|
pc87307_gpio_remove(pc87307_t *dev)
|
||||||
{
|
{
|
||||||
if (dev->gpio_base != 0xffff) {
|
if (dev->gpio_base != 0xffff) {
|
||||||
io_removehandler(dev->gpio_base, 0x0002,
|
io_removehandler(dev->gpio_base, 0x0002,
|
||||||
pc87307_gpio_read, NULL, NULL, pc87307_gpio_write, NULL, NULL, dev);
|
pc87307_gpio_read, NULL, NULL, pc87307_gpio_write, NULL, NULL, dev);
|
||||||
dev->gpio_base = 0xffff;
|
dev->gpio_base = 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->gpio_base2 != 0xffff) {
|
if (dev->gpio_base2 != 0xffff) {
|
||||||
io_removehandler(dev->gpio_base2, 0x0002,
|
io_removehandler(dev->gpio_base2, 0x0002,
|
||||||
pc87307_gpio_read, NULL, NULL, pc87307_gpio_write, NULL, NULL, dev);
|
pc87307_gpio_read, NULL, NULL, pc87307_gpio_write, NULL, NULL, dev);
|
||||||
dev->gpio_base2 = 0xffff;
|
dev->gpio_base2 = 0xffff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87307_gpio_init(pc87307_t *dev, int bank, uint16_t addr)
|
pc87307_gpio_init(pc87307_t *dev, int bank, uint16_t addr)
|
||||||
{
|
{
|
||||||
@@ -106,352 +100,347 @@ pc87307_gpio_init(pc87307_t *dev, int bank, uint16_t addr)
|
|||||||
*bank_base = addr;
|
*bank_base = addr;
|
||||||
|
|
||||||
io_sethandler(*bank_base, 0x0002,
|
io_sethandler(*bank_base, 0x0002,
|
||||||
pc87307_gpio_read, NULL, NULL, pc87307_gpio_write, NULL, NULL, dev);
|
pc87307_gpio_read, NULL, NULL, pc87307_gpio_write, NULL, NULL, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87307_pm_write(uint16_t port, uint8_t val, void *priv)
|
pc87307_pm_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
pc87307_t *dev = (pc87307_t *) priv;
|
pc87307_t *dev = (pc87307_t *) priv;
|
||||||
|
|
||||||
if (port & 1)
|
if (port & 1)
|
||||||
dev->pm[dev->pm_idx] = val;
|
dev->pm[dev->pm_idx] = val;
|
||||||
else {
|
else {
|
||||||
dev->pm_idx = val & 0x07;
|
dev->pm_idx = val & 0x07;
|
||||||
switch (dev->pm_idx) {
|
switch (dev->pm_idx) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
fdc_handler(dev);
|
fdc_handler(dev);
|
||||||
lpt1_handler(dev);
|
lpt1_handler(dev);
|
||||||
serial_handler(dev, 1);
|
serial_handler(dev, 1);
|
||||||
serial_handler(dev, 0);
|
serial_handler(dev, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
pc87307_pm_read(uint16_t port, void *priv)
|
pc87307_pm_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
pc87307_t *dev = (pc87307_t *) priv;
|
pc87307_t *dev = (pc87307_t *) priv;
|
||||||
|
|
||||||
if (port & 1)
|
if (port & 1)
|
||||||
return dev->pm[dev->pm_idx];
|
return dev->pm[dev->pm_idx];
|
||||||
else
|
else
|
||||||
return dev->pm_idx;
|
return dev->pm_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87307_pm_remove(pc87307_t *dev)
|
pc87307_pm_remove(pc87307_t *dev)
|
||||||
{
|
{
|
||||||
if (dev->pm_base != 0xffff) {
|
if (dev->pm_base != 0xffff) {
|
||||||
io_removehandler(dev->pm_base, 0x0008,
|
io_removehandler(dev->pm_base, 0x0008,
|
||||||
pc87307_pm_read, NULL, NULL, pc87307_pm_write, NULL, NULL, dev);
|
pc87307_pm_read, NULL, NULL, pc87307_pm_write, NULL, NULL, dev);
|
||||||
dev->pm_base = 0xffff;
|
dev->pm_base = 0xffff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87307_pm_init(pc87307_t *dev, uint16_t addr)
|
pc87307_pm_init(pc87307_t *dev, uint16_t addr)
|
||||||
{
|
{
|
||||||
dev->pm_base = addr;
|
dev->pm_base = addr;
|
||||||
|
|
||||||
io_sethandler(dev->pm_base, 0x0008,
|
io_sethandler(dev->pm_base, 0x0008,
|
||||||
pc87307_pm_read, NULL, NULL, pc87307_pm_write, NULL, NULL, dev);
|
pc87307_pm_read, NULL, NULL, pc87307_pm_write, NULL, NULL, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc_handler(pc87307_t *dev)
|
fdc_handler(pc87307_t *dev)
|
||||||
{
|
{
|
||||||
uint8_t irq, active;
|
uint8_t irq, active;
|
||||||
uint16_t addr;
|
uint16_t addr;
|
||||||
|
|
||||||
fdc_remove(dev->fdc);
|
fdc_remove(dev->fdc);
|
||||||
|
|
||||||
active = (dev->ld_regs[0x03][0x00] & 0x01) && (dev->pm[0x00] & 0x08);
|
active = (dev->ld_regs[0x03][0x00] & 0x01) && (dev->pm[0x00] & 0x08);
|
||||||
addr = ((dev->ld_regs[0x03][0x30] << 8) | dev->ld_regs[0x03][0x31]) - 0x0002;
|
addr = ((dev->ld_regs[0x03][0x30] << 8) | dev->ld_regs[0x03][0x31]) - 0x0002;
|
||||||
irq = (dev->ld_regs[0x03][0x40] & 0x0f);
|
irq = (dev->ld_regs[0x03][0x40] & 0x0f);
|
||||||
|
|
||||||
if (active && (addr <= 0xfff8)) {
|
if (active && (addr <= 0xfff8)) {
|
||||||
fdc_set_base(dev->fdc, addr);
|
fdc_set_base(dev->fdc, addr);
|
||||||
fdc_set_irq(dev->fdc, irq);
|
fdc_set_irq(dev->fdc, irq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lpt1_handler(pc87307_t *dev)
|
lpt1_handler(pc87307_t *dev)
|
||||||
{
|
{
|
||||||
uint8_t irq, active;
|
uint8_t irq, active;
|
||||||
uint16_t addr;
|
uint16_t addr;
|
||||||
|
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
|
|
||||||
active = (dev->ld_regs[0x04][0x00] & 0x01) && (dev->pm[0x00] & 0x10);
|
active = (dev->ld_regs[0x04][0x00] & 0x01) && (dev->pm[0x00] & 0x10);
|
||||||
addr = (dev->ld_regs[0x04][0x30] << 8) | dev->ld_regs[0x04][0x31];
|
addr = (dev->ld_regs[0x04][0x30] << 8) | dev->ld_regs[0x04][0x31];
|
||||||
irq = (dev->ld_regs[0x04][0x40] & 0x0f);
|
irq = (dev->ld_regs[0x04][0x40] & 0x0f);
|
||||||
|
|
||||||
if (active && (addr <= 0xfffc)) {
|
if (active && (addr <= 0xfffc)) {
|
||||||
lpt1_init(addr);
|
lpt1_init(addr);
|
||||||
lpt1_irq(irq);
|
lpt1_irq(irq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
serial_handler(pc87307_t *dev, int uart)
|
serial_handler(pc87307_t *dev, int uart)
|
||||||
{
|
{
|
||||||
uint8_t irq, active;
|
uint8_t irq, active;
|
||||||
uint16_t addr;
|
uint16_t addr;
|
||||||
|
|
||||||
serial_remove(dev->uart[uart]);
|
serial_remove(dev->uart[uart]);
|
||||||
|
|
||||||
active = (dev->ld_regs[0x06 - uart][0x00] & 0x01) && (dev->pm[0x00] & (1 << (6 - uart)));
|
active = (dev->ld_regs[0x06 - uart][0x00] & 0x01) && (dev->pm[0x00] & (1 << (6 - uart)));
|
||||||
addr = (dev->ld_regs[0x06 - uart][0x30] << 8) | dev->ld_regs[0x06 - uart][0x31];
|
addr = (dev->ld_regs[0x06 - uart][0x30] << 8) | dev->ld_regs[0x06 - uart][0x31];
|
||||||
irq = (dev->ld_regs[0x06 - uart][0x40] & 0x0f);
|
irq = (dev->ld_regs[0x06 - uart][0x40] & 0x0f);
|
||||||
|
|
||||||
if (active && (addr <= 0xfff8))
|
if (active && (addr <= 0xfff8))
|
||||||
serial_setup(dev->uart[uart], addr, irq);
|
serial_setup(dev->uart[uart], addr, irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gpio_handler(pc87307_t *dev)
|
gpio_handler(pc87307_t *dev)
|
||||||
{
|
{
|
||||||
uint8_t active;
|
uint8_t active;
|
||||||
uint16_t addr;
|
uint16_t addr;
|
||||||
|
|
||||||
pc87307_gpio_remove(dev);
|
pc87307_gpio_remove(dev);
|
||||||
|
|
||||||
active = (dev->ld_regs[0x07][0x00] & 0x01);
|
active = (dev->ld_regs[0x07][0x00] & 0x01);
|
||||||
addr = (dev->ld_regs[0x07][0x30] << 8) | dev->ld_regs[0x07][0x31];
|
addr = (dev->ld_regs[0x07][0x30] << 8) | dev->ld_regs[0x07][0x31];
|
||||||
|
|
||||||
if (active)
|
if (active)
|
||||||
pc87307_gpio_init(dev, 0, addr);
|
pc87307_gpio_init(dev, 0, addr);
|
||||||
|
|
||||||
addr = (dev->ld_regs[0x07][0x32] << 8) | dev->ld_regs[0x07][0x33];
|
addr = (dev->ld_regs[0x07][0x32] << 8) | dev->ld_regs[0x07][0x33];
|
||||||
|
|
||||||
if (active)
|
if (active)
|
||||||
pc87307_gpio_init(dev, 1, addr);
|
pc87307_gpio_init(dev, 1, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pm_handler(pc87307_t *dev)
|
pm_handler(pc87307_t *dev)
|
||||||
{
|
{
|
||||||
uint8_t active;
|
uint8_t active;
|
||||||
uint16_t addr;
|
uint16_t addr;
|
||||||
|
|
||||||
pc87307_pm_remove(dev);
|
pc87307_pm_remove(dev);
|
||||||
|
|
||||||
active = (dev->ld_regs[0x08][0x00] & 0x01);
|
active = (dev->ld_regs[0x08][0x00] & 0x01);
|
||||||
addr = (dev->ld_regs[0x08][0x30] << 8) | dev->ld_regs[0x08][0x31];
|
addr = (dev->ld_regs[0x08][0x30] << 8) | dev->ld_regs[0x08][0x31];
|
||||||
|
|
||||||
if (active)
|
if (active)
|
||||||
pc87307_pm_init(dev, addr);
|
pc87307_pm_init(dev, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87307_write(uint16_t port, uint8_t val, void *priv)
|
pc87307_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
pc87307_t *dev = (pc87307_t *) priv;
|
pc87307_t *dev = (pc87307_t *) priv;
|
||||||
uint8_t index;
|
uint8_t index;
|
||||||
|
|
||||||
index = (port & 1) ? 0 : 1;
|
index = (port & 1) ? 0 : 1;
|
||||||
|
|
||||||
if (index) {
|
if (index) {
|
||||||
dev->cur_reg = val;
|
dev->cur_reg = val;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
switch (dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0x00: case 0x02: case 0x03: case 0x06:
|
case 0x00:
|
||||||
case 0x07: case 0x21:
|
case 0x02:
|
||||||
dev->regs[dev->cur_reg] = val;
|
case 0x03:
|
||||||
break;
|
case 0x06:
|
||||||
case 0x22:
|
case 0x07:
|
||||||
dev->regs[dev->cur_reg] = val & 0x7f;
|
case 0x21:
|
||||||
break;
|
dev->regs[dev->cur_reg] = val;
|
||||||
case 0x23:
|
break;
|
||||||
dev->regs[dev->cur_reg] = val & 0x0f;
|
case 0x22:
|
||||||
break;
|
dev->regs[dev->cur_reg] = val & 0x7f;
|
||||||
case 0x24:
|
break;
|
||||||
dev->pcregs[dev->regs[0x23]] = val;
|
case 0x23:
|
||||||
break;
|
dev->regs[dev->cur_reg] = val & 0x0f;
|
||||||
default:
|
break;
|
||||||
if (dev->cur_reg >= 0x30) {
|
case 0x24:
|
||||||
if ((dev->regs[0x07] != 0x06) || !(dev->regs[0x21] & 0x10))
|
dev->pcregs[dev->regs[0x23]] = val;
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val;
|
break;
|
||||||
}
|
default:
|
||||||
break;
|
if (dev->cur_reg >= 0x30) {
|
||||||
}
|
if ((dev->regs[0x07] != 0x06) || !(dev->regs[0x21] & 0x10))
|
||||||
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0x30:
|
case 0x30:
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x01;
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x01;
|
||||||
switch (dev->regs[0x07]) {
|
switch (dev->regs[0x07]) {
|
||||||
case 0x03:
|
case 0x03:
|
||||||
fdc_handler(dev);
|
fdc_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 0x04:
|
case 0x04:
|
||||||
lpt1_handler(dev);
|
lpt1_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 0x05:
|
case 0x05:
|
||||||
serial_handler(dev, 1);
|
serial_handler(dev, 1);
|
||||||
break;
|
break;
|
||||||
case 0x06:
|
case 0x06:
|
||||||
serial_handler(dev, 0);
|
serial_handler(dev, 0);
|
||||||
break;
|
break;
|
||||||
case 0x07:
|
case 0x07:
|
||||||
gpio_handler(dev);
|
gpio_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 0x08:
|
case 0x08:
|
||||||
pm_handler(dev);
|
pm_handler(dev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x60: case 0x62:
|
case 0x60:
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x07;
|
case 0x62:
|
||||||
if ((dev->cur_reg == 0x62) && (dev->regs[0x07] != 0x07))
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x07;
|
||||||
break;
|
if ((dev->cur_reg == 0x62) && (dev->regs[0x07] != 0x07))
|
||||||
switch (dev->regs[0x07]) {
|
break;
|
||||||
case 0x03:
|
switch (dev->regs[0x07]) {
|
||||||
fdc_handler(dev);
|
case 0x03:
|
||||||
break;
|
fdc_handler(dev);
|
||||||
case 0x04:
|
break;
|
||||||
lpt1_handler(dev);
|
case 0x04:
|
||||||
break;
|
lpt1_handler(dev);
|
||||||
case 0x05:
|
break;
|
||||||
serial_handler(dev, 1);
|
case 0x05:
|
||||||
break;
|
serial_handler(dev, 1);
|
||||||
case 0x06:
|
break;
|
||||||
serial_handler(dev, 0);
|
case 0x06:
|
||||||
break;
|
serial_handler(dev, 0);
|
||||||
case 0x07:
|
break;
|
||||||
gpio_handler(dev);
|
case 0x07:
|
||||||
break;
|
gpio_handler(dev);
|
||||||
case 0x08:
|
break;
|
||||||
pm_handler(dev);
|
case 0x08:
|
||||||
break;
|
pm_handler(dev);
|
||||||
}
|
break;
|
||||||
break;
|
}
|
||||||
case 0x61:
|
break;
|
||||||
switch (dev->regs[0x07]) {
|
case 0x61:
|
||||||
case 0x00:
|
switch (dev->regs[0x07]) {
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfb;
|
case 0x00:
|
||||||
break;
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfb;
|
||||||
case 0x03:
|
break;
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfa) | 0x02;
|
case 0x03:
|
||||||
fdc_handler(dev);
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfa) | 0x02;
|
||||||
break;
|
fdc_handler(dev);
|
||||||
case 0x04:
|
break;
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfc;
|
case 0x04:
|
||||||
lpt1_handler(dev);
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfc;
|
||||||
break;
|
lpt1_handler(dev);
|
||||||
case 0x05:
|
break;
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8;
|
case 0x05:
|
||||||
serial_handler(dev, 1);
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8;
|
||||||
break;
|
serial_handler(dev, 1);
|
||||||
case 0x06:
|
break;
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8;
|
case 0x06:
|
||||||
serial_handler(dev, 0);
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8;
|
||||||
break;
|
serial_handler(dev, 0);
|
||||||
case 0x07:
|
break;
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8;
|
case 0x07:
|
||||||
gpio_handler(dev);
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8;
|
||||||
break;
|
gpio_handler(dev);
|
||||||
case 0x08:
|
break;
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe;
|
case 0x08:
|
||||||
pm_handler(dev);
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe;
|
||||||
break;
|
pm_handler(dev);
|
||||||
}
|
break;
|
||||||
break;
|
}
|
||||||
case 0x63:
|
break;
|
||||||
if (dev->regs[0x07] == 0x00)
|
case 0x63:
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfb) | 0x04;
|
if (dev->regs[0x07] == 0x00)
|
||||||
else if (dev->regs[0x07] == 0x07) {
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfb) | 0x04;
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe;
|
else if (dev->regs[0x07] == 0x07) {
|
||||||
gpio_handler(dev);
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe;
|
||||||
}
|
gpio_handler(dev);
|
||||||
break;
|
}
|
||||||
case 0x70:
|
break;
|
||||||
case 0x74: case 0x75:
|
case 0x70:
|
||||||
switch (dev->regs[0x07]) {
|
case 0x74:
|
||||||
case 0x03:
|
case 0x75:
|
||||||
fdc_handler(dev);
|
switch (dev->regs[0x07]) {
|
||||||
break;
|
case 0x03:
|
||||||
case 0x04:
|
fdc_handler(dev);
|
||||||
lpt1_handler(dev);
|
break;
|
||||||
break;
|
case 0x04:
|
||||||
case 0x05:
|
lpt1_handler(dev);
|
||||||
serial_handler(dev, 1);
|
break;
|
||||||
break;
|
case 0x05:
|
||||||
case 0x06:
|
serial_handler(dev, 1);
|
||||||
serial_handler(dev, 0);
|
break;
|
||||||
break;
|
case 0x06:
|
||||||
case 0x07:
|
serial_handler(dev, 0);
|
||||||
gpio_handler(dev);
|
break;
|
||||||
break;
|
case 0x07:
|
||||||
case 0x08:
|
gpio_handler(dev);
|
||||||
pm_handler(dev);
|
break;
|
||||||
break;
|
case 0x08:
|
||||||
}
|
pm_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 0xf0:
|
}
|
||||||
switch (dev->regs[0x07]) {
|
break;
|
||||||
case 0x00:
|
case 0xf0:
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xc1;
|
switch (dev->regs[0x07]) {
|
||||||
break;
|
case 0x00:
|
||||||
case 0x03:
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xc1;
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xe1;
|
break;
|
||||||
fdc_update_densel_polarity(dev->fdc, (val & 0x20) ? 1 : 0);
|
case 0x03:
|
||||||
fdc_update_enh_mode(dev->fdc, (val & 0x40) ? 1 : 0);
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xe1;
|
||||||
break;
|
fdc_update_densel_polarity(dev->fdc, (val & 0x20) ? 1 : 0);
|
||||||
case 0x04:
|
fdc_update_enh_mode(dev->fdc, (val & 0x40) ? 1 : 0);
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf3;
|
break;
|
||||||
lpt1_handler(dev);
|
case 0x04:
|
||||||
break;
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf3;
|
||||||
case 0x05: case 0x06:
|
lpt1_handler(dev);
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x87;
|
break;
|
||||||
break;
|
case 0x05:
|
||||||
}
|
case 0x06:
|
||||||
break;
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x87;
|
||||||
case 0xf1:
|
break;
|
||||||
if (dev->regs[0x07] == 0x03)
|
}
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x0f;
|
break;
|
||||||
break;
|
case 0xf1:
|
||||||
|
if (dev->regs[0x07] == 0x03)
|
||||||
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x0f;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
pc87307_read(uint16_t port, void *priv)
|
pc87307_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
pc87307_t *dev = (pc87307_t *) priv;
|
pc87307_t *dev = (pc87307_t *) priv;
|
||||||
uint8_t ret = 0xff, index;
|
uint8_t ret = 0xff, index;
|
||||||
|
|
||||||
index = (port & 1) ? 0 : 1;
|
index = (port & 1) ? 0 : 1;
|
||||||
|
|
||||||
if (index)
|
if (index)
|
||||||
ret = dev->cur_reg;
|
ret = dev->cur_reg;
|
||||||
else {
|
else {
|
||||||
if (dev->cur_reg >= 0x30)
|
if (dev->cur_reg >= 0x30)
|
||||||
ret = dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30];
|
ret = dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30];
|
||||||
else if (dev->cur_reg == 0x24)
|
else if (dev->cur_reg == 0x24)
|
||||||
ret = dev->pcregs[dev->regs[0x23]];
|
ret = dev->pcregs[dev->regs[0x23]];
|
||||||
else
|
else
|
||||||
ret = dev->regs[dev->cur_reg];
|
ret = dev->regs[dev->cur_reg];
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
pc87307_reset(pc87307_t *dev)
|
pc87307_reset(pc87307_t *dev)
|
||||||
{
|
{
|
||||||
@@ -459,7 +448,7 @@ pc87307_reset(pc87307_t *dev)
|
|||||||
|
|
||||||
memset(dev->regs, 0x00, 0x30);
|
memset(dev->regs, 0x00, 0x30);
|
||||||
for (i = 0; i < 256; i++)
|
for (i = 0; i < 256; i++)
|
||||||
memset(dev->ld_regs[i], 0x00, 0xd0);
|
memset(dev->ld_regs[i], 0x00, 0xd0);
|
||||||
memset(dev->pcregs, 0x00, 0x10);
|
memset(dev->pcregs, 0x00, 0x10);
|
||||||
memset(dev->gpio, 0xff, 0x08);
|
memset(dev->gpio, 0xff, 0x08);
|
||||||
memset(dev->pm, 0x00, 0x08);
|
memset(dev->pm, 0x00, 0x08);
|
||||||
@@ -544,8 +533,8 @@ pc87307_reset(pc87307_t *dev)
|
|||||||
dev->gpio_base = dev->pm_base = 0xffff;
|
dev->gpio_base = dev->pm_base = 0xffff;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
0 = 360 rpm @ 500 kbps for 3.5"
|
0 = 360 rpm @ 500 kbps for 3.5"
|
||||||
1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5"
|
1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5"
|
||||||
*/
|
*/
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
serial_remove(dev->uart[0]);
|
serial_remove(dev->uart[0]);
|
||||||
@@ -553,7 +542,6 @@ pc87307_reset(pc87307_t *dev)
|
|||||||
fdc_reset(dev->fdc);
|
fdc_reset(dev->fdc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87307_close(void *priv)
|
pc87307_close(void *priv)
|
||||||
{
|
{
|
||||||
@@ -562,7 +550,6 @@ pc87307_close(void *priv)
|
|||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
pc87307_init(const device_t *info)
|
pc87307_init(const device_t *info)
|
||||||
{
|
{
|
||||||
@@ -579,69 +566,69 @@ pc87307_init(const device_t *info)
|
|||||||
pc87307_reset(dev);
|
pc87307_reset(dev);
|
||||||
|
|
||||||
if (info->local & 0x100) {
|
if (info->local & 0x100) {
|
||||||
io_sethandler(0x02e, 0x0002,
|
io_sethandler(0x02e, 0x0002,
|
||||||
pc87307_read, NULL, NULL, pc87307_write, NULL, NULL, dev);
|
pc87307_read, NULL, NULL, pc87307_write, NULL, NULL, dev);
|
||||||
}
|
}
|
||||||
if (info->local & 0x200) {
|
if (info->local & 0x200) {
|
||||||
io_sethandler(0x15c, 0x0002,
|
io_sethandler(0x15c, 0x0002,
|
||||||
pc87307_read, NULL, NULL, pc87307_write, NULL, NULL, dev);
|
pc87307_read, NULL, NULL, pc87307_write, NULL, NULL, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
const device_t pc87307_device = {
|
const device_t pc87307_device = {
|
||||||
.name = "National Semiconductor PC87307 Super I/O",
|
.name = "National Semiconductor PC87307 Super I/O",
|
||||||
.internal_name = "pc87307",
|
.internal_name = "pc87307",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x1c0,
|
.local = 0x1c0,
|
||||||
.init = pc87307_init,
|
.init = pc87307_init,
|
||||||
.close = pc87307_close,
|
.close = pc87307_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t pc87307_15c_device = {
|
const device_t pc87307_15c_device = {
|
||||||
.name = "National Semiconductor PC87307 Super I/O (Port 15Ch)",
|
.name = "National Semiconductor PC87307 Super I/O (Port 15Ch)",
|
||||||
.internal_name = "pc87307_15c",
|
.internal_name = "pc87307_15c",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x2c0,
|
.local = 0x2c0,
|
||||||
.init = pc87307_init,
|
.init = pc87307_init,
|
||||||
.close = pc87307_close,
|
.close = pc87307_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t pc87307_both_device = {
|
const device_t pc87307_both_device = {
|
||||||
.name = "National Semiconductor PC87307 Super I/O (Ports 2Eh and 15Ch)",
|
.name = "National Semiconductor PC87307 Super I/O (Ports 2Eh and 15Ch)",
|
||||||
.internal_name = "pc87307_both",
|
.internal_name = "pc87307_both",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x3c0,
|
.local = 0x3c0,
|
||||||
.init = pc87307_init,
|
.init = pc87307_init,
|
||||||
.close = pc87307_close,
|
.close = pc87307_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t pc97307_device = {
|
const device_t pc97307_device = {
|
||||||
.name = "National Semiconductor PC97307 Super I/O",
|
.name = "National Semiconductor PC97307 Super I/O",
|
||||||
.internal_name = "pc97307",
|
.internal_name = "pc97307",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x1cf,
|
.local = 0x1cf,
|
||||||
.init = pc87307_init,
|
.init = pc87307_init,
|
||||||
.close = pc87307_close,
|
.close = pc87307_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,22 +34,19 @@
|
|||||||
#include <86box/fdc.h>
|
#include <86box/fdc.h>
|
||||||
#include <86box/sio.h>
|
#include <86box/sio.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t id, pm_idx,
|
uint8_t id, pm_idx,
|
||||||
regs[48], ld_regs[256][208],
|
regs[48], ld_regs[256][208],
|
||||||
pm[8];
|
pm[8];
|
||||||
uint16_t pm_base;
|
uint16_t pm_base;
|
||||||
int cur_reg;
|
int cur_reg;
|
||||||
fdc_t *fdc;
|
fdc_t *fdc;
|
||||||
serial_t *uart[2];
|
serial_t *uart[2];
|
||||||
} pc87309_t;
|
} pc87309_t;
|
||||||
|
|
||||||
|
static void fdc_handler(pc87309_t *dev);
|
||||||
static void fdc_handler(pc87309_t *dev);
|
static void lpt1_handler(pc87309_t *dev);
|
||||||
static void lpt1_handler(pc87309_t *dev);
|
static void serial_handler(pc87309_t *dev, int uart);
|
||||||
static void serial_handler(pc87309_t *dev, int uart);
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87309_pm_write(uint16_t port, uint8_t val, void *priv)
|
pc87309_pm_write(uint16_t port, uint8_t val, void *priv)
|
||||||
@@ -57,296 +54,293 @@ pc87309_pm_write(uint16_t port, uint8_t val, void *priv)
|
|||||||
pc87309_t *dev = (pc87309_t *) priv;
|
pc87309_t *dev = (pc87309_t *) priv;
|
||||||
|
|
||||||
if (port & 1) {
|
if (port & 1) {
|
||||||
dev->pm[dev->pm_idx] = val;
|
dev->pm[dev->pm_idx] = val;
|
||||||
|
|
||||||
switch (dev->pm_idx) {
|
switch (dev->pm_idx) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
fdc_handler(dev);
|
fdc_handler(dev);
|
||||||
lpt1_handler(dev);
|
lpt1_handler(dev);
|
||||||
serial_handler(dev, 1);
|
serial_handler(dev, 1);
|
||||||
serial_handler(dev, 0);
|
serial_handler(dev, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
dev->pm_idx = val & 0x07;
|
dev->pm_idx = val & 0x07;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
pc87309_pm_read(uint16_t port, void *priv)
|
pc87309_pm_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
pc87309_t *dev = (pc87309_t *) priv;
|
pc87309_t *dev = (pc87309_t *) priv;
|
||||||
|
|
||||||
if (port & 1)
|
if (port & 1)
|
||||||
return dev->pm[dev->pm_idx];
|
return dev->pm[dev->pm_idx];
|
||||||
else
|
else
|
||||||
return dev->pm_idx;
|
return dev->pm_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87309_pm_remove(pc87309_t *dev)
|
pc87309_pm_remove(pc87309_t *dev)
|
||||||
{
|
{
|
||||||
if (dev->pm_base != 0xffff) {
|
if (dev->pm_base != 0xffff) {
|
||||||
io_removehandler(dev->pm_base, 0x0008,
|
io_removehandler(dev->pm_base, 0x0008,
|
||||||
pc87309_pm_read, NULL, NULL, pc87309_pm_write, NULL, NULL, dev);
|
pc87309_pm_read, NULL, NULL, pc87309_pm_write, NULL, NULL, dev);
|
||||||
dev->pm_base = 0xffff;
|
dev->pm_base = 0xffff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87309_pm_init(pc87309_t *dev, uint16_t addr)
|
pc87309_pm_init(pc87309_t *dev, uint16_t addr)
|
||||||
{
|
{
|
||||||
dev->pm_base = addr;
|
dev->pm_base = addr;
|
||||||
|
|
||||||
io_sethandler(dev->pm_base, 0x0008,
|
io_sethandler(dev->pm_base, 0x0008,
|
||||||
pc87309_pm_read, NULL, NULL, pc87309_pm_write, NULL, NULL, dev);
|
pc87309_pm_read, NULL, NULL, pc87309_pm_write, NULL, NULL, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fdc_handler(pc87309_t *dev)
|
fdc_handler(pc87309_t *dev)
|
||||||
{
|
{
|
||||||
uint8_t irq, active;
|
uint8_t irq, active;
|
||||||
uint16_t addr;
|
uint16_t addr;
|
||||||
|
|
||||||
fdc_remove(dev->fdc);
|
fdc_remove(dev->fdc);
|
||||||
|
|
||||||
active = (dev->ld_regs[0x00][0x00] & 0x01) && (dev->pm[0x00] & 0x08);
|
active = (dev->ld_regs[0x00][0x00] & 0x01) && (dev->pm[0x00] & 0x08);
|
||||||
addr = ((dev->ld_regs[0x00][0x30] << 8) | dev->ld_regs[0x00][0x31]) - 0x0002;
|
addr = ((dev->ld_regs[0x00][0x30] << 8) | dev->ld_regs[0x00][0x31]) - 0x0002;
|
||||||
irq = (dev->ld_regs[0x00][0x40] & 0x0f);
|
irq = (dev->ld_regs[0x00][0x40] & 0x0f);
|
||||||
|
|
||||||
if (active) {
|
if (active) {
|
||||||
fdc_set_base(dev->fdc, addr);
|
fdc_set_base(dev->fdc, addr);
|
||||||
fdc_set_irq(dev->fdc, irq);
|
fdc_set_irq(dev->fdc, irq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lpt1_handler(pc87309_t *dev)
|
lpt1_handler(pc87309_t *dev)
|
||||||
{
|
{
|
||||||
uint8_t irq, active;
|
uint8_t irq, active;
|
||||||
uint16_t addr;
|
uint16_t addr;
|
||||||
|
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
|
|
||||||
active = (dev->ld_regs[0x01][0x00] & 0x01) && (dev->pm[0x00] & 0x10);
|
active = (dev->ld_regs[0x01][0x00] & 0x01) && (dev->pm[0x00] & 0x10);
|
||||||
addr = (dev->ld_regs[0x01][0x30] << 8) | dev->ld_regs[0x01][0x31];
|
addr = (dev->ld_regs[0x01][0x30] << 8) | dev->ld_regs[0x01][0x31];
|
||||||
irq = (dev->ld_regs[0x01][0x40] & 0x0f);
|
irq = (dev->ld_regs[0x01][0x40] & 0x0f);
|
||||||
|
|
||||||
if (active) {
|
if (active) {
|
||||||
lpt1_init(addr);
|
lpt1_init(addr);
|
||||||
lpt1_irq(irq);
|
lpt1_irq(irq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
serial_handler(pc87309_t *dev, int uart)
|
serial_handler(pc87309_t *dev, int uart)
|
||||||
{
|
{
|
||||||
uint8_t irq, active;
|
uint8_t irq, active;
|
||||||
uint16_t addr;
|
uint16_t addr;
|
||||||
|
|
||||||
serial_remove(dev->uart[uart]);
|
serial_remove(dev->uart[uart]);
|
||||||
|
|
||||||
active = (dev->ld_regs[0x03 - uart][0x00] & 0x01) && (dev->pm[0x00] & (1 << (6 - uart)));
|
active = (dev->ld_regs[0x03 - uart][0x00] & 0x01) && (dev->pm[0x00] & (1 << (6 - uart)));
|
||||||
addr = (dev->ld_regs[0x03 - uart][0x30] << 8) | dev->ld_regs[0x03 - uart][0x31];
|
addr = (dev->ld_regs[0x03 - uart][0x30] << 8) | dev->ld_regs[0x03 - uart][0x31];
|
||||||
irq = (dev->ld_regs[0x03 - uart][0x40] & 0x0f);
|
irq = (dev->ld_regs[0x03 - uart][0x40] & 0x0f);
|
||||||
|
|
||||||
if (active)
|
if (active)
|
||||||
serial_setup(dev->uart[uart], addr, irq);
|
serial_setup(dev->uart[uart], addr, irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pm_handler(pc87309_t *dev)
|
pm_handler(pc87309_t *dev)
|
||||||
{
|
{
|
||||||
uint8_t active;
|
uint8_t active;
|
||||||
uint16_t addr;
|
uint16_t addr;
|
||||||
|
|
||||||
pc87309_pm_remove(dev);
|
pc87309_pm_remove(dev);
|
||||||
|
|
||||||
active = (dev->ld_regs[0x04][0x00] & 0x01);
|
active = (dev->ld_regs[0x04][0x00] & 0x01);
|
||||||
addr = (dev->ld_regs[0x04][0x30] << 8) | dev->ld_regs[0x04][0x31];
|
addr = (dev->ld_regs[0x04][0x30] << 8) | dev->ld_regs[0x04][0x31];
|
||||||
|
|
||||||
if (active)
|
if (active)
|
||||||
pc87309_pm_init(dev, addr);
|
pc87309_pm_init(dev, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87309_write(uint16_t port, uint8_t val, void *priv)
|
pc87309_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
pc87309_t *dev = (pc87309_t *) priv;
|
pc87309_t *dev = (pc87309_t *) priv;
|
||||||
uint8_t index;
|
uint8_t index;
|
||||||
|
|
||||||
index = (port & 1) ? 0 : 1;
|
index = (port & 1) ? 0 : 1;
|
||||||
|
|
||||||
if (index) {
|
if (index) {
|
||||||
dev->cur_reg = val;
|
dev->cur_reg = val;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
switch (dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0x00: case 0x02: case 0x03: case 0x06:
|
case 0x00:
|
||||||
case 0x07: case 0x21:
|
case 0x02:
|
||||||
dev->regs[dev->cur_reg] = val;
|
case 0x03:
|
||||||
break;
|
case 0x06:
|
||||||
case 0x22:
|
case 0x07:
|
||||||
dev->regs[dev->cur_reg] = val & 0x7f;
|
case 0x21:
|
||||||
break;
|
dev->regs[dev->cur_reg] = val;
|
||||||
default:
|
break;
|
||||||
if (dev->cur_reg >= 0x30) {
|
case 0x22:
|
||||||
if ((dev->regs[0x07] != 0x06) || !(dev->regs[0x21] & 0x10))
|
dev->regs[dev->cur_reg] = val & 0x7f;
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val;
|
break;
|
||||||
}
|
default:
|
||||||
break;
|
if (dev->cur_reg >= 0x30) {
|
||||||
}
|
if ((dev->regs[0x07] != 0x06) || !(dev->regs[0x21] & 0x10))
|
||||||
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0x30:
|
case 0x30:
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x01;
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x01;
|
||||||
switch (dev->regs[0x07]) {
|
switch (dev->regs[0x07]) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
fdc_handler(dev);
|
fdc_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 0x01:
|
case 0x01:
|
||||||
lpt1_handler(dev);
|
lpt1_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 0x02:
|
case 0x02:
|
||||||
serial_handler(dev, 1);
|
serial_handler(dev, 1);
|
||||||
break;
|
break;
|
||||||
case 0x03:
|
case 0x03:
|
||||||
serial_handler(dev, 0);
|
serial_handler(dev, 0);
|
||||||
break;
|
break;
|
||||||
case 0x04:
|
case 0x04:
|
||||||
pm_handler(dev);
|
pm_handler(dev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x60: case 0x62:
|
case 0x60:
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x07;
|
case 0x62:
|
||||||
if (dev->cur_reg == 0x62)
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x07;
|
||||||
break;
|
if (dev->cur_reg == 0x62)
|
||||||
switch (dev->regs[0x07]) {
|
break;
|
||||||
case 0x00:
|
switch (dev->regs[0x07]) {
|
||||||
fdc_handler(dev);
|
case 0x00:
|
||||||
break;
|
fdc_handler(dev);
|
||||||
case 0x01:
|
break;
|
||||||
lpt1_handler(dev);
|
case 0x01:
|
||||||
break;
|
lpt1_handler(dev);
|
||||||
case 0x02:
|
break;
|
||||||
serial_handler(dev, 1);
|
case 0x02:
|
||||||
break;
|
serial_handler(dev, 1);
|
||||||
case 0x03:
|
break;
|
||||||
serial_handler(dev, 0);
|
case 0x03:
|
||||||
break;
|
serial_handler(dev, 0);
|
||||||
case 0x04:
|
break;
|
||||||
pm_handler(dev);
|
case 0x04:
|
||||||
break;
|
pm_handler(dev);
|
||||||
}
|
break;
|
||||||
break;
|
}
|
||||||
case 0x63:
|
break;
|
||||||
if (dev->regs[0x07] == 0x06)
|
case 0x63:
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xf8) | 0x04;
|
if (dev->regs[0x07] == 0x06)
|
||||||
break;
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xf8) | 0x04;
|
||||||
case 0x61:
|
break;
|
||||||
switch (dev->regs[0x07]) {
|
case 0x61:
|
||||||
case 0x00:
|
switch (dev->regs[0x07]) {
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfa) | 0x02;
|
case 0x00:
|
||||||
fdc_handler(dev);
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfa) | 0x02;
|
||||||
break;
|
fdc_handler(dev);
|
||||||
case 0x01:
|
break;
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfc;
|
case 0x01:
|
||||||
lpt1_handler(dev);
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfc;
|
||||||
break;
|
lpt1_handler(dev);
|
||||||
case 0x02:
|
break;
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8;
|
case 0x02:
|
||||||
serial_handler(dev, 1);
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8;
|
||||||
break;
|
serial_handler(dev, 1);
|
||||||
case 0x03:
|
break;
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8;
|
case 0x03:
|
||||||
serial_handler(dev, 0);
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8;
|
||||||
break;
|
serial_handler(dev, 0);
|
||||||
case 0x04:
|
break;
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe;
|
case 0x04:
|
||||||
pm_handler(dev);
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe;
|
||||||
break;
|
pm_handler(dev);
|
||||||
case 0x06:
|
break;
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8;
|
case 0x06:
|
||||||
break;
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8;
|
||||||
}
|
break;
|
||||||
break;
|
}
|
||||||
case 0x70:
|
break;
|
||||||
case 0x74: case 0x75:
|
case 0x70:
|
||||||
switch (dev->regs[0x07]) {
|
case 0x74:
|
||||||
case 0x00:
|
case 0x75:
|
||||||
fdc_handler(dev);
|
switch (dev->regs[0x07]) {
|
||||||
break;
|
case 0x00:
|
||||||
case 0x01:
|
fdc_handler(dev);
|
||||||
lpt1_handler(dev);
|
break;
|
||||||
break;
|
case 0x01:
|
||||||
case 0x02:
|
lpt1_handler(dev);
|
||||||
serial_handler(dev, 1);
|
break;
|
||||||
break;
|
case 0x02:
|
||||||
case 0x03:
|
serial_handler(dev, 1);
|
||||||
serial_handler(dev, 0);
|
break;
|
||||||
break;
|
case 0x03:
|
||||||
case 0x04:
|
serial_handler(dev, 0);
|
||||||
pm_handler(dev);
|
break;
|
||||||
break;
|
case 0x04:
|
||||||
}
|
pm_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 0xf0:
|
}
|
||||||
switch (dev->regs[0x07]) {
|
break;
|
||||||
case 0x00:
|
case 0xf0:
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xe1;
|
switch (dev->regs[0x07]) {
|
||||||
fdc_update_densel_polarity(dev->fdc, (val & 0x20) ? 1 : 0);
|
case 0x00:
|
||||||
fdc_update_enh_mode(dev->fdc, (val & 0x40) ? 1 : 0);
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xe1;
|
||||||
break;
|
fdc_update_densel_polarity(dev->fdc, (val & 0x20) ? 1 : 0);
|
||||||
case 0x01:
|
fdc_update_enh_mode(dev->fdc, (val & 0x40) ? 1 : 0);
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf3;
|
break;
|
||||||
lpt1_handler(dev);
|
case 0x01:
|
||||||
break;
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf3;
|
||||||
case 0x02: case 0x03:
|
lpt1_handler(dev);
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x87;
|
break;
|
||||||
break;
|
case 0x02:
|
||||||
case 0x06:
|
case 0x03:
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xc1;
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x87;
|
||||||
break;
|
break;
|
||||||
}
|
case 0x06:
|
||||||
break;
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xc1;
|
||||||
case 0xf1:
|
break;
|
||||||
if (dev->regs[0x07] == 0x00)
|
}
|
||||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x0f;
|
break;
|
||||||
break;
|
case 0xf1:
|
||||||
|
if (dev->regs[0x07] == 0x00)
|
||||||
|
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x0f;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
pc87309_read(uint16_t port, void *priv)
|
pc87309_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
pc87309_t *dev = (pc87309_t *) priv;
|
pc87309_t *dev = (pc87309_t *) priv;
|
||||||
uint8_t ret = 0xff, index;
|
uint8_t ret = 0xff, index;
|
||||||
|
|
||||||
index = (port & 1) ? 0 : 1;
|
index = (port & 1) ? 0 : 1;
|
||||||
|
|
||||||
if (index)
|
if (index)
|
||||||
ret = dev->cur_reg & 0x1f;
|
ret = dev->cur_reg & 0x1f;
|
||||||
else {
|
else {
|
||||||
if (dev->cur_reg >= 0x30)
|
if (dev->cur_reg >= 0x30)
|
||||||
ret = dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30];
|
ret = dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30];
|
||||||
else
|
else
|
||||||
ret = dev->regs[dev->cur_reg];
|
ret = dev->regs[dev->cur_reg];
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
pc87309_reset(pc87309_t *dev)
|
pc87309_reset(pc87309_t *dev)
|
||||||
{
|
{
|
||||||
@@ -354,7 +348,7 @@ pc87309_reset(pc87309_t *dev)
|
|||||||
|
|
||||||
memset(dev->regs, 0x00, 0x30);
|
memset(dev->regs, 0x00, 0x30);
|
||||||
for (i = 0; i < 256; i++)
|
for (i = 0; i < 256; i++)
|
||||||
memset(dev->ld_regs[i], 0x00, 0xd0);
|
memset(dev->ld_regs[i], 0x00, 0xd0);
|
||||||
memset(dev->pm, 0x00, 0x08);
|
memset(dev->pm, 0x00, 0x08);
|
||||||
|
|
||||||
dev->regs[0x20] = dev->id;
|
dev->regs[0x20] = dev->id;
|
||||||
@@ -426,8 +420,8 @@ pc87309_reset(pc87309_t *dev)
|
|||||||
dev->pm_base = 0xffff;
|
dev->pm_base = 0xffff;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
0 = 360 rpm @ 500 kbps for 3.5"
|
0 = 360 rpm @ 500 kbps for 3.5"
|
||||||
1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5"
|
1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5"
|
||||||
*/
|
*/
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
serial_remove(dev->uart[0]);
|
serial_remove(dev->uart[0]);
|
||||||
@@ -435,7 +429,6 @@ pc87309_reset(pc87309_t *dev)
|
|||||||
fdc_reset(dev->fdc);
|
fdc_reset(dev->fdc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87309_close(void *priv)
|
pc87309_close(void *priv)
|
||||||
{
|
{
|
||||||
@@ -444,7 +437,6 @@ pc87309_close(void *priv)
|
|||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
pc87309_init(const device_t *info)
|
pc87309_init(const device_t *info)
|
||||||
{
|
{
|
||||||
@@ -461,40 +453,40 @@ pc87309_init(const device_t *info)
|
|||||||
pc87309_reset(dev);
|
pc87309_reset(dev);
|
||||||
|
|
||||||
if (info->local & 0x100) {
|
if (info->local & 0x100) {
|
||||||
io_sethandler(0x15c, 0x0002,
|
io_sethandler(0x15c, 0x0002,
|
||||||
pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev);
|
pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev);
|
||||||
} else {
|
} else {
|
||||||
io_sethandler(0x02e, 0x0002,
|
io_sethandler(0x02e, 0x0002,
|
||||||
pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev);
|
pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
const device_t pc87309_device = {
|
const device_t pc87309_device = {
|
||||||
.name = "National Semiconductor PC87309 Super I/O",
|
.name = "National Semiconductor PC87309 Super I/O",
|
||||||
.internal_name = "pc87309",
|
.internal_name = "pc87309",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0xe0,
|
.local = 0xe0,
|
||||||
.init = pc87309_init,
|
.init = pc87309_init,
|
||||||
.close = pc87309_close,
|
.close = pc87309_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t pc87309_15c_device = {
|
const device_t pc87309_15c_device = {
|
||||||
.name = "National Semiconductor PC87309 Super I/O (Port 15Ch)",
|
.name = "National Semiconductor PC87309 Super I/O (Port 15Ch)",
|
||||||
.internal_name = "pc87309_15c",
|
.internal_name = "pc87309_15c",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x1e0,
|
.local = 0x1e0,
|
||||||
.init = pc87309_init,
|
.init = pc87309_init,
|
||||||
.close = pc87309_close,
|
.close = pc87309_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -50,31 +50,29 @@ pc87310_log(const char *fmt, ...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (pc87310_do_log)
|
if (pc87310_do_log) {
|
||||||
{
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
pclog_ex(fmt, ap);
|
pclog_ex(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define pc87310_log(fmt, ...)
|
# define pc87310_log(fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t tries, ide_function,
|
uint8_t tries, ide_function,
|
||||||
reg;
|
reg;
|
||||||
fdc_t *fdc;
|
fdc_t *fdc;
|
||||||
serial_t *uart[2];
|
serial_t *uart[2];
|
||||||
} pc87310_t;
|
} pc87310_t;
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lpt1_handler(pc87310_t *dev)
|
lpt1_handler(pc87310_t *dev)
|
||||||
{
|
{
|
||||||
int temp;
|
int temp;
|
||||||
uint16_t lpt_port = LPT1_ADDR;
|
uint16_t lpt_port = LPT1_ADDR;
|
||||||
uint8_t lpt_irq = LPT1_IRQ;
|
uint8_t lpt_irq = LPT1_IRQ;
|
||||||
|
|
||||||
/* bits 0-1:
|
/* bits 0-1:
|
||||||
* 00 378h
|
* 00 378h
|
||||||
@@ -85,28 +83,27 @@ lpt1_handler(pc87310_t *dev)
|
|||||||
temp = dev->reg & 3;
|
temp = dev->reg & 3;
|
||||||
|
|
||||||
switch (temp) {
|
switch (temp) {
|
||||||
case 0:
|
case 0:
|
||||||
lpt_port = LPT1_ADDR;
|
lpt_port = LPT1_ADDR;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
lpt_port = LPT_MDA_ADDR;
|
lpt_port = LPT_MDA_ADDR;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
lpt_port = LPT2_ADDR;
|
lpt_port = LPT2_ADDR;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
lpt_port = 0x000;
|
lpt_port = 0x000;
|
||||||
lpt_irq = 0xff;
|
lpt_irq = 0xff;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lpt_port)
|
if (lpt_port)
|
||||||
lpt1_init(lpt_port);
|
lpt1_init(lpt_port);
|
||||||
|
|
||||||
lpt1_irq(lpt_irq);
|
lpt1_irq(lpt_irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
serial_handler(pc87310_t *dev, int uart)
|
serial_handler(pc87310_t *dev, int uart)
|
||||||
{
|
{
|
||||||
@@ -117,9 +114,9 @@ serial_handler(pc87310_t *dev, int uart)
|
|||||||
*/
|
*/
|
||||||
temp = (dev->reg >> (2 + uart)) & 1;
|
temp = (dev->reg >> (2 + uart)) & 1;
|
||||||
|
|
||||||
//current serial port is enabled
|
// current serial port is enabled
|
||||||
if (!temp){
|
if (!temp) {
|
||||||
//configure serial port as COM2
|
// configure serial port as COM2
|
||||||
if (((dev->reg >> 4) & 1) ^ uart)
|
if (((dev->reg >> 4) & 1) ^ uart)
|
||||||
serial_setup(dev->uart[uart], COM2_ADDR, COM2_IRQ);
|
serial_setup(dev->uart[uart], COM2_ADDR, COM2_IRQ);
|
||||||
// configure serial port as COM1
|
// configure serial port as COM1
|
||||||
@@ -128,23 +125,22 @@ serial_handler(pc87310_t *dev, int uart)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87310_write(uint16_t port, uint8_t val, void *priv)
|
pc87310_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
pc87310_t *dev = (pc87310_t *) priv;
|
pc87310_t *dev = (pc87310_t *) priv;
|
||||||
uint8_t valxor;
|
uint8_t valxor;
|
||||||
|
|
||||||
// second write to config register
|
// second write to config register
|
||||||
if (dev->tries) {
|
if (dev->tries) {
|
||||||
valxor = val ^ dev->reg;
|
valxor = val ^ dev->reg;
|
||||||
dev->tries = 0;
|
dev->tries = 0;
|
||||||
dev->reg = val;
|
dev->reg = val;
|
||||||
// first write to config register
|
// first write to config register
|
||||||
} else {
|
} else {
|
||||||
dev->tries++;
|
dev->tries++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pc87310_log("SIO: written %01X\n", val);
|
pc87310_log("SIO: written %01X\n", val);
|
||||||
|
|
||||||
@@ -191,12 +187,11 @@ pc87310_write(uint16_t port, uint8_t val, void *priv)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
pc87310_read(uint16_t port, void *priv)
|
pc87310_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
pc87310_t *dev = (pc87310_t *) priv;
|
pc87310_t *dev = (pc87310_t *) priv;
|
||||||
uint8_t ret = 0xff;
|
uint8_t ret = 0xff;
|
||||||
|
|
||||||
dev->tries = 0;
|
dev->tries = 0;
|
||||||
|
|
||||||
@@ -207,15 +202,14 @@ pc87310_read(uint16_t port, void *priv)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
pc87310_reset(pc87310_t *dev)
|
pc87310_reset(pc87310_t *dev)
|
||||||
{
|
{
|
||||||
dev->reg = 0x0;
|
dev->reg = 0x0;
|
||||||
dev->tries = 0;
|
dev->tries = 0;
|
||||||
/*
|
/*
|
||||||
0 = 360 rpm @ 500 kbps for 3.5"
|
0 = 360 rpm @ 500 kbps for 3.5"
|
||||||
1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5"
|
1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5"
|
||||||
*/
|
*/
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
lpt1_handler(dev);
|
lpt1_handler(dev);
|
||||||
@@ -224,10 +218,9 @@ pc87310_reset(pc87310_t *dev)
|
|||||||
serial_handler(dev, 0);
|
serial_handler(dev, 0);
|
||||||
serial_handler(dev, 1);
|
serial_handler(dev, 1);
|
||||||
fdc_reset(dev->fdc);
|
fdc_reset(dev->fdc);
|
||||||
//ide_pri_enable();
|
// ide_pri_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87310_close(void *priv)
|
pc87310_close(void *priv)
|
||||||
{
|
{
|
||||||
@@ -236,7 +229,6 @@ pc87310_close(void *priv)
|
|||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
pc87310_init(const device_t *info)
|
pc87310_init(const device_t *info)
|
||||||
{
|
{
|
||||||
@@ -257,36 +249,35 @@ pc87310_init(const device_t *info)
|
|||||||
pc87310_reset(dev);
|
pc87310_reset(dev);
|
||||||
|
|
||||||
io_sethandler(0x3f3, 0x0001,
|
io_sethandler(0x3f3, 0x0001,
|
||||||
pc87310_read, NULL, NULL, pc87310_write, NULL, NULL, dev);
|
pc87310_read, NULL, NULL, pc87310_write, NULL, NULL, dev);
|
||||||
|
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
const device_t pc87310_device = {
|
const device_t pc87310_device = {
|
||||||
.name = "National Semiconductor PC87310 Super I/O",
|
.name = "National Semiconductor PC87310 Super I/O",
|
||||||
.internal_name = "pc87310",
|
.internal_name = "pc87310",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0,
|
.local = 0,
|
||||||
.init = pc87310_init,
|
.init = pc87310_init,
|
||||||
.close = pc87310_close,
|
.close = pc87310_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t pc87310_ide_device = {
|
const device_t pc87310_ide_device = {
|
||||||
.name = "National Semiconductor PC87310 Super I/O with IDE functionality",
|
.name = "National Semiconductor PC87310 Super I/O with IDE functionality",
|
||||||
.internal_name = "pc87310_ide",
|
.internal_name = "pc87310_ide",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 1,
|
.local = 1,
|
||||||
.init = pc87310_init,
|
.init = pc87310_init,
|
||||||
.close = pc87310_close,
|
.close = pc87310_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -33,15 +33,15 @@
|
|||||||
#define HAS_IDE_FUNCTIONALITY dev->ide_function
|
#define HAS_IDE_FUNCTIONALITY dev->ide_function
|
||||||
|
|
||||||
/* Basic Functionalities */
|
/* Basic Functionalities */
|
||||||
#define FUNCTION_ENABLE dev->regs[0x00]
|
#define FUNCTION_ENABLE dev->regs[0x00]
|
||||||
#define FUNCTION_ADDRESS dev->regs[0x01]
|
#define FUNCTION_ADDRESS dev->regs[0x01]
|
||||||
#define POWER_TEST dev->regs[0x02]
|
#define POWER_TEST dev->regs[0x02]
|
||||||
|
|
||||||
/* Base Addresses */
|
/* Base Addresses */
|
||||||
#define LPT_BA (FUNCTION_ADDRESS & 0x03)
|
#define LPT_BA (FUNCTION_ADDRESS & 0x03)
|
||||||
#define UART1_BA ((FUNCTION_ADDRESS >> 2) & 0x03)
|
#define UART1_BA ((FUNCTION_ADDRESS >> 2) & 0x03)
|
||||||
#define UART2_BA ((FUNCTION_ADDRESS >> 4) & 0x03)
|
#define UART2_BA ((FUNCTION_ADDRESS >> 4) & 0x03)
|
||||||
#define COM_BA ((FUNCTION_ADDRESS >> 6) & 0x03)
|
#define COM_BA ((FUNCTION_ADDRESS >> 6) & 0x03)
|
||||||
|
|
||||||
#ifdef ENABLE_PC87311_LOG
|
#ifdef ENABLE_PC87311_LOG
|
||||||
int pc87311_do_log = ENABLE_PC87311_LOG;
|
int pc87311_do_log = ENABLE_PC87311_LOG;
|
||||||
@@ -50,22 +50,21 @@ pc87311_log(const char *fmt, ...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (pc87311_do_log)
|
if (pc87311_do_log) {
|
||||||
{
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
pclog_ex(fmt, ap);
|
pclog_ex(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define pc87311_log(fmt, ...)
|
# define pc87311_log(fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint8_t index, regs[256], cfg_lock, ide_function;
|
uint8_t index, regs[256], cfg_lock, ide_function;
|
||||||
uint16_t base, irq;
|
uint16_t base, irq;
|
||||||
fdc_t *fdc_controller;
|
fdc_t *fdc_controller;
|
||||||
serial_t *uart[2];
|
serial_t *uart[2];
|
||||||
|
|
||||||
} pc87311_t;
|
} pc87311_t;
|
||||||
@@ -79,30 +78,28 @@ void pc87311_enable(pc87311_t *dev);
|
|||||||
static void
|
static void
|
||||||
pc87311_write(uint16_t addr, uint8_t val, void *priv)
|
pc87311_write(uint16_t addr, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
pc87311_t *dev = (pc87311_t *)priv;
|
pc87311_t *dev = (pc87311_t *) priv;
|
||||||
|
|
||||||
switch (addr)
|
switch (addr) {
|
||||||
{
|
case 0x398:
|
||||||
case 0x398:
|
case 0x26e:
|
||||||
case 0x26e:
|
dev->index = val;
|
||||||
dev->index = val;
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x399:
|
case 0x399:
|
||||||
case 0x26f:
|
case 0x26f:
|
||||||
switch (dev->index)
|
switch (dev->index) {
|
||||||
{
|
case 0x00:
|
||||||
case 0x00:
|
FUNCTION_ENABLE = val;
|
||||||
FUNCTION_ENABLE = val;
|
break;
|
||||||
|
case 0x01:
|
||||||
|
FUNCTION_ADDRESS = val;
|
||||||
|
break;
|
||||||
|
case 0x02:
|
||||||
|
POWER_TEST = val;
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0x01:
|
|
||||||
FUNCTION_ADDRESS = val;
|
|
||||||
break;
|
|
||||||
case 0x02:
|
|
||||||
POWER_TEST = val;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pc87311_enable(dev);
|
pc87311_enable(dev);
|
||||||
@@ -111,103 +108,105 @@ pc87311_write(uint16_t addr, uint8_t val, void *priv)
|
|||||||
static uint8_t
|
static uint8_t
|
||||||
pc87311_read(uint16_t addr, void *priv)
|
pc87311_read(uint16_t addr, void *priv)
|
||||||
{
|
{
|
||||||
pc87311_t *dev = (pc87311_t *)priv;
|
pc87311_t *dev = (pc87311_t *) priv;
|
||||||
|
|
||||||
return dev->regs[dev->index];
|
return dev->regs[dev->index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void pc87311_fdc_handler(pc87311_t *dev)
|
void
|
||||||
|
pc87311_fdc_handler(pc87311_t *dev)
|
||||||
{
|
{
|
||||||
fdc_remove(dev->fdc_controller);
|
fdc_remove(dev->fdc_controller);
|
||||||
fdc_set_base(dev->fdc_controller, (FUNCTION_ENABLE & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
|
fdc_set_base(dev->fdc_controller, (FUNCTION_ENABLE & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
|
||||||
pc87311_log("PC87311-FDC: BASE %04x\n", (FUNCTION_ENABLE & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
|
pc87311_log("PC87311-FDC: BASE %04x\n", (FUNCTION_ENABLE & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t com3(pc87311_t *dev)
|
uint16_t
|
||||||
|
com3(pc87311_t *dev)
|
||||||
{
|
{
|
||||||
switch (COM_BA)
|
switch (COM_BA) {
|
||||||
{
|
case 0:
|
||||||
case 0:
|
return COM3_ADDR;
|
||||||
return COM3_ADDR;
|
case 1:
|
||||||
case 1:
|
return 0x0338;
|
||||||
return 0x0338;
|
case 2:
|
||||||
case 2:
|
return COM4_ADDR;
|
||||||
return COM4_ADDR;
|
case 3:
|
||||||
case 3:
|
return 0x0220;
|
||||||
return 0x0220;
|
default:
|
||||||
default:
|
return COM3_ADDR;
|
||||||
return COM3_ADDR;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t com4(pc87311_t *dev)
|
uint16_t
|
||||||
|
com4(pc87311_t *dev)
|
||||||
{
|
{
|
||||||
switch (COM_BA)
|
switch (COM_BA) {
|
||||||
{
|
case 0:
|
||||||
case 0:
|
return COM4_ADDR;
|
||||||
return COM4_ADDR;
|
case 1:
|
||||||
case 1:
|
return 0x0238;
|
||||||
return 0x0238;
|
case 2:
|
||||||
case 2:
|
return 0x02e0;
|
||||||
return 0x02e0;
|
case 3:
|
||||||
case 3:
|
return 0x0228;
|
||||||
return 0x0228;
|
default:
|
||||||
default:
|
return COM4_ADDR;
|
||||||
return COM4_ADDR;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pc87311_uart_handler(uint8_t num, pc87311_t *dev)
|
void
|
||||||
|
pc87311_uart_handler(uint8_t num, pc87311_t *dev)
|
||||||
{
|
{
|
||||||
serial_remove(dev->uart[num & 1]);
|
serial_remove(dev->uart[num & 1]);
|
||||||
|
|
||||||
switch (!(num & 1) ? UART1_BA : UART2_BA)
|
switch (!(num & 1) ? UART1_BA : UART2_BA) {
|
||||||
{
|
case 0:
|
||||||
case 0:
|
dev->base = COM1_ADDR;
|
||||||
dev->base = COM1_ADDR;
|
dev->irq = COM1_IRQ;
|
||||||
dev->irq = COM1_IRQ;
|
break;
|
||||||
break;
|
case 1:
|
||||||
case 1:
|
dev->base = COM2_ADDR;
|
||||||
dev->base = COM2_ADDR;
|
dev->irq = COM2_IRQ;
|
||||||
dev->irq = COM2_IRQ;
|
break;
|
||||||
break;
|
case 2:
|
||||||
case 2:
|
dev->base = com3(dev);
|
||||||
dev->base = com3(dev);
|
dev->irq = COM3_IRQ;
|
||||||
dev->irq = COM3_IRQ;
|
break;
|
||||||
break;
|
case 3:
|
||||||
case 3:
|
dev->base = com4(dev);
|
||||||
dev->base = com4(dev);
|
dev->irq = COM4_IRQ;
|
||||||
dev->irq = COM4_IRQ;
|
break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
serial_setup(dev->uart[num & 1], dev->base, dev->irq);
|
serial_setup(dev->uart[num & 1], dev->base, dev->irq);
|
||||||
pc87311_log("PC87311-UART%01x: BASE %04x IRQ %01x\n", num & 1, dev->base, dev->irq);
|
pc87311_log("PC87311-UART%01x: BASE %04x IRQ %01x\n", num & 1, dev->base, dev->irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pc87311_lpt_handler(pc87311_t *dev)
|
void
|
||||||
|
pc87311_lpt_handler(pc87311_t *dev)
|
||||||
{
|
{
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
switch (LPT_BA)
|
switch (LPT_BA) {
|
||||||
{
|
case 0:
|
||||||
case 0:
|
dev->base = LPT1_ADDR;
|
||||||
dev->base = LPT1_ADDR;
|
dev->irq = (POWER_TEST & 0x08) ? LPT1_IRQ : LPT2_IRQ;
|
||||||
dev->irq = (POWER_TEST & 0x08) ? LPT1_IRQ : LPT2_IRQ;
|
break;
|
||||||
break;
|
case 1:
|
||||||
case 1:
|
dev->base = LPT_MDA_ADDR;
|
||||||
dev->base = LPT_MDA_ADDR;
|
dev->irq = LPT_MDA_IRQ;
|
||||||
dev->irq = LPT_MDA_IRQ;
|
break;
|
||||||
break;
|
case 2:
|
||||||
case 2:
|
dev->base = LPT2_ADDR;
|
||||||
dev->base = LPT2_ADDR;
|
dev->irq = LPT2_IRQ;
|
||||||
dev->irq = LPT2_IRQ;
|
break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
lpt1_init(dev->base);
|
lpt1_init(dev->base);
|
||||||
lpt1_irq(dev->irq);
|
lpt1_irq(dev->irq);
|
||||||
pc87311_log("PC87311-LPT: BASE %04x IRQ %01x\n", dev->base, dev->irq);
|
pc87311_log("PC87311-LPT: BASE %04x IRQ %01x\n", dev->base, dev->irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pc87311_ide_handler(pc87311_t *dev)
|
void
|
||||||
|
pc87311_ide_handler(pc87311_t *dev)
|
||||||
{
|
{
|
||||||
ide_pri_disable();
|
ide_pri_disable();
|
||||||
ide_sec_disable();
|
ide_sec_disable();
|
||||||
@@ -216,8 +215,7 @@ void pc87311_ide_handler(pc87311_t *dev)
|
|||||||
ide_set_side(0, 0x3f6);
|
ide_set_side(0, 0x3f6);
|
||||||
ide_pri_enable();
|
ide_pri_enable();
|
||||||
|
|
||||||
if (FUNCTION_ENABLE & 0x80)
|
if (FUNCTION_ENABLE & 0x80) {
|
||||||
{
|
|
||||||
ide_set_base(1, 0x170);
|
ide_set_base(1, 0x170);
|
||||||
ide_set_side(1, 0x376);
|
ide_set_side(1, 0x376);
|
||||||
ide_sec_enable();
|
ide_sec_enable();
|
||||||
@@ -225,7 +223,8 @@ void pc87311_ide_handler(pc87311_t *dev)
|
|||||||
pc87311_log("PC87311-IDE: PRI %01x SEC %01x\n", (FUNCTION_ENABLE >> 6) & 1, (FUNCTION_ENABLE >> 7) & 1);
|
pc87311_log("PC87311-IDE: PRI %01x SEC %01x\n", (FUNCTION_ENABLE >> 6) & 1, (FUNCTION_ENABLE >> 7) & 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pc87311_enable(pc87311_t *dev)
|
void
|
||||||
|
pc87311_enable(pc87311_t *dev)
|
||||||
{
|
{
|
||||||
(FUNCTION_ENABLE & 0x01) ? pc87311_lpt_handler(dev) : lpt1_remove();
|
(FUNCTION_ENABLE & 0x01) ? pc87311_lpt_handler(dev) : lpt1_remove();
|
||||||
(FUNCTION_ENABLE & 0x02) ? pc87311_uart_handler(0, dev) : serial_remove(dev->uart[0]);
|
(FUNCTION_ENABLE & 0x02) ? pc87311_uart_handler(0, dev) : serial_remove(dev->uart[0]);
|
||||||
@@ -233,8 +232,7 @@ void pc87311_enable(pc87311_t *dev)
|
|||||||
(FUNCTION_ENABLE & 0x08) ? pc87311_fdc_handler(dev) : fdc_remove(dev->fdc_controller);
|
(FUNCTION_ENABLE & 0x08) ? pc87311_fdc_handler(dev) : fdc_remove(dev->fdc_controller);
|
||||||
if (FUNCTION_ENABLE & 0x20)
|
if (FUNCTION_ENABLE & 0x20)
|
||||||
pc87311_fdc_handler(dev);
|
pc87311_fdc_handler(dev);
|
||||||
if (HAS_IDE_FUNCTIONALITY)
|
if (HAS_IDE_FUNCTIONALITY) {
|
||||||
{
|
|
||||||
(FUNCTION_ENABLE & 0x40) ? pc87311_ide_handler(dev) : ide_pri_disable();
|
(FUNCTION_ENABLE & 0x40) ? pc87311_ide_handler(dev) : ide_pri_disable();
|
||||||
(FUNCTION_ADDRESS & 0x80) ? pc87311_ide_handler(dev) : ide_sec_disable();
|
(FUNCTION_ADDRESS & 0x80) ? pc87311_ide_handler(dev) : ide_sec_disable();
|
||||||
}
|
}
|
||||||
@@ -243,7 +241,7 @@ void pc87311_enable(pc87311_t *dev)
|
|||||||
static void
|
static void
|
||||||
pc87311_close(void *priv)
|
pc87311_close(void *priv)
|
||||||
{
|
{
|
||||||
pc87311_t *dev = (pc87311_t *)priv;
|
pc87311_t *dev = (pc87311_t *) priv;
|
||||||
|
|
||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
@@ -251,15 +249,15 @@ pc87311_close(void *priv)
|
|||||||
static void *
|
static void *
|
||||||
pc87311_init(const device_t *info)
|
pc87311_init(const device_t *info)
|
||||||
{
|
{
|
||||||
pc87311_t *dev = (pc87311_t *)malloc(sizeof(pc87311_t));
|
pc87311_t *dev = (pc87311_t *) malloc(sizeof(pc87311_t));
|
||||||
memset(dev, 0, sizeof(pc87311_t));
|
memset(dev, 0, sizeof(pc87311_t));
|
||||||
|
|
||||||
/* Avoid conflicting with machines that make no use of the PC87311 Internal IDE */
|
/* Avoid conflicting with machines that make no use of the PC87311 Internal IDE */
|
||||||
HAS_IDE_FUNCTIONALITY = info->local;
|
HAS_IDE_FUNCTIONALITY = info->local;
|
||||||
|
|
||||||
dev->fdc_controller = device_add(&fdc_at_nsc_device);
|
dev->fdc_controller = device_add(&fdc_at_nsc_device);
|
||||||
dev->uart[0] = device_add_inst(&ns16450_device, 1);
|
dev->uart[0] = device_add_inst(&ns16450_device, 1);
|
||||||
dev->uart[1] = device_add_inst(&ns16450_device, 2);
|
dev->uart[1] = device_add_inst(&ns16450_device, 2);
|
||||||
|
|
||||||
if (HAS_IDE_FUNCTIONALITY)
|
if (HAS_IDE_FUNCTIONALITY)
|
||||||
device_add(&ide_isa_2ch_device);
|
device_add(&ide_isa_2ch_device);
|
||||||
@@ -273,29 +271,29 @@ pc87311_init(const device_t *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const device_t pc87311_device = {
|
const device_t pc87311_device = {
|
||||||
.name = "National Semiconductor PC87311",
|
.name = "National Semiconductor PC87311",
|
||||||
.internal_name = "pc87311",
|
.internal_name = "pc87311",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0,
|
.local = 0,
|
||||||
.init = pc87311_init,
|
.init = pc87311_init,
|
||||||
.close = pc87311_close,
|
.close = pc87311_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t pc87311_ide_device = {
|
const device_t pc87311_ide_device = {
|
||||||
.name = "National Semiconductor PC87311 with IDE functionality",
|
.name = "National Semiconductor PC87311 with IDE functionality",
|
||||||
.internal_name = "pc87311_ide",
|
.internal_name = "pc87311_ide",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 1,
|
.local = 1,
|
||||||
.init = pc87311_init,
|
.init = pc87311_init,
|
||||||
.close = pc87311_close,
|
.close = pc87311_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,51 +34,48 @@
|
|||||||
#include <86box/fdc.h>
|
#include <86box/fdc.h>
|
||||||
#include <86box/sio.h>
|
#include <86box/sio.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t tries, has_ide,
|
uint8_t tries, has_ide,
|
||||||
fdc_on, regs[15];
|
fdc_on, regs[15];
|
||||||
int cur_reg;
|
int cur_reg;
|
||||||
fdc_t *fdc;
|
fdc_t *fdc;
|
||||||
serial_t *uart[2];
|
serial_t *uart[2];
|
||||||
} pc87332_t;
|
} pc87332_t;
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lpt1_handler(pc87332_t *dev)
|
lpt1_handler(pc87332_t *dev)
|
||||||
{
|
{
|
||||||
int temp;
|
int temp;
|
||||||
uint16_t lpt_port = LPT1_ADDR;
|
uint16_t lpt_port = LPT1_ADDR;
|
||||||
uint8_t lpt_irq = LPT2_IRQ;
|
uint8_t lpt_irq = LPT2_IRQ;
|
||||||
|
|
||||||
temp = dev->regs[0x01] & 3;
|
temp = dev->regs[0x01] & 3;
|
||||||
|
|
||||||
switch (temp) {
|
switch (temp) {
|
||||||
case 0:
|
case 0:
|
||||||
lpt_port = LPT1_ADDR;
|
lpt_port = LPT1_ADDR;
|
||||||
lpt_irq = (dev->regs[0x02] & 0x08) ? LPT1_IRQ : LPT2_IRQ;
|
lpt_irq = (dev->regs[0x02] & 0x08) ? LPT1_IRQ : LPT2_IRQ;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
lpt_port = LPT_MDA_ADDR;
|
lpt_port = LPT_MDA_ADDR;
|
||||||
lpt_irq = LPT_MDA_IRQ;
|
lpt_irq = LPT_MDA_IRQ;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
lpt_port = LPT2_ADDR;
|
lpt_port = LPT2_ADDR;
|
||||||
lpt_irq = LPT2_IRQ;
|
lpt_irq = LPT2_IRQ;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
lpt_port = 0x000;
|
lpt_port = 0x000;
|
||||||
lpt_irq = 0xff;
|
lpt_irq = 0xff;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lpt_port)
|
if (lpt_port)
|
||||||
lpt1_init(lpt_port);
|
lpt1_init(lpt_port);
|
||||||
|
|
||||||
lpt1_irq(lpt_irq);
|
lpt1_irq(lpt_irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
serial_handler(pc87332_t *dev, int uart)
|
serial_handler(pc87332_t *dev, int uart)
|
||||||
{
|
{
|
||||||
@@ -87,187 +84,183 @@ serial_handler(pc87332_t *dev, int uart)
|
|||||||
temp = (dev->regs[1] >> (2 << uart)) & 3;
|
temp = (dev->regs[1] >> (2 << uart)) & 3;
|
||||||
|
|
||||||
switch (temp) {
|
switch (temp) {
|
||||||
case 0:
|
case 0:
|
||||||
serial_setup(dev->uart[uart], COM1_ADDR, 4);
|
serial_setup(dev->uart[uart], COM1_ADDR, 4);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
serial_setup(dev->uart[uart], COM2_ADDR, 3);
|
serial_setup(dev->uart[uart], COM2_ADDR, 3);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
switch ((dev->regs[1] >> 6) & 3) {
|
switch ((dev->regs[1] >> 6) & 3) {
|
||||||
case 0:
|
case 0:
|
||||||
serial_setup(dev->uart[uart], COM3_ADDR, COM3_IRQ);
|
serial_setup(dev->uart[uart], COM3_ADDR, COM3_IRQ);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
serial_setup(dev->uart[uart], 0x338, COM3_IRQ);
|
serial_setup(dev->uart[uart], 0x338, COM3_IRQ);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
serial_setup(dev->uart[uart], COM4_ADDR, COM3_IRQ);
|
serial_setup(dev->uart[uart], COM4_ADDR, COM3_IRQ);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
serial_setup(dev->uart[uart], 0x220, COM3_IRQ);
|
serial_setup(dev->uart[uart], 0x220, COM3_IRQ);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
switch ((dev->regs[1] >> 6) & 3) {
|
switch ((dev->regs[1] >> 6) & 3) {
|
||||||
case 0:
|
case 0:
|
||||||
serial_setup(dev->uart[uart], COM4_ADDR, COM4_IRQ);
|
serial_setup(dev->uart[uart], COM4_ADDR, COM4_IRQ);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
serial_setup(dev->uart[uart], 0x238, COM4_IRQ);
|
serial_setup(dev->uart[uart], 0x238, COM4_IRQ);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
serial_setup(dev->uart[uart], 0x2e0, COM4_IRQ);
|
serial_setup(dev->uart[uart], 0x2e0, COM4_IRQ);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
serial_setup(dev->uart[uart], 0x228, COM4_IRQ);
|
serial_setup(dev->uart[uart], 0x228, COM4_IRQ);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ide_handler(pc87332_t *dev)
|
ide_handler(pc87332_t *dev)
|
||||||
{
|
{
|
||||||
/* TODO: Make an ide_disable(channel) and ide_enable(channel) so we can simplify this. */
|
/* TODO: Make an ide_disable(channel) and ide_enable(channel) so we can simplify this. */
|
||||||
if (dev->has_ide == 2) {
|
if (dev->has_ide == 2) {
|
||||||
ide_sec_disable();
|
ide_sec_disable();
|
||||||
ide_set_base(1, (dev->regs[0x00] & 0x80) ? 0x170 : 0x1f0);
|
ide_set_base(1, (dev->regs[0x00] & 0x80) ? 0x170 : 0x1f0);
|
||||||
ide_set_side(1, (dev->regs[0x00] & 0x80) ? 0x376 : 0x3f6);
|
ide_set_side(1, (dev->regs[0x00] & 0x80) ? 0x376 : 0x3f6);
|
||||||
if (dev->regs[0x00] & 0x40)
|
if (dev->regs[0x00] & 0x40)
|
||||||
ide_sec_enable();
|
ide_sec_enable();
|
||||||
} else if (dev->has_ide == 1) {
|
} else if (dev->has_ide == 1) {
|
||||||
ide_pri_disable();
|
ide_pri_disable();
|
||||||
ide_set_base(0, (dev->regs[0x00] & 0x80) ? 0x170 : 0x1f0);
|
ide_set_base(0, (dev->regs[0x00] & 0x80) ? 0x170 : 0x1f0);
|
||||||
ide_set_side(0, (dev->regs[0x00] & 0x80) ? 0x376 : 0x3f6);
|
ide_set_side(0, (dev->regs[0x00] & 0x80) ? 0x376 : 0x3f6);
|
||||||
if (dev->regs[0x00] & 0x40)
|
if (dev->regs[0x00] & 0x40)
|
||||||
ide_pri_enable();
|
ide_pri_enable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87332_write(uint16_t port, uint8_t val, void *priv)
|
pc87332_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
pc87332_t *dev = (pc87332_t *) priv;
|
pc87332_t *dev = (pc87332_t *) priv;
|
||||||
uint8_t index, valxor;
|
uint8_t index, valxor;
|
||||||
|
|
||||||
index = (port & 1) ? 0 : 1;
|
index = (port & 1) ? 0 : 1;
|
||||||
|
|
||||||
if (index) {
|
if (index) {
|
||||||
dev->cur_reg = val & 0x1f;
|
dev->cur_reg = val & 0x1f;
|
||||||
dev->tries = 0;
|
dev->tries = 0;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (dev->tries) {
|
if (dev->tries) {
|
||||||
valxor = val ^ dev->regs[dev->cur_reg];
|
valxor = val ^ dev->regs[dev->cur_reg];
|
||||||
dev->tries = 0;
|
dev->tries = 0;
|
||||||
if ((dev->cur_reg <= 14) && (dev->cur_reg != 8))
|
if ((dev->cur_reg <= 14) && (dev->cur_reg != 8))
|
||||||
dev->regs[dev->cur_reg] = val;
|
dev->regs[dev->cur_reg] = val;
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
dev->tries++;
|
dev->tries++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0:
|
case 0:
|
||||||
if (valxor & 1) {
|
if (valxor & 1) {
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
if ((val & 1) && !(dev->regs[2] & 1))
|
if ((val & 1) && !(dev->regs[2] & 1))
|
||||||
lpt1_handler(dev);
|
lpt1_handler(dev);
|
||||||
}
|
}
|
||||||
if (valxor & 2) {
|
if (valxor & 2) {
|
||||||
serial_remove(dev->uart[0]);
|
serial_remove(dev->uart[0]);
|
||||||
if ((val & 2) && !(dev->regs[2] & 1))
|
if ((val & 2) && !(dev->regs[2] & 1))
|
||||||
serial_handler(dev, 0);
|
serial_handler(dev, 0);
|
||||||
}
|
}
|
||||||
if (valxor & 4) {
|
if (valxor & 4) {
|
||||||
serial_remove(dev->uart[1]);
|
serial_remove(dev->uart[1]);
|
||||||
if ((val & 4) && !(dev->regs[2] & 1))
|
if ((val & 4) && !(dev->regs[2] & 1))
|
||||||
serial_handler(dev, 1);
|
serial_handler(dev, 1);
|
||||||
}
|
}
|
||||||
if (valxor & 0x28) {
|
if (valxor & 0x28) {
|
||||||
fdc_remove(dev->fdc);
|
fdc_remove(dev->fdc);
|
||||||
if ((val & 8) && !(dev->regs[2] & 1))
|
if ((val & 8) && !(dev->regs[2] & 1))
|
||||||
fdc_set_base(dev->fdc, (val & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
|
fdc_set_base(dev->fdc, (val & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
|
||||||
}
|
}
|
||||||
if (dev->has_ide && (valxor & 0xc0))
|
if (dev->has_ide && (valxor & 0xc0))
|
||||||
ide_handler(dev);
|
ide_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (valxor & 3) {
|
if (valxor & 3) {
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
if ((dev->regs[0] & 1) && !(dev->regs[2] & 1))
|
if ((dev->regs[0] & 1) && !(dev->regs[2] & 1))
|
||||||
lpt1_handler(dev);
|
lpt1_handler(dev);
|
||||||
}
|
}
|
||||||
if (valxor & 0xcc) {
|
if (valxor & 0xcc) {
|
||||||
serial_remove(dev->uart[0]);
|
serial_remove(dev->uart[0]);
|
||||||
if ((dev->regs[0] & 2) && !(dev->regs[2] & 1))
|
if ((dev->regs[0] & 2) && !(dev->regs[2] & 1))
|
||||||
serial_handler(dev, 0);
|
serial_handler(dev, 0);
|
||||||
}
|
}
|
||||||
if (valxor & 0xf0) {
|
if (valxor & 0xf0) {
|
||||||
serial_remove(dev->uart[1]);
|
serial_remove(dev->uart[1]);
|
||||||
if ((dev->regs[0] & 4) && !(dev->regs[2] & 1))
|
if ((dev->regs[0] & 4) && !(dev->regs[2] & 1))
|
||||||
serial_handler(dev, 1);
|
serial_handler(dev, 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (valxor & 1) {
|
if (valxor & 1) {
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
serial_remove(dev->uart[0]);
|
serial_remove(dev->uart[0]);
|
||||||
serial_remove(dev->uart[1]);
|
serial_remove(dev->uart[1]);
|
||||||
fdc_remove(dev->fdc);
|
fdc_remove(dev->fdc);
|
||||||
|
|
||||||
if (!(val & 1)) {
|
if (!(val & 1)) {
|
||||||
if (dev->regs[0] & 1)
|
if (dev->regs[0] & 1)
|
||||||
lpt1_handler(dev);
|
lpt1_handler(dev);
|
||||||
if (dev->regs[0] & 2)
|
if (dev->regs[0] & 2)
|
||||||
serial_handler(dev, 0);
|
serial_handler(dev, 0);
|
||||||
if (dev->regs[0] & 4)
|
if (dev->regs[0] & 4)
|
||||||
serial_handler(dev, 1);
|
serial_handler(dev, 1);
|
||||||
if (dev->regs[0] & 8)
|
if (dev->regs[0] & 8)
|
||||||
fdc_set_base(dev->fdc, (dev->regs[0] & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
|
fdc_set_base(dev->fdc, (dev->regs[0] & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (valxor & 8) {
|
if (valxor & 8) {
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
if ((dev->regs[0] & 1) && !(dev->regs[2] & 1))
|
if ((dev->regs[0] & 1) && !(dev->regs[2] & 1))
|
||||||
lpt1_handler(dev);
|
lpt1_handler(dev);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
pc87332_read(uint16_t port, void *priv)
|
pc87332_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
pc87332_t *dev = (pc87332_t *) priv;
|
pc87332_t *dev = (pc87332_t *) priv;
|
||||||
uint8_t ret = 0xff, index;
|
uint8_t ret = 0xff, index;
|
||||||
|
|
||||||
index = (port & 1) ? 0 : 1;
|
index = (port & 1) ? 0 : 1;
|
||||||
|
|
||||||
dev->tries = 0;
|
dev->tries = 0;
|
||||||
|
|
||||||
if (index)
|
if (index)
|
||||||
ret = dev->cur_reg & 0x1f;
|
ret = dev->cur_reg & 0x1f;
|
||||||
else {
|
else {
|
||||||
if (dev->cur_reg == 8)
|
if (dev->cur_reg == 8)
|
||||||
ret = 0x10;
|
ret = 0x10;
|
||||||
else if (dev->cur_reg < 14)
|
else if (dev->cur_reg < 14)
|
||||||
ret = dev->regs[dev->cur_reg];
|
ret = dev->regs[dev->cur_reg];
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
pc87332_reset(pc87332_t *dev)
|
pc87332_reset(pc87332_t *dev)
|
||||||
{
|
{
|
||||||
@@ -275,15 +268,15 @@ pc87332_reset(pc87332_t *dev)
|
|||||||
|
|
||||||
dev->regs[0x00] = dev->fdc_on ? 0x4f : 0x07;
|
dev->regs[0x00] = dev->fdc_on ? 0x4f : 0x07;
|
||||||
if (dev->has_ide == 2)
|
if (dev->has_ide == 2)
|
||||||
dev->regs[0x00] |= 0x80;
|
dev->regs[0x00] |= 0x80;
|
||||||
dev->regs[0x01] = 0x10;
|
dev->regs[0x01] = 0x10;
|
||||||
dev->regs[0x03] = 0x01;
|
dev->regs[0x03] = 0x01;
|
||||||
dev->regs[0x05] = 0x0D;
|
dev->regs[0x05] = 0x0D;
|
||||||
dev->regs[0x08] = 0x70;
|
dev->regs[0x08] = 0x70;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
0 = 360 rpm @ 500 kbps for 3.5"
|
0 = 360 rpm @ 500 kbps for 3.5"
|
||||||
1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5"
|
1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5"
|
||||||
*/
|
*/
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
lpt1_handler(dev);
|
lpt1_handler(dev);
|
||||||
@@ -293,13 +286,12 @@ pc87332_reset(pc87332_t *dev)
|
|||||||
serial_handler(dev, 1);
|
serial_handler(dev, 1);
|
||||||
fdc_reset(dev->fdc);
|
fdc_reset(dev->fdc);
|
||||||
if (!dev->fdc_on)
|
if (!dev->fdc_on)
|
||||||
fdc_remove(dev->fdc);
|
fdc_remove(dev->fdc);
|
||||||
|
|
||||||
if (dev->has_ide)
|
if (dev->has_ide)
|
||||||
ide_handler(dev);
|
ide_handler(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pc87332_close(void *priv)
|
pc87332_close(void *priv)
|
||||||
{
|
{
|
||||||
@@ -308,7 +300,6 @@ pc87332_close(void *priv)
|
|||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
pc87332_init(const device_t *info)
|
pc87332_init(const device_t *info)
|
||||||
{
|
{
|
||||||
@@ -321,86 +312,86 @@ pc87332_init(const device_t *info)
|
|||||||
dev->uart[1] = device_add_inst(&ns16550_device, 2);
|
dev->uart[1] = device_add_inst(&ns16550_device, 2);
|
||||||
|
|
||||||
dev->has_ide = (info->local >> 8) & 0xff;
|
dev->has_ide = (info->local >> 8) & 0xff;
|
||||||
dev->fdc_on = (info->local >> 16) & 0xff;
|
dev->fdc_on = (info->local >> 16) & 0xff;
|
||||||
pc87332_reset(dev);
|
pc87332_reset(dev);
|
||||||
|
|
||||||
if ((info->local & 0xff) == (0x01)) {
|
if ((info->local & 0xff) == (0x01)) {
|
||||||
io_sethandler(0x398, 0x0002,
|
io_sethandler(0x398, 0x0002,
|
||||||
pc87332_read, NULL, NULL, pc87332_write, NULL, NULL, dev);
|
pc87332_read, NULL, NULL, pc87332_write, NULL, NULL, dev);
|
||||||
} else {
|
} else {
|
||||||
io_sethandler(0x02e, 0x0002,
|
io_sethandler(0x02e, 0x0002,
|
||||||
pc87332_read, NULL, NULL, pc87332_write, NULL, NULL, dev);
|
pc87332_read, NULL, NULL, pc87332_write, NULL, NULL, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
const device_t pc87332_device = {
|
const device_t pc87332_device = {
|
||||||
.name = "National Semiconductor PC87332 Super I/O",
|
.name = "National Semiconductor PC87332 Super I/O",
|
||||||
.internal_name = "pc87332",
|
.internal_name = "pc87332",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x00,
|
.local = 0x00,
|
||||||
.init = pc87332_init,
|
.init = pc87332_init,
|
||||||
.close = pc87332_close,
|
.close = pc87332_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t pc87332_398_device = {
|
const device_t pc87332_398_device = {
|
||||||
.name = "National Semiconductor PC87332 Super I/O (Port 398h)",
|
.name = "National Semiconductor PC87332 Super I/O (Port 398h)",
|
||||||
.internal_name = "pc87332_398",
|
.internal_name = "pc87332_398",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x01,
|
.local = 0x01,
|
||||||
.init = pc87332_init,
|
.init = pc87332_init,
|
||||||
.close = pc87332_close,
|
.close = pc87332_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t pc87332_398_ide_device = {
|
const device_t pc87332_398_ide_device = {
|
||||||
.name = "National Semiconductor PC87332 Super I/O (Port 398h) (With IDE)",
|
.name = "National Semiconductor PC87332 Super I/O (Port 398h) (With IDE)",
|
||||||
.internal_name = "pc87332_398_ide",
|
.internal_name = "pc87332_398_ide",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x101,
|
.local = 0x101,
|
||||||
.init = pc87332_init,
|
.init = pc87332_init,
|
||||||
.close = pc87332_close,
|
.close = pc87332_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t pc87332_398_ide_sec_device = {
|
const device_t pc87332_398_ide_sec_device = {
|
||||||
.name = "National Semiconductor PC87332 Super I/O (Port 398h) (With Secondary IDE)",
|
.name = "National Semiconductor PC87332 Super I/O (Port 398h) (With Secondary IDE)",
|
||||||
.internal_name = "pc87332_398_ide_sec",
|
.internal_name = "pc87332_398_ide_sec",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x201,
|
.local = 0x201,
|
||||||
.init = pc87332_init,
|
.init = pc87332_init,
|
||||||
.close = pc87332_close,
|
.close = pc87332_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t pc87332_398_ide_fdcon_device = {
|
const device_t pc87332_398_ide_fdcon_device = {
|
||||||
.name = "National Semiconductor PC87332 Super I/O (Port 398h) (With IDE and FDC on)",
|
.name = "National Semiconductor PC87332 Super I/O (Port 398h) (With IDE and FDC on)",
|
||||||
.internal_name = "pc87332_398_ide_fdcon",
|
.internal_name = "pc87332_398_ide_fdcon",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x10101,
|
.local = 0x10101,
|
||||||
.init = pc87332_init,
|
.init = pc87332_init,
|
||||||
.close = pc87332_close,
|
.close = pc87332_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -30,9 +30,9 @@
|
|||||||
#include <86box/fdc.h>
|
#include <86box/fdc.h>
|
||||||
#include <86box/sio.h>
|
#include <86box/sio.h>
|
||||||
|
|
||||||
#define FSR dev->regs[0xa0]
|
#define FSR dev->regs[0xa0]
|
||||||
#define ASR dev->regs[0xa1]
|
#define ASR dev->regs[0xa1]
|
||||||
#define PDR dev->regs[0xa2]
|
#define PDR dev->regs[0xa2]
|
||||||
#define HAS_IDE_FUNCTIONALITY dev->ide_function
|
#define HAS_IDE_FUNCTIONALITY dev->ide_function
|
||||||
|
|
||||||
#ifdef ENABLE_PRIME3B_LOG
|
#ifdef ENABLE_PRIME3B_LOG
|
||||||
@@ -42,23 +42,22 @@ prime3b_log(const char *fmt, ...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (prime3b_do_log)
|
if (prime3b_do_log) {
|
||||||
{
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
pclog_ex(fmt, ap);
|
pclog_ex(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define prime3b_log(fmt, ...)
|
# define prime3b_log(fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint8_t index, regs[256], cfg_lock, ide_function;
|
uint8_t index, regs[256], cfg_lock, ide_function;
|
||||||
uint16_t com3_addr, com4_addr;
|
uint16_t com3_addr, com4_addr;
|
||||||
|
|
||||||
fdc_t *fdc_controller;
|
fdc_t *fdc_controller;
|
||||||
serial_t *uart[2];
|
serial_t *uart[2];
|
||||||
|
|
||||||
} prime3b_t;
|
} prime3b_t;
|
||||||
@@ -73,10 +72,9 @@ void prime3b_powerdown(prime3b_t *dev);
|
|||||||
static void
|
static void
|
||||||
prime3b_write(uint16_t addr, uint8_t val, void *priv)
|
prime3b_write(uint16_t addr, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
prime3b_t *dev = (prime3b_t *)priv;
|
prime3b_t *dev = (prime3b_t *) priv;
|
||||||
|
|
||||||
if (addr == 0x398)
|
if (addr == 0x398) {
|
||||||
{
|
|
||||||
dev->index = val;
|
dev->index = val;
|
||||||
|
|
||||||
/* Enter/Escape Configuration Mode */
|
/* Enter/Escape Configuration Mode */
|
||||||
@@ -84,50 +82,46 @@ prime3b_write(uint16_t addr, uint8_t val, void *priv)
|
|||||||
dev->cfg_lock = 0;
|
dev->cfg_lock = 0;
|
||||||
else if (val == 0xcc)
|
else if (val == 0xcc)
|
||||||
dev->cfg_lock = 1;
|
dev->cfg_lock = 1;
|
||||||
}
|
} else if ((addr == 0x399) && !dev->cfg_lock) {
|
||||||
else if ((addr == 0x399) && !dev->cfg_lock)
|
switch (dev->index) {
|
||||||
{
|
case 0xa0: /* Function Selection Register (FSR) */
|
||||||
switch (dev->index)
|
FSR = val;
|
||||||
{
|
prime3b_enable(dev);
|
||||||
case 0xa0: /* Function Selection Register (FSR) */
|
|
||||||
FSR = val;
|
|
||||||
prime3b_enable(dev);
|
|
||||||
break;
|
|
||||||
case 0xa1: /* Address Selection Register (ASR) */
|
|
||||||
ASR = val;
|
|
||||||
prime3b_enable(dev);
|
|
||||||
break;
|
|
||||||
case 0xa2: /* Power Down Register (PDR) */
|
|
||||||
dev->regs[0xa2] = val;
|
|
||||||
break;
|
|
||||||
case 0xa3: /* Test Mode Register (TMR) */
|
|
||||||
dev->regs[0xa3] = val;
|
|
||||||
break;
|
|
||||||
case 0xa4: /* Miscellaneous Function Register */
|
|
||||||
dev->regs[0xa4] = val;
|
|
||||||
switch ((dev->regs[0xa4] >> 6) & 3)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
dev->com3_addr = COM3_ADDR;
|
|
||||||
dev->com4_addr = COM4_ADDR;
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 0xa1: /* Address Selection Register (ASR) */
|
||||||
dev->com3_addr = 0x338;
|
ASR = val;
|
||||||
dev->com4_addr = 0x238;
|
prime3b_enable(dev);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 0xa2: /* Power Down Register (PDR) */
|
||||||
dev->com3_addr = COM4_ADDR;
|
dev->regs[0xa2] = val;
|
||||||
dev->com4_addr = 0x2e0;
|
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 0xa3: /* Test Mode Register (TMR) */
|
||||||
dev->com3_addr = 0x220;
|
dev->regs[0xa3] = val;
|
||||||
dev->com4_addr = 0x228;
|
break;
|
||||||
|
case 0xa4: /* Miscellaneous Function Register */
|
||||||
|
dev->regs[0xa4] = val;
|
||||||
|
switch ((dev->regs[0xa4] >> 6) & 3) {
|
||||||
|
case 0:
|
||||||
|
dev->com3_addr = COM3_ADDR;
|
||||||
|
dev->com4_addr = COM4_ADDR;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
dev->com3_addr = 0x338;
|
||||||
|
dev->com4_addr = 0x238;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
dev->com3_addr = COM4_ADDR;
|
||||||
|
dev->com4_addr = 0x2e0;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
dev->com3_addr = 0x220;
|
||||||
|
dev->com4_addr = 0x228;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0xa5: /* ECP Register */
|
||||||
|
dev->regs[0xa5] = val;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0xa5: /* ECP Register */
|
|
||||||
dev->regs[0xa5] = val;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,12 +129,13 @@ prime3b_write(uint16_t addr, uint8_t val, void *priv)
|
|||||||
static uint8_t
|
static uint8_t
|
||||||
prime3b_read(uint16_t addr, void *priv)
|
prime3b_read(uint16_t addr, void *priv)
|
||||||
{
|
{
|
||||||
prime3b_t *dev = (prime3b_t *)priv;
|
prime3b_t *dev = (prime3b_t *) priv;
|
||||||
|
|
||||||
return dev->regs[dev->index];
|
return dev->regs[dev->index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void prime3b_fdc_handler(prime3b_t *dev)
|
void
|
||||||
|
prime3b_fdc_handler(prime3b_t *dev)
|
||||||
{
|
{
|
||||||
uint16_t fdc_base = !(ASR & 0x40) ? FDC_PRIMARY_ADDR : FDC_SECONDARY_ADDR;
|
uint16_t fdc_base = !(ASR & 0x40) ? FDC_PRIMARY_ADDR : FDC_SECONDARY_ADDR;
|
||||||
fdc_remove(dev->fdc_controller);
|
fdc_remove(dev->fdc_controller);
|
||||||
@@ -148,7 +143,8 @@ void prime3b_fdc_handler(prime3b_t *dev)
|
|||||||
prime3b_log("Prime3B-FDC: Enabled with base %03x\n", fdc_base);
|
prime3b_log("Prime3B-FDC: Enabled with base %03x\n", fdc_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
void prime3b_uart_handler(uint8_t num, prime3b_t *dev)
|
void
|
||||||
|
prime3b_uart_handler(uint8_t num, prime3b_t *dev)
|
||||||
{
|
{
|
||||||
uint16_t uart_base;
|
uint16_t uart_base;
|
||||||
if ((ASR >> (3 + 2 * num)) & 1)
|
if ((ASR >> (3 + 2 * num)) & 1)
|
||||||
@@ -161,7 +157,8 @@ void prime3b_uart_handler(uint8_t num, prime3b_t *dev)
|
|||||||
prime3b_log("Prime3B-UART%d: Enabled with base %03x\n", num, uart_base);
|
prime3b_log("Prime3B-UART%d: Enabled with base %03x\n", num, uart_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
void prime3b_lpt_handler(prime3b_t *dev)
|
void
|
||||||
|
prime3b_lpt_handler(prime3b_t *dev)
|
||||||
{
|
{
|
||||||
uint16_t lpt_base = (ASR & 2) ? LPT_MDA_ADDR : (!(ASR & 1) ? LPT1_ADDR : LPT2_ADDR);
|
uint16_t lpt_base = (ASR & 2) ? LPT_MDA_ADDR : (!(ASR & 1) ? LPT1_ADDR : LPT2_ADDR);
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
@@ -170,7 +167,8 @@ void prime3b_lpt_handler(prime3b_t *dev)
|
|||||||
prime3b_log("Prime3B-LPT: Enabled with base %03x\n", lpt_base);
|
prime3b_log("Prime3B-LPT: Enabled with base %03x\n", lpt_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
void prime3b_ide_handler(prime3b_t *dev)
|
void
|
||||||
|
prime3b_ide_handler(prime3b_t *dev)
|
||||||
{
|
{
|
||||||
ide_pri_disable();
|
ide_pri_disable();
|
||||||
uint16_t ide_base = !(ASR & 0x80) ? 0x1f0 : 0x170;
|
uint16_t ide_base = !(ASR & 0x80) ? 0x1f0 : 0x170;
|
||||||
@@ -180,7 +178,8 @@ void prime3b_ide_handler(prime3b_t *dev)
|
|||||||
prime3b_log("Prime3B-IDE: Enabled with base %03x and side %03x\n", ide_base, ide_side);
|
prime3b_log("Prime3B-IDE: Enabled with base %03x and side %03x\n", ide_base, ide_side);
|
||||||
}
|
}
|
||||||
|
|
||||||
void prime3b_enable(prime3b_t *dev)
|
void
|
||||||
|
prime3b_enable(prime3b_t *dev)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Simulate a device enable/disable scenario
|
Simulate a device enable/disable scenario
|
||||||
@@ -205,7 +204,8 @@ void prime3b_enable(prime3b_t *dev)
|
|||||||
(FSR & 0x20) ? prime3b_ide_handler(dev) : ide_pri_disable();
|
(FSR & 0x20) ? prime3b_ide_handler(dev) : ide_pri_disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void prime3b_powerdown(prime3b_t *dev)
|
void
|
||||||
|
prime3b_powerdown(prime3b_t *dev)
|
||||||
{
|
{
|
||||||
/* Note: It can be done more efficiently for sure */
|
/* Note: It can be done more efficiently for sure */
|
||||||
uint8_t old_base = PDR;
|
uint8_t old_base = PDR;
|
||||||
@@ -235,7 +235,7 @@ void prime3b_powerdown(prime3b_t *dev)
|
|||||||
static void
|
static void
|
||||||
prime3b_close(void *priv)
|
prime3b_close(void *priv)
|
||||||
{
|
{
|
||||||
prime3b_t *dev = (prime3b_t *)priv;
|
prime3b_t *dev = (prime3b_t *) priv;
|
||||||
|
|
||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
@@ -243,7 +243,7 @@ prime3b_close(void *priv)
|
|||||||
static void *
|
static void *
|
||||||
prime3b_init(const device_t *info)
|
prime3b_init(const device_t *info)
|
||||||
{
|
{
|
||||||
prime3b_t *dev = (prime3b_t *)malloc(sizeof(prime3b_t));
|
prime3b_t *dev = (prime3b_t *) malloc(sizeof(prime3b_t));
|
||||||
memset(dev, 0, sizeof(prime3b_t));
|
memset(dev, 0, sizeof(prime3b_t));
|
||||||
|
|
||||||
/* Avoid conflicting with machines that make no use of the Prime3B Internal IDE */
|
/* Avoid conflicting with machines that make no use of the Prime3B Internal IDE */
|
||||||
@@ -252,8 +252,8 @@ prime3b_init(const device_t *info)
|
|||||||
dev->regs[0xa0] = 3;
|
dev->regs[0xa0] = 3;
|
||||||
|
|
||||||
dev->fdc_controller = device_add(&fdc_at_device);
|
dev->fdc_controller = device_add(&fdc_at_device);
|
||||||
dev->uart[0] = device_add_inst(&ns16550_device, 1);
|
dev->uart[0] = device_add_inst(&ns16550_device, 1);
|
||||||
dev->uart[1] = device_add_inst(&ns16550_device, 2);
|
dev->uart[1] = device_add_inst(&ns16550_device, 2);
|
||||||
if (HAS_IDE_FUNCTIONALITY)
|
if (HAS_IDE_FUNCTIONALITY)
|
||||||
device_add(&ide_isa_device);
|
device_add(&ide_isa_device);
|
||||||
|
|
||||||
@@ -269,29 +269,29 @@ prime3b_init(const device_t *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const device_t prime3b_device = {
|
const device_t prime3b_device = {
|
||||||
.name = "Goldstar Prime3B",
|
.name = "Goldstar Prime3B",
|
||||||
.internal_name = "prime3b",
|
.internal_name = "prime3b",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0,
|
.local = 0,
|
||||||
.init = prime3b_init,
|
.init = prime3b_init,
|
||||||
.close = prime3b_close,
|
.close = prime3b_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t prime3b_ide_device = {
|
const device_t prime3b_ide_device = {
|
||||||
.name = "Goldstar Prime3B with IDE functionality",
|
.name = "Goldstar Prime3B with IDE functionality",
|
||||||
.internal_name = "prime3b_ide",
|
.internal_name = "prime3b_ide",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 1,
|
.local = 1,
|
||||||
.init = prime3b_init,
|
.init = prime3b_init,
|
||||||
.close = prime3b_close,
|
.close = prime3b_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -37,25 +37,24 @@ prime3c_log(const char *fmt, ...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (prime3c_do_log)
|
if (prime3c_do_log) {
|
||||||
{
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
pclog_ex(fmt, ap);
|
pclog_ex(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define prime3c_log(fmt, ...)
|
# define prime3c_log(fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Function Select(Note on prime3c_enable) */
|
/* Function Select(Note on prime3c_enable) */
|
||||||
#define FUNCTION_SELECT dev->regs[0xc2]
|
#define FUNCTION_SELECT dev->regs[0xc2]
|
||||||
|
|
||||||
/* Base Address Registers */
|
/* Base Address Registers */
|
||||||
#define FDC_BASE_ADDRESS dev->regs[0xc3]
|
#define FDC_BASE_ADDRESS dev->regs[0xc3]
|
||||||
#define IDE_BASE_ADDRESS dev->regs[0xc4]
|
#define IDE_BASE_ADDRESS dev->regs[0xc4]
|
||||||
#define IDE_SIDE_ADDRESS dev->regs[0xc5]
|
#define IDE_SIDE_ADDRESS dev->regs[0xc5]
|
||||||
#define LPT_BASE_ADDRESS dev->regs[0xc6]
|
#define LPT_BASE_ADDRESS dev->regs[0xc6]
|
||||||
#define UART1_BASE_ADDRESS dev->regs[0xc7]
|
#define UART1_BASE_ADDRESS dev->regs[0xc7]
|
||||||
#define UART2_BASE_ADDRESS dev->regs[0xc8]
|
#define UART2_BASE_ADDRESS dev->regs[0xc8]
|
||||||
|
|
||||||
@@ -76,7 +75,7 @@ typedef struct
|
|||||||
{
|
{
|
||||||
uint8_t index, regs[256], cfg_lock, ide_function;
|
uint8_t index, regs[256], cfg_lock, ide_function;
|
||||||
|
|
||||||
fdc_t *fdc_controller;
|
fdc_t *fdc_controller;
|
||||||
serial_t *uart[2];
|
serial_t *uart[2];
|
||||||
|
|
||||||
} prime3c_t;
|
} prime3c_t;
|
||||||
@@ -90,124 +89,121 @@ void prime3c_enable(prime3c_t *dev);
|
|||||||
static void
|
static void
|
||||||
prime3c_write(uint16_t addr, uint8_t val, void *priv)
|
prime3c_write(uint16_t addr, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
prime3c_t *dev = (prime3c_t *)priv;
|
prime3c_t *dev = (prime3c_t *) priv;
|
||||||
|
|
||||||
switch (addr)
|
switch (addr) {
|
||||||
{
|
case 0x398:
|
||||||
case 0x398:
|
dev->index = val;
|
||||||
dev->index = val;
|
|
||||||
|
|
||||||
/* Enter/Escape Configuration Mode */
|
/* Enter/Escape Configuration Mode */
|
||||||
if (val == 0x33)
|
if (val == 0x33)
|
||||||
dev->cfg_lock = 0;
|
dev->cfg_lock = 0;
|
||||||
else if (val == 0x55)
|
else if (val == 0x55)
|
||||||
dev->cfg_lock = 1;
|
dev->cfg_lock = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x399:
|
case 0x399:
|
||||||
if (!dev->cfg_lock)
|
if (!dev->cfg_lock) {
|
||||||
{
|
switch (dev->index) {
|
||||||
switch (dev->index)
|
case 0xc2:
|
||||||
{
|
FUNCTION_SELECT = val & 0xbf;
|
||||||
case 0xc2:
|
prime3c_enable(dev);
|
||||||
FUNCTION_SELECT = val & 0xbf;
|
break;
|
||||||
prime3c_enable(dev);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xc3:
|
case 0xc3:
|
||||||
FDC_BASE_ADDRESS = val & 0xfc;
|
FDC_BASE_ADDRESS = val & 0xfc;
|
||||||
prime3c_fdc_handler(dev);
|
prime3c_fdc_handler(dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xc4:
|
case 0xc4:
|
||||||
IDE_BASE_ADDRESS = val & 0xfc;
|
IDE_BASE_ADDRESS = val & 0xfc;
|
||||||
if (HAS_IDE_FUNCTIONALITY)
|
if (HAS_IDE_FUNCTIONALITY)
|
||||||
prime3c_ide_handler(dev);
|
prime3c_ide_handler(dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xc5:
|
case 0xc5:
|
||||||
IDE_SIDE_ADDRESS = (val & 0xfc) | 0x02;
|
IDE_SIDE_ADDRESS = (val & 0xfc) | 0x02;
|
||||||
if (HAS_IDE_FUNCTIONALITY)
|
if (HAS_IDE_FUNCTIONALITY)
|
||||||
prime3c_ide_handler(dev);
|
prime3c_ide_handler(dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xc6:
|
case 0xc6:
|
||||||
LPT_BASE_ADDRESS = val;
|
LPT_BASE_ADDRESS = val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xc7:
|
case 0xc7:
|
||||||
UART1_BASE_ADDRESS = val & 0xfe;
|
UART1_BASE_ADDRESS = val & 0xfe;
|
||||||
prime3c_uart_handler(0, dev);
|
prime3c_uart_handler(0, dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xc8:
|
case 0xc8:
|
||||||
UART2_BASE_ADDRESS = val & 0xfe;
|
UART2_BASE_ADDRESS = val & 0xfe;
|
||||||
prime3c_uart_handler(1, dev);
|
prime3c_uart_handler(1, dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xc9:
|
case 0xc9:
|
||||||
FDC_LPT_DMA = val;
|
FDC_LPT_DMA = val;
|
||||||
prime3c_fdc_handler(dev);
|
prime3c_fdc_handler(dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xca:
|
case 0xca:
|
||||||
FDC_LPT_IRQ = val;
|
FDC_LPT_IRQ = val;
|
||||||
prime3c_fdc_handler(dev);
|
prime3c_fdc_handler(dev);
|
||||||
prime3c_lpt_handler(dev);
|
prime3c_lpt_handler(dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xcb:
|
case 0xcb:
|
||||||
UART_IRQ = val;
|
UART_IRQ = val;
|
||||||
prime3c_uart_handler(0, dev);
|
prime3c_uart_handler(0, dev);
|
||||||
prime3c_uart_handler(1, dev);
|
prime3c_uart_handler(1, dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xcd:
|
case 0xcd:
|
||||||
case 0xce:
|
case 0xce:
|
||||||
dev->regs[dev->index] = val;
|
dev->regs[dev->index] = val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xcf:
|
case 0xcf:
|
||||||
dev->regs[dev->index] = val & 0x3f;
|
dev->regs[dev->index] = val & 0x3f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xd0:
|
case 0xd0:
|
||||||
dev->regs[dev->index] = val & 0xfc;
|
dev->regs[dev->index] = val & 0xfc;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xd1:
|
case 0xd1:
|
||||||
dev->regs[dev->index] = val & 0x3f;
|
dev->regs[dev->index] = val & 0x3f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xd3:
|
case 0xd3:
|
||||||
dev->regs[dev->index] = val & 0x7c;
|
dev->regs[dev->index] = val & 0x7c;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xd5:
|
case 0xd5:
|
||||||
case 0xd6:
|
case 0xd6:
|
||||||
case 0xd7:
|
case 0xd7:
|
||||||
case 0xd8:
|
case 0xd8:
|
||||||
dev->regs[dev->index] = val;
|
dev->regs[dev->index] = val;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
prime3c_read(uint16_t addr, void *priv)
|
prime3c_read(uint16_t addr, void *priv)
|
||||||
{
|
{
|
||||||
prime3c_t *dev = (prime3c_t *)priv;
|
prime3c_t *dev = (prime3c_t *) priv;
|
||||||
|
|
||||||
return dev->regs[dev->index];
|
return dev->regs[dev->index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void prime3c_fdc_handler(prime3c_t *dev)
|
void
|
||||||
|
prime3c_fdc_handler(prime3c_t *dev)
|
||||||
{
|
{
|
||||||
fdc_remove(dev->fdc_controller);
|
fdc_remove(dev->fdc_controller);
|
||||||
if (FUNCTION_SELECT & 0x10)
|
if (FUNCTION_SELECT & 0x10) {
|
||||||
{
|
|
||||||
fdc_set_base(dev->fdc_controller, FDC_BASE_ADDRESS << 2);
|
fdc_set_base(dev->fdc_controller, FDC_BASE_ADDRESS << 2);
|
||||||
fdc_set_irq(dev->fdc_controller, (FDC_LPT_IRQ >> 4) & 0xf);
|
fdc_set_irq(dev->fdc_controller, (FDC_LPT_IRQ >> 4) & 0xf);
|
||||||
fdc_set_dma_ch(dev->fdc_controller, (FDC_LPT_DMA >> 4) & 0xf);
|
fdc_set_dma_ch(dev->fdc_controller, (FDC_LPT_DMA >> 4) & 0xf);
|
||||||
@@ -216,21 +212,21 @@ void prime3c_fdc_handler(prime3c_t *dev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void prime3c_uart_handler(uint8_t num, prime3c_t *dev)
|
void
|
||||||
|
prime3c_uart_handler(uint8_t num, prime3c_t *dev)
|
||||||
{
|
{
|
||||||
serial_remove(dev->uart[num & 1]);
|
serial_remove(dev->uart[num & 1]);
|
||||||
if (FUNCTION_SELECT & (!(num & 1) ? 0x04 : 0x08))
|
if (FUNCTION_SELECT & (!(num & 1) ? 0x04 : 0x08)) {
|
||||||
{
|
|
||||||
serial_setup(dev->uart[num & 1], (!(num & 1) ? UART1_BASE_ADDRESS : UART2_BASE_ADDRESS) << 2, (UART_IRQ >> (!(num & 1) ? 4 : 0)) & 0xf);
|
serial_setup(dev->uart[num & 1], (!(num & 1) ? UART1_BASE_ADDRESS : UART2_BASE_ADDRESS) << 2, (UART_IRQ >> (!(num & 1) ? 4 : 0)) & 0xf);
|
||||||
prime3c_log("Prime3C-UART%01x: BASE %04x IRQ %01x\n", num & 1, (!(num & 1) ? UART1_BASE_ADDRESS : UART2_BASE_ADDRESS) << 2, (UART_IRQ >> (!(num & 1) ? 4 : 0)) & 0xf);
|
prime3c_log("Prime3C-UART%01x: BASE %04x IRQ %01x\n", num & 1, (!(num & 1) ? UART1_BASE_ADDRESS : UART2_BASE_ADDRESS) << 2, (UART_IRQ >> (!(num & 1) ? 4 : 0)) & 0xf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void prime3c_lpt_handler(prime3c_t *dev)
|
void
|
||||||
|
prime3c_lpt_handler(prime3c_t *dev)
|
||||||
{
|
{
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
if (!(FUNCTION_SELECT & 0x03))
|
if (!(FUNCTION_SELECT & 0x03)) {
|
||||||
{
|
|
||||||
|
|
||||||
lpt1_init(LPT_BASE_ADDRESS << 2);
|
lpt1_init(LPT_BASE_ADDRESS << 2);
|
||||||
lpt1_irq(FDC_LPT_IRQ & 0xf);
|
lpt1_irq(FDC_LPT_IRQ & 0xf);
|
||||||
@@ -238,11 +234,11 @@ void prime3c_lpt_handler(prime3c_t *dev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void prime3c_ide_handler(prime3c_t *dev)
|
void
|
||||||
|
prime3c_ide_handler(prime3c_t *dev)
|
||||||
{
|
{
|
||||||
ide_pri_disable();
|
ide_pri_disable();
|
||||||
if (FUNCTION_SELECT & 0x20)
|
if (FUNCTION_SELECT & 0x20) {
|
||||||
{
|
|
||||||
ide_set_base(0, IDE_BASE_ADDRESS << 2);
|
ide_set_base(0, IDE_BASE_ADDRESS << 2);
|
||||||
ide_set_side(0, IDE_SIDE_ADDRESS << 2);
|
ide_set_side(0, IDE_SIDE_ADDRESS << 2);
|
||||||
ide_pri_enable();
|
ide_pri_enable();
|
||||||
@@ -250,35 +246,36 @@ void prime3c_ide_handler(prime3c_t *dev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void prime3c_enable(prime3c_t *dev)
|
void
|
||||||
|
prime3c_enable(prime3c_t *dev)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Simulate a device enable/disable scenario
|
Simulate a device enable/disable scenario
|
||||||
|
|
||||||
Register C2: Function Select
|
Register C2: Function Select
|
||||||
Bit 7: Gameport
|
Bit 7: Gameport
|
||||||
Bit 6: Reserved
|
Bit 6: Reserved
|
||||||
Bit 5: IDE
|
Bit 5: IDE
|
||||||
Bit 4: FDC
|
Bit 4: FDC
|
||||||
Bit 3: UART 2
|
Bit 3: UART 2
|
||||||
Bit 2: UART 1
|
Bit 2: UART 1
|
||||||
Bit 1/0: PIO (0/0 Unidirectional , 0/1 ECP, 1/0 EPP, 1/1 Disabled)
|
Bit 1/0: PIO (0/0 Unidirectional , 0/1 ECP, 1/0 EPP, 1/1 Disabled)
|
||||||
|
|
||||||
Note: 86Box LPT is simplistic and can't do ECP or EPP.
|
Note: 86Box LPT is simplistic and can't do ECP or EPP.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
!(FUNCTION_SELECT & 0x03) ? prime3c_lpt_handler(dev) : lpt1_remove();
|
!(FUNCTION_SELECT & 0x03) ? prime3c_lpt_handler(dev) : lpt1_remove();
|
||||||
(FUNCTION_SELECT & 0x04) ? prime3c_uart_handler(0, dev) : serial_remove(dev->uart[0]);
|
(FUNCTION_SELECT & 0x04) ? prime3c_uart_handler(0, dev) : serial_remove(dev->uart[0]);
|
||||||
(FUNCTION_SELECT & 0x08) ? prime3c_uart_handler(1, dev) : serial_remove(dev->uart[1]);
|
(FUNCTION_SELECT & 0x08) ? prime3c_uart_handler(1, dev) : serial_remove(dev->uart[1]);
|
||||||
(FUNCTION_SELECT & 0x10) ? prime3c_fdc_handler(dev) : fdc_remove(dev->fdc_controller);
|
(FUNCTION_SELECT & 0x10) ? prime3c_fdc_handler(dev) : fdc_remove(dev->fdc_controller);
|
||||||
if (HAS_IDE_FUNCTIONALITY)
|
if (HAS_IDE_FUNCTIONALITY)
|
||||||
(FUNCTION_SELECT & 0x20) ? prime3c_ide_handler(dev) : ide_pri_disable();
|
(FUNCTION_SELECT & 0x20) ? prime3c_ide_handler(dev) : ide_pri_disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
prime3c_close(void *priv)
|
prime3c_close(void *priv)
|
||||||
{
|
{
|
||||||
prime3c_t *dev = (prime3c_t *)priv;
|
prime3c_t *dev = (prime3c_t *) priv;
|
||||||
|
|
||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
@@ -286,7 +283,7 @@ prime3c_close(void *priv)
|
|||||||
static void *
|
static void *
|
||||||
prime3c_init(const device_t *info)
|
prime3c_init(const device_t *info)
|
||||||
{
|
{
|
||||||
prime3c_t *dev = (prime3c_t *)malloc(sizeof(prime3c_t));
|
prime3c_t *dev = (prime3c_t *) malloc(sizeof(prime3c_t));
|
||||||
memset(dev, 0, sizeof(prime3c_t));
|
memset(dev, 0, sizeof(prime3c_t));
|
||||||
|
|
||||||
/* Avoid conflicting with machines that make no use of the Prime3C Internal IDE */
|
/* Avoid conflicting with machines that make no use of the Prime3C Internal IDE */
|
||||||
@@ -300,8 +297,8 @@ prime3c_init(const device_t *info)
|
|||||||
dev->regs[0xd5] = 0x3c;
|
dev->regs[0xd5] = 0x3c;
|
||||||
|
|
||||||
dev->fdc_controller = device_add(&fdc_at_device);
|
dev->fdc_controller = device_add(&fdc_at_device);
|
||||||
dev->uart[0] = device_add_inst(&ns16550_device, 1);
|
dev->uart[0] = device_add_inst(&ns16550_device, 1);
|
||||||
dev->uart[1] = device_add_inst(&ns16550_device, 2);
|
dev->uart[1] = device_add_inst(&ns16550_device, 2);
|
||||||
if (HAS_IDE_FUNCTIONALITY)
|
if (HAS_IDE_FUNCTIONALITY)
|
||||||
device_add(&ide_isa_device);
|
device_add(&ide_isa_device);
|
||||||
|
|
||||||
@@ -318,29 +315,29 @@ prime3c_init(const device_t *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const device_t prime3c_device = {
|
const device_t prime3c_device = {
|
||||||
.name = "Goldstar Prime3C",
|
.name = "Goldstar Prime3C",
|
||||||
.internal_name = "prime3c",
|
.internal_name = "prime3c",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0,
|
.local = 0,
|
||||||
.init = prime3c_init,
|
.init = prime3c_init,
|
||||||
.close = prime3c_close,
|
.close = prime3c_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t prime3c_ide_device = {
|
const device_t prime3c_ide_device = {
|
||||||
.name = "Goldstar Prime3C with IDE functionality",
|
.name = "Goldstar Prime3C with IDE functionality",
|
||||||
.internal_name = "prime3c_ide",
|
.internal_name = "prime3c_ide",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 1,
|
.local = 1,
|
||||||
.init = prime3c_init,
|
.init = prime3c_init,
|
||||||
.close = prime3c_close,
|
.close = prime3c_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -38,33 +38,32 @@
|
|||||||
#include <86box/sio.h>
|
#include <86box/sio.h>
|
||||||
#include <86box/isapnp.h>
|
#include <86box/isapnp.h>
|
||||||
|
|
||||||
|
|
||||||
/* This ROM was reconstructed out of many assumptions, some of which based on the IT8671F. */
|
/* This ROM was reconstructed out of many assumptions, some of which based on the IT8671F. */
|
||||||
static uint8_t um8669f_pnp_rom[] = {
|
static uint8_t um8669f_pnp_rom[] = {
|
||||||
0x55, 0xa3, 0x86, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, /* UMC8669, dummy checksum (filled in by isapnp_add_card) */
|
0x55, 0xa3, 0x86, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, /* UMC8669, dummy checksum (filled in by isapnp_add_card) */
|
||||||
0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */
|
0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */
|
||||||
|
|
||||||
0x15, 0x41, 0xd0, 0x07, 0x00, 0x01, /* logical device PNP0700, can participate in boot */
|
0x15, 0x41, 0xd0, 0x07, 0x00, 0x01, /* logical device PNP0700, can participate in boot */
|
||||||
0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */
|
0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */
|
||||||
0x2a, 0x0f, 0x0c, /* DMA 0/1/2/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */
|
0x2a, 0x0f, 0x0c, /* DMA 0/1/2/3, compatibility, no count by word, count by byte, is bus master, 8-bit only */
|
||||||
0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */
|
0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */
|
||||||
|
|
||||||
0x15, 0x41, 0xd0, 0x05, 0x01, 0x01, /* logical device PNP0501, can participate in boot */
|
0x15, 0x41, 0xd0, 0x05, 0x01, 0x01, /* logical device PNP0501, can participate in boot */
|
||||||
0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */
|
0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */
|
||||||
0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */
|
0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */
|
||||||
|
|
||||||
0x15, 0x41, 0xd0, 0x05, 0x01, 0x01, /* logical device PNP0501, can participate in boot */
|
0x15, 0x41, 0xd0, 0x05, 0x01, 0x01, /* logical device PNP0501, can participate in boot */
|
||||||
0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */
|
0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */
|
||||||
0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */
|
0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */
|
||||||
|
|
||||||
0x15, 0x41, 0xd0, 0x04, 0x00, 0x01, /* logical device PNP0400, can participate in boot */
|
0x15, 0x41, 0xd0, 0x04, 0x00, 0x01, /* logical device PNP0400, can participate in boot */
|
||||||
0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */
|
0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */
|
||||||
0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */
|
0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */
|
||||||
|
|
||||||
0x15, 0x41, 0xd0, 0xff, 0xff, 0x00, /* logical device PNPFFFF (just a dummy to create a gap in LDNs) */
|
0x15, 0x41, 0xd0, 0xff, 0xff, 0x00, /* logical device PNPFFFF (just a dummy to create a gap in LDNs) */
|
||||||
|
|
||||||
0x15, 0x41, 0xd0, 0xb0, 0x2f, 0x01, /* logical device PNPB02F, can participate in boot */
|
0x15, 0x41, 0xd0, 0xb0, 0x2f, 0x01, /* logical device PNPB02F, can participate in boot */
|
||||||
0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */
|
0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */
|
||||||
|
|
||||||
0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */
|
0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */
|
||||||
};
|
};
|
||||||
@@ -94,106 +93,100 @@ static const isapnp_device_config_t um8669f_pnp_defaults[] = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_UM8669F_LOG
|
#ifdef ENABLE_UM8669F_LOG
|
||||||
int um8669f_do_log = ENABLE_UM8669F_LOG;
|
int um8669f_do_log = ENABLE_UM8669F_LOG;
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
um8669f_log(const char *fmt, ...)
|
um8669f_log(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (um8669f_do_log) {
|
if (um8669f_do_log) {
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
pclog_ex(fmt, ap);
|
pclog_ex(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define um8669f_log(fmt, ...)
|
# define um8669f_log(fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef struct um8669f_t {
|
||||||
typedef struct um8669f_t
|
int locked, cur_reg_108;
|
||||||
{
|
void *pnp_card;
|
||||||
int locked, cur_reg_108;
|
|
||||||
void *pnp_card;
|
|
||||||
isapnp_device_config_t *pnp_config[5];
|
isapnp_device_config_t *pnp_config[5];
|
||||||
|
|
||||||
uint8_t regs_108[256];
|
uint8_t regs_108[256];
|
||||||
|
|
||||||
fdc_t *fdc;
|
fdc_t *fdc;
|
||||||
serial_t *uart[2];
|
serial_t *uart[2];
|
||||||
void *gameport;
|
void *gameport;
|
||||||
} um8669f_t;
|
} um8669f_t;
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
um8669f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv)
|
um8669f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv)
|
||||||
{
|
{
|
||||||
if (ld > 5) {
|
if (ld > 5) {
|
||||||
um8669f_log("UM8669F: Unknown logical device %d\n", ld);
|
um8669f_log("UM8669F: Unknown logical device %d\n", ld);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
um8669f_t *dev = (um8669f_t *) priv;
|
um8669f_t *dev = (um8669f_t *) priv;
|
||||||
|
|
||||||
switch (ld) {
|
switch (ld) {
|
||||||
case 0:
|
case 0:
|
||||||
fdc_remove(dev->fdc);
|
fdc_remove(dev->fdc);
|
||||||
|
|
||||||
if (config->activate) {
|
if (config->activate) {
|
||||||
um8669f_log("UM8669F: FDC enabled at port %04X IRQ %d DMA %d\n", config->io[0].base, config->irq[0].irq, (config->dma[0].dma == ISAPNP_DMA_DISABLED) ? -1 : config->dma[0].dma);
|
um8669f_log("UM8669F: FDC enabled at port %04X IRQ %d DMA %d\n", config->io[0].base, config->irq[0].irq, (config->dma[0].dma == ISAPNP_DMA_DISABLED) ? -1 : config->dma[0].dma);
|
||||||
|
|
||||||
if (config->io[0].base != ISAPNP_IO_DISABLED)
|
if (config->io[0].base != ISAPNP_IO_DISABLED)
|
||||||
fdc_set_base(dev->fdc, config->io[0].base);
|
fdc_set_base(dev->fdc, config->io[0].base);
|
||||||
|
|
||||||
fdc_set_irq(dev->fdc, config->irq[0].irq);
|
fdc_set_irq(dev->fdc, config->irq[0].irq);
|
||||||
fdc_set_dma_ch(dev->fdc, (config->dma[0].dma == ISAPNP_DMA_DISABLED) ? -1 : config->dma[0].dma);
|
fdc_set_dma_ch(dev->fdc, (config->dma[0].dma == ISAPNP_DMA_DISABLED) ? -1 : config->dma[0].dma);
|
||||||
} else {
|
} else {
|
||||||
um8669f_log("UM8669F: FDC disabled\n");
|
um8669f_log("UM8669F: FDC disabled\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
serial_remove(dev->uart[ld - 1]);
|
serial_remove(dev->uart[ld - 1]);
|
||||||
|
|
||||||
if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) {
|
if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) {
|
||||||
um8669f_log("UM8669F: UART %d enabled at port %04X IRQ %d\n", ld - 1, config->io[0].base, config->irq[0].irq);
|
um8669f_log("UM8669F: UART %d enabled at port %04X IRQ %d\n", ld - 1, config->io[0].base, config->irq[0].irq);
|
||||||
serial_setup(dev->uart[ld - 1], config->io[0].base, config->irq[0].irq);
|
serial_setup(dev->uart[ld - 1], config->io[0].base, config->irq[0].irq);
|
||||||
} else {
|
} else {
|
||||||
um8669f_log("UM8669F: UART %d disabled\n", ld - 1);
|
um8669f_log("UM8669F: UART %d disabled\n", ld - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
|
|
||||||
if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) {
|
if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) {
|
||||||
um8669f_log("UM8669F: LPT enabled at port %04X IRQ %d\n", config->io[0].base, config->irq[0].irq);
|
um8669f_log("UM8669F: LPT enabled at port %04X IRQ %d\n", config->io[0].base, config->irq[0].irq);
|
||||||
lpt1_init(config->io[0].base);
|
lpt1_init(config->io[0].base);
|
||||||
} else {
|
} else {
|
||||||
um8669f_log("UM8669F: LPT disabled\n");
|
um8669f_log("UM8669F: LPT disabled\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) {
|
if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) {
|
||||||
um8669f_log("UM8669F: Game port enabled at port %04X\n", config->io[0].base);
|
um8669f_log("UM8669F: Game port enabled at port %04X\n", config->io[0].base);
|
||||||
gameport_remap(dev->gameport, config->io[0].base);
|
gameport_remap(dev->gameport, config->io[0].base);
|
||||||
} else {
|
} else {
|
||||||
um8669f_log("UM8669F: Game port disabled\n");
|
um8669f_log("UM8669F: Game port disabled\n");
|
||||||
gameport_remap(dev->gameport, 0);
|
gameport_remap(dev->gameport, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
um8669f_write(uint16_t port, uint8_t val, void *priv)
|
um8669f_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
@@ -202,37 +195,36 @@ um8669f_write(uint16_t port, uint8_t val, void *priv)
|
|||||||
um8669f_log("UM8669F: write(%04X, %02X)\n", port, val);
|
um8669f_log("UM8669F: write(%04X, %02X)\n", port, val);
|
||||||
|
|
||||||
if (dev->locked) {
|
if (dev->locked) {
|
||||||
if ((port == 0x108) && (val == 0xaa))
|
if ((port == 0x108) && (val == 0xaa))
|
||||||
dev->locked = 0;
|
dev->locked = 0;
|
||||||
} else {
|
} else {
|
||||||
if (port == 0x108) {
|
if (port == 0x108) {
|
||||||
if (val == 0x55)
|
if (val == 0x55)
|
||||||
dev->locked = 1;
|
dev->locked = 1;
|
||||||
else
|
else
|
||||||
dev->cur_reg_108 = val;
|
dev->cur_reg_108 = val;
|
||||||
} else {
|
} else {
|
||||||
dev->regs_108[dev->cur_reg_108] = val;
|
dev->regs_108[dev->cur_reg_108] = val;
|
||||||
|
|
||||||
if (dev->cur_reg_108 == 0xc1) {
|
if (dev->cur_reg_108 == 0xc1) {
|
||||||
um8669f_log("UM8669F: ISAPnP %sabled\n", (val & 0x80) ? "en" : "dis");
|
um8669f_log("UM8669F: ISAPnP %sabled\n", (val & 0x80) ? "en" : "dis");
|
||||||
isapnp_enable_card(dev->pnp_card, (val & 0x80) ? ISAPNP_CARD_FORCE_CONFIG : ISAPNP_CARD_DISABLE);
|
isapnp_enable_card(dev->pnp_card, (val & 0x80) ? ISAPNP_CARD_FORCE_CONFIG : ISAPNP_CARD_DISABLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
um8669f_read(uint16_t port, void *priv)
|
um8669f_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
um8669f_t *dev = (um8669f_t *) priv;
|
um8669f_t *dev = (um8669f_t *) priv;
|
||||||
uint8_t ret = 0xff;
|
uint8_t ret = 0xff;
|
||||||
|
|
||||||
if (!dev->locked) {
|
if (!dev->locked) {
|
||||||
if (port == 0x108)
|
if (port == 0x108)
|
||||||
ret = dev->cur_reg_108; /* ??? */
|
ret = dev->cur_reg_108; /* ??? */
|
||||||
else
|
else
|
||||||
ret = dev->regs_108[dev->cur_reg_108];
|
ret = dev->regs_108[dev->cur_reg_108];
|
||||||
}
|
}
|
||||||
|
|
||||||
um8669f_log("UM8669F: read(%04X) = %02X\n", port, ret);
|
um8669f_log("UM8669F: read(%04X) = %02X\n", port, ret);
|
||||||
@@ -240,7 +232,6 @@ um8669f_read(uint16_t port, void *priv)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
um8669f_reset(um8669f_t *dev)
|
um8669f_reset(um8669f_t *dev)
|
||||||
{
|
{
|
||||||
@@ -261,7 +252,6 @@ um8669f_reset(um8669f_t *dev)
|
|||||||
isapnp_reset_card(dev->pnp_card);
|
isapnp_reset_card(dev->pnp_card);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
um8669f_close(void *priv)
|
um8669f_close(void *priv)
|
||||||
{
|
{
|
||||||
@@ -272,7 +262,6 @@ um8669f_close(void *priv)
|
|||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
um8669f_init(const device_t *info)
|
um8669f_init(const device_t *info)
|
||||||
{
|
{
|
||||||
@@ -283,7 +272,7 @@ um8669f_init(const device_t *info)
|
|||||||
|
|
||||||
dev->pnp_card = isapnp_add_card(um8669f_pnp_rom, sizeof(um8669f_pnp_rom), um8669f_pnp_config_changed, NULL, NULL, NULL, dev);
|
dev->pnp_card = isapnp_add_card(um8669f_pnp_rom, sizeof(um8669f_pnp_rom), um8669f_pnp_config_changed, NULL, NULL, NULL, dev);
|
||||||
for (uint8_t i = 0; i < (sizeof(um8669f_pnp_defaults) / sizeof(isapnp_device_config_t)); i++)
|
for (uint8_t i = 0; i < (sizeof(um8669f_pnp_defaults) / sizeof(isapnp_device_config_t)); i++)
|
||||||
isapnp_set_device_defaults(dev->pnp_card, i, &um8669f_pnp_defaults[i]);
|
isapnp_set_device_defaults(dev->pnp_card, i, &um8669f_pnp_defaults[i]);
|
||||||
|
|
||||||
dev->fdc = device_add(&fdc_at_smc_device);
|
dev->fdc = device_add(&fdc_at_smc_device);
|
||||||
|
|
||||||
@@ -293,24 +282,23 @@ um8669f_init(const device_t *info)
|
|||||||
dev->gameport = gameport_add(&gameport_sio_device);
|
dev->gameport = gameport_add(&gameport_sio_device);
|
||||||
|
|
||||||
io_sethandler(0x0108, 0x0002,
|
io_sethandler(0x0108, 0x0002,
|
||||||
um8669f_read, NULL, NULL, um8669f_write, NULL, NULL, dev);
|
um8669f_read, NULL, NULL, um8669f_write, NULL, NULL, dev);
|
||||||
|
|
||||||
um8669f_reset(dev);
|
um8669f_reset(dev);
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const device_t um8669f_device = {
|
const device_t um8669f_device = {
|
||||||
.name = "UMC UM8669F Super I/O",
|
.name = "UMC UM8669F Super I/O",
|
||||||
.internal_name = "um8669f",
|
.internal_name = "um8669f",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0,
|
.local = 0,
|
||||||
.init = um8669f_init,
|
.init = um8669f_init,
|
||||||
.close = um8669f_close,
|
.close = um8669f_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -32,27 +32,24 @@
|
|||||||
#include <86box/fdc.h>
|
#include <86box/fdc.h>
|
||||||
#include <86box/sio.h>
|
#include <86box/sio.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t cur_reg, last_val, regs[25],
|
uint8_t cur_reg, last_val, regs[25],
|
||||||
fdc_dma, fdc_irq, uart_irq[2], lpt_dma, lpt_irq;
|
fdc_dma, fdc_irq, uart_irq[2], lpt_dma, lpt_irq;
|
||||||
fdc_t *fdc;
|
fdc_t *fdc;
|
||||||
serial_t *uart[2];
|
serial_t *uart[2];
|
||||||
} vt82c686_t;
|
} vt82c686_t;
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
get_lpt_length(vt82c686_t *dev)
|
get_lpt_length(vt82c686_t *dev)
|
||||||
{
|
{
|
||||||
uint8_t length = 4; /* non-EPP */
|
uint8_t length = 4; /* non-EPP */
|
||||||
|
|
||||||
if ((dev->regs[0x02] & 0x03) == 0x02)
|
if ((dev->regs[0x02] & 0x03) == 0x02)
|
||||||
length = 8; /* EPP */
|
length = 8; /* EPP */
|
||||||
|
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vt82c686_fdc_handler(vt82c686_t *dev)
|
vt82c686_fdc_handler(vt82c686_t *dev)
|
||||||
{
|
{
|
||||||
@@ -61,47 +58,44 @@ vt82c686_fdc_handler(vt82c686_t *dev)
|
|||||||
fdc_remove(dev->fdc);
|
fdc_remove(dev->fdc);
|
||||||
|
|
||||||
if (dev->regs[0x02] & 0x10)
|
if (dev->regs[0x02] & 0x10)
|
||||||
fdc_set_base(dev->fdc, io_base);
|
fdc_set_base(dev->fdc, io_base);
|
||||||
|
|
||||||
fdc_set_dma_ch(dev->fdc, dev->fdc_dma);
|
fdc_set_dma_ch(dev->fdc, dev->fdc_dma);
|
||||||
fdc_set_irq(dev->fdc, dev->fdc_irq);
|
fdc_set_irq(dev->fdc, dev->fdc_irq);
|
||||||
fdc_set_swap(dev->fdc, dev->regs[0x16] & 0x01);
|
fdc_set_swap(dev->fdc, dev->regs[0x16] & 0x01);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vt82c686_lpt_handler(vt82c686_t *dev)
|
vt82c686_lpt_handler(vt82c686_t *dev)
|
||||||
{
|
{
|
||||||
uint16_t io_mask, io_base = dev->regs[0x06] << 2;
|
uint16_t io_mask, io_base = dev->regs[0x06] << 2;
|
||||||
int io_len = get_lpt_length(dev);
|
int io_len = get_lpt_length(dev);
|
||||||
io_base &= (0xff8 | io_len);
|
io_base &= (0xff8 | io_len);
|
||||||
io_mask = 0x3fc; /* non-EPP */
|
io_mask = 0x3fc; /* non-EPP */
|
||||||
if (io_len == 8)
|
if (io_len == 8)
|
||||||
io_mask = 0x3f8; /* EPP */
|
io_mask = 0x3f8; /* EPP */
|
||||||
|
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
|
|
||||||
if (((dev->regs[0x02] & 0x03) != 0x03) && (io_base >= 0x100) && (io_base <= io_mask))
|
if (((dev->regs[0x02] & 0x03) != 0x03) && (io_base >= 0x100) && (io_base <= io_mask))
|
||||||
lpt1_init(io_base);
|
lpt1_init(io_base);
|
||||||
|
|
||||||
if (dev->lpt_irq) {
|
if (dev->lpt_irq) {
|
||||||
lpt1_irq(dev->lpt_irq);
|
lpt1_irq(dev->lpt_irq);
|
||||||
} else {
|
} else {
|
||||||
lpt1_irq(0xff);
|
lpt1_irq(0xff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vt82c686_serial_handler(vt82c686_t *dev, int uart)
|
vt82c686_serial_handler(vt82c686_t *dev, int uart)
|
||||||
{
|
{
|
||||||
serial_remove(dev->uart[uart]);
|
serial_remove(dev->uart[uart]);
|
||||||
|
|
||||||
if (dev->regs[0x02] & (0x04 << uart))
|
if (dev->regs[0x02] & (0x04 << uart))
|
||||||
serial_setup(dev->uart[uart], dev->regs[0x07 + uart] << 2, dev->uart_irq[uart]);
|
serial_setup(dev->uart[uart], dev->regs[0x07 + uart] << 2, dev->uart_irq[uart]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vt82c686_write(uint16_t port, uint8_t val, void *priv)
|
vt82c686_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
@@ -112,86 +106,87 @@ vt82c686_write(uint16_t port, uint8_t val, void *priv)
|
|||||||
|
|
||||||
/* Write current register index on port 0. */
|
/* Write current register index on port 0. */
|
||||||
if (!(port & 1)) {
|
if (!(port & 1)) {
|
||||||
dev->cur_reg = val;
|
dev->cur_reg = val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE: Registers are [0xE0:0xF8] but we store them as [0x00:0x18]. */
|
/* NOTE: Registers are [0xE0:0xF8] but we store them as [0x00:0x18]. */
|
||||||
if ((dev->cur_reg < 0xe0) || (dev->cur_reg > 0xf8))
|
if ((dev->cur_reg < 0xe0) || (dev->cur_reg > 0xf8))
|
||||||
return;
|
return;
|
||||||
uint8_t reg = dev->cur_reg & 0x1f;
|
uint8_t reg = dev->cur_reg & 0x1f;
|
||||||
|
|
||||||
/* Read-only registers. */
|
/* Read-only registers. */
|
||||||
if ((reg < 0x02) || (reg == 0x0c))
|
if ((reg < 0x02) || (reg == 0x0c))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Write current register value on port 1. */
|
/* Write current register value on port 1. */
|
||||||
dev->regs[reg] = val;
|
dev->regs[reg] = val;
|
||||||
|
|
||||||
/* Update device state. */
|
/* Update device state. */
|
||||||
switch (reg) {
|
switch (reg) {
|
||||||
case 0x02:
|
case 0x02:
|
||||||
dev->regs[reg] &= 0xbf;
|
dev->regs[reg] &= 0xbf;
|
||||||
vt82c686_lpt_handler(dev);
|
vt82c686_lpt_handler(dev);
|
||||||
vt82c686_serial_handler(dev, 0);
|
vt82c686_serial_handler(dev, 0);
|
||||||
vt82c686_serial_handler(dev, 1);
|
vt82c686_serial_handler(dev, 1);
|
||||||
vt82c686_fdc_handler(dev);
|
vt82c686_fdc_handler(dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03:
|
case 0x03:
|
||||||
dev->regs[reg] &= 0xfc;
|
dev->regs[reg] &= 0xfc;
|
||||||
vt82c686_fdc_handler(dev);
|
vt82c686_fdc_handler(dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x04:
|
case 0x04:
|
||||||
dev->regs[reg] &= 0xfc;
|
dev->regs[reg] &= 0xfc;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x05:
|
case 0x05:
|
||||||
dev->regs[reg] |= 0x03;
|
dev->regs[reg] |= 0x03;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x06:
|
case 0x06:
|
||||||
vt82c686_lpt_handler(dev);
|
vt82c686_lpt_handler(dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x07: case 0x08:
|
case 0x07:
|
||||||
dev->regs[reg] &= 0xfe;
|
case 0x08:
|
||||||
vt82c686_serial_handler(dev, reg == 0x08);
|
dev->regs[reg] &= 0xfe;
|
||||||
break;
|
vt82c686_serial_handler(dev, reg == 0x08);
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x0d:
|
case 0x0d:
|
||||||
dev->regs[reg] &= 0x0f;
|
dev->regs[reg] &= 0x0f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0f:
|
case 0x0f:
|
||||||
dev->regs[reg] &= 0x7f;
|
dev->regs[reg] &= 0x7f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x10:
|
case 0x10:
|
||||||
dev->regs[reg] &= 0xf4;
|
dev->regs[reg] &= 0xf4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x11:
|
case 0x11:
|
||||||
dev->regs[reg] &= 0x3f;
|
dev->regs[reg] &= 0x3f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x13:
|
case 0x13:
|
||||||
dev->regs[reg] &= 0xfb;
|
dev->regs[reg] &= 0xfb;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x14: case 0x17:
|
case 0x14:
|
||||||
dev->regs[reg] &= 0xfe;
|
case 0x17:
|
||||||
break;
|
dev->regs[reg] &= 0xfe;
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x16:
|
case 0x16:
|
||||||
dev->regs[reg] &= 0xf7;
|
dev->regs[reg] &= 0xf7;
|
||||||
vt82c686_fdc_handler(dev);
|
vt82c686_fdc_handler(dev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
vt82c686_read(uint16_t port, void *priv)
|
vt82c686_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
@@ -201,14 +196,13 @@ vt82c686_read(uint16_t port, void *priv)
|
|||||||
Real 686B echoes the last read/written value when reading from
|
Real 686B echoes the last read/written value when reading from
|
||||||
registers outside that range. */
|
registers outside that range. */
|
||||||
if (!(port & 1))
|
if (!(port & 1))
|
||||||
dev->last_val = dev->cur_reg;
|
dev->last_val = dev->cur_reg;
|
||||||
else if ((dev->cur_reg >= 0xe0) && (dev->cur_reg <= 0xf8))
|
else if ((dev->cur_reg >= 0xe0) && (dev->cur_reg <= 0xf8))
|
||||||
dev->last_val = dev->regs[dev->cur_reg & 0x1f];
|
dev->last_val = dev->regs[dev->cur_reg & 0x1f];
|
||||||
|
|
||||||
return dev->last_val;
|
return dev->last_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Writes to Super I/O-related configuration space registers
|
/* Writes to Super I/O-related configuration space registers
|
||||||
of the VT82C686 PCI-ISA bridge are sent here by via_pipc.c */
|
of the VT82C686 PCI-ISA bridge are sent here by via_pipc.c */
|
||||||
void
|
void
|
||||||
@@ -217,36 +211,35 @@ vt82c686_sio_write(uint8_t addr, uint8_t val, void *priv)
|
|||||||
vt82c686_t *dev = (vt82c686_t *) priv;
|
vt82c686_t *dev = (vt82c686_t *) priv;
|
||||||
|
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case 0x50:
|
case 0x50:
|
||||||
dev->fdc_dma = val & 0x03;
|
dev->fdc_dma = val & 0x03;
|
||||||
vt82c686_fdc_handler(dev);
|
vt82c686_fdc_handler(dev);
|
||||||
dev->lpt_dma = (val >> 2) & 0x03;
|
dev->lpt_dma = (val >> 2) & 0x03;
|
||||||
vt82c686_lpt_handler(dev);
|
vt82c686_lpt_handler(dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x51:
|
case 0x51:
|
||||||
dev->fdc_irq = val & 0x0f;
|
dev->fdc_irq = val & 0x0f;
|
||||||
vt82c686_fdc_handler(dev);
|
vt82c686_fdc_handler(dev);
|
||||||
dev->lpt_irq = val >> 4;
|
dev->lpt_irq = val >> 4;
|
||||||
vt82c686_lpt_handler(dev);
|
vt82c686_lpt_handler(dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x52:
|
case 0x52:
|
||||||
dev->uart_irq[0] = val & 0x0f;
|
dev->uart_irq[0] = val & 0x0f;
|
||||||
vt82c686_serial_handler(dev, 0);
|
vt82c686_serial_handler(dev, 0);
|
||||||
dev->uart_irq[1] = val >> 4;
|
dev->uart_irq[1] = val >> 4;
|
||||||
vt82c686_serial_handler(dev, 1);
|
vt82c686_serial_handler(dev, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x85:
|
case 0x85:
|
||||||
io_removehandler(FDC_PRIMARY_ADDR, 2, vt82c686_read, NULL, NULL, vt82c686_write, NULL, NULL, dev);
|
io_removehandler(FDC_PRIMARY_ADDR, 2, vt82c686_read, NULL, NULL, vt82c686_write, NULL, NULL, dev);
|
||||||
if (val & 0x02)
|
if (val & 0x02)
|
||||||
io_sethandler(FDC_PRIMARY_ADDR, 2, vt82c686_read, NULL, NULL, vt82c686_write, NULL, NULL, dev);
|
io_sethandler(FDC_PRIMARY_ADDR, 2, vt82c686_read, NULL, NULL, vt82c686_write, NULL, NULL, dev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vt82c686_reset(vt82c686_t *dev)
|
vt82c686_reset(vt82c686_t *dev)
|
||||||
{
|
{
|
||||||
@@ -272,7 +265,6 @@ vt82c686_reset(vt82c686_t *dev)
|
|||||||
vt82c686_sio_write(0x85, 0x00, dev);
|
vt82c686_sio_write(0x85, 0x00, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vt82c686_close(void *priv)
|
vt82c686_close(void *priv)
|
||||||
{
|
{
|
||||||
@@ -281,14 +273,13 @@ vt82c686_close(void *priv)
|
|||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
vt82c686_init(const device_t *info)
|
vt82c686_init(const device_t *info)
|
||||||
{
|
{
|
||||||
vt82c686_t *dev = (vt82c686_t *) malloc(sizeof(vt82c686_t));
|
vt82c686_t *dev = (vt82c686_t *) malloc(sizeof(vt82c686_t));
|
||||||
memset(dev, 0, sizeof(vt82c686_t));
|
memset(dev, 0, sizeof(vt82c686_t));
|
||||||
|
|
||||||
dev->fdc = device_add(&fdc_at_smc_device);
|
dev->fdc = device_add(&fdc_at_smc_device);
|
||||||
dev->fdc_dma = 2;
|
dev->fdc_dma = 2;
|
||||||
|
|
||||||
dev->uart[0] = device_add_inst(&ns16550_device, 1);
|
dev->uart[0] = device_add_inst(&ns16550_device, 1);
|
||||||
@@ -301,17 +292,16 @@ vt82c686_init(const device_t *info)
|
|||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const device_t via_vt82c686_sio_device = {
|
const device_t via_vt82c686_sio_device = {
|
||||||
.name = "VIA VT82C686 Integrated Super I/O",
|
.name = "VIA VT82C686 Integrated Super I/O",
|
||||||
.internal_name = "via_vt82c686_sio",
|
.internal_name = "via_vt82c686_sio",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0,
|
.local = 0,
|
||||||
.init = vt82c686_init,
|
.init = vt82c686_init,
|
||||||
.close = vt82c686_close,
|
.close = vt82c686_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -44,64 +44,60 @@ w83787_log(const char *fmt, ...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (w83787_do_log)
|
if (w83787_do_log) {
|
||||||
{
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
pclog_ex(fmt, ap);
|
pclog_ex(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define w83787_log(fmt, ...)
|
# define w83787_log(fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define FDDA_TYPE (dev->regs[7] & 3)
|
#define FDDA_TYPE (dev->regs[7] & 3)
|
||||||
#define FDDB_TYPE ((dev->regs[7] >> 2) & 3)
|
#define FDDB_TYPE ((dev->regs[7] >> 2) & 3)
|
||||||
#define FDDC_TYPE ((dev->regs[7] >> 4) & 3)
|
#define FDDC_TYPE ((dev->regs[7] >> 4) & 3)
|
||||||
#define FDDD_TYPE ((dev->regs[7] >> 6) & 3)
|
#define FDDD_TYPE ((dev->regs[7] >> 6) & 3)
|
||||||
|
|
||||||
#define FD_BOOT (dev->regs[8] & 3)
|
#define FD_BOOT (dev->regs[8] & 3)
|
||||||
#define SWWP ((dev->regs[8] >> 4) & 1)
|
#define SWWP ((dev->regs[8] >> 4) & 1)
|
||||||
#define DISFDDWR ((dev->regs[8] >> 5) & 1)
|
#define DISFDDWR ((dev->regs[8] >> 5) & 1)
|
||||||
|
|
||||||
#define EN3MODE ((dev->regs[9] >> 5) & 1)
|
#define EN3MODE ((dev->regs[9] >> 5) & 1)
|
||||||
|
|
||||||
#define DRV2EN_NEG (dev->regs[0xB] & 1) /* 0 = drive 2 installed */
|
#define DRV2EN_NEG (dev->regs[0xB] & 1) /* 0 = drive 2 installed */
|
||||||
#define INVERTZ ((dev->regs[0xB] >> 1) & 1) /* 0 = invert DENSEL polarity */
|
#define INVERTZ ((dev->regs[0xB] >> 1) & 1) /* 0 = invert DENSEL polarity */
|
||||||
#define IDENT ((dev->regs[0xB] >> 3) & 1)
|
#define IDENT ((dev->regs[0xB] >> 3) & 1)
|
||||||
|
|
||||||
#define HEFERE ((dev->regs[0xC] >> 5) & 1)
|
#define HEFERE ((dev->regs[0xC] >> 5) & 1)
|
||||||
|
|
||||||
#define HAS_IDE_FUNCTIONALITY dev->ide_function
|
#define HAS_IDE_FUNCTIONALITY dev->ide_function
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t tries, regs[42];
|
uint8_t tries, regs[42];
|
||||||
uint16_t reg_init;
|
uint16_t reg_init;
|
||||||
int locked, rw_locked,
|
int locked, rw_locked,
|
||||||
cur_reg,
|
cur_reg,
|
||||||
key, ide_function,
|
key, ide_function,
|
||||||
ide_start;
|
ide_start;
|
||||||
fdc_t *fdc;
|
fdc_t *fdc;
|
||||||
serial_t *uart[2];
|
serial_t *uart[2];
|
||||||
void *gameport;
|
void *gameport;
|
||||||
} w83787f_t;
|
} w83787f_t;
|
||||||
|
|
||||||
|
static void w83787f_write(uint16_t port, uint8_t val, void *priv);
|
||||||
static void w83787f_write(uint16_t port, uint8_t val, void *priv);
|
static uint8_t w83787f_read(uint16_t port, void *priv);
|
||||||
static uint8_t w83787f_read(uint16_t port, void *priv);
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83787f_remap(w83787f_t *dev)
|
w83787f_remap(w83787f_t *dev)
|
||||||
{
|
{
|
||||||
io_removehandler(0x250, 0x0004,
|
io_removehandler(0x250, 0x0004,
|
||||||
w83787f_read, NULL, NULL, w83787f_write, NULL, NULL, dev);
|
w83787f_read, NULL, NULL, w83787f_write, NULL, NULL, dev);
|
||||||
io_sethandler(0x250, 0x0004,
|
io_sethandler(0x250, 0x0004,
|
||||||
w83787f_read, NULL, NULL, w83787f_write, NULL, NULL, dev);
|
w83787f_read, NULL, NULL, w83787f_write, NULL, NULL, dev);
|
||||||
dev->key = 0x88 | HEFERE;
|
dev->key = 0x88 | HEFERE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef FIXME
|
#ifdef FIXME
|
||||||
/* FIXME: Implement EPP (and ECP) parallel port modes. */
|
/* FIXME: Implement EPP (and ECP) parallel port modes. */
|
||||||
static uint8_t
|
static uint8_t
|
||||||
@@ -110,269 +106,261 @@ get_lpt_length(w83787f_t *dev)
|
|||||||
uint8_t length = 4;
|
uint8_t length = 4;
|
||||||
|
|
||||||
if (dev->regs[9] & 0x80) {
|
if (dev->regs[9] & 0x80) {
|
||||||
if (dev->regs[0] & 0x04)
|
if (dev->regs[0] & 0x04)
|
||||||
length = 8; /* EPP mode. */
|
length = 8; /* EPP mode. */
|
||||||
if (dev->regs[0] & 0x08)
|
if (dev->regs[0] & 0x08)
|
||||||
length |= 0x80; /* ECP mode. */
|
length |= 0x80; /* ECP mode. */
|
||||||
}
|
}
|
||||||
|
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83787f_serial_handler(w83787f_t *dev, int uart)
|
w83787f_serial_handler(w83787f_t *dev, int uart)
|
||||||
{
|
{
|
||||||
int urs0 = !!(dev->regs[1] & (1 << uart));
|
int urs0 = !!(dev->regs[1] & (1 << uart));
|
||||||
int urs1 = !!(dev->regs[1] & (4 << uart));
|
int urs1 = !!(dev->regs[1] & (4 << uart));
|
||||||
int urs2 = !!(dev->regs[3] & (8 >> uart));
|
int urs2 = !!(dev->regs[3] & (8 >> uart));
|
||||||
int urs, irq = COM1_IRQ;
|
int urs, irq = COM1_IRQ;
|
||||||
uint16_t addr = COM1_ADDR, enable = 1;
|
uint16_t addr = COM1_ADDR, enable = 1;
|
||||||
|
|
||||||
urs = (urs1 << 1) | urs0;
|
urs = (urs1 << 1) | urs0;
|
||||||
|
|
||||||
if (urs2) {
|
if (urs2) {
|
||||||
addr = uart ? COM1_ADDR : COM2_ADDR;
|
addr = uart ? COM1_ADDR : COM2_ADDR;
|
||||||
irq = uart ? COM1_IRQ : COM2_IRQ;
|
irq = uart ? COM1_IRQ : COM2_IRQ;
|
||||||
} else {
|
} else {
|
||||||
switch (urs) {
|
switch (urs) {
|
||||||
case 0:
|
case 0:
|
||||||
addr = uart ? COM3_ADDR : COM4_ADDR;
|
addr = uart ? COM3_ADDR : COM4_ADDR;
|
||||||
irq = uart ? COM3_IRQ : COM4_IRQ;
|
irq = uart ? COM3_IRQ : COM4_IRQ;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
addr = uart ? COM4_ADDR : COM3_ADDR;
|
addr = uart ? COM4_ADDR : COM3_ADDR;
|
||||||
irq = uart ? COM4_IRQ : COM3_IRQ;
|
irq = uart ? COM4_IRQ : COM3_IRQ;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
addr = uart ? COM2_ADDR : COM1_ADDR;
|
addr = uart ? COM2_ADDR : COM1_ADDR;
|
||||||
irq = uart ? COM2_IRQ : COM1_IRQ;
|
irq = uart ? COM2_IRQ : COM1_IRQ;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
default:
|
default:
|
||||||
enable = 0;
|
enable = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->regs[4] & (0x20 >> uart))
|
if (dev->regs[4] & (0x20 >> uart))
|
||||||
enable = 0;
|
enable = 0;
|
||||||
|
|
||||||
serial_remove(dev->uart[uart]);
|
serial_remove(dev->uart[uart]);
|
||||||
if (enable)
|
if (enable)
|
||||||
serial_setup(dev->uart[uart], addr, irq);
|
serial_setup(dev->uart[uart], addr, irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83787f_lpt_handler(w83787f_t *dev)
|
w83787f_lpt_handler(w83787f_t *dev)
|
||||||
{
|
{
|
||||||
int ptras = (dev->regs[1] >> 4) & 0x03;
|
int ptras = (dev->regs[1] >> 4) & 0x03;
|
||||||
int irq = LPT1_IRQ;
|
int irq = LPT1_IRQ;
|
||||||
uint16_t addr = LPT1_ADDR, enable = 1;
|
uint16_t addr = LPT1_ADDR, enable = 1;
|
||||||
|
|
||||||
switch (ptras) {
|
switch (ptras) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
addr = LPT_MDA_ADDR;
|
addr = LPT_MDA_ADDR;
|
||||||
irq = LPT_MDA_IRQ;
|
irq = LPT_MDA_IRQ;
|
||||||
break;
|
break;
|
||||||
case 0x01:
|
case 0x01:
|
||||||
addr = LPT2_ADDR;
|
addr = LPT2_ADDR;
|
||||||
irq = LPT2_IRQ;
|
irq = LPT2_IRQ;
|
||||||
break;
|
break;
|
||||||
case 0x02:
|
case 0x02:
|
||||||
addr = LPT1_ADDR;
|
addr = LPT1_ADDR;
|
||||||
irq = LPT1_IRQ;
|
irq = LPT1_IRQ;
|
||||||
break;
|
break;
|
||||||
case 0x03:
|
case 0x03:
|
||||||
default:
|
default:
|
||||||
enable = 0;
|
enable = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->regs[4] & 0x80)
|
if (dev->regs[4] & 0x80)
|
||||||
enable = 0;
|
enable = 0;
|
||||||
|
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
if (enable) {
|
if (enable) {
|
||||||
lpt1_init(addr);
|
lpt1_init(addr);
|
||||||
lpt1_irq(irq);
|
lpt1_irq(irq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83787f_gameport_handler(w83787f_t *dev)
|
w83787f_gameport_handler(w83787f_t *dev)
|
||||||
{
|
{
|
||||||
if (!(dev->regs[3] & 0x40) && !(dev->regs[4] & 0x40))
|
if (!(dev->regs[3] & 0x40) && !(dev->regs[4] & 0x40))
|
||||||
gameport_remap(dev->gameport, 0x201);
|
gameport_remap(dev->gameport, 0x201);
|
||||||
else
|
else
|
||||||
gameport_remap(dev->gameport, 0);
|
gameport_remap(dev->gameport, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83787f_fdc_handler(w83787f_t *dev)
|
w83787f_fdc_handler(w83787f_t *dev)
|
||||||
{
|
{
|
||||||
fdc_remove(dev->fdc);
|
fdc_remove(dev->fdc);
|
||||||
if (!(dev->regs[0] & 0x20) && !(dev->regs[6] & 0x08))
|
if (!(dev->regs[0] & 0x20) && !(dev->regs[6] & 0x08))
|
||||||
fdc_set_base(dev->fdc, (dev->regs[0] & 0x10) ? FDC_PRIMARY_ADDR : FDC_SECONDARY_ADDR);
|
fdc_set_base(dev->fdc, (dev->regs[0] & 0x10) ? FDC_PRIMARY_ADDR : FDC_SECONDARY_ADDR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83787f_ide_handler(w83787f_t *dev)
|
w83787f_ide_handler(w83787f_t *dev)
|
||||||
{
|
{
|
||||||
if (dev->ide_function & 0x20) {
|
if (dev->ide_function & 0x20) {
|
||||||
ide_sec_disable();
|
ide_sec_disable();
|
||||||
if (!(dev->regs[0] & 0x80)) {
|
if (!(dev->regs[0] & 0x80)) {
|
||||||
ide_set_base(1, (dev->regs[0] & 0x40) ? 0x1f0 : 0x170);
|
ide_set_base(1, (dev->regs[0] & 0x40) ? 0x1f0 : 0x170);
|
||||||
ide_set_side(1, (dev->regs[0] & 0x40) ? 0x3f6 : 0x376);
|
ide_set_side(1, (dev->regs[0] & 0x40) ? 0x3f6 : 0x376);
|
||||||
ide_sec_enable();
|
ide_sec_enable();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ide_pri_disable();
|
ide_pri_disable();
|
||||||
if (!(dev->regs[0] & 0x80)) {
|
if (!(dev->regs[0] & 0x80)) {
|
||||||
ide_set_base(0, (dev->regs[0] & 0x40) ? 0x1f0 : 0x170);
|
ide_set_base(0, (dev->regs[0] & 0x40) ? 0x1f0 : 0x170);
|
||||||
ide_set_side(0, (dev->regs[0] & 0x40) ? 0x3f6 : 0x376);
|
ide_set_side(0, (dev->regs[0] & 0x40) ? 0x3f6 : 0x376);
|
||||||
ide_pri_enable();
|
ide_pri_enable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83787f_write(uint16_t port, uint8_t val, void *priv)
|
w83787f_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
w83787f_t *dev = (w83787f_t *) priv;
|
w83787f_t *dev = (w83787f_t *) priv;
|
||||||
uint8_t valxor = 0;
|
uint8_t valxor = 0;
|
||||||
uint8_t max = 0x15;
|
uint8_t max = 0x15;
|
||||||
|
|
||||||
if (port == 0x250) {
|
if (port == 0x250) {
|
||||||
if (val == dev->key)
|
if (val == dev->key)
|
||||||
dev->locked = 1;
|
dev->locked = 1;
|
||||||
else
|
else
|
||||||
dev->locked = 0;
|
dev->locked = 0;
|
||||||
return;
|
return;
|
||||||
} else if (port == 0x251) {
|
} else if (port == 0x251) {
|
||||||
if (val <= max)
|
if (val <= max)
|
||||||
dev->cur_reg = val;
|
dev->cur_reg = val;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (dev->locked) {
|
if (dev->locked) {
|
||||||
if (dev->rw_locked)
|
if (dev->rw_locked)
|
||||||
return;
|
return;
|
||||||
if (dev->cur_reg == 6)
|
if (dev->cur_reg == 6)
|
||||||
val &= 0xF3;
|
val &= 0xF3;
|
||||||
valxor = val ^ dev->regs[dev->cur_reg];
|
valxor = val ^ dev->regs[dev->cur_reg];
|
||||||
dev->regs[dev->cur_reg] = val;
|
dev->regs[dev->cur_reg] = val;
|
||||||
} else
|
} else
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0:
|
case 0:
|
||||||
w83787_log("REG 00: %02X\n", val);
|
w83787_log("REG 00: %02X\n", val);
|
||||||
if ((valxor & 0xc0) && (HAS_IDE_FUNCTIONALITY))
|
if ((valxor & 0xc0) && (HAS_IDE_FUNCTIONALITY))
|
||||||
w83787f_ide_handler(dev);
|
w83787f_ide_handler(dev);
|
||||||
if (valxor & 0x30)
|
if (valxor & 0x30)
|
||||||
w83787f_fdc_handler(dev);
|
w83787f_fdc_handler(dev);
|
||||||
if (valxor & 0x0c)
|
if (valxor & 0x0c)
|
||||||
w83787f_lpt_handler(dev);
|
w83787f_lpt_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (valxor & 0x80)
|
if (valxor & 0x80)
|
||||||
fdc_set_swap(dev->fdc, (dev->regs[1] & 0x80) ? 1 : 0);
|
fdc_set_swap(dev->fdc, (dev->regs[1] & 0x80) ? 1 : 0);
|
||||||
if (valxor & 0x30)
|
if (valxor & 0x30)
|
||||||
w83787f_lpt_handler(dev);
|
w83787f_lpt_handler(dev);
|
||||||
if (valxor & 0x0a)
|
if (valxor & 0x0a)
|
||||||
w83787f_serial_handler(dev, 1);
|
w83787f_serial_handler(dev, 1);
|
||||||
if (valxor & 0x05)
|
if (valxor & 0x05)
|
||||||
w83787f_serial_handler(dev, 0);
|
w83787f_serial_handler(dev, 0);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (valxor & 0x80)
|
if (valxor & 0x80)
|
||||||
w83787f_lpt_handler(dev);
|
w83787f_lpt_handler(dev);
|
||||||
if (valxor & 0x40)
|
if (valxor & 0x40)
|
||||||
w83787f_gameport_handler(dev);
|
w83787f_gameport_handler(dev);
|
||||||
if (valxor & 0x08)
|
if (valxor & 0x08)
|
||||||
w83787f_serial_handler(dev, 0);
|
w83787f_serial_handler(dev, 0);
|
||||||
if (valxor & 0x04)
|
if (valxor & 0x04)
|
||||||
w83787f_serial_handler(dev, 1);
|
w83787f_serial_handler(dev, 1);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if (valxor & 0x10)
|
if (valxor & 0x10)
|
||||||
w83787f_serial_handler(dev, 1);
|
w83787f_serial_handler(dev, 1);
|
||||||
if (valxor & 0x20)
|
if (valxor & 0x20)
|
||||||
w83787f_serial_handler(dev, 0);
|
w83787f_serial_handler(dev, 0);
|
||||||
if (valxor & 0x80)
|
if (valxor & 0x80)
|
||||||
w83787f_lpt_handler(dev);
|
w83787f_lpt_handler(dev);
|
||||||
if (valxor & 0x40)
|
if (valxor & 0x40)
|
||||||
w83787f_gameport_handler(dev);
|
w83787f_gameport_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
if (valxor & 0x08)
|
if (valxor & 0x08)
|
||||||
w83787f_fdc_handler(dev);
|
w83787f_fdc_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
if (valxor & 0x03)
|
if (valxor & 0x03)
|
||||||
fdc_update_rwc(dev->fdc, 0, FDDA_TYPE);
|
fdc_update_rwc(dev->fdc, 0, FDDA_TYPE);
|
||||||
if (valxor & 0x0c)
|
if (valxor & 0x0c)
|
||||||
fdc_update_rwc(dev->fdc, 1, FDDB_TYPE);
|
fdc_update_rwc(dev->fdc, 1, FDDB_TYPE);
|
||||||
if (valxor & 0x30)
|
if (valxor & 0x30)
|
||||||
fdc_update_rwc(dev->fdc, 2, FDDC_TYPE);
|
fdc_update_rwc(dev->fdc, 2, FDDC_TYPE);
|
||||||
if (valxor & 0xc0)
|
if (valxor & 0xc0)
|
||||||
fdc_update_rwc(dev->fdc, 3, FDDD_TYPE);
|
fdc_update_rwc(dev->fdc, 3, FDDD_TYPE);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
if (valxor & 0x03)
|
if (valxor & 0x03)
|
||||||
fdc_update_boot_drive(dev->fdc, FD_BOOT);
|
fdc_update_boot_drive(dev->fdc, FD_BOOT);
|
||||||
if (valxor & 0x10)
|
if (valxor & 0x10)
|
||||||
fdc_set_swwp(dev->fdc, SWWP ? 1 : 0);
|
fdc_set_swwp(dev->fdc, SWWP ? 1 : 0);
|
||||||
if (valxor & 0x20)
|
if (valxor & 0x20)
|
||||||
fdc_set_diswr(dev->fdc, DISFDDWR ? 1 : 0);
|
fdc_set_diswr(dev->fdc, DISFDDWR ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
if (valxor & 0x20)
|
if (valxor & 0x20)
|
||||||
fdc_update_enh_mode(dev->fdc, EN3MODE ? 1 : 0);
|
fdc_update_enh_mode(dev->fdc, EN3MODE ? 1 : 0);
|
||||||
if (valxor & 0x40)
|
if (valxor & 0x40)
|
||||||
dev->rw_locked = (val & 0x40) ? 1 : 0;
|
dev->rw_locked = (val & 0x40) ? 1 : 0;
|
||||||
if (valxor & 0x80)
|
if (valxor & 0x80)
|
||||||
w83787f_lpt_handler(dev);
|
w83787f_lpt_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 0xB:
|
case 0xB:
|
||||||
w83787_log("Writing %02X to CRB\n", val);
|
w83787_log("Writing %02X to CRB\n", val);
|
||||||
break;
|
break;
|
||||||
case 0xC:
|
case 0xC:
|
||||||
if (valxor & 0x20)
|
if (valxor & 0x20)
|
||||||
w83787f_remap(dev);
|
w83787f_remap(dev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
w83787f_read(uint16_t port, void *priv)
|
w83787f_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
w83787f_t *dev = (w83787f_t *) priv;
|
w83787f_t *dev = (w83787f_t *) priv;
|
||||||
uint8_t ret = 0xff;
|
uint8_t ret = 0xff;
|
||||||
|
|
||||||
if (dev->locked) {
|
if (dev->locked) {
|
||||||
if (port == 0x251)
|
if (port == 0x251)
|
||||||
ret = dev->cur_reg;
|
ret = dev->cur_reg;
|
||||||
else if (port == 0x252) {
|
else if (port == 0x252) {
|
||||||
if (dev->cur_reg == 7)
|
if (dev->cur_reg == 7)
|
||||||
ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2));
|
ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2));
|
||||||
else if (!dev->rw_locked)
|
else if (!dev->rw_locked)
|
||||||
ret = dev->regs[dev->cur_reg];
|
ret = dev->regs[dev->cur_reg];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83787f_reset(w83787f_t *dev)
|
w83787f_reset(w83787f_t *dev)
|
||||||
{
|
{
|
||||||
@@ -383,27 +371,27 @@ w83787f_reset(w83787f_t *dev)
|
|||||||
memset(dev->regs, 0, 0x2A);
|
memset(dev->regs, 0, 0x2A);
|
||||||
|
|
||||||
if (HAS_IDE_FUNCTIONALITY) {
|
if (HAS_IDE_FUNCTIONALITY) {
|
||||||
if (dev->ide_function & 0x20) {
|
if (dev->ide_function & 0x20) {
|
||||||
dev->regs[0x00] = 0x90;
|
dev->regs[0x00] = 0x90;
|
||||||
ide_sec_disable();
|
ide_sec_disable();
|
||||||
ide_set_base(1, 0x170);
|
ide_set_base(1, 0x170);
|
||||||
ide_set_side(1, 0x376);
|
ide_set_side(1, 0x376);
|
||||||
} else {
|
} else {
|
||||||
dev->regs[0x00] = 0xd0;
|
dev->regs[0x00] = 0xd0;
|
||||||
ide_pri_disable();
|
ide_pri_disable();
|
||||||
ide_set_base(0, 0x1f0);
|
ide_set_base(0, 0x1f0);
|
||||||
ide_set_side(0, 0x3f6);
|
ide_set_side(0, 0x3f6);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->ide_start) {
|
if (dev->ide_start) {
|
||||||
dev->regs[0x00] &= 0x7f;
|
dev->regs[0x00] &= 0x7f;
|
||||||
if (dev->ide_function & 0x20)
|
if (dev->ide_function & 0x20)
|
||||||
ide_sec_enable();
|
ide_sec_enable();
|
||||||
else
|
else
|
||||||
ide_pri_enable();
|
ide_pri_enable();
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
dev->regs[0x00] = 0xd0;
|
dev->regs[0x00] = 0xd0;
|
||||||
|
|
||||||
fdc_reset(dev->fdc);
|
fdc_reset(dev->fdc);
|
||||||
|
|
||||||
@@ -426,11 +414,10 @@ w83787f_reset(w83787f_t *dev)
|
|||||||
|
|
||||||
w83787f_remap(dev);
|
w83787f_remap(dev);
|
||||||
|
|
||||||
dev->locked = 0;
|
dev->locked = 0;
|
||||||
dev->rw_locked = 0;
|
dev->rw_locked = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83787f_close(void *priv)
|
w83787f_close(void *priv)
|
||||||
{
|
{
|
||||||
@@ -439,7 +426,6 @@ w83787f_close(void *priv)
|
|||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
w83787f_init(const device_t *info)
|
w83787f_init(const device_t *info)
|
||||||
{
|
{
|
||||||
@@ -456,7 +442,7 @@ w83787f_init(const device_t *info)
|
|||||||
dev->gameport = gameport_add(&gameport_sio_1io_device);
|
dev->gameport = gameport_add(&gameport_sio_1io_device);
|
||||||
|
|
||||||
if ((dev->ide_function & 0x30) == 0x10)
|
if ((dev->ide_function & 0x30) == 0x10)
|
||||||
device_add(&ide_isa_device);
|
device_add(&ide_isa_device);
|
||||||
|
|
||||||
dev->ide_start = !!(info->local & 0x40);
|
dev->ide_start = !!(info->local & 0x40);
|
||||||
|
|
||||||
@@ -467,57 +453,57 @@ w83787f_init(const device_t *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const device_t w83787f_device = {
|
const device_t w83787f_device = {
|
||||||
.name = "Winbond W83787F/IF Super I/O",
|
.name = "Winbond W83787F/IF Super I/O",
|
||||||
.internal_name = "w83787f",
|
.internal_name = "w83787f",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x09,
|
.local = 0x09,
|
||||||
.init = w83787f_init,
|
.init = w83787f_init,
|
||||||
.close = w83787f_close,
|
.close = w83787f_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t w83787f_ide_device = {
|
const device_t w83787f_ide_device = {
|
||||||
.name = "Winbond W83787F/IF Super I/O (With IDE)",
|
.name = "Winbond W83787F/IF Super I/O (With IDE)",
|
||||||
.internal_name = "w83787f_ide",
|
.internal_name = "w83787f_ide",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x19,
|
.local = 0x19,
|
||||||
.init = w83787f_init,
|
.init = w83787f_init,
|
||||||
.close = w83787f_close,
|
.close = w83787f_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t w83787f_ide_en_device = {
|
const device_t w83787f_ide_en_device = {
|
||||||
.name = "Winbond W83787F/IF Super I/O (With IDE Enabled)",
|
.name = "Winbond W83787F/IF Super I/O (With IDE Enabled)",
|
||||||
.internal_name = "w83787f_ide_en",
|
.internal_name = "w83787f_ide_en",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x59,
|
.local = 0x59,
|
||||||
.init = w83787f_init,
|
.init = w83787f_init,
|
||||||
.close = w83787f_close,
|
.close = w83787f_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t w83787f_ide_sec_device = {
|
const device_t w83787f_ide_sec_device = {
|
||||||
.name = "Winbond W83787F/IF Super I/O (With Secondary IDE)",
|
.name = "Winbond W83787F/IF Super I/O (With Secondary IDE)",
|
||||||
.internal_name = "w83787f_ide_sec",
|
.internal_name = "w83787f_ide_sec",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x39,
|
.local = 0x39,
|
||||||
.init = w83787f_init,
|
.init = w83787f_init,
|
||||||
.close = w83787f_close,
|
.close = w83787f_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,45 +34,41 @@
|
|||||||
#include <86box/fdc.h>
|
#include <86box/fdc.h>
|
||||||
#include <86box/sio.h>
|
#include <86box/sio.h>
|
||||||
|
|
||||||
|
#define FDDA_TYPE (dev->regs[7] & 3)
|
||||||
|
#define FDDB_TYPE ((dev->regs[7] >> 2) & 3)
|
||||||
|
#define FDDC_TYPE ((dev->regs[7] >> 4) & 3)
|
||||||
|
#define FDDD_TYPE ((dev->regs[7] >> 6) & 3)
|
||||||
|
|
||||||
#define FDDA_TYPE (dev->regs[7] & 3)
|
#define FD_BOOT (dev->regs[8] & 3)
|
||||||
#define FDDB_TYPE ((dev->regs[7] >> 2) & 3)
|
#define SWWP ((dev->regs[8] >> 4) & 1)
|
||||||
#define FDDC_TYPE ((dev->regs[7] >> 4) & 3)
|
#define DISFDDWR ((dev->regs[8] >> 5) & 1)
|
||||||
#define FDDD_TYPE ((dev->regs[7] >> 6) & 3)
|
|
||||||
|
|
||||||
#define FD_BOOT (dev->regs[8] & 3)
|
#define EN3MODE ((dev->regs[9] >> 5) & 1)
|
||||||
#define SWWP ((dev->regs[8] >> 4) & 1)
|
|
||||||
#define DISFDDWR ((dev->regs[8] >> 5) & 1)
|
|
||||||
|
|
||||||
#define EN3MODE ((dev->regs[9] >> 5) & 1)
|
#define DRV2EN_NEG (dev->regs[0xB] & 1) /* 0 = drive 2 installed */
|
||||||
|
#define INVERTZ ((dev->regs[0xB] >> 1) & 1) /* 0 = invert DENSEL polarity */
|
||||||
|
#define IDENT ((dev->regs[0xB] >> 3) & 1)
|
||||||
|
|
||||||
#define DRV2EN_NEG (dev->regs[0xB] & 1) /* 0 = drive 2 installed */
|
#define HEFERE ((dev->regs[0xC] >> 5) & 1)
|
||||||
#define INVERTZ ((dev->regs[0xB] >> 1) & 1) /* 0 = invert DENSEL polarity */
|
|
||||||
#define IDENT ((dev->regs[0xB] >> 3) & 1)
|
|
||||||
|
|
||||||
#define HEFERE ((dev->regs[0xC] >> 5) & 1)
|
#define HEFRAS (dev->regs[0x16] & 1)
|
||||||
|
|
||||||
#define HEFRAS (dev->regs[0x16] & 1)
|
|
||||||
|
|
||||||
#define PRTIQS (dev->regs[0x27] & 0x0f)
|
|
||||||
#define ECPIRQ ((dev->regs[0x27] >> 5) & 0x07)
|
|
||||||
|
|
||||||
|
#define PRTIQS (dev->regs[0x27] & 0x0f)
|
||||||
|
#define ECPIRQ ((dev->regs[0x27] >> 5) & 0x07)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t tries, regs[42];
|
uint8_t tries, regs[42];
|
||||||
uint16_t reg_init;
|
uint16_t reg_init;
|
||||||
int locked, rw_locked,
|
int locked, rw_locked,
|
||||||
cur_reg,
|
cur_reg,
|
||||||
base_address, key,
|
base_address, key,
|
||||||
key_times;
|
key_times;
|
||||||
fdc_t *fdc;
|
fdc_t *fdc;
|
||||||
serial_t *uart[2];
|
serial_t *uart[2];
|
||||||
} w83877f_t;
|
} w83877f_t;
|
||||||
|
|
||||||
|
static void w83877f_write(uint16_t port, uint8_t val, void *priv);
|
||||||
static void w83877f_write(uint16_t port, uint8_t val, void *priv);
|
static uint8_t w83877f_read(uint16_t port, void *priv);
|
||||||
static uint8_t w83877f_read(uint16_t port, void *priv);
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83877f_remap(w83877f_t *dev)
|
w83877f_remap(w83877f_t *dev)
|
||||||
@@ -80,83 +76,83 @@ w83877f_remap(w83877f_t *dev)
|
|||||||
uint8_t hefras = HEFRAS;
|
uint8_t hefras = HEFRAS;
|
||||||
|
|
||||||
io_removehandler(0x250, 0x0002,
|
io_removehandler(0x250, 0x0002,
|
||||||
w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev);
|
w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev);
|
||||||
io_removehandler(FDC_PRIMARY_ADDR, 0x0002,
|
io_removehandler(FDC_PRIMARY_ADDR, 0x0002,
|
||||||
w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev);
|
w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev);
|
||||||
dev->base_address = (hefras ? FDC_PRIMARY_ADDR : 0x250);
|
dev->base_address = (hefras ? FDC_PRIMARY_ADDR : 0x250);
|
||||||
io_sethandler(dev->base_address, 0x0002,
|
io_sethandler(dev->base_address, 0x0002,
|
||||||
w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev);
|
w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, dev);
|
||||||
dev->key_times = hefras + 1;
|
dev->key_times = hefras + 1;
|
||||||
dev->key = (hefras ? 0x86 : 0x88) | HEFERE;
|
dev->key = (hefras ? 0x86 : 0x88) | HEFERE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
get_lpt_length(w83877f_t *dev)
|
get_lpt_length(w83877f_t *dev)
|
||||||
{
|
{
|
||||||
uint8_t length = 4;
|
uint8_t length = 4;
|
||||||
|
|
||||||
if (dev->regs[9] & 0x80) {
|
if (dev->regs[9] & 0x80) {
|
||||||
if (dev->regs[0] & 0x04)
|
if (dev->regs[0] & 0x04)
|
||||||
length = 8; /* EPP mode. */
|
length = 8; /* EPP mode. */
|
||||||
if (dev->regs[0] & 0x08)
|
if (dev->regs[0] & 0x08)
|
||||||
length |= 0x80; /* ECP mode. */
|
length |= 0x80; /* ECP mode. */
|
||||||
}
|
}
|
||||||
|
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint16_t
|
static uint16_t
|
||||||
make_port(w83877f_t *dev, uint8_t reg)
|
make_port(w83877f_t *dev, uint8_t reg)
|
||||||
{
|
{
|
||||||
uint16_t p = 0;
|
uint16_t p = 0;
|
||||||
uint8_t l;
|
uint8_t l;
|
||||||
|
|
||||||
switch (reg) {
|
switch (reg) {
|
||||||
case 0x20:
|
case 0x20:
|
||||||
p = ((uint16_t) (dev->regs[reg] & 0xfc)) << 2;
|
p = ((uint16_t) (dev->regs[reg] & 0xfc)) << 2;
|
||||||
p &= 0xFF0;
|
p &= 0xFF0;
|
||||||
if ((p < 0x100) || (p > 0x3F0)) p = 0x3F0;
|
if ((p < 0x100) || (p > 0x3F0))
|
||||||
break;
|
p = 0x3F0;
|
||||||
case 0x23:
|
break;
|
||||||
l = get_lpt_length(dev);
|
case 0x23:
|
||||||
p = ((uint16_t) (dev->regs[reg] & 0xff)) << 2;
|
l = get_lpt_length(dev);
|
||||||
/* 8 ports in EPP mode, 4 in non-EPP mode. */
|
p = ((uint16_t) (dev->regs[reg] & 0xff)) << 2;
|
||||||
if ((l & 0x0f) == 8)
|
/* 8 ports in EPP mode, 4 in non-EPP mode. */
|
||||||
p &= 0x3F8;
|
if ((l & 0x0f) == 8)
|
||||||
else
|
p &= 0x3F8;
|
||||||
p &= 0x3FC;
|
else
|
||||||
if ((p < 0x100) || (p > 0x3FF)) p = LPT1_ADDR;
|
p &= 0x3FC;
|
||||||
/* In ECP mode, A10 is active. */
|
if ((p < 0x100) || (p > 0x3FF))
|
||||||
if (l & 0x80)
|
p = LPT1_ADDR;
|
||||||
p |= 0x400;
|
/* In ECP mode, A10 is active. */
|
||||||
break;
|
if (l & 0x80)
|
||||||
case 0x24:
|
p |= 0x400;
|
||||||
p = ((uint16_t) (dev->regs[reg] & 0xfe)) << 2;
|
break;
|
||||||
p &= 0xFF8;
|
case 0x24:
|
||||||
if ((p < 0x100) || (p > 0x3F8)) p = COM1_ADDR;
|
p = ((uint16_t) (dev->regs[reg] & 0xfe)) << 2;
|
||||||
break;
|
p &= 0xFF8;
|
||||||
case 0x25:
|
if ((p < 0x100) || (p > 0x3F8))
|
||||||
p = ((uint16_t) (dev->regs[reg] & 0xfe)) << 2;
|
p = COM1_ADDR;
|
||||||
p &= 0xFF8;
|
break;
|
||||||
if ((p < 0x100) || (p > 0x3F8)) p = COM2_ADDR;
|
case 0x25:
|
||||||
break;
|
p = ((uint16_t) (dev->regs[reg] & 0xfe)) << 2;
|
||||||
|
p &= 0xFF8;
|
||||||
|
if ((p < 0x100) || (p > 0x3F8))
|
||||||
|
p = COM2_ADDR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83877f_fdc_handler(w83877f_t *dev)
|
w83877f_fdc_handler(w83877f_t *dev)
|
||||||
{
|
{
|
||||||
fdc_remove(dev->fdc);
|
fdc_remove(dev->fdc);
|
||||||
if (!(dev->regs[6] & 0x08) && (dev->regs[0x20] & 0xc0))
|
if (!(dev->regs[6] & 0x08) && (dev->regs[0x20] & 0xc0))
|
||||||
fdc_set_base(dev->fdc, FDC_PRIMARY_ADDR);
|
fdc_set_base(dev->fdc, FDC_PRIMARY_ADDR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83877f_lpt_handler(w83877f_t *dev)
|
w83877f_lpt_handler(w83877f_t *dev)
|
||||||
{
|
{
|
||||||
@@ -165,230 +161,226 @@ w83877f_lpt_handler(w83877f_t *dev)
|
|||||||
|
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
if (!(dev->regs[4] & 0x80) && (dev->regs[0x23] & 0xc0))
|
if (!(dev->regs[4] & 0x80) && (dev->regs[0x23] & 0xc0))
|
||||||
lpt1_init(make_port(dev, 0x23));
|
lpt1_init(make_port(dev, 0x23));
|
||||||
|
|
||||||
lpt_irq = 0xff;
|
lpt_irq = 0xff;
|
||||||
|
|
||||||
lpt_irq = lpt_irqs[ECPIRQ];
|
lpt_irq = lpt_irqs[ECPIRQ];
|
||||||
if (lpt_irq == 0)
|
if (lpt_irq == 0)
|
||||||
lpt_irq = PRTIQS;
|
lpt_irq = PRTIQS;
|
||||||
|
|
||||||
lpt1_irq(lpt_irq);
|
lpt1_irq(lpt_irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83877f_serial_handler(w83877f_t *dev, int uart)
|
w83877f_serial_handler(w83877f_t *dev, int uart)
|
||||||
{
|
{
|
||||||
int reg_mask = uart ? 0x10 : 0x20;
|
int reg_mask = uart ? 0x10 : 0x20;
|
||||||
int reg_id = uart ? 0x25 : 0x24;
|
int reg_id = uart ? 0x25 : 0x24;
|
||||||
int irq_mask = uart ? 0x0f : 0xf0;
|
int irq_mask = uart ? 0x0f : 0xf0;
|
||||||
int irq_shift = uart ? 0 : 4;
|
int irq_shift = uart ? 0 : 4;
|
||||||
double clock_src = 24000000.0 / 13.0;
|
double clock_src = 24000000.0 / 13.0;
|
||||||
|
|
||||||
serial_remove(dev->uart[uart]);
|
serial_remove(dev->uart[uart]);
|
||||||
if (!(dev->regs[4] & reg_mask) && (dev->regs[reg_id] & 0xc0))
|
if (!(dev->regs[4] & reg_mask) && (dev->regs[reg_id] & 0xc0))
|
||||||
serial_setup(dev->uart[uart], make_port(dev, reg_id), (dev->regs[0x28] & irq_mask) >> irq_shift);
|
serial_setup(dev->uart[uart], make_port(dev, reg_id), (dev->regs[0x28] & irq_mask) >> irq_shift);
|
||||||
|
|
||||||
if (dev->regs[0x19] & (0x02 >> uart)) {
|
if (dev->regs[0x19] & (0x02 >> uart)) {
|
||||||
clock_src = 14769000.0;
|
clock_src = 14769000.0;
|
||||||
} else if (dev->regs[0x03] & (0x02 >> uart)) {
|
} else if (dev->regs[0x03] & (0x02 >> uart)) {
|
||||||
clock_src = 24000000.0 / 12.0;
|
clock_src = 24000000.0 / 12.0;
|
||||||
} else {
|
} else {
|
||||||
clock_src = 24000000.0 / 13.0;
|
clock_src = 24000000.0 / 13.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
serial_set_clock_src(dev->uart[uart], clock_src);
|
serial_set_clock_src(dev->uart[uart], clock_src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83877f_write(uint16_t port, uint8_t val, void *priv)
|
w83877f_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
w83877f_t *dev = (w83877f_t *) priv;
|
w83877f_t *dev = (w83877f_t *) priv;
|
||||||
uint8_t valxor = 0;
|
uint8_t valxor = 0;
|
||||||
uint8_t max = 0x2A;
|
uint8_t max = 0x2A;
|
||||||
|
|
||||||
if (port == 0x250) {
|
if (port == 0x250) {
|
||||||
if (val == dev->key)
|
if (val == dev->key)
|
||||||
dev->locked = 1;
|
dev->locked = 1;
|
||||||
else
|
else
|
||||||
dev->locked = 0;
|
dev->locked = 0;
|
||||||
return;
|
return;
|
||||||
} else if (port == 0x251) {
|
} else if (port == 0x251) {
|
||||||
if (val <= max)
|
if (val <= max)
|
||||||
dev->cur_reg = val;
|
dev->cur_reg = val;
|
||||||
return;
|
return;
|
||||||
} else if (port == FDC_PRIMARY_ADDR) {
|
} else if (port == FDC_PRIMARY_ADDR) {
|
||||||
if ((val == dev->key) && !dev->locked) {
|
if ((val == dev->key) && !dev->locked) {
|
||||||
if (dev->key_times == 2) {
|
if (dev->key_times == 2) {
|
||||||
if (dev->tries) {
|
if (dev->tries) {
|
||||||
dev->locked = 1;
|
dev->locked = 1;
|
||||||
dev->tries = 0;
|
dev->tries = 0;
|
||||||
} else
|
} else
|
||||||
dev->tries++;
|
dev->tries++;
|
||||||
} else {
|
} else {
|
||||||
dev->locked = 1;
|
dev->locked = 1;
|
||||||
dev->tries = 0;
|
dev->tries = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (dev->locked) {
|
if (dev->locked) {
|
||||||
if (val < max)
|
if (val < max)
|
||||||
dev->cur_reg = val;
|
dev->cur_reg = val;
|
||||||
if (val == 0xaa)
|
if (val == 0xaa)
|
||||||
dev->locked = 0;
|
dev->locked = 0;
|
||||||
} else {
|
} else {
|
||||||
if (dev->tries)
|
if (dev->tries)
|
||||||
dev->tries = 0;
|
dev->tries = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if ((port == 0x252) || (port == 0x3f1)) {
|
} else if ((port == 0x252) || (port == 0x3f1)) {
|
||||||
if (dev->locked) {
|
if (dev->locked) {
|
||||||
if (dev->rw_locked)
|
if (dev->rw_locked)
|
||||||
return;
|
return;
|
||||||
if ((dev->cur_reg >= 0x26) && (dev->cur_reg <= 0x27))
|
if ((dev->cur_reg >= 0x26) && (dev->cur_reg <= 0x27))
|
||||||
return;
|
return;
|
||||||
if (dev->cur_reg == 0x29)
|
if (dev->cur_reg == 0x29)
|
||||||
return;
|
return;
|
||||||
if (dev->cur_reg == 6)
|
if (dev->cur_reg == 6)
|
||||||
val &= 0xF3;
|
val &= 0xF3;
|
||||||
valxor = val ^ dev->regs[dev->cur_reg];
|
valxor = val ^ dev->regs[dev->cur_reg];
|
||||||
dev->regs[dev->cur_reg] = val;
|
dev->regs[dev->cur_reg] = val;
|
||||||
} else
|
} else
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0:
|
case 0:
|
||||||
if (valxor & 0x0c)
|
if (valxor & 0x0c)
|
||||||
w83877f_lpt_handler(dev);
|
w83877f_lpt_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (valxor & 0x80)
|
if (valxor & 0x80)
|
||||||
fdc_set_swap(dev->fdc, (dev->regs[1] & 0x80) ? 1 : 0);
|
fdc_set_swap(dev->fdc, (dev->regs[1] & 0x80) ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (valxor & 0x02)
|
if (valxor & 0x02)
|
||||||
w83877f_serial_handler(dev, 0);
|
w83877f_serial_handler(dev, 0);
|
||||||
if (valxor & 0x01)
|
if (valxor & 0x01)
|
||||||
w83877f_serial_handler(dev, 1);
|
w83877f_serial_handler(dev, 1);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if (valxor & 0x10)
|
if (valxor & 0x10)
|
||||||
w83877f_serial_handler(dev, 1);
|
w83877f_serial_handler(dev, 1);
|
||||||
if (valxor & 0x20)
|
if (valxor & 0x20)
|
||||||
w83877f_serial_handler(dev, 0);
|
w83877f_serial_handler(dev, 0);
|
||||||
if (valxor & 0x80)
|
if (valxor & 0x80)
|
||||||
w83877f_lpt_handler(dev);
|
w83877f_lpt_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
if (valxor & 0x08)
|
if (valxor & 0x08)
|
||||||
w83877f_fdc_handler(dev);
|
w83877f_fdc_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
if (valxor & 0x03)
|
if (valxor & 0x03)
|
||||||
fdc_update_rwc(dev->fdc, 0, FDDA_TYPE);
|
fdc_update_rwc(dev->fdc, 0, FDDA_TYPE);
|
||||||
if (valxor & 0x0c)
|
if (valxor & 0x0c)
|
||||||
fdc_update_rwc(dev->fdc, 1, FDDB_TYPE);
|
fdc_update_rwc(dev->fdc, 1, FDDB_TYPE);
|
||||||
if (valxor & 0x30)
|
if (valxor & 0x30)
|
||||||
fdc_update_rwc(dev->fdc, 2, FDDC_TYPE);
|
fdc_update_rwc(dev->fdc, 2, FDDC_TYPE);
|
||||||
if (valxor & 0xc0)
|
if (valxor & 0xc0)
|
||||||
fdc_update_rwc(dev->fdc, 3, FDDD_TYPE);
|
fdc_update_rwc(dev->fdc, 3, FDDD_TYPE);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
if (valxor & 0x03)
|
if (valxor & 0x03)
|
||||||
fdc_update_boot_drive(dev->fdc, FD_BOOT);
|
fdc_update_boot_drive(dev->fdc, FD_BOOT);
|
||||||
if (valxor & 0x10)
|
if (valxor & 0x10)
|
||||||
fdc_set_swwp(dev->fdc, SWWP ? 1 : 0);
|
fdc_set_swwp(dev->fdc, SWWP ? 1 : 0);
|
||||||
if (valxor & 0x20)
|
if (valxor & 0x20)
|
||||||
fdc_set_diswr(dev->fdc, DISFDDWR ? 1 : 0);
|
fdc_set_diswr(dev->fdc, DISFDDWR ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
if (valxor & 0x20)
|
if (valxor & 0x20)
|
||||||
fdc_update_enh_mode(dev->fdc, EN3MODE ? 1 : 0);
|
fdc_update_enh_mode(dev->fdc, EN3MODE ? 1 : 0);
|
||||||
if (valxor & 0x40)
|
if (valxor & 0x40)
|
||||||
dev->rw_locked = (val & 0x40) ? 1 : 0;
|
dev->rw_locked = (val & 0x40) ? 1 : 0;
|
||||||
if (valxor & 0x80)
|
if (valxor & 0x80)
|
||||||
w83877f_lpt_handler(dev);
|
w83877f_lpt_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 0xB:
|
case 0xB:
|
||||||
if (valxor & 1)
|
if (valxor & 1)
|
||||||
fdc_update_drv2en(dev->fdc, DRV2EN_NEG ? 0 : 1);
|
fdc_update_drv2en(dev->fdc, DRV2EN_NEG ? 0 : 1);
|
||||||
if (valxor & 2)
|
if (valxor & 2)
|
||||||
fdc_update_densel_polarity(dev->fdc, INVERTZ ? 1 : 0);
|
fdc_update_densel_polarity(dev->fdc, INVERTZ ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
case 0xC:
|
case 0xC:
|
||||||
if (valxor & 0x20)
|
if (valxor & 0x20)
|
||||||
w83877f_remap(dev);
|
w83877f_remap(dev);
|
||||||
break;
|
break;
|
||||||
case 0x16:
|
case 0x16:
|
||||||
if (valxor & 1)
|
if (valxor & 1)
|
||||||
w83877f_remap(dev);
|
w83877f_remap(dev);
|
||||||
break;
|
break;
|
||||||
case 0x19:
|
case 0x19:
|
||||||
if (valxor & 0x02)
|
if (valxor & 0x02)
|
||||||
w83877f_serial_handler(dev, 0);
|
w83877f_serial_handler(dev, 0);
|
||||||
if (valxor & 0x01)
|
if (valxor & 0x01)
|
||||||
w83877f_serial_handler(dev, 1);
|
w83877f_serial_handler(dev, 1);
|
||||||
break;
|
break;
|
||||||
case 0x20:
|
case 0x20:
|
||||||
if (valxor)
|
if (valxor)
|
||||||
w83877f_fdc_handler(dev);
|
w83877f_fdc_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 0x23:
|
case 0x23:
|
||||||
if (valxor)
|
if (valxor)
|
||||||
w83877f_lpt_handler(dev);
|
w83877f_lpt_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 0x24:
|
case 0x24:
|
||||||
if (valxor & 0xfe)
|
if (valxor & 0xfe)
|
||||||
w83877f_serial_handler(dev, 0);
|
w83877f_serial_handler(dev, 0);
|
||||||
break;
|
break;
|
||||||
case 0x25:
|
case 0x25:
|
||||||
if (valxor & 0xfe)
|
if (valxor & 0xfe)
|
||||||
w83877f_serial_handler(dev, 1);
|
w83877f_serial_handler(dev, 1);
|
||||||
break;
|
break;
|
||||||
case 0x27:
|
case 0x27:
|
||||||
if (valxor & 0xef)
|
if (valxor & 0xef)
|
||||||
w83877f_lpt_handler(dev);
|
w83877f_lpt_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 0x28:
|
case 0x28:
|
||||||
if (valxor & 0xf) {
|
if (valxor & 0xf) {
|
||||||
if ((dev->regs[0x28] & 0x0f) == 0)
|
if ((dev->regs[0x28] & 0x0f) == 0)
|
||||||
dev->regs[0x28] |= 0x03;
|
dev->regs[0x28] |= 0x03;
|
||||||
w83877f_serial_handler(dev, 1);
|
w83877f_serial_handler(dev, 1);
|
||||||
}
|
}
|
||||||
if (valxor & 0xf0) {
|
if (valxor & 0xf0) {
|
||||||
if ((dev->regs[0x28] & 0xf0) == 0)
|
if ((dev->regs[0x28] & 0xf0) == 0)
|
||||||
dev->regs[0x28] |= 0x40;
|
dev->regs[0x28] |= 0x40;
|
||||||
w83877f_serial_handler(dev, 0);
|
w83877f_serial_handler(dev, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
w83877f_read(uint16_t port, void *priv)
|
w83877f_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
w83877f_t *dev = (w83877f_t *) priv;
|
w83877f_t *dev = (w83877f_t *) priv;
|
||||||
uint8_t ret = 0xff;
|
uint8_t ret = 0xff;
|
||||||
|
|
||||||
if (dev->locked) {
|
if (dev->locked) {
|
||||||
if ((port == FDC_PRIMARY_ADDR) || (port == 0x251))
|
if ((port == FDC_PRIMARY_ADDR) || (port == 0x251))
|
||||||
ret = dev->cur_reg;
|
ret = dev->cur_reg;
|
||||||
else if ((port == 0x3f1) || (port == 0x252)) {
|
else if ((port == 0x3f1) || (port == 0x252)) {
|
||||||
if (dev->cur_reg == 7)
|
if (dev->cur_reg == 7)
|
||||||
ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6));
|
ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6));
|
||||||
else if ((dev->cur_reg >= 0x18) || !dev->rw_locked)
|
else if ((dev->cur_reg >= 0x18) || !dev->rw_locked)
|
||||||
ret = dev->regs[dev->cur_reg];
|
ret = dev->regs[dev->cur_reg];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83877f_reset(w83877f_t *dev)
|
w83877f_reset(w83877f_t *dev)
|
||||||
{
|
{
|
||||||
@@ -422,16 +414,15 @@ w83877f_reset(w83877f_t *dev)
|
|||||||
w83877f_serial_handler(dev, 1);
|
w83877f_serial_handler(dev, 1);
|
||||||
|
|
||||||
dev->base_address = FDC_PRIMARY_ADDR;
|
dev->base_address = FDC_PRIMARY_ADDR;
|
||||||
dev->key = 0x89;
|
dev->key = 0x89;
|
||||||
dev->key_times = 1;
|
dev->key_times = 1;
|
||||||
|
|
||||||
w83877f_remap(dev);
|
w83877f_remap(dev);
|
||||||
|
|
||||||
dev->locked = 0;
|
dev->locked = 0;
|
||||||
dev->rw_locked = 0;
|
dev->rw_locked = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83877f_close(void *priv)
|
w83877f_close(void *priv)
|
||||||
{
|
{
|
||||||
@@ -440,7 +431,6 @@ w83877f_close(void *priv)
|
|||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
w83877f_init(const device_t *info)
|
w83877f_init(const device_t *info)
|
||||||
{
|
{
|
||||||
@@ -460,57 +450,57 @@ w83877f_init(const device_t *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const device_t w83877f_device = {
|
const device_t w83877f_device = {
|
||||||
.name = "Winbond W83877F Super I/O",
|
.name = "Winbond W83877F Super I/O",
|
||||||
.internal_name = "w83877f",
|
.internal_name = "w83877f",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x0a05,
|
.local = 0x0a05,
|
||||||
.init = w83877f_init,
|
.init = w83877f_init,
|
||||||
.close = w83877f_close,
|
.close = w83877f_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t w83877f_president_device = {
|
const device_t w83877f_president_device = {
|
||||||
.name = "Winbond W83877F Super I/O (President)",
|
.name = "Winbond W83877F Super I/O (President)",
|
||||||
.internal_name = "w83877f_president",
|
.internal_name = "w83877f_president",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x0a04,
|
.local = 0x0a04,
|
||||||
.init = w83877f_init,
|
.init = w83877f_init,
|
||||||
.close = w83877f_close,
|
.close = w83877f_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t w83877tf_device = {
|
const device_t w83877tf_device = {
|
||||||
.name = "Winbond W83877TF Super I/O",
|
.name = "Winbond W83877TF Super I/O",
|
||||||
.internal_name = "w83877tf",
|
.internal_name = "w83877tf",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x0c04,
|
.local = 0x0c04,
|
||||||
.init = w83877f_init,
|
.init = w83877f_init,
|
||||||
.close = w83877f_close,
|
.close = w83877f_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t w83877tf_acorp_device = {
|
const device_t w83877tf_acorp_device = {
|
||||||
.name = "Winbond W83877TF Super I/O",
|
.name = "Winbond W83877TF Super I/O",
|
||||||
.internal_name = "w83877tf_acorp",
|
.internal_name = "w83877tf_acorp",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x0c05,
|
.local = 0x0c05,
|
||||||
.init = w83877f_init,
|
.init = w83877f_init,
|
||||||
.close = w83877f_close,
|
.close = w83877f_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,333 +34,331 @@
|
|||||||
#include <86box/fdc.h>
|
#include <86box/fdc.h>
|
||||||
#include <86box/sio.h>
|
#include <86box/sio.h>
|
||||||
|
|
||||||
|
#define HEFRAS (dev->regs[0x26] & 0x40)
|
||||||
#define HEFRAS (dev->regs[0x26] & 0x40)
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t id, tries,
|
uint8_t id, tries,
|
||||||
regs[48],
|
regs[48],
|
||||||
dev_regs[256][208];
|
dev_regs[256][208];
|
||||||
int locked, rw_locked,
|
int locked, rw_locked,
|
||||||
cur_reg, base_address,
|
cur_reg, base_address,
|
||||||
type, hefras;
|
type, hefras;
|
||||||
fdc_t *fdc;
|
fdc_t *fdc;
|
||||||
serial_t *uart[2];
|
serial_t *uart[2];
|
||||||
} w83977f_t;
|
} w83977f_t;
|
||||||
|
|
||||||
|
static int next_id = 0;
|
||||||
|
|
||||||
static int next_id = 0;
|
static void w83977f_write(uint16_t port, uint8_t val, void *priv);
|
||||||
|
static uint8_t w83977f_read(uint16_t port, void *priv);
|
||||||
|
|
||||||
static void w83977f_write(uint16_t port, uint8_t val, void *priv);
|
|
||||||
static uint8_t w83977f_read(uint16_t port, void *priv);
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83977f_remap(w83977f_t *dev)
|
w83977f_remap(w83977f_t *dev)
|
||||||
{
|
{
|
||||||
io_removehandler(FDC_PRIMARY_ADDR, 0x0002,
|
io_removehandler(FDC_PRIMARY_ADDR, 0x0002,
|
||||||
w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev);
|
w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev);
|
||||||
io_removehandler(FDC_SECONDARY_ADDR, 0x0002,
|
io_removehandler(FDC_SECONDARY_ADDR, 0x0002,
|
||||||
w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev);
|
w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev);
|
||||||
|
|
||||||
dev->base_address = (HEFRAS ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
|
dev->base_address = (HEFRAS ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR);
|
||||||
|
|
||||||
io_sethandler(dev->base_address, 0x0002,
|
io_sethandler(dev->base_address, 0x0002,
|
||||||
w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev);
|
w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
get_lpt_length(w83977f_t *dev)
|
get_lpt_length(w83977f_t *dev)
|
||||||
{
|
{
|
||||||
uint8_t length = 4;
|
uint8_t length = 4;
|
||||||
|
|
||||||
if (((dev->dev_regs[1][0xc0] & 0x07) != 0x00) && ((dev->dev_regs[1][0xc0] & 0x07) != 0x02) &&
|
if (((dev->dev_regs[1][0xc0] & 0x07) != 0x00) && ((dev->dev_regs[1][0xc0] & 0x07) != 0x02) && ((dev->dev_regs[1][0xc0] & 0x07) != 0x04))
|
||||||
((dev->dev_regs[1][0xc0] & 0x07) != 0x04))
|
length = 8;
|
||||||
length = 8;
|
|
||||||
|
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83977f_fdc_handler(w83977f_t *dev)
|
w83977f_fdc_handler(w83977f_t *dev)
|
||||||
{
|
{
|
||||||
uint16_t io_base = (dev->dev_regs[0][0x30] << 8) | dev->dev_regs[0][0x31];
|
uint16_t io_base = (dev->dev_regs[0][0x30] << 8) | dev->dev_regs[0][0x31];
|
||||||
|
|
||||||
if (dev->id == 1)
|
if (dev->id == 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fdc_remove(dev->fdc);
|
fdc_remove(dev->fdc);
|
||||||
|
|
||||||
if ((dev->dev_regs[0][0x00] & 0x01) && (dev->regs[0x22] & 0x01) && (io_base >= 0x100) && (io_base <= 0xff8))
|
if ((dev->dev_regs[0][0x00] & 0x01) && (dev->regs[0x22] & 0x01) && (io_base >= 0x100) && (io_base <= 0xff8))
|
||||||
fdc_set_base(dev->fdc, io_base);
|
fdc_set_base(dev->fdc, io_base);
|
||||||
|
|
||||||
fdc_set_irq(dev->fdc, dev->dev_regs[0][0x40] & 0x0f);
|
fdc_set_irq(dev->fdc, dev->dev_regs[0][0x40] & 0x0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83977f_lpt_handler(w83977f_t *dev)
|
w83977f_lpt_handler(w83977f_t *dev)
|
||||||
{
|
{
|
||||||
uint16_t io_mask, io_base = (dev->dev_regs[1][0x30] << 8) | dev->dev_regs[1][0x31];
|
uint16_t io_mask, io_base = (dev->dev_regs[1][0x30] << 8) | dev->dev_regs[1][0x31];
|
||||||
int io_len = get_lpt_length(dev);
|
int io_len = get_lpt_length(dev);
|
||||||
io_base &= (0xff8 | io_len);
|
io_base &= (0xff8 | io_len);
|
||||||
io_mask = 0xffc;
|
io_mask = 0xffc;
|
||||||
if (io_len == 8)
|
if (io_len == 8)
|
||||||
io_mask = 0xff8;
|
io_mask = 0xff8;
|
||||||
|
|
||||||
if (dev->id == 1) {
|
if (dev->id == 1) {
|
||||||
lpt2_remove();
|
lpt2_remove();
|
||||||
|
|
||||||
if ((dev->dev_regs[1][0x00] & 0x01) && (dev->regs[0x22] & 0x08) && (io_base >= 0x100) && (io_base <= io_mask))
|
if ((dev->dev_regs[1][0x00] & 0x01) && (dev->regs[0x22] & 0x08) && (io_base >= 0x100) && (io_base <= io_mask))
|
||||||
lpt2_init(io_base);
|
lpt2_init(io_base);
|
||||||
|
|
||||||
lpt2_irq(dev->dev_regs[1][0x40] & 0x0f);
|
lpt2_irq(dev->dev_regs[1][0x40] & 0x0f);
|
||||||
} else {
|
} else {
|
||||||
lpt1_remove();
|
lpt1_remove();
|
||||||
|
|
||||||
if ((dev->dev_regs[1][0x00] & 0x01) && (dev->regs[0x22] & 0x08) && (io_base >= 0x100) && (io_base <= io_mask))
|
if ((dev->dev_regs[1][0x00] & 0x01) && (dev->regs[0x22] & 0x08) && (io_base >= 0x100) && (io_base <= io_mask))
|
||||||
lpt1_init(io_base);
|
lpt1_init(io_base);
|
||||||
|
|
||||||
lpt1_irq(dev->dev_regs[1][0x40] & 0x0f);
|
lpt1_irq(dev->dev_regs[1][0x40] & 0x0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83977f_serial_handler(w83977f_t *dev, int uart)
|
w83977f_serial_handler(w83977f_t *dev, int uart)
|
||||||
{
|
{
|
||||||
uint16_t io_base = (dev->dev_regs[2 + uart][0x30] << 8) | dev->dev_regs[2 + uart][0x31];
|
uint16_t io_base = (dev->dev_regs[2 + uart][0x30] << 8) | dev->dev_regs[2 + uart][0x31];
|
||||||
double clock_src = 24000000.0 / 13.0;
|
double clock_src = 24000000.0 / 13.0;
|
||||||
|
|
||||||
serial_remove(dev->uart[uart]);
|
serial_remove(dev->uart[uart]);
|
||||||
|
|
||||||
if ((dev->dev_regs[2 + uart][0x00] & 0x01) && (dev->regs[0x22] & (0x10 << uart)) && (io_base >= 0x100) && (io_base <= 0xff8))
|
if ((dev->dev_regs[2 + uart][0x00] & 0x01) && (dev->regs[0x22] & (0x10 << uart)) && (io_base >= 0x100) && (io_base <= 0xff8))
|
||||||
serial_setup(dev->uart[uart], io_base, dev->dev_regs[2 + uart][0x40] & 0x0f);
|
serial_setup(dev->uart[uart], io_base, dev->dev_regs[2 + uart][0x40] & 0x0f);
|
||||||
|
|
||||||
switch (dev->dev_regs[2 + uart][0xc0] & 0x03) {
|
switch (dev->dev_regs[2 + uart][0xc0] & 0x03) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
clock_src = 24000000.0 / 13.0;
|
clock_src = 24000000.0 / 13.0;
|
||||||
break;
|
break;
|
||||||
case 0x01:
|
case 0x01:
|
||||||
clock_src = 24000000.0 / 12.0;
|
clock_src = 24000000.0 / 12.0;
|
||||||
break;
|
break;
|
||||||
case 0x02:
|
case 0x02:
|
||||||
clock_src = 24000000.0 / 1.0;
|
clock_src = 24000000.0 / 1.0;
|
||||||
break;
|
break;
|
||||||
case 0x03:
|
case 0x03:
|
||||||
clock_src = 24000000.0 / 1.625;
|
clock_src = 24000000.0 / 1.625;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
serial_set_clock_src(dev->uart[uart], clock_src);
|
serial_set_clock_src(dev->uart[uart], clock_src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83977f_write(uint16_t port, uint8_t val, void *priv)
|
w83977f_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
w83977f_t *dev = (w83977f_t *) priv;
|
w83977f_t *dev = (w83977f_t *) priv;
|
||||||
uint8_t index = (port & 1) ? 0 : 1;
|
uint8_t index = (port & 1) ? 0 : 1;
|
||||||
uint8_t valxor = 0;
|
uint8_t valxor = 0;
|
||||||
uint8_t ld = dev->regs[7];
|
uint8_t ld = dev->regs[7];
|
||||||
|
|
||||||
if (index) {
|
if (index) {
|
||||||
if ((val == 0x87) && !dev->locked) {
|
if ((val == 0x87) && !dev->locked) {
|
||||||
if (dev->tries) {
|
if (dev->tries) {
|
||||||
dev->locked = 1;
|
dev->locked = 1;
|
||||||
dev->tries = 0;
|
dev->tries = 0;
|
||||||
} else
|
} else
|
||||||
dev->tries++;
|
dev->tries++;
|
||||||
} else {
|
} else {
|
||||||
if (dev->locked) {
|
if (dev->locked) {
|
||||||
if (val == 0xaa)
|
if (val == 0xaa)
|
||||||
dev->locked = 0;
|
dev->locked = 0;
|
||||||
else
|
else
|
||||||
dev->cur_reg = val;
|
dev->cur_reg = val;
|
||||||
} else {
|
} else {
|
||||||
if (dev->tries)
|
if (dev->tries)
|
||||||
dev->tries = 0;
|
dev->tries = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (dev->locked) {
|
if (dev->locked) {
|
||||||
if (dev->rw_locked)
|
if (dev->rw_locked)
|
||||||
return;
|
return;
|
||||||
if (dev->cur_reg >= 0x30) {
|
if (dev->cur_reg >= 0x30) {
|
||||||
valxor = val ^ dev->dev_regs[ld][dev->cur_reg - 0x30];
|
valxor = val ^ dev->dev_regs[ld][dev->cur_reg - 0x30];
|
||||||
dev->dev_regs[ld][dev->cur_reg - 0x30] = val;
|
dev->dev_regs[ld][dev->cur_reg - 0x30] = val;
|
||||||
} else {
|
} else {
|
||||||
valxor = val ^ dev->regs[dev->cur_reg];
|
valxor = val ^ dev->regs[dev->cur_reg];
|
||||||
dev->regs[dev->cur_reg] = val;
|
dev->regs[dev->cur_reg] = val;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (dev->cur_reg) {
|
switch (dev->cur_reg) {
|
||||||
case 0x02:
|
case 0x02:
|
||||||
/* if (valxor & 0x02)
|
/* if (valxor & 0x02)
|
||||||
softresetx86(); */
|
softresetx86(); */
|
||||||
break;
|
break;
|
||||||
case 0x22:
|
case 0x22:
|
||||||
if (valxor & 0x20)
|
if (valxor & 0x20)
|
||||||
w83977f_serial_handler(dev, 1);
|
w83977f_serial_handler(dev, 1);
|
||||||
if (valxor & 0x10)
|
if (valxor & 0x10)
|
||||||
w83977f_serial_handler(dev, 0);
|
w83977f_serial_handler(dev, 0);
|
||||||
if (valxor & 0x08)
|
if (valxor & 0x08)
|
||||||
w83977f_lpt_handler(dev);
|
w83977f_lpt_handler(dev);
|
||||||
if (valxor & 0x01)
|
if (valxor & 0x01)
|
||||||
w83977f_fdc_handler(dev);
|
w83977f_fdc_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 0x26:
|
case 0x26:
|
||||||
if (valxor & 0x40)
|
if (valxor & 0x40)
|
||||||
w83977f_remap(dev);
|
w83977f_remap(dev);
|
||||||
if (valxor & 0x20)
|
if (valxor & 0x20)
|
||||||
dev->rw_locked = (val & 0x20) ? 1 : 0;
|
dev->rw_locked = (val & 0x20) ? 1 : 0;
|
||||||
break;
|
break;
|
||||||
case 0x30:
|
case 0x30:
|
||||||
if (valxor & 0x01) switch (ld) {
|
if (valxor & 0x01)
|
||||||
case 0x00:
|
switch (ld) {
|
||||||
w83977f_fdc_handler(dev);
|
case 0x00:
|
||||||
break;
|
w83977f_fdc_handler(dev);
|
||||||
case 0x01:
|
break;
|
||||||
w83977f_lpt_handler(dev);
|
case 0x01:
|
||||||
break;
|
w83977f_lpt_handler(dev);
|
||||||
case 0x02: case 0x03:
|
break;
|
||||||
w83977f_serial_handler(dev, ld - 2);
|
case 0x02:
|
||||||
break;
|
case 0x03:
|
||||||
}
|
w83977f_serial_handler(dev, ld - 2);
|
||||||
break;
|
break;
|
||||||
case 0x60: case 0x61:
|
}
|
||||||
if (valxor & 0xff) switch (ld) {
|
break;
|
||||||
case 0x00:
|
case 0x60:
|
||||||
w83977f_fdc_handler(dev);
|
case 0x61:
|
||||||
break;
|
if (valxor & 0xff)
|
||||||
case 0x01:
|
switch (ld) {
|
||||||
w83977f_lpt_handler(dev);
|
case 0x00:
|
||||||
break;
|
w83977f_fdc_handler(dev);
|
||||||
case 0x02: case 0x03:
|
break;
|
||||||
w83977f_serial_handler(dev, ld - 2);
|
case 0x01:
|
||||||
break;
|
w83977f_lpt_handler(dev);
|
||||||
}
|
break;
|
||||||
break;
|
case 0x02:
|
||||||
case 0x70:
|
case 0x03:
|
||||||
if (valxor & 0x0f) switch (ld) {
|
w83977f_serial_handler(dev, ld - 2);
|
||||||
case 0x00:
|
break;
|
||||||
w83977f_fdc_handler(dev);
|
}
|
||||||
break;
|
break;
|
||||||
case 0x01:
|
case 0x70:
|
||||||
w83977f_lpt_handler(dev);
|
if (valxor & 0x0f)
|
||||||
break;
|
switch (ld) {
|
||||||
case 0x02: case 0x03:
|
case 0x00:
|
||||||
w83977f_serial_handler(dev, ld - 2);
|
w83977f_fdc_handler(dev);
|
||||||
break;
|
break;
|
||||||
}
|
case 0x01:
|
||||||
break;
|
w83977f_lpt_handler(dev);
|
||||||
case 0xf0:
|
break;
|
||||||
switch (ld) {
|
case 0x02:
|
||||||
case 0x00:
|
case 0x03:
|
||||||
if (dev->id == 1)
|
w83977f_serial_handler(dev, ld - 2);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0xf0:
|
||||||
|
switch (ld) {
|
||||||
|
case 0x00:
|
||||||
|
if (dev->id == 1)
|
||||||
|
break;
|
||||||
|
|
||||||
if (!dev->id && (valxor & 0x20))
|
if (!dev->id && (valxor & 0x20))
|
||||||
fdc_update_drv2en(dev->fdc, (val & 0x20) ? 0 : 1);
|
fdc_update_drv2en(dev->fdc, (val & 0x20) ? 0 : 1);
|
||||||
if (!dev->id && (valxor & 0x10))
|
if (!dev->id && (valxor & 0x10))
|
||||||
fdc_set_swap(dev->fdc, (val & 0x10) ? 1 : 0);
|
fdc_set_swap(dev->fdc, (val & 0x10) ? 1 : 0);
|
||||||
if (!dev->id && (valxor & 0x01))
|
if (!dev->id && (valxor & 0x01))
|
||||||
fdc_update_enh_mode(dev->fdc, (val & 0x01) ? 1 : 0);
|
fdc_update_enh_mode(dev->fdc, (val & 0x01) ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
case 0x01:
|
case 0x01:
|
||||||
if (valxor & 0x07)
|
if (valxor & 0x07)
|
||||||
w83977f_lpt_handler(dev);
|
w83977f_lpt_handler(dev);
|
||||||
break;
|
break;
|
||||||
case 0x02: case 0x03:
|
case 0x02:
|
||||||
if (valxor & 0x03)
|
case 0x03:
|
||||||
w83977f_serial_handler(dev, ld - 2);
|
if (valxor & 0x03)
|
||||||
break;
|
w83977f_serial_handler(dev, ld - 2);
|
||||||
}
|
break;
|
||||||
break;
|
}
|
||||||
case 0xf1:
|
break;
|
||||||
switch (ld) {
|
case 0xf1:
|
||||||
case 0x00:
|
switch (ld) {
|
||||||
if (dev->id == 1)
|
case 0x00:
|
||||||
break;
|
if (dev->id == 1)
|
||||||
|
break;
|
||||||
|
|
||||||
if (!dev->id && (valxor & 0xc0))
|
if (!dev->id && (valxor & 0xc0))
|
||||||
fdc_update_boot_drive(dev->fdc, (val & 0xc0) >> 6);
|
fdc_update_boot_drive(dev->fdc, (val & 0xc0) >> 6);
|
||||||
if (!dev->id && (valxor & 0x0c))
|
if (!dev->id && (valxor & 0x0c))
|
||||||
fdc_update_densel_force(dev->fdc, (val & 0x0c) >> 2);
|
fdc_update_densel_force(dev->fdc, (val & 0x0c) >> 2);
|
||||||
if (!dev->id && (valxor & 0x02))
|
if (!dev->id && (valxor & 0x02))
|
||||||
fdc_set_diswr(dev->fdc, (val & 0x02) ? 1 : 0);
|
fdc_set_diswr(dev->fdc, (val & 0x02) ? 1 : 0);
|
||||||
if (!dev->id && (valxor & 0x01))
|
if (!dev->id && (valxor & 0x01))
|
||||||
fdc_set_swwp(dev->fdc, (val & 0x01) ? 1 : 0);
|
fdc_set_swwp(dev->fdc, (val & 0x01) ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xf2:
|
case 0xf2:
|
||||||
switch (ld) {
|
switch (ld) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
if (dev->id == 1)
|
if (dev->id == 1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!dev->id && (valxor & 0xc0))
|
if (!dev->id && (valxor & 0xc0))
|
||||||
fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6);
|
fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6);
|
||||||
if (!dev->id && (valxor & 0x30))
|
if (!dev->id && (valxor & 0x30))
|
||||||
fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4);
|
fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4);
|
||||||
if (!dev->id && (valxor & 0x0c))
|
if (!dev->id && (valxor & 0x0c))
|
||||||
fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2);
|
fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2);
|
||||||
if (!dev->id && (valxor & 0x03))
|
if (!dev->id && (valxor & 0x03))
|
||||||
fdc_update_rwc(dev->fdc, 0, val & 0x03);
|
fdc_update_rwc(dev->fdc, 0, val & 0x03);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xf4: case 0xf5: case 0xf6: case 0xf7:
|
case 0xf4:
|
||||||
switch (ld) {
|
case 0xf5:
|
||||||
case 0x00:
|
case 0xf6:
|
||||||
if (dev->id == 1)
|
case 0xf7:
|
||||||
break;
|
switch (ld) {
|
||||||
|
case 0x00:
|
||||||
|
if (dev->id == 1)
|
||||||
|
break;
|
||||||
|
|
||||||
if (!dev->id && (valxor & 0x18))
|
if (!dev->id && (valxor & 0x18))
|
||||||
fdc_update_drvrate(dev->fdc, dev->cur_reg & 0x03, (val & 0x18) >> 3);
|
fdc_update_drvrate(dev->fdc, dev->cur_reg & 0x03, (val & 0x18) >> 3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
w83977f_read(uint16_t port, void *priv)
|
w83977f_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
w83977f_t *dev = (w83977f_t *) priv;
|
w83977f_t *dev = (w83977f_t *) priv;
|
||||||
uint8_t ret = 0xff;
|
uint8_t ret = 0xff;
|
||||||
uint8_t index = (port & 1) ? 0 : 1;
|
uint8_t index = (port & 1) ? 0 : 1;
|
||||||
uint8_t ld = dev->regs[7];
|
uint8_t ld = dev->regs[7];
|
||||||
|
|
||||||
if (dev->locked) {
|
if (dev->locked) {
|
||||||
if (index)
|
if (index)
|
||||||
ret = dev->cur_reg;
|
ret = dev->cur_reg;
|
||||||
else {
|
else {
|
||||||
if (!dev->rw_locked) {
|
if (!dev->rw_locked) {
|
||||||
if (!dev->id && ((dev->cur_reg == 0xf2) && (ld == 0x00)))
|
if (!dev->id && ((dev->cur_reg == 0xf2) && (ld == 0x00)))
|
||||||
ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6));
|
ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6));
|
||||||
else if (dev->cur_reg >= 0x30)
|
else if (dev->cur_reg >= 0x30)
|
||||||
ret = dev->dev_regs[ld][dev->cur_reg - 0x30];
|
ret = dev->dev_regs[ld][dev->cur_reg - 0x30];
|
||||||
else
|
else
|
||||||
ret = dev->regs[dev->cur_reg];
|
ret = dev->regs[dev->cur_reg];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83977f_reset(w83977f_t *dev)
|
w83977f_reset(w83977f_t *dev)
|
||||||
{
|
{
|
||||||
@@ -368,14 +366,14 @@ w83977f_reset(w83977f_t *dev)
|
|||||||
|
|
||||||
memset(dev->regs, 0, 48);
|
memset(dev->regs, 0, 48);
|
||||||
for (i = 0; i < 256; i++)
|
for (i = 0; i < 256; i++)
|
||||||
memset(dev->dev_regs[i], 0, 208);
|
memset(dev->dev_regs[i], 0, 208);
|
||||||
|
|
||||||
if (dev->type < 2) {
|
if (dev->type < 2) {
|
||||||
dev->regs[0x20] = 0x97;
|
dev->regs[0x20] = 0x97;
|
||||||
dev->regs[0x21] = dev->type ? 0x73 : 0x71;
|
dev->regs[0x21] = dev->type ? 0x73 : 0x71;
|
||||||
} else {
|
} else {
|
||||||
dev->regs[0x20] = 0x52;
|
dev->regs[0x20] = 0x52;
|
||||||
dev->regs[0x21] = 0xf0;
|
dev->regs[0x21] = 0xf0;
|
||||||
}
|
}
|
||||||
dev->regs[0x22] = 0xff;
|
dev->regs[0x22] = 0xff;
|
||||||
dev->regs[0x24] = dev->type ? 0x84 : 0xa4;
|
dev->regs[0x24] = dev->type ? 0x84 : 0xa4;
|
||||||
@@ -385,137 +383,159 @@ w83977f_reset(w83977f_t *dev)
|
|||||||
/* Logical Device 0 (FDC) */
|
/* Logical Device 0 (FDC) */
|
||||||
dev->dev_regs[0][0x00] = 0x01;
|
dev->dev_regs[0][0x00] = 0x01;
|
||||||
if (!dev->type)
|
if (!dev->type)
|
||||||
dev->dev_regs[0][0x01] = 0x02;
|
dev->dev_regs[0][0x01] = 0x02;
|
||||||
if (next_id == 1) {
|
if (next_id == 1) {
|
||||||
dev->dev_regs[0][0x30] = 0x03; dev->dev_regs[0][0x31] = 0x70;
|
dev->dev_regs[0][0x30] = 0x03;
|
||||||
|
dev->dev_regs[0][0x31] = 0x70;
|
||||||
} else {
|
} else {
|
||||||
dev->dev_regs[0][0x30] = 0x03; dev->dev_regs[0][0x31] = 0xf0;
|
dev->dev_regs[0][0x30] = 0x03;
|
||||||
|
dev->dev_regs[0][0x31] = 0xf0;
|
||||||
}
|
}
|
||||||
dev->dev_regs[0][0x40] = 0x06;
|
dev->dev_regs[0][0x40] = 0x06;
|
||||||
if (!dev->type)
|
if (!dev->type)
|
||||||
dev->dev_regs[0][0x41] = 0x02; /* Read-only */
|
dev->dev_regs[0][0x41] = 0x02; /* Read-only */
|
||||||
dev->dev_regs[0][0x44] = 0x02;
|
dev->dev_regs[0][0x44] = 0x02;
|
||||||
dev->dev_regs[0][0xc0] = 0x0e;
|
dev->dev_regs[0][0xc0] = 0x0e;
|
||||||
|
|
||||||
/* Logical Device 1 (Parallel Port) */
|
/* Logical Device 1 (Parallel Port) */
|
||||||
dev->dev_regs[1][0x00] = 0x01;
|
dev->dev_regs[1][0x00] = 0x01;
|
||||||
if (!dev->type)
|
if (!dev->type)
|
||||||
dev->dev_regs[1][0x01] = 0x02;
|
dev->dev_regs[1][0x01] = 0x02;
|
||||||
if (next_id == 1) {
|
if (next_id == 1) {
|
||||||
dev->dev_regs[1][0x30] = 0x02; dev->dev_regs[1][0x31] = 0x78;
|
dev->dev_regs[1][0x30] = 0x02;
|
||||||
dev->dev_regs[1][0x40] = 0x05;
|
dev->dev_regs[1][0x31] = 0x78;
|
||||||
|
dev->dev_regs[1][0x40] = 0x05;
|
||||||
} else {
|
} else {
|
||||||
dev->dev_regs[1][0x30] = 0x03; dev->dev_regs[1][0x31] = 0x78;
|
dev->dev_regs[1][0x30] = 0x03;
|
||||||
dev->dev_regs[1][0x40] = 0x07;
|
dev->dev_regs[1][0x31] = 0x78;
|
||||||
|
dev->dev_regs[1][0x40] = 0x07;
|
||||||
}
|
}
|
||||||
if (!dev->type)
|
if (!dev->type)
|
||||||
dev->dev_regs[1][0x41] = 0x01 /*0x02*/; /* Read-only */
|
dev->dev_regs[1][0x41] = 0x01 /*0x02*/; /* Read-only */
|
||||||
dev->dev_regs[1][0x44] = 0x04;
|
dev->dev_regs[1][0x44] = 0x04;
|
||||||
dev->dev_regs[1][0xc0] = 0x3c; /* The datasheet says default is 3f, but also default is printer mode. */
|
dev->dev_regs[1][0xc0] = 0x3c; /* The datasheet says default is 3f, but also default is printer mode. */
|
||||||
|
|
||||||
/* Logical Device 2 (UART A) */
|
/* Logical Device 2 (UART A) */
|
||||||
dev->dev_regs[2][0x00] = 0x01;
|
dev->dev_regs[2][0x00] = 0x01;
|
||||||
if (!dev->type)
|
if (!dev->type)
|
||||||
dev->dev_regs[2][0x01] = 0x02;
|
dev->dev_regs[2][0x01] = 0x02;
|
||||||
if (next_id == 1) {
|
if (next_id == 1) {
|
||||||
dev->dev_regs[2][0x30] = 0x03; dev->dev_regs[2][0x31] = 0xe8;
|
dev->dev_regs[2][0x30] = 0x03;
|
||||||
|
dev->dev_regs[2][0x31] = 0xe8;
|
||||||
} else {
|
} else {
|
||||||
dev->dev_regs[2][0x30] = 0x03; dev->dev_regs[2][0x31] = 0xf8;
|
dev->dev_regs[2][0x30] = 0x03;
|
||||||
|
dev->dev_regs[2][0x31] = 0xf8;
|
||||||
}
|
}
|
||||||
dev->dev_regs[2][0x40] = 0x04;
|
dev->dev_regs[2][0x40] = 0x04;
|
||||||
if (!dev->type)
|
if (!dev->type)
|
||||||
dev->dev_regs[2][0x41] = 0x02; /* Read-only */
|
dev->dev_regs[2][0x41] = 0x02; /* Read-only */
|
||||||
|
|
||||||
/* Logical Device 3 (UART B) */
|
/* Logical Device 3 (UART B) */
|
||||||
dev->dev_regs[3][0x00] = 0x01;
|
dev->dev_regs[3][0x00] = 0x01;
|
||||||
if (!dev->type)
|
if (!dev->type)
|
||||||
dev->dev_regs[3][0x01] = 0x02;
|
dev->dev_regs[3][0x01] = 0x02;
|
||||||
if (next_id == 1) {
|
if (next_id == 1) {
|
||||||
dev->dev_regs[3][0x30] = 0x02; dev->dev_regs[3][0x31] = 0xe8;
|
dev->dev_regs[3][0x30] = 0x02;
|
||||||
|
dev->dev_regs[3][0x31] = 0xe8;
|
||||||
} else {
|
} else {
|
||||||
dev->dev_regs[3][0x30] = 0x02; dev->dev_regs[3][0x31] = 0xf8;
|
dev->dev_regs[3][0x30] = 0x02;
|
||||||
|
dev->dev_regs[3][0x31] = 0xf8;
|
||||||
}
|
}
|
||||||
dev->dev_regs[3][0x40] = 0x03;
|
dev->dev_regs[3][0x40] = 0x03;
|
||||||
if (!dev->type)
|
if (!dev->type)
|
||||||
dev->dev_regs[3][0x41] = 0x02; /* Read-only */
|
dev->dev_regs[3][0x41] = 0x02; /* Read-only */
|
||||||
|
|
||||||
/* Logical Device 4 (RTC) */
|
/* Logical Device 4 (RTC) */
|
||||||
if (!dev->type) {
|
if (!dev->type) {
|
||||||
dev->dev_regs[4][0x00] = 0x01;
|
dev->dev_regs[4][0x00] = 0x01;
|
||||||
dev->dev_regs[4][0x01] = 0x02;
|
dev->dev_regs[4][0x01] = 0x02;
|
||||||
dev->dev_regs[4][0x30] = 0x00; dev->dev_regs[4][0x31] = 0x70;
|
dev->dev_regs[4][0x30] = 0x00;
|
||||||
dev->dev_regs[4][0x40] = 0x08;
|
dev->dev_regs[4][0x31] = 0x70;
|
||||||
dev->dev_regs[4][0x41] = 0x02; /* Read-only */
|
dev->dev_regs[4][0x40] = 0x08;
|
||||||
|
dev->dev_regs[4][0x41] = 0x02; /* Read-only */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Logical Device 5 (KBC) */
|
/* Logical Device 5 (KBC) */
|
||||||
dev->dev_regs[5][0x00] = 0x01;
|
dev->dev_regs[5][0x00] = 0x01;
|
||||||
if (!dev->type)
|
if (!dev->type)
|
||||||
dev->dev_regs[5][0x01] = 0x02;
|
dev->dev_regs[5][0x01] = 0x02;
|
||||||
dev->dev_regs[5][0x30] = 0x00; dev->dev_regs[5][0x31] = 0x60;
|
dev->dev_regs[5][0x30] = 0x00;
|
||||||
dev->dev_regs[5][0x32] = 0x00; dev->dev_regs[5][0x33] = 0x64;
|
dev->dev_regs[5][0x31] = 0x60;
|
||||||
|
dev->dev_regs[5][0x32] = 0x00;
|
||||||
|
dev->dev_regs[5][0x33] = 0x64;
|
||||||
dev->dev_regs[5][0x40] = 0x01;
|
dev->dev_regs[5][0x40] = 0x01;
|
||||||
if (!dev->type)
|
if (!dev->type)
|
||||||
dev->dev_regs[5][0x41] = 0x02; /* Read-only */
|
dev->dev_regs[5][0x41] = 0x02; /* Read-only */
|
||||||
dev->dev_regs[5][0x42] = 0x0c;
|
dev->dev_regs[5][0x42] = 0x0c;
|
||||||
if (!dev->type)
|
if (!dev->type)
|
||||||
dev->dev_regs[5][0x43] = 0x02; /* Read-only? */
|
dev->dev_regs[5][0x43] = 0x02; /* Read-only? */
|
||||||
dev->dev_regs[5][0xc0] = dev->type ? 0x83 : 0x40;
|
dev->dev_regs[5][0xc0] = dev->type ? 0x83 : 0x40;
|
||||||
|
|
||||||
/* Logical Device 6 (IR) = UART C */
|
/* Logical Device 6 (IR) = UART C */
|
||||||
if (!dev->type) {
|
if (!dev->type) {
|
||||||
dev->dev_regs[6][0x01] = 0x02;
|
dev->dev_regs[6][0x01] = 0x02;
|
||||||
dev->dev_regs[6][0x41] = 0x02; /* Read-only */
|
dev->dev_regs[6][0x41] = 0x02; /* Read-only */
|
||||||
dev->dev_regs[6][0x44] = 0x04;
|
dev->dev_regs[6][0x44] = 0x04;
|
||||||
dev->dev_regs[6][0x45] = 0x04;
|
dev->dev_regs[6][0x45] = 0x04;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Logical Device 7 (Auxiliary I/O Part I) */
|
/* Logical Device 7 (Auxiliary I/O Part I) */
|
||||||
if (!dev->type)
|
if (!dev->type)
|
||||||
dev->dev_regs[7][0x01] = 0x02;
|
dev->dev_regs[7][0x01] = 0x02;
|
||||||
if (!dev->type)
|
if (!dev->type)
|
||||||
dev->dev_regs[7][0x41] = 0x02; /* Read-only */
|
dev->dev_regs[7][0x41] = 0x02; /* Read-only */
|
||||||
if (!dev->type)
|
if (!dev->type)
|
||||||
dev->dev_regs[7][0x43] = 0x02; /* Read-only? */
|
dev->dev_regs[7][0x43] = 0x02; /* Read-only? */
|
||||||
dev->dev_regs[7][0xb0] = 0x01; dev->dev_regs[7][0xb1] = 0x01;
|
dev->dev_regs[7][0xb0] = 0x01;
|
||||||
dev->dev_regs[7][0xb2] = 0x01; dev->dev_regs[7][0xb3] = 0x01;
|
dev->dev_regs[7][0xb1] = 0x01;
|
||||||
dev->dev_regs[7][0xb4] = 0x01; dev->dev_regs[7][0xb5] = 0x01;
|
dev->dev_regs[7][0xb2] = 0x01;
|
||||||
|
dev->dev_regs[7][0xb3] = 0x01;
|
||||||
|
dev->dev_regs[7][0xb4] = 0x01;
|
||||||
|
dev->dev_regs[7][0xb5] = 0x01;
|
||||||
dev->dev_regs[7][0xb6] = 0x01;
|
dev->dev_regs[7][0xb6] = 0x01;
|
||||||
if (dev->type)
|
if (dev->type)
|
||||||
dev->dev_regs[7][0xb7] = 0x01;
|
dev->dev_regs[7][0xb7] = 0x01;
|
||||||
|
|
||||||
/* Logical Device 8 (Auxiliary I/O Part II) */
|
/* Logical Device 8 (Auxiliary I/O Part II) */
|
||||||
if (!dev->type)
|
if (!dev->type)
|
||||||
dev->dev_regs[8][0x01] = 0x02;
|
dev->dev_regs[8][0x01] = 0x02;
|
||||||
if (!dev->type)
|
if (!dev->type)
|
||||||
dev->dev_regs[8][0x41] = 0x02; /* Read-only */
|
dev->dev_regs[8][0x41] = 0x02; /* Read-only */
|
||||||
if (!dev->type)
|
if (!dev->type)
|
||||||
dev->dev_regs[8][0x43] = 0x02; /* Read-only? */
|
dev->dev_regs[8][0x43] = 0x02; /* Read-only? */
|
||||||
dev->dev_regs[8][0xb8] = 0x01; dev->dev_regs[8][0xb9] = 0x01;
|
dev->dev_regs[8][0xb8] = 0x01;
|
||||||
dev->dev_regs[8][0xba] = 0x01; dev->dev_regs[8][0xbb] = 0x01;
|
dev->dev_regs[8][0xb9] = 0x01;
|
||||||
dev->dev_regs[8][0xbc] = 0x01; dev->dev_regs[8][0xbd] = 0x01;
|
dev->dev_regs[8][0xba] = 0x01;
|
||||||
dev->dev_regs[8][0xbe] = 0x01; dev->dev_regs[8][0xbf] = 0x01;
|
dev->dev_regs[8][0xbb] = 0x01;
|
||||||
|
dev->dev_regs[8][0xbc] = 0x01;
|
||||||
|
dev->dev_regs[8][0xbd] = 0x01;
|
||||||
|
dev->dev_regs[8][0xbe] = 0x01;
|
||||||
|
dev->dev_regs[8][0xbf] = 0x01;
|
||||||
|
|
||||||
/* Logical Device 9 (Auxiliary I/O Part III) */
|
/* Logical Device 9 (Auxiliary I/O Part III) */
|
||||||
if (dev->type) {
|
if (dev->type) {
|
||||||
dev->dev_regs[9][0xb0] = 0x01; dev->dev_regs[9][0xb1] = 0x01;
|
dev->dev_regs[9][0xb0] = 0x01;
|
||||||
dev->dev_regs[9][0xb2] = 0x01; dev->dev_regs[9][0xb3] = 0x01;
|
dev->dev_regs[9][0xb1] = 0x01;
|
||||||
dev->dev_regs[9][0xb4] = 0x01; dev->dev_regs[9][0xb5] = 0x01;
|
dev->dev_regs[9][0xb2] = 0x01;
|
||||||
dev->dev_regs[9][0xb6] = 0x01; dev->dev_regs[9][0xb7] = 0x01;
|
dev->dev_regs[9][0xb3] = 0x01;
|
||||||
|
dev->dev_regs[9][0xb4] = 0x01;
|
||||||
|
dev->dev_regs[9][0xb5] = 0x01;
|
||||||
|
dev->dev_regs[9][0xb6] = 0x01;
|
||||||
|
dev->dev_regs[9][0xb7] = 0x01;
|
||||||
|
|
||||||
dev->dev_regs[10][0xc0] = 0x8f;
|
dev->dev_regs[10][0xc0] = 0x8f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->id == 1) {
|
if (dev->id == 1) {
|
||||||
serial_setup(dev->uart[0], COM3_ADDR, COM3_IRQ);
|
serial_setup(dev->uart[0], COM3_ADDR, COM3_IRQ);
|
||||||
serial_setup(dev->uart[1], COM4_ADDR, COM4_IRQ);
|
serial_setup(dev->uart[1], COM4_ADDR, COM4_IRQ);
|
||||||
} else {
|
} else {
|
||||||
fdc_reset(dev->fdc);
|
fdc_reset(dev->fdc);
|
||||||
|
|
||||||
serial_setup(dev->uart[0], COM1_ADDR, COM1_IRQ);
|
serial_setup(dev->uart[0], COM1_ADDR, COM1_IRQ);
|
||||||
serial_setup(dev->uart[1], COM2_ADDR, COM2_IRQ);
|
serial_setup(dev->uart[1], COM2_ADDR, COM2_IRQ);
|
||||||
|
|
||||||
w83977f_fdc_handler(dev);
|
w83977f_fdc_handler(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
w83977f_lpt_handler(dev);
|
w83977f_lpt_handler(dev);
|
||||||
@@ -524,11 +544,10 @@ w83977f_reset(w83977f_t *dev)
|
|||||||
|
|
||||||
w83977f_remap(dev);
|
w83977f_remap(dev);
|
||||||
|
|
||||||
dev->locked = 0;
|
dev->locked = 0;
|
||||||
dev->rw_locked = 0;
|
dev->rw_locked = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w83977f_close(void *priv)
|
w83977f_close(void *priv)
|
||||||
{
|
{
|
||||||
@@ -539,22 +558,21 @@ w83977f_close(void *priv)
|
|||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
w83977f_init(const device_t *info)
|
w83977f_init(const device_t *info)
|
||||||
{
|
{
|
||||||
w83977f_t *dev = (w83977f_t *) malloc(sizeof(w83977f_t));
|
w83977f_t *dev = (w83977f_t *) malloc(sizeof(w83977f_t));
|
||||||
memset(dev, 0, sizeof(w83977f_t));
|
memset(dev, 0, sizeof(w83977f_t));
|
||||||
|
|
||||||
dev->type = info->local & 0x0f;
|
dev->type = info->local & 0x0f;
|
||||||
dev->hefras = info->local & 0x40;
|
dev->hefras = info->local & 0x40;
|
||||||
|
|
||||||
dev->id = next_id;
|
dev->id = next_id;
|
||||||
|
|
||||||
if (next_id == 1)
|
if (next_id == 1)
|
||||||
dev->hefras ^= 0x40;
|
dev->hefras ^= 0x40;
|
||||||
else
|
else
|
||||||
dev->fdc = device_add(&fdc_at_smc_device);
|
dev->fdc = device_add(&fdc_at_smc_device);
|
||||||
|
|
||||||
dev->uart[0] = device_add_inst(&ns16550_device, (next_id << 1) + 1);
|
dev->uart[0] = device_add_inst(&ns16550_device, (next_id << 1) + 1);
|
||||||
dev->uart[1] = device_add_inst(&ns16550_device, (next_id << 1) + 2);
|
dev->uart[1] = device_add_inst(&ns16550_device, (next_id << 1) + 2);
|
||||||
@@ -567,71 +585,71 @@ w83977f_init(const device_t *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const device_t w83977f_device = {
|
const device_t w83977f_device = {
|
||||||
.name = "Winbond W83977F Super I/O",
|
.name = "Winbond W83977F Super I/O",
|
||||||
.internal_name = "w83977f",
|
.internal_name = "w83977f",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0,
|
.local = 0,
|
||||||
.init = w83977f_init,
|
.init = w83977f_init,
|
||||||
.close = w83977f_close,
|
.close = w83977f_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t w83977f_370_device = {
|
const device_t w83977f_370_device = {
|
||||||
.name = "Winbond W83977F Super I/O (Port 370h)",
|
.name = "Winbond W83977F Super I/O (Port 370h)",
|
||||||
.internal_name = "w83977f_370",
|
.internal_name = "w83977f_370",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x40,
|
.local = 0x40,
|
||||||
.init = w83977f_init,
|
.init = w83977f_init,
|
||||||
.close = w83977f_close,
|
.close = w83977f_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t w83977tf_device = {
|
const device_t w83977tf_device = {
|
||||||
.name = "Winbond W83977TF Super I/O",
|
.name = "Winbond W83977TF Super I/O",
|
||||||
.internal_name = "w83977tf",
|
.internal_name = "w83977tf",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 1,
|
.local = 1,
|
||||||
.init = w83977f_init,
|
.init = w83977f_init,
|
||||||
.close = w83977f_close,
|
.close = w83977f_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t w83977ef_device = {
|
const device_t w83977ef_device = {
|
||||||
.name = "Winbond W83977TF Super I/O",
|
.name = "Winbond W83977TF Super I/O",
|
||||||
.internal_name = "w83977ef",
|
.internal_name = "w83977ef",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 2,
|
.local = 2,
|
||||||
.init = w83977f_init,
|
.init = w83977f_init,
|
||||||
.close = w83977f_close,
|
.close = w83977f_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t w83977ef_370_device = {
|
const device_t w83977ef_370_device = {
|
||||||
.name = "Winbond W83977TF Super I/O (Port 370h)",
|
.name = "Winbond W83977TF Super I/O (Port 370h)",
|
||||||
.internal_name = "w83977ef_370",
|
.internal_name = "w83977ef_370",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = 0x42,
|
.local = 0x42,
|
||||||
.init = w83977f_init,
|
.init = w83977f_init,
|
||||||
.close = w83977f_close,
|
.close = w83977f_close,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user