Merge pull request #1581 from 86Box/master

Bring the branch up to par with master.
This commit is contained in:
Miran Grča
2021-08-04 09:15:08 +02:00
committed by GitHub
30 changed files with 2075 additions and 480 deletions

View File

@@ -39,7 +39,7 @@
#include <86box/isapnp.h>
/* This ROM is reconstructed out of several assumptions, some of which are 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[] = {
0x55, 0xa3, 0x86, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, /* UMC8669, dummy checksum (filled in by isapnp_add_card) */
0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */
@@ -61,7 +61,7 @@ static uint8_t um8669f_pnp_rom[] = {
0x22, 0xfa, 0x1f, /* IRQ 1/3/4/5/6/7/8/9/10/11/12 */
0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */
0x15, 0x55, 0xa3, 0x86, 0x69, 0x00, /* logical device UMC8669 (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 */
0x47, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x08, 0x08, /* I/O 0x100-0x3F8, decodes 10-bit, 8-byte alignment, 8 addresses */
@@ -151,8 +151,9 @@ um8669f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *pri
fdc_set_irq(dev->fdc, config->irq[0].irq);
fdc_set_dma_ch(dev->fdc, (config->dma[0].dma == ISAPNP_DMA_DISABLED) ? -1 : config->dma[0].dma);
} else
} else {
um8669f_log("UM8669F: FDC disabled\n");
}
break;
@@ -163,8 +164,9 @@ um8669f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *pri
if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) {
um8669f_log("UM8669F: UART %d enabled at port %04X IRQ %d\n", ld - 1, config->io[0].base, config->irq[0].irq);
serial_setup(dev->uart[ld - 1], config->io[0].base, config->irq[0].irq);
} else
} else {
um8669f_log("UM8669F: UART %d disabled\n", ld - 1);
}
break;
@@ -174,8 +176,9 @@ um8669f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *pri
if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) {
um8669f_log("UM8669F: LPT enabled at port %04X IRQ %d\n", config->io[0].base, config->irq[0].irq);
lpt1_init(config->io[0].base);
} else
} else {
um8669f_log("UM8669F: LPT disabled\n");
}
break;

View File

@@ -34,7 +34,8 @@
typedef struct {
uint8_t cur_reg, regs[32], fdc_dma, fdc_irq, uart_irq[2], lpt_dma, lpt_irq;
uint8_t cur_reg, last_val, regs[25],
fdc_dma, fdc_irq, uart_irq[2], lpt_dma, lpt_irq;
fdc_t *fdc;
serial_t *uart[2];
} vt82c686_t;
@@ -43,10 +44,10 @@ typedef struct {
static uint8_t
get_lpt_length(vt82c686_t *dev)
{
uint8_t length = 4;
uint8_t length = 4; /* non-EPP */
if ((dev->regs[0x02] & 0x03) == 0x2)
length = 8;
if ((dev->regs[0x02] & 0x03) == 0x02)
length = 8; /* EPP */
return length;
}
@@ -64,6 +65,7 @@ vt82c686_fdc_handler(vt82c686_t *dev)
fdc_set_dma_ch(dev->fdc, dev->fdc_dma);
fdc_set_irq(dev->fdc, dev->fdc_irq);
fdc_set_swap(dev->fdc, dev->regs[0x16] & 0x01);
}
@@ -73,16 +75,20 @@ vt82c686_lpt_handler(vt82c686_t *dev)
uint16_t io_mask, io_base = dev->regs[0x06] << 2;
int io_len = get_lpt_length(dev);
io_base &= (0xff8 | io_len);
io_mask = 0x3fc;
io_mask = 0x3fc; /* non-EPP */
if (io_len == 8)
io_mask = 0x3f8;
io_mask = 0x3f8; /* EPP */
lpt1_remove();
if (((dev->regs[0x02] & 0x03) != 0x03) && (io_base >= 0x100) && (io_base <= io_mask))
lpt1_init(io_base);
lpt1_irq(dev->lpt_irq);
if (dev->lpt_irq) {
lpt1_irq(dev->lpt_irq);
} else {
lpt1_irq(0xff);
}
}
@@ -91,8 +97,8 @@ vt82c686_serial_handler(vt82c686_t *dev, int uart)
{
serial_remove(dev->uart[uart]);
if (dev->regs[0x02] & (uart ? 0x08 : 0x04))
serial_setup(dev->uart[uart], (dev->regs[0x07 + uart] & 0xfe) << 2, dev->uart_irq[uart]);
if (dev->regs[0x02] & (0x04 << uart))
serial_setup(dev->uart[uart], dev->regs[0x07 + uart] << 2, dev->uart_irq[uart]);
}
@@ -101,25 +107,31 @@ vt82c686_write(uint16_t port, uint8_t val, void *priv)
{
vt82c686_t *dev = (vt82c686_t *) priv;
/* Store last written value for echo (see comment on read). */
dev->last_val = val;
/* Write current register index on port 0. */
if (!(port & 1)) {
dev->cur_reg = val;
return;
}
/* NOTE: Registers are [0xE0:0xFF] but we store them as [0x00:0x1F]. */
if (dev->cur_reg < 0xe0)
return;
/* NOTE: Registers are [0xE0:0xF8] but we store them as [0x00:0x18]. */
if ((dev->cur_reg < 0xe0) || (dev->cur_reg > 0xf8))
return;
uint8_t reg = dev->cur_reg & 0x1f;
/* Read-only registers */
if ((reg < 0x02) || (reg == 0x04) || (reg == 0x05) || ((reg >= 0x09) && (reg < 0x0e)) ||
(reg == 0x13) || (reg == 0x15) || (reg == 0x17) || (reg >= 0x19))
/* Read-only registers. */
if ((reg < 0x02) || (reg == 0x0c))
return;
/* Write current register value on port 1. */
dev->regs[reg] = val;
/* Update device state. */
switch (reg) {
case 0x02:
dev->regs[reg] &= 0xbf;
vt82c686_lpt_handler(dev);
vt82c686_serial_handler(dev, 0);
vt82c686_serial_handler(dev, 1);
@@ -127,19 +139,54 @@ vt82c686_write(uint16_t port, uint8_t val, void *priv)
break;
case 0x03:
dev->regs[reg] &= 0xfc;
vt82c686_fdc_handler(dev);
break;
case 0x04:
dev->regs[reg] &= 0xfc;
break;
case 0x05:
dev->regs[reg] |= 0x03;
break;
case 0x06:
vt82c686_lpt_handler(dev);
break;
case 0x07:
vt82c686_serial_handler(dev, 0);
case 0x07: case 0x08:
dev->regs[reg] &= 0xfe;
vt82c686_serial_handler(dev, reg == 0x08);
break;
case 0x08:
vt82c686_serial_handler(dev, 1);
case 0x0d:
dev->regs[reg] &= 0x0f;
break;
case 0x0f:
dev->regs[reg] &= 0x7f;
break;
case 0x10:
dev->regs[reg] &= 0xf4;
break;
case 0x11:
dev->regs[reg] &= 0x3f;
break;
case 0x13:
dev->regs[reg] &= 0xfb;
break;
case 0x14: case 0x17:
dev->regs[reg] &= 0xfe;
break;
case 0x16:
dev->regs[reg] &= 0xf7;
vt82c686_fdc_handler(dev);
break;
}
}
@@ -149,17 +196,16 @@ static uint8_t
vt82c686_read(uint16_t port, void *priv)
{
vt82c686_t *dev = (vt82c686_t *) priv;
uint8_t ret = 0xff;
/* NOTE: Registers are [0xE0:0xFF] but we store them as [0x00:0x1F]. */
/* NOTE: Registers are [0xE0:0xF8] but we store them as [0x00:0x18].
Real 686B echoes the last read/written value when reading from
registers outside that range. */
if (!(port & 1))
ret = dev->cur_reg;
else if (dev->cur_reg < 0xe0)
ret = 0xff;
else
ret = dev->regs[dev->cur_reg & 0x1f];
dev->last_val = dev->cur_reg;
else if ((dev->cur_reg >= 0xe0) && (dev->cur_reg <= 0xf8))
dev->last_val = dev->regs[dev->cur_reg & 0x1f];
return ret;
return dev->last_val;
}
@@ -205,7 +251,7 @@ static void
vt82c686_reset(vt82c686_t *dev)
{
memset(dev->regs, 0, 20);
dev->regs[0x00] = 0x3c;
dev->regs[0x02] = 0x03;
dev->regs[0x03] = 0xfc;