mirror of
https://github.com/86Box/86Box.git
synced 2026-02-22 09:35:32 -07:00
Merge pull request #1 from 86Box/master
Bring up to par with main 86Box master.
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
#include <86box/pit.h>
|
||||
#include <86box/apm.h>
|
||||
#include <86box/acpi.h>
|
||||
#include <86box/dma.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/i2c.h>
|
||||
#include <86box/video.h>
|
||||
@@ -1025,8 +1026,13 @@ acpi_reg_write_common_regs(UNUSED(int size), uint16_t addr, uint8_t val, void *p
|
||||
nvr_reg_write(0x000f, 0xff, dev->nvr);
|
||||
}
|
||||
|
||||
if (sus_typ & SUS_RESET_PCI)
|
||||
if (sus_typ & SUS_RESET_PCI) {
|
||||
/* DMA is part of the southbridge so it responds to PCI reset. */
|
||||
dma_reset();
|
||||
dma_set_at(1);
|
||||
|
||||
device_reset_all(DEVICE_PCI);
|
||||
}
|
||||
|
||||
if (sus_typ & SUS_RESET_CPU)
|
||||
cpu_alt_reset = 0;
|
||||
|
||||
@@ -155,6 +155,7 @@ piix_ide_handlers(piix_t *dev, int bus)
|
||||
uint16_t side;
|
||||
|
||||
if (bus & 0x01) {
|
||||
piix_log("Disabling primary IDE...\n");
|
||||
ide_pri_disable();
|
||||
|
||||
if (dev->type == 5) {
|
||||
@@ -170,11 +171,14 @@ piix_ide_handlers(piix_t *dev, int bus)
|
||||
ide_set_side(0, side);
|
||||
}
|
||||
|
||||
if ((dev->regs[1][0x04] & 0x01) && (dev->regs[1][0x41] & 0x80))
|
||||
if ((dev->regs[1][0x04] & 0x01) && (dev->regs[1][0x41] & 0x80)) {
|
||||
piix_log("Enabling primary IDE...\n");
|
||||
ide_pri_enable();
|
||||
}
|
||||
}
|
||||
|
||||
if (bus & 0x02) {
|
||||
piix_log("Disabling secondary IDE...\n");
|
||||
ide_sec_disable();
|
||||
|
||||
if (dev->type == 5) {
|
||||
@@ -190,8 +194,10 @@ piix_ide_handlers(piix_t *dev, int bus)
|
||||
ide_set_side(1, side);
|
||||
}
|
||||
|
||||
if ((dev->regs[1][0x04] & 0x01) && (dev->regs[1][0x43] & 0x80))
|
||||
if ((dev->regs[1][0x04] & 0x01) && (dev->regs[1][0x43] & 0x80)) {
|
||||
piix_log("Enabling secondary IDE...\n");
|
||||
ide_sec_enable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,6 +471,13 @@ piix_write(int func, int addr, uint8_t val, void *priv)
|
||||
uint8_t *fregs;
|
||||
uint16_t base;
|
||||
|
||||
/* Dell OptiPlex Gn+ shows that register 02:FF is aliased in 01:FF. */
|
||||
if ((dev->type == 4) && (func == 1) && (addr == 0xff))
|
||||
func = 2;
|
||||
|
||||
if ((func == 1) || (addr == 0xf8) || (addr == 0xf9))
|
||||
piix_log("[W] %02X:%02X = %02X\n", func, addr, val);
|
||||
|
||||
/* Return on unsupported function. */
|
||||
if (dev->max_func > 0) {
|
||||
if (func > dev->max_func)
|
||||
@@ -736,6 +749,8 @@ piix_write(int func, int addr, uint8_t val, void *priv)
|
||||
fregs[addr] = val;
|
||||
break;
|
||||
case 0xb0:
|
||||
if (val & 0x10)
|
||||
warning("Write %02X to B0\n", val);
|
||||
if (dev->type == 4)
|
||||
fregs[addr] = (fregs[addr] & 0x8c) | (val & 0x73);
|
||||
else if (dev->type == 5)
|
||||
@@ -745,6 +760,8 @@ piix_write(int func, int addr, uint8_t val, void *priv)
|
||||
alt_access = !!(val & 0x20);
|
||||
break;
|
||||
case 0xb1:
|
||||
if (val & 0x18)
|
||||
warning("Write %02X to B1\n", val);
|
||||
if (dev->type > 3)
|
||||
fregs[addr] = val & 0xdf;
|
||||
break;
|
||||
@@ -923,6 +940,12 @@ piix_write(int func, int addr, uint8_t val, void *priv)
|
||||
if (dev->type > 4)
|
||||
fregs[addr] = val;
|
||||
break;
|
||||
case 0xf8:
|
||||
case 0xf9:
|
||||
/* Undocumented! */
|
||||
if (dev->type == 4)
|
||||
fregs[addr] = val;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1169,6 +1192,10 @@ piix_read(int func, int addr, void *priv)
|
||||
uint8_t ret = 0xff;
|
||||
const uint8_t *fregs;
|
||||
|
||||
/* Dell OptiPlex Gn+ shows that register 02:FF is aliased in 01:FF. */
|
||||
if ((dev->type == 4) && (func == 1) && (addr == 0xff))
|
||||
func = 2;
|
||||
|
||||
if ((dev->type == 3) && (func == 2) && (dev->max_func == 1) && (addr >= 0x40))
|
||||
ret = 0x00;
|
||||
|
||||
@@ -1199,7 +1226,7 @@ piix_reset_hard(piix_t *dev)
|
||||
|
||||
sff_set_slot(dev->bm[1], dev->pci_slot);
|
||||
sff_set_irq_pin(dev->bm[1], PCI_INTA);
|
||||
sff_set_irq_line(dev->bm[1], 14);
|
||||
sff_set_irq_line(dev->bm[1], 15);
|
||||
sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY);
|
||||
}
|
||||
|
||||
@@ -1315,6 +1342,10 @@ piix_reset_hard(piix_t *dev)
|
||||
fregs[0x45] = 0x55;
|
||||
fregs[0x46] = 0x01;
|
||||
}
|
||||
if (dev->type == 4) {
|
||||
fregs[0xf8] = 0x30;
|
||||
fregs[0xf9] = 0x0f;
|
||||
}
|
||||
if ((dev->type == 1) && (dev->rev == 2))
|
||||
dev->max_func = 0; /* It starts with IDE disabled, then enables it. */
|
||||
else
|
||||
@@ -1678,7 +1709,7 @@ const device_t piix4_device = {
|
||||
.name = "Intel 82371AB/EB (PIIX4/PIIX4E)",
|
||||
.internal_name = "piix4",
|
||||
.flags = DEVICE_PCI,
|
||||
.local = 0x71100004,
|
||||
.local = 0x71100014,
|
||||
.init = piix_init,
|
||||
.close = piix_close,
|
||||
.reset = piix_reset,
|
||||
|
||||
@@ -145,6 +145,11 @@ typedef struct atkbc_t {
|
||||
/* Internal FIFO for the purpose of commands with multi-byte output. */
|
||||
uint8_t key_ctrl_queue[64];
|
||||
|
||||
uint8_t handler_enable[2];
|
||||
|
||||
uint16_t base_addr[2];
|
||||
uint16_t irq[2];
|
||||
|
||||
uint32_t flags;
|
||||
|
||||
/* Main timers. */
|
||||
@@ -157,8 +162,13 @@ typedef struct atkbc_t {
|
||||
/* Local copies of the pointers to both ports for easier swapping (AMI '5' MegaKey). */
|
||||
kbc_at_port_t *ports[2];
|
||||
|
||||
uint8_t (*write60_ven)(void *priv, uint8_t val);
|
||||
uint8_t (*write64_ven)(void *priv, uint8_t val);
|
||||
struct {
|
||||
uint8_t (*read)(uint16_t port, void *priv);
|
||||
void (*write)(uint16_t port, uint8_t val, void *priv);
|
||||
} handlers[2];
|
||||
|
||||
uint8_t (*write_cmd_data_ven)(void *priv, uint8_t val);
|
||||
uint8_t (*write_cmd_ven)(void *priv, uint8_t val);
|
||||
} atkbc_t;
|
||||
|
||||
/* Keyboard controller ports. */
|
||||
@@ -167,8 +177,6 @@ kbc_at_port_t *kbc_at_ports[2] = { NULL, NULL };
|
||||
static uint8_t kbc_ami_revision = '8';
|
||||
static uint8_t kbc_award_revision = 0x42;
|
||||
|
||||
static uint8_t kbc_handler_set = 0;
|
||||
|
||||
static void (*kbc_at_do_poll)(atkbc_t *dev);
|
||||
|
||||
/* Non-translated to translated scan codes. */
|
||||
@@ -362,12 +370,19 @@ kbc_do_irq(atkbc_t *dev)
|
||||
if (dev->do_irq) {
|
||||
/* WARNING: On PS/2, all IRQ's are level-triggered, but the IBM PS/2 KBC firmware is explicitly
|
||||
written to pulse its P2 IRQ bits, so they should be kept as as edge-triggered here. */
|
||||
picint_common(1 << 1, 0, 0, NULL);
|
||||
picint_common(1 << 12, 0, 0, NULL);
|
||||
if (dev->channel >= 2)
|
||||
picint_common(1 << 12, 0, 1, NULL);
|
||||
else
|
||||
picint_common(1 << 1, 0, 1, NULL);
|
||||
if (dev->irq[0] != 0xffff)
|
||||
picint_common(1 << dev->irq[0], 0, 0, NULL);
|
||||
|
||||
if (dev->irq[1] != 0xffff)
|
||||
picint_common(1 << dev->irq[1], 0, 0, NULL);
|
||||
|
||||
if (dev->channel >= 2) {
|
||||
if (dev->irq[1] != 0xffff)
|
||||
picint_common(1 << dev->irq[1], 0, 1, NULL);
|
||||
} else {
|
||||
if (dev->irq[0] != 0xffff)
|
||||
picint_common(1 << dev->irq[0], 0, 1, NULL);
|
||||
}
|
||||
|
||||
dev->do_irq = 0;
|
||||
}
|
||||
@@ -404,7 +419,9 @@ kbc_send_to_ob(atkbc_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi)
|
||||
} else if (dev->mem[0x20] & 0x01)
|
||||
kbc_set_do_irq(dev, channel);
|
||||
} else if (dev->mem[0x20] & 0x01)
|
||||
picintlevel(1 << 1, &dev->irq_state); /* AT KBC: IRQ 1 is level-triggered because it is tied to OBF. */
|
||||
/* AT KBC: IRQ 1 is level-triggered because it is tied to OBF. */
|
||||
if (dev->irq[0] != 0xffff)
|
||||
picintlevel(1 << dev->irq[0], &dev->irq_state);
|
||||
|
||||
#ifdef WRONG_CONDITION
|
||||
if ((dev->channel > 0) || dev->is_asic || (kbc_ven == KBC_VEN_IBM_PS1) || (kbc_ven == KBC_VEN_IBM))
|
||||
@@ -784,10 +801,12 @@ write_p2(atkbc_t *dev, uint8_t val)
|
||||
/* PS/2: Handle IRQ's. */
|
||||
if (dev->misc_flags & FLAG_PS2) {
|
||||
/* IRQ 12 */
|
||||
picint_common(1 << 12, 0, val & 0x20, NULL);
|
||||
if (dev->irq[1] != 0xffff)
|
||||
picint_common(1 << dev->irq[1], 0, val & 0x20, NULL);
|
||||
|
||||
/* IRQ 1 */
|
||||
picint_common(1 << 1, 0, val & 0x10, NULL);
|
||||
if (dev->irq[0] != 0xffff)
|
||||
picint_common(1 << dev->irq[0], 0, val & 0x10, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -932,7 +951,7 @@ pulse_poll(void *priv)
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write64_generic(void *priv, uint8_t val)
|
||||
write_cmd_generic(void *priv, uint8_t val)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
uint8_t current_drive;
|
||||
@@ -1106,6 +1125,14 @@ write64_generic(void *priv, uint8_t val)
|
||||
*/
|
||||
uint8_t p1 = 0x30;
|
||||
kbc_delay_to_ob(dev, p1, 0, 0x00);
|
||||
} else if (!strcmp(machine_get_internal_name(), "dellplato") || !strcmp(machine_get_internal_name(), "dellhannibalp")) {
|
||||
/*
|
||||
Dell Dimension XPS Pxxx & Pxxxa/Mxxxa:
|
||||
- Bit 3: Password disable jumper (must be clear);
|
||||
- Bit 4: Clear CMOS jumper (must be set);
|
||||
*/
|
||||
uint8_t p1 = 0x10;
|
||||
kbc_delay_to_ob(dev, p1, 0, 0x00);
|
||||
} else {
|
||||
/* (B0 or F0) | (0x08 or 0x0c) */
|
||||
uint8_t p1_out = ((dev->p1 | fixed_bits) & 0xf0) |
|
||||
@@ -1170,7 +1197,7 @@ write64_generic(void *priv, uint8_t val)
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write60_ami(void *priv, uint8_t val)
|
||||
write_cmd_data_ami(void *priv, uint8_t val)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
@@ -1240,7 +1267,7 @@ kbc_at_set_ps2(void *priv, const uint8_t ps2)
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write64_ami(void *priv, uint8_t val)
|
||||
write_cmd_ami(void *priv, uint8_t val)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
uint8_t kbc_ven = dev->flags & KBC_VEN_MASK;
|
||||
@@ -1445,11 +1472,11 @@ write64_ami(void *priv, uint8_t val)
|
||||
break;
|
||||
}
|
||||
|
||||
return write64_generic(dev, val);
|
||||
return write_cmd_generic(dev, val);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write60_phoenix(void *priv, uint8_t val)
|
||||
write_cmd_data_phoenix(void *priv, uint8_t val)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
@@ -1522,7 +1549,7 @@ write60_phoenix(void *priv, uint8_t val)
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write64_phoenix(void *priv, uint8_t val)
|
||||
write_cmd_phoenix(void *priv, uint8_t val)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
@@ -1668,11 +1695,11 @@ write64_phoenix(void *priv, uint8_t val)
|
||||
break;
|
||||
}
|
||||
|
||||
return write64_generic(dev, val);
|
||||
return write_cmd_generic(dev, val);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write64_siemens(void *priv, uint8_t val)
|
||||
write_cmd_siemens(void *priv, uint8_t val)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
@@ -1701,11 +1728,11 @@ write64_siemens(void *priv, uint8_t val)
|
||||
break;
|
||||
}
|
||||
|
||||
return write64_ami(dev, val);
|
||||
return write_cmd_ami(dev, val);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write60_quadtel(void *priv, UNUSED(uint8_t val))
|
||||
write_cmd_data_quadtel(void *priv, UNUSED(uint8_t val))
|
||||
{
|
||||
const atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
@@ -1722,7 +1749,7 @@ write60_quadtel(void *priv, UNUSED(uint8_t val))
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write64_olivetti(void *priv, uint8_t val)
|
||||
write_cmd_olivetti(void *priv, uint8_t val)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
@@ -1743,11 +1770,11 @@ write64_olivetti(void *priv, uint8_t val)
|
||||
break;
|
||||
}
|
||||
|
||||
return write64_generic(dev, val);
|
||||
return write_cmd_generic(dev, val);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write64_quadtel(void *priv, uint8_t val)
|
||||
write_cmd_quadtel(void *priv, uint8_t val)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
@@ -1766,11 +1793,11 @@ write64_quadtel(void *priv, uint8_t val)
|
||||
break;
|
||||
}
|
||||
|
||||
return write64_generic(dev, val);
|
||||
return write_cmd_generic(dev, val);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write60_toshiba(void *priv, uint8_t val)
|
||||
write_cmd_data_toshiba(void *priv, uint8_t val)
|
||||
{
|
||||
const atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
@@ -1788,7 +1815,7 @@ write60_toshiba(void *priv, uint8_t val)
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write64_toshiba(void *priv, uint8_t val)
|
||||
write_cmd_toshiba(void *priv, uint8_t val)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
@@ -1877,7 +1904,7 @@ write64_toshiba(void *priv, uint8_t val)
|
||||
break;
|
||||
}
|
||||
|
||||
return write64_generic(dev, val);
|
||||
return write_cmd_generic(dev, val);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1921,8 +1948,10 @@ kbc_at_process_cmd(void *priv)
|
||||
/* TODO: Proper P1 implementation, with OR and AND flags in the machine table. */
|
||||
dev->p1 = dev->p1 & 0xff;
|
||||
write_p2(dev, 0x4b);
|
||||
picintc(0x1000);
|
||||
picintc(0x0002);
|
||||
if (dev->irq[1] != 0xffff)
|
||||
picintc(1 << dev->irq[1]);
|
||||
if (dev->irq[0] != 0xffff)
|
||||
picintc(1 << dev->irq[0]);
|
||||
}
|
||||
|
||||
dev->status = (dev->status & 0x0f) | 0x60;
|
||||
@@ -1941,7 +1970,8 @@ kbc_at_process_cmd(void *priv)
|
||||
/* TODO: Proper P1 implementation, with OR and AND flags in the machine table. */
|
||||
dev->p1 = dev->p1 & 0xff;
|
||||
write_p2(dev, 0xcf);
|
||||
picintclevel(0x0002, &dev->irq_state);
|
||||
if (dev->irq[0] != 0xffff)
|
||||
picintclevel(1 << dev->irq[0], &dev->irq_state);
|
||||
dev->irq_state = 0;
|
||||
}
|
||||
|
||||
@@ -2056,8 +2086,8 @@ kbc_at_process_cmd(void *priv)
|
||||
* that. Otherwise, or if that handler fails,
|
||||
* log a bad command.
|
||||
*/
|
||||
if (dev->write64_ven)
|
||||
bad = dev->write64_ven(dev, dev->ib);
|
||||
if (dev->write_cmd_ven)
|
||||
bad = dev->write_cmd_ven(dev, dev->ib);
|
||||
|
||||
kbc_at_log(bad ? "ATkbc: bad controller command %02X\n" : "", dev->ib);
|
||||
}
|
||||
@@ -2143,8 +2173,8 @@ kbc_at_process_cmd(void *priv)
|
||||
* it returns an error, log a bad
|
||||
* controller command.
|
||||
*/
|
||||
if (dev->write60_ven)
|
||||
bad = dev->write60_ven(dev, dev->ib);
|
||||
if (dev->write_cmd_data_ven)
|
||||
bad = dev->write_cmd_data_ven(dev, dev->ib);
|
||||
|
||||
if (bad) {
|
||||
kbc_at_log("ATkbc: bad controller command %02x data %02x\n", dev->command, dev->ib);
|
||||
@@ -2154,7 +2184,7 @@ kbc_at_process_cmd(void *priv)
|
||||
}
|
||||
|
||||
static void
|
||||
kbc_at_write(uint16_t port, uint8_t val, void *priv)
|
||||
kbc_at_port_1_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
uint8_t kbc_ven = dev->flags & KBC_VEN_MASK;
|
||||
@@ -2162,83 +2192,89 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv)
|
||||
|
||||
kbc_at_log("ATkbc: [%04X:%08X] write(%04X) = %02X\n", CS, cpu_state.pc, port, val);
|
||||
|
||||
switch (port) {
|
||||
case 0x60:
|
||||
dev->status &= ~STAT_CD;
|
||||
if (fast_a20 && dev->wantdata && (dev->command == 0xd1)) {
|
||||
kbc_at_log("ATkbc: write P2\n");
|
||||
dev->status &= ~STAT_CD;
|
||||
|
||||
/* Fast A20 - ignore all other bits. */
|
||||
write_p2_fast_a20(dev, (dev->p2 & 0xfd) | (val & 0x02));
|
||||
if (fast_a20 && dev->wantdata && (dev->command == 0xd1)) {
|
||||
kbc_at_log("ATkbc: write P2\n");
|
||||
|
||||
dev->wantdata = 0;
|
||||
dev->state = STATE_MAIN_IBF;
|
||||
/* Fast A20 - ignore all other bits. */
|
||||
write_p2_fast_a20(dev, (dev->p2 & 0xfd) | (val & 0x02));
|
||||
|
||||
/*
|
||||
Explicitly clear IBF so that any preceding
|
||||
command is not executed.
|
||||
*/
|
||||
dev->status &= ~STAT_IFULL;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
dev->wantdata = 0;
|
||||
dev->state = STATE_MAIN_IBF;
|
||||
|
||||
case 0x64:
|
||||
dev->status |= STAT_CD;
|
||||
if (fast_a20 && (val == 0xd1)) {
|
||||
kbc_at_log("ATkbc: write P2\n");
|
||||
dev->wantdata = 1;
|
||||
dev->state = STATE_KBC_PARAM;
|
||||
dev->command = 0xd1;
|
||||
/*
|
||||
Explicitly clear IBF so that any preceding
|
||||
command is not executed.
|
||||
*/
|
||||
dev->status &= ~STAT_IFULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Explicitly clear IBF so that any preceding
|
||||
command is not executed.
|
||||
*/
|
||||
dev->status &= ~STAT_IFULL;
|
||||
return;
|
||||
} else if (fast_reset && ((val & 0xf0) == 0xf0)) {
|
||||
pulse_output(dev, val & 0x0f);
|
||||
dev->ib = val;
|
||||
dev->status |= STAT_IFULL;
|
||||
}
|
||||
|
||||
dev->state = STATE_MAIN_IBF;
|
||||
static void
|
||||
kbc_at_port_2_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
uint8_t kbc_ven = dev->flags & KBC_VEN_MASK;
|
||||
uint8_t fast_a20 = (kbc_ven != KBC_VEN_SIEMENS);
|
||||
|
||||
/*
|
||||
Explicitly clear IBF so that any preceding
|
||||
command is not executed.
|
||||
*/
|
||||
dev->status &= ~STAT_IFULL;
|
||||
return;
|
||||
} else if (val == 0xad) {
|
||||
/* Fast track it because of the Bochs BIOS. */
|
||||
kbc_at_log("ATkbc: disable keyboard\n");
|
||||
set_enable_kbd(dev, 0);
|
||||
kbc_at_log("ATkbc: [%04X:%08X] write(%04X) = %02X\n", CS, cpu_state.pc, port, val);
|
||||
|
||||
dev->state = STATE_MAIN_IBF;
|
||||
dev->status |= STAT_CD;
|
||||
|
||||
/*
|
||||
Explicitly clear IBF so that any preceding
|
||||
command is not executed.
|
||||
*/
|
||||
dev->status &= ~STAT_IFULL;
|
||||
return;
|
||||
} else if (val == 0xae) {
|
||||
/* Fast track it because of the LG MultiNet. */
|
||||
kbc_at_log("ATkbc: enable keyboard\n");
|
||||
set_enable_kbd(dev, 1);
|
||||
if (fast_a20 && (val == 0xd1)) {
|
||||
kbc_at_log("ATkbc: write P2\n");
|
||||
dev->wantdata = 1;
|
||||
dev->state = STATE_KBC_PARAM;
|
||||
dev->command = 0xd1;
|
||||
|
||||
dev->state = STATE_MAIN_IBF;
|
||||
/*
|
||||
Explicitly clear IBF so that any preceding
|
||||
command is not executed.
|
||||
*/
|
||||
dev->status &= ~STAT_IFULL;
|
||||
return;
|
||||
} else if (fast_reset && ((val & 0xf0) == 0xf0)) {
|
||||
pulse_output(dev, val & 0x0f);
|
||||
|
||||
/*
|
||||
Explicitly clear IBF so that any preceding
|
||||
command is not executed.
|
||||
*/
|
||||
dev->status &= ~STAT_IFULL;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
dev->state = STATE_MAIN_IBF;
|
||||
|
||||
default:
|
||||
break;
|
||||
/*
|
||||
Explicitly clear IBF so that any preceding
|
||||
command is not executed.
|
||||
*/
|
||||
dev->status &= ~STAT_IFULL;
|
||||
return;
|
||||
} else if (val == 0xad) {
|
||||
/* Fast track it because of the Bochs BIOS. */
|
||||
kbc_at_log("ATkbc: disable keyboard\n");
|
||||
set_enable_kbd(dev, 0);
|
||||
|
||||
dev->state = STATE_MAIN_IBF;
|
||||
|
||||
/*
|
||||
Explicitly clear IBF so that any preceding
|
||||
command is not executed.
|
||||
*/
|
||||
dev->status &= ~STAT_IFULL;
|
||||
return;
|
||||
} else if (val == 0xae) {
|
||||
/* Fast track it because of the LG MultiNet. */
|
||||
kbc_at_log("ATkbc: enable keyboard\n");
|
||||
set_enable_kbd(dev, 1);
|
||||
|
||||
dev->state = STATE_MAIN_IBF;
|
||||
|
||||
/*
|
||||
Explicitly clear IBF so that any preceding
|
||||
command is not executed.
|
||||
*/
|
||||
dev->status &= ~STAT_IFULL;
|
||||
return;
|
||||
}
|
||||
|
||||
dev->ib = val;
|
||||
@@ -2246,7 +2282,7 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv)
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
kbc_at_read(uint16_t port, void *priv)
|
||||
kbc_at_port_1_read(uint16_t port, void *priv)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
@@ -2254,26 +2290,32 @@ kbc_at_read(uint16_t port, void *priv)
|
||||
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1)
|
||||
cycles -= ISA_CYCLES(8);
|
||||
|
||||
switch (port) {
|
||||
case 0x60:
|
||||
ret = dev->ob;
|
||||
dev->status &= ~STAT_OFULL;
|
||||
/* TODO: IRQ is only tied to OBF on the AT KBC, on the PS/2 KBC, it is controlled by a P2 bit.
|
||||
This also means that in AT mode, the IRQ is level-triggered. */
|
||||
if (!(dev->misc_flags & FLAG_PS2))
|
||||
picintclevel(1 << 1, &dev->irq_state);
|
||||
if ((strstr(machine_get_internal_name(), "pb41") != NULL) && (cpu_override_dynarec == 1))
|
||||
cpu_override_dynarec = 0;
|
||||
break;
|
||||
ret = dev->ob;
|
||||
dev->status &= ~STAT_OFULL;
|
||||
/*
|
||||
TODO: IRQ is only tied to OBF on the AT KBC, on the PS/2 KBC, it is controlled by a P2 bit.
|
||||
This also means that in AT mode, the IRQ is level-triggered.
|
||||
*/
|
||||
if (!(dev->misc_flags & FLAG_PS2) && (dev->irq[0] != 0xffff))
|
||||
picintclevel(1 << dev->irq[0], &dev->irq_state);
|
||||
if ((strstr(machine_get_internal_name(), "pb41") != NULL) && (cpu_override_dynarec == 1))
|
||||
cpu_override_dynarec = 0;
|
||||
|
||||
case 0x64:
|
||||
ret = dev->status;
|
||||
break;
|
||||
kbc_at_log("ATkbc: [%04X:%08X] read (%04X) = %02X\n", CS, cpu_state.pc, port, ret);
|
||||
|
||||
default:
|
||||
kbc_at_log("ATkbc: read(%04x) invalid!\n",port);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
kbc_at_port_2_read(uint16_t port, void *priv)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1)
|
||||
cycles -= ISA_CYCLES(8);
|
||||
|
||||
ret = dev->status;
|
||||
|
||||
kbc_at_log("ATkbc: [%04X:%08X] read (%04X) = %02X\n", CS, cpu_state.pc, port, ret);
|
||||
|
||||
@@ -2312,11 +2354,14 @@ kbc_at_reset(void *priv)
|
||||
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) {
|
||||
dev->misc_flags |= FLAG_PS2;
|
||||
kbc_at_do_poll = kbc_at_poll_ps2;
|
||||
picintc(0x1000);
|
||||
picintc(0x0002);
|
||||
if (dev->irq[1] != 0xffff)
|
||||
picintc(1 << dev->irq[1]);
|
||||
if (dev->irq[0] != 0xffff)
|
||||
picintc(1 << dev->irq[0]);
|
||||
} else {
|
||||
kbc_at_do_poll = kbc_at_poll_at;
|
||||
picintclevel(0x0002, &dev->irq_state);
|
||||
if (dev->irq[0] != 0xffff)
|
||||
picintclevel(1 << dev->irq[0], &dev->irq_state);
|
||||
dev->irq_state = 0;
|
||||
}
|
||||
|
||||
@@ -2359,19 +2404,44 @@ kbc_at_close(void *priv)
|
||||
}
|
||||
|
||||
void
|
||||
kbc_at_handler(int set, void *priv)
|
||||
kbc_at_port_handler(int num, int set, uint16_t port, void *priv)
|
||||
{
|
||||
if (kbc_handler_set) {
|
||||
io_removehandler(0x0060, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, priv);
|
||||
io_removehandler(0x0064, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, priv);
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
if (dev->handler_enable[num] && (dev->base_addr[num] != 0x0000))
|
||||
io_removehandler(dev->base_addr[num], 1,
|
||||
dev->handlers[num].read, NULL, NULL,
|
||||
dev->handlers[num].write, NULL, NULL, priv);
|
||||
|
||||
dev->handler_enable[num] = set;
|
||||
dev->base_addr[num] = port;
|
||||
|
||||
if (dev->handler_enable[num] && (dev->base_addr[num] != 0x0000))
|
||||
io_sethandler(dev->base_addr[num], 1,
|
||||
dev->handlers[num].read, NULL, NULL,
|
||||
dev->handlers[num].write, NULL, NULL, priv);
|
||||
}
|
||||
|
||||
void
|
||||
kbc_at_handler(int set, uint16_t port, void *priv)
|
||||
{
|
||||
kbc_at_port_handler(0, set, port, priv);
|
||||
kbc_at_port_handler(1, set, port + 0x0004, priv);
|
||||
}
|
||||
|
||||
void
|
||||
kbc_at_set_irq(int num, uint16_t irq, void *priv)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
if (dev->irq[num] != 0xffff) {
|
||||
if ((num == 0) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_1))
|
||||
picintclevel(1 << dev->irq[num], &dev->irq_state);
|
||||
else
|
||||
picintc(1 << dev->irq[num]);
|
||||
}
|
||||
|
||||
kbc_handler_set = set;
|
||||
|
||||
if (kbc_handler_set) {
|
||||
io_sethandler(0x0060, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, priv);
|
||||
io_sethandler(0x0064, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, priv);
|
||||
}
|
||||
dev->irq[num] = irq;
|
||||
}
|
||||
|
||||
static void *
|
||||
@@ -2392,16 +2462,21 @@ kbc_at_init(const device_t *info)
|
||||
if (info->flags & DEVICE_PCI)
|
||||
dev->misc_flags |= FLAG_PCI;
|
||||
|
||||
kbc_handler_set = 0;
|
||||
kbc_at_handler(1, dev);
|
||||
dev->handlers[0].read = kbc_at_port_1_read;
|
||||
dev->handlers[0].write = kbc_at_port_1_write;
|
||||
dev->handlers[1].read = kbc_at_port_2_read;
|
||||
dev->handlers[1].write = kbc_at_port_2_write;
|
||||
|
||||
dev->irq[0] = 1;
|
||||
dev->irq[1] = 12;
|
||||
|
||||
timer_add(&dev->kbc_poll_timer, kbc_at_poll, dev, 1);
|
||||
timer_add(&dev->pulse_cb, pulse_poll, dev, 0);
|
||||
|
||||
timer_add(&dev->kbc_dev_poll_timer, kbc_at_dev_poll, dev, 1);
|
||||
|
||||
dev->write60_ven = NULL;
|
||||
dev->write64_ven = NULL;
|
||||
dev->write_cmd_data_ven = NULL;
|
||||
dev->write_cmd_ven = NULL;
|
||||
|
||||
kbc_ami_revision = '8';
|
||||
kbc_award_revision = 0x42;
|
||||
@@ -2410,8 +2485,8 @@ kbc_at_init(const device_t *info)
|
||||
case KBC_VEN_SIEMENS:
|
||||
kbc_ami_revision = '8';
|
||||
kbc_award_revision = 0x42;
|
||||
dev->write60_ven = write60_ami;
|
||||
dev->write64_ven = write64_siemens;
|
||||
dev->write_cmd_data_ven = write_cmd_data_ami;
|
||||
dev->write_cmd_ven = write_cmd_siemens;
|
||||
break;
|
||||
|
||||
case KBC_VEN_ACER:
|
||||
@@ -2420,24 +2495,24 @@ kbc_at_init(const device_t *info)
|
||||
case KBC_VEN_IBM_PS1:
|
||||
case KBC_VEN_IBM:
|
||||
case KBC_VEN_COMPAQ:
|
||||
dev->write64_ven = write64_generic;
|
||||
dev->write_cmd_ven = write_cmd_generic;
|
||||
break;
|
||||
|
||||
case KBC_VEN_OLIVETTI:
|
||||
dev->write64_ven = write64_olivetti;
|
||||
dev->write_cmd_ven = write_cmd_olivetti;
|
||||
break;
|
||||
|
||||
case KBC_VEN_ALI:
|
||||
kbc_ami_revision = 'F';
|
||||
kbc_award_revision = 0x43;
|
||||
dev->write60_ven = write60_ami;
|
||||
dev->write64_ven = write64_ami;
|
||||
dev->write_cmd_data_ven = write_cmd_data_ami;
|
||||
dev->write_cmd_ven = write_cmd_ami;
|
||||
break;
|
||||
|
||||
case KBC_VEN_TRIGEM_AMI:
|
||||
kbc_ami_revision = 'Z';
|
||||
dev->write60_ven = write60_ami;
|
||||
dev->write64_ven = write64_ami;
|
||||
dev->write_cmd_data_ven = write_cmd_data_ami;
|
||||
dev->write_cmd_ven = write_cmd_ami;
|
||||
break;
|
||||
|
||||
case KBC_VEN_AMI:
|
||||
@@ -2460,23 +2535,23 @@ kbc_at_init(const device_t *info)
|
||||
else
|
||||
kbc_ami_revision = 'F';
|
||||
|
||||
dev->write60_ven = write60_ami;
|
||||
dev->write64_ven = write64_ami;
|
||||
dev->write_cmd_data_ven = write_cmd_data_ami;
|
||||
dev->write_cmd_ven = write_cmd_ami;
|
||||
break;
|
||||
|
||||
case KBC_VEN_PHOENIX:
|
||||
dev->write60_ven = write60_phoenix;
|
||||
dev->write64_ven = write64_phoenix;
|
||||
dev->write_cmd_data_ven = write_cmd_data_phoenix;
|
||||
dev->write_cmd_ven = write_cmd_phoenix;
|
||||
break;
|
||||
|
||||
case KBC_VEN_QUADTEL:
|
||||
dev->write60_ven = write60_quadtel;
|
||||
dev->write64_ven = write64_quadtel;
|
||||
dev->write_cmd_data_ven = write_cmd_data_quadtel;
|
||||
dev->write_cmd_ven = write_cmd_quadtel;
|
||||
break;
|
||||
|
||||
case KBC_VEN_TOSHIBA:
|
||||
dev->write60_ven = write60_toshiba;
|
||||
dev->write64_ven = write64_toshiba;
|
||||
dev->write_cmd_data_ven = write_cmd_data_toshiba;
|
||||
dev->write_cmd_ven = write_cmd_toshiba;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -2502,6 +2577,8 @@ kbc_at_init(const device_t *info)
|
||||
|
||||
fast_reset = 0x00;
|
||||
|
||||
kbc_at_handler(1, 0x0060, dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,11 +30,13 @@
|
||||
#include "cpu.h"
|
||||
|
||||
uint8_t postcard_codes[POSTCARDS_NUM];
|
||||
char postcard_diags[5] = { 0 };
|
||||
|
||||
static uint16_t postcard_port;
|
||||
static uint8_t postcard_written[POSTCARDS_NUM];
|
||||
static uint8_t postcard_ports_num = 1;
|
||||
static uint8_t postcard_prev_codes[POSTCARDS_NUM];
|
||||
static char postcard_prev_diags[5] = { 0 };
|
||||
#define UISTR_LEN 32
|
||||
static char postcard_str[UISTR_LEN]; /* UI output string */
|
||||
|
||||
@@ -97,6 +99,22 @@ postcard_setui(void)
|
||||
ps[1][0], ps[1][1], ps[1][2], ps[1][3]);
|
||||
break;
|
||||
}
|
||||
} else if (strstr(machines[machine].name, " Dell ")) {
|
||||
char dell_diags[10] = { 0 };
|
||||
|
||||
if (!postcard_written[1])
|
||||
snprintf(dell_diags, sizeof(dell_diags), "---- ----");
|
||||
else if (postcard_written[1] == 1)
|
||||
snprintf(dell_diags, sizeof(dell_diags), "%s ----", postcard_diags);
|
||||
else
|
||||
snprintf(dell_diags, sizeof(dell_diags), "%s %s", postcard_diags, postcard_prev_diags);
|
||||
|
||||
if (!postcard_written[0])
|
||||
snprintf(postcard_str, sizeof(postcard_str), "POST: -- -- %s", dell_diags);
|
||||
else if (postcard_written[0] == 1)
|
||||
snprintf(postcard_str, sizeof(postcard_str), "POST: %02X -- %s", postcard_codes[0], dell_diags);
|
||||
else
|
||||
snprintf(postcard_str, sizeof(postcard_str), "POST: %02X %02X %s", postcard_codes[0], postcard_prev_codes[0], dell_diags);
|
||||
} else {
|
||||
if (!postcard_written[0])
|
||||
snprintf(postcard_str, sizeof(postcard_str), "POST: -- --");
|
||||
@@ -122,6 +140,9 @@ postcard_reset(void)
|
||||
memset(postcard_codes, 0x00, POSTCARDS_NUM * sizeof(uint8_t));
|
||||
memset(postcard_prev_codes, 0x00, POSTCARDS_NUM * sizeof(uint8_t));
|
||||
|
||||
memset(postcard_diags, 0x00, 5 * sizeof(char));
|
||||
memset(postcard_prev_diags, 0x00, 5 * sizeof(char));
|
||||
|
||||
postcard_setui();
|
||||
}
|
||||
|
||||
@@ -140,6 +161,35 @@ postcard_write(uint16_t port, uint8_t val, UNUSED(void *priv))
|
||||
postcard_setui();
|
||||
}
|
||||
|
||||
static int
|
||||
postcard_cmp_diags(uint32_t val)
|
||||
{
|
||||
int ret = 0;
|
||||
char *pv = (char *) &val;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
ret = ret || (pv[i] != postcard_diags[3 - i]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
postcard_writel(uint16_t port, uint32_t val, UNUSED(void *priv))
|
||||
{
|
||||
char *pv = (char *) &val;
|
||||
|
||||
if (postcard_written[1] && !postcard_cmp_diags(val))
|
||||
return;
|
||||
|
||||
*(uint32_t *) postcard_prev_diags = *(uint32_t *) postcard_diags;
|
||||
for (int i = 0; i < 4; i++)
|
||||
postcard_diags[i] = pv[3 - i];
|
||||
if (postcard_written[1] < 2)
|
||||
postcard_written[1]++;
|
||||
|
||||
postcard_setui();
|
||||
}
|
||||
|
||||
static void *
|
||||
postcard_init(UNUSED(const device_t *info))
|
||||
{
|
||||
@@ -173,6 +223,10 @@ postcard_init(UNUSED(const device_t *info))
|
||||
io_sethandler(postcard_port, postcard_ports_num,
|
||||
NULL, NULL, NULL, postcard_write, NULL, NULL, NULL);
|
||||
|
||||
if (strstr(machines[machine].name, " Dell "))
|
||||
io_sethandler(0x00e0, 0x0001,
|
||||
NULL, NULL, NULL, NULL, NULL, postcard_writel, NULL);
|
||||
|
||||
return postcard_write;
|
||||
}
|
||||
|
||||
|
||||
@@ -856,7 +856,7 @@ dma16_read(uint16_t addr, UNUSED(void *priv))
|
||||
break;
|
||||
}
|
||||
|
||||
dma_log("dma16_read(%08X) = %02X\n", port, ret);
|
||||
dma_log("dma16_read(%08X) = %02X\n", addr, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -377,6 +377,15 @@ fdc_set_power_down(fdc_t *fdc, uint8_t power_down)
|
||||
fdc->power_down = power_down;
|
||||
}
|
||||
|
||||
void
|
||||
fdc_toggle_flag(fdc_t *fdc, int flag, int on)
|
||||
{
|
||||
if (on)
|
||||
fdc->flags |= flag;
|
||||
else
|
||||
fdc->flags &= ~flag;
|
||||
}
|
||||
|
||||
void
|
||||
fdc_update_max_track(fdc_t *fdc, int max_track)
|
||||
{
|
||||
@@ -1484,7 +1493,7 @@ fdc_read(uint16_t addr, void *priv)
|
||||
fdc->step = 0;
|
||||
break;
|
||||
default:
|
||||
ret = 0xFF;
|
||||
ret = 0xff;
|
||||
}
|
||||
fdc_log("[%04X:%08X] Read FDC %04X %02X [%i:%02X]\n", CS, cpu_state.pc, addr, ret, drive, fdc->dor & (0x10 << drive));
|
||||
return ret;
|
||||
@@ -2235,9 +2244,13 @@ fdc_set_base(fdc_t *fdc, int base)
|
||||
{
|
||||
int super_io = (fdc->flags & FDC_FLAG_SUPERIO);
|
||||
|
||||
if (base == 0x0000) {
|
||||
fdc->base_address = base;
|
||||
return;
|
||||
}
|
||||
|
||||
if (fdc->flags & FDC_FLAG_NSC) {
|
||||
io_sethandler(base + 2, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_sethandler(base + 4, 0x0002, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_sethandler(base + 2, 0x0004, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_sethandler(base + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
} else {
|
||||
if ((fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_AMSTRAD)) {
|
||||
@@ -2266,10 +2279,12 @@ fdc_remove(fdc_t *fdc)
|
||||
{
|
||||
int super_io = (fdc->flags & FDC_FLAG_SUPERIO);
|
||||
|
||||
if (fdc->base_address == 0x0000)
|
||||
return;
|
||||
|
||||
fdc_log("FDC Removed (%04X)\n", fdc->base_address);
|
||||
if (fdc->flags & FDC_FLAG_NSC) {
|
||||
io_removehandler(fdc->base_address + 2, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_removehandler(fdc->base_address + 4, 0x0002, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_removehandler(fdc->base_address + 2, 0x0004, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_removehandler(fdc->base_address + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
} else {
|
||||
if ((fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_AMSTRAD)) {
|
||||
|
||||
@@ -183,6 +183,7 @@ extern uint8_t fdc_get_densel_polarity(fdc_t *fdc);
|
||||
extern void fdc_update_densel_force(fdc_t *fdc, int densel_force);
|
||||
extern void fdc_update_drvrate(fdc_t *fdc, int drive, int drvrate);
|
||||
extern void fdc_update_drv2en(fdc_t *fdc, int drv2en);
|
||||
extern void fdc_toggle_flag(fdc_t *fdc, int flag, int on);
|
||||
|
||||
extern void fdc_noidam(fdc_t *fdc);
|
||||
extern void fdc_nosector(fdc_t *fdc);
|
||||
|
||||
@@ -289,7 +289,9 @@ extern uint8_t kbc_at_read_p(void *priv, uint8_t port, uint8_t mask);
|
||||
extern void kbc_at_write_p(void *priv, uint8_t port, uint8_t mask, uint8_t val);
|
||||
|
||||
extern void kbc_at_set_fast_reset(uint8_t new_fast_reset);
|
||||
extern void kbc_at_handler(int set, void *priv);
|
||||
extern void kbc_at_port_handler(int num, int set, uint16_t port, void *priv);
|
||||
extern void kbc_at_handler(int set, uint16_t port, void *priv);
|
||||
extern void kbc_at_set_irq(int num, uint16_t irq, void *priv);
|
||||
|
||||
extern void kbc_at_dev_queue_reset(atkbc_dev_t *dev, uint8_t reset_main);
|
||||
extern uint8_t kbc_at_dev_queue_pos(atkbc_dev_t *dev, uint8_t main);
|
||||
|
||||
@@ -752,6 +752,7 @@ extern int machine_at_gw2kte_init(const machine_t *);
|
||||
extern int machine_at_ma23c_init(const machine_t *);
|
||||
extern int machine_at_nupro592_init(const machine_t *);
|
||||
extern int machine_at_tx97_init(const machine_t *);
|
||||
extern int machine_at_optiplex_gn_init(const machine_t *);
|
||||
#ifdef USE_AN430TX
|
||||
extern int machine_at_an430tx_init(const machine_t *);
|
||||
#endif /* USE_AN430TX */
|
||||
|
||||
@@ -92,13 +92,23 @@ extern const device_t pc87332_398_ide_device;
|
||||
extern const device_t pc87332_398_ide_sec_device;
|
||||
extern const device_t pc87332_398_ide_fdcon_device;
|
||||
|
||||
#define PCX7307_PC87307 0x00c0
|
||||
#define PCX7307_PC97307 0x00cf
|
||||
|
||||
#define PC87309_PC87309 0x00e0
|
||||
|
||||
#define PCX730X_CHIP_ID 0x00ff
|
||||
|
||||
#define PCX730X_AMI 0x0200 /* AMI '5' Megakey KBC firmware. */
|
||||
#define PCX730X_PHOENIX_42 0x0500 /* Phoenix Multikey/42 1.37 KBC firmware. */
|
||||
#define PCX730X_PHOENIX_42I 0x0700 /* Phoenix Multikey/42i 4.16 KBC firmware. */
|
||||
#define PCX730X_KBC 0x0f00
|
||||
|
||||
#define PCX730X_15C 0x2000
|
||||
|
||||
extern const device_t pc87307_device;
|
||||
extern const device_t pc87307_15c_device;
|
||||
extern const device_t pc87307_both_device;
|
||||
extern const device_t pc97307_device;
|
||||
|
||||
extern const device_t pc87309_device;
|
||||
extern const device_t pc87309_15c_device;
|
||||
|
||||
/* LG Prime */
|
||||
extern const device_t prime3b_device;
|
||||
|
||||
@@ -229,9 +229,9 @@ void
|
||||
lpt_port_setup(int i, uint16_t port)
|
||||
{
|
||||
if (lpt_ports[i].enabled) {
|
||||
if (lpt_ports[i].addr != 0xffff)
|
||||
if ((lpt_ports[i].addr != 0xffff) && (lpt_ports[i].addr != 0x0000))
|
||||
io_removehandler(lpt_ports[i].addr, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
|
||||
if (port != 0xffff)
|
||||
if ((port != 0xffff) && (port != 0x0000))
|
||||
io_sethandler(port, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]);
|
||||
lpt_ports[i].addr = port;
|
||||
} else
|
||||
|
||||
@@ -396,7 +396,7 @@ machine_at_pb410a_init(const machine_t *model)
|
||||
device_add(&phoenix_486_jumper_device);
|
||||
|
||||
if (gfxcard[0] == VID_INTERNAL)
|
||||
device_add(&ht216_32_pb410a_device);
|
||||
device_add(machine_get_vid_device(machine));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -584,8 +584,7 @@ machine_at_s1846_init(const machine_t *model)
|
||||
pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4);
|
||||
device_add(&i440bx_device);
|
||||
device_add(&piix4e_device);
|
||||
device_add(&pc87309_device);
|
||||
device_add(&keyboard_ps2_ami_pci_device);
|
||||
device_add_params(&pc87309_device, (void *) (PCX730X_AMI | PC87309_PC87309));
|
||||
device_add(&intel_flash_bxt_device);
|
||||
spd_register(SPD_TYPE_SDRAM, 0x7, 256);
|
||||
|
||||
|
||||
@@ -140,8 +140,7 @@ machine_at_fw6400gx_init(const machine_t *model)
|
||||
|
||||
device_add(&i440gx_device);
|
||||
device_add(&piix4e_device);
|
||||
device_add(&keyboard_ps2_ami_pci_device);
|
||||
device_add(&pc87309_15c_device);
|
||||
device_add_params(&pc87309_device, (void *) (PCX730X_15C | PCX730X_AMI | PC87309_PC87309));
|
||||
device_add(ics9xxx_get(ICS9250_08));
|
||||
device_add(&sst_flash_29ee020_device);
|
||||
spd_register(SPD_TYPE_SDRAM, 0xF, 512);
|
||||
|
||||
@@ -969,6 +969,42 @@ machine_at_tx97_init(const machine_t *model)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
machine_at_optiplex_gn_init(const machine_t *model)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bios_load_linear("roms/machines/optiplex_gn/DELL.ROM",
|
||||
0x000c0000, 262144, 0);
|
||||
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
machine_at_common_init_ex(model, 2);
|
||||
|
||||
pci_init(PCI_CONFIG_TYPE_1);
|
||||
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 1, 2, 3, 4);
|
||||
pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 2, 1);
|
||||
pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 1, 3, 4);
|
||||
pci_register_slot(0x10, PCI_CARD_VIDEO, 4, 0, 0, 0); /* Trio64V2/GX, temporarily Trio64V2/DX is given */
|
||||
pci_register_slot(0x11, PCI_CARD_NETWORK, 4, 0, 0, 0); /* 3C905, not yet emulated */
|
||||
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4);
|
||||
|
||||
if (gfxcard[0] == VID_INTERNAL)
|
||||
device_add(machine_get_vid_device(machine));
|
||||
|
||||
if ((sound_card_current[0] == SOUND_INTERNAL) && machine_get_snd_device(machine)->available())
|
||||
machine_snd = device_add(machine_get_snd_device(machine));
|
||||
|
||||
device_add(&i430tx_device);
|
||||
device_add(&piix4_device);
|
||||
device_add_params(&pc87307_device, (void *) (PCX730X_PHOENIX_42 | PCX7307_PC87307));
|
||||
device_add(&intel_flash_bxt_device);
|
||||
spd_register(SPD_TYPE_SDRAM, 0x3, 128);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef USE_AN430TX
|
||||
int
|
||||
machine_at_an430tx_init(const machine_t *model)
|
||||
@@ -1006,8 +1042,7 @@ machine_at_an430tx_init(const machine_t *model)
|
||||
pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3);
|
||||
device_add(&i430tx_device);
|
||||
device_add(&piix4_device);
|
||||
device_add(&keyboard_ps2_ami_pci_device);
|
||||
device_add(&pc87307_both_device);
|
||||
device_add_params(&pc87307_device, (void *) (PCX730X_PHOENIX_42I | PCX7307_PC97307));
|
||||
device_add(&intel_flash_bxt_ami_device);
|
||||
spd_register(SPD_TYPE_SDRAM, 0x3, 128);
|
||||
|
||||
|
||||
@@ -250,8 +250,7 @@ machine_at_vs440fx_init(const machine_t *model)
|
||||
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
|
||||
device_add(&i440fx_device);
|
||||
device_add(&piix3_device);
|
||||
device_add(&keyboard_ps2_intel_ami_pci_device);
|
||||
device_add(&pc87307_device);
|
||||
device_add_params(&pc87307_device, (void *) (PCX730X_AMI | PCX7307_PC87307));
|
||||
|
||||
device_add(&intel_flash_bxt_ami_device);
|
||||
|
||||
@@ -287,8 +286,7 @@ machine_at_gw2kvenus_init(const machine_t *model)
|
||||
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
|
||||
device_add(&i440fx_device);
|
||||
device_add(&piix3_device);
|
||||
device_add(&keyboard_ps2_intel_ami_pci_device);
|
||||
device_add(&pc87307_device);
|
||||
device_add_params(&pc87307_device, (void *) (PCX730X_AMI | PCX7307_PC87307));
|
||||
|
||||
device_add(&intel_flash_bxt_ami_device);
|
||||
|
||||
@@ -324,8 +322,7 @@ machine_at_ap440fx_init(const machine_t *model)
|
||||
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4);
|
||||
device_add(&i440fx_device);
|
||||
device_add(&piix3_device);
|
||||
device_add(&keyboard_ps2_ami_pci_device);
|
||||
device_add(&pc87307_device);
|
||||
device_add_params(&pc87307_device, (void *) (PCX730X_AMI | PCX7307_PC87307));
|
||||
device_add(&intel_flash_bxt_ami_device);
|
||||
|
||||
if (sound_card_current[0] == SOUND_INTERNAL)
|
||||
|
||||
@@ -6647,7 +6647,7 @@ const machine_t machines[] = {
|
||||
.device = NULL,
|
||||
.fdc_device = NULL,
|
||||
.sio_device = NULL,
|
||||
.vid_device = NULL,
|
||||
.vid_device = &ht216_32_pb410a_device,
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
@@ -13143,6 +13143,56 @@ const machine_t machines[] = {
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
/*
|
||||
According to Dell specifications, it can have either National Semiconductor
|
||||
PC87307 or PC87309 Super I/O. All known instances have the former, although
|
||||
other similar Dells of the era have pinouts for accompanying either so this
|
||||
likely also does.
|
||||
|
||||
The KBC is either an AMI '5' MegaKey, Phoenix MultiKey/42 1.37, or Phoenix
|
||||
MultiKey/42i 4.16.
|
||||
*/
|
||||
{
|
||||
.name = "[i430TX] Dell OptiPlex GN+",
|
||||
.internal_name = "optiplex_gn",
|
||||
.type = MACHINE_TYPE_SOCKET7,
|
||||
.chipset = MACHINE_CHIPSET_INTEL_430TX,
|
||||
.init = machine_at_optiplex_gn_init,
|
||||
.p1_handler = NULL,
|
||||
.gpio_handler = NULL,
|
||||
.available_flag = MACHINE_AVAILABLE,
|
||||
.gpio_acpi_handler = NULL,
|
||||
.cpu = {
|
||||
.package = CPU_PKG_SOCKET5_7,
|
||||
.block = CPU_BLOCK_NONE,
|
||||
.min_bus = 50000000,
|
||||
.max_bus = 66666667,
|
||||
.min_voltage = 2500,
|
||||
.max_voltage = 3520,
|
||||
.min_multi = 1.5,
|
||||
.max_multi = 3.5
|
||||
},
|
||||
.bus_flags = MACHINE_PS2_PCI,
|
||||
/* Video: S3 86C785 (Trio64V2/GX), ethernet: 3C905. */
|
||||
.flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_VIDEO | MACHINE_SOUND,
|
||||
.ram = {
|
||||
.min = 8192,
|
||||
.max = 262144,
|
||||
.step = 8192
|
||||
},
|
||||
.nvrmask = 255,
|
||||
.kbc_device = NULL,
|
||||
.kbc_p1 = 0xff,
|
||||
.gpio = 0xffffffff,
|
||||
.gpio_acpi = 0xffffffff,
|
||||
.device = NULL,
|
||||
.fdc_device = NULL,
|
||||
.sio_device = NULL,
|
||||
/* Stop-gap measure until the Trio64V2/GX is emulated, as both use the same VBIOS. */
|
||||
.vid_device = &s3_trio64v2_dx_onboard_pci_device,
|
||||
.snd_device = &sb_vibra16xv_onboard_device,
|
||||
.net_device = NULL
|
||||
},
|
||||
/* [TEST] Has AMI Megakey '5' KBC firmware on the SM(S)C FDC37C67x Super I/O chip. */
|
||||
{
|
||||
.name = "[i430TX] Gateway E-1000",
|
||||
|
||||
@@ -1107,9 +1107,10 @@ nvr_at_init(const device_t *info)
|
||||
case 1: /* standard AT */
|
||||
case 5: /* AMI WinBIOS 1994 */
|
||||
case 6: /* AMI BIOS 1995 */
|
||||
if ((info->local & 0x1f) == 0x11)
|
||||
if ((info->local & 0x1f) == 0x11) {
|
||||
local->flags |= FLAG_PIIX4;
|
||||
else {
|
||||
local->def = 0x00;
|
||||
} else {
|
||||
local->def = 0x00;
|
||||
if ((info->local & 0x1f) == 0x15)
|
||||
local->flags |= FLAG_AMI_1994_HACK;
|
||||
|
||||
@@ -61,6 +61,11 @@ struct mouseinputdata {
|
||||
static mouseinputdata mousedata;
|
||||
|
||||
extern MainWindow *main_window;
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
HWND rw_hwnd;
|
||||
#endif
|
||||
|
||||
RendererStack::RendererStack(QWidget *parent, int monitor_index)
|
||||
: QStackedWidget(parent)
|
||||
, ui(new Ui::RendererStack)
|
||||
@@ -251,7 +256,9 @@ RendererStack::mouseMoveEvent(QMouseEvent *event)
|
||||
leaveEvent((QEvent *) event);
|
||||
ignoreNextMouseEvent--;
|
||||
}
|
||||
#if !defined _WIN32
|
||||
QCursor::setPos(mapToGlobal(QPoint(width() / 2, height() / 2)));
|
||||
#endif
|
||||
ignoreNextMouseEvent = 2;
|
||||
oldPos = event->pos();
|
||||
#endif
|
||||
@@ -405,8 +412,15 @@ RendererStack::createRenderer(Renderer renderer)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (current.get() == nullptr)
|
||||
if (current.get() == nullptr) {
|
||||
#ifdef Q_OS_WINDOWS
|
||||
rw_hwnd = NULL;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#ifdef Q_OS_WINDOWS
|
||||
rw_hwnd = (HWND) this->winId();
|
||||
#endif
|
||||
current->setFocusPolicy(Qt::NoFocus);
|
||||
current->setFocusProxy(this);
|
||||
current->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
@@ -649,6 +663,14 @@ RendererStack::setFocusRenderer()
|
||||
void
|
||||
RendererStack::onResize(int width, int height)
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
if (mouse_capture) {
|
||||
RECT rect;
|
||||
if (GetWindowRect((HWND)this->winId(), &rect)) {
|
||||
ClipCursor(&rect);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (rendererWindow) {
|
||||
rendererWindow->r_monitor_index = m_monitor_index;
|
||||
rendererWindow->onResize(width, height);
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <QStatusBar>
|
||||
#include <QApplication>
|
||||
|
||||
#include "qt_mainwindow.hpp"
|
||||
#include "qt_machinestatus.hpp"
|
||||
@@ -122,6 +123,10 @@ plat_resize(int w, int h, int monitor_index)
|
||||
main_window->resizeContents(w, h);
|
||||
}
|
||||
|
||||
#if defined _WIN32
|
||||
extern HWND rw_hwnd;
|
||||
#endif
|
||||
|
||||
void
|
||||
plat_mouse_capture(int on)
|
||||
{
|
||||
@@ -129,6 +134,26 @@ plat_mouse_capture(int on)
|
||||
return;
|
||||
|
||||
main_window->setMouseCapture(on > 0 ? true : false);
|
||||
|
||||
#if defined _WIN32
|
||||
if (on) {
|
||||
QCursor cursor(Qt::BlankCursor);
|
||||
|
||||
QApplication::setOverrideCursor(cursor);
|
||||
QApplication::changeOverrideCursor(cursor);
|
||||
|
||||
RECT rect;
|
||||
|
||||
GetWindowRect(rw_hwnd, &rect);
|
||||
|
||||
ClipCursor(&rect);
|
||||
|
||||
} else {
|
||||
ClipCursor(NULL);
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -395,7 +395,7 @@ WindowsRawInputFilter::mouse_handle(PRAWINPUT raw)
|
||||
|
||||
mouse_scale(delta_x, delta_y);
|
||||
|
||||
HWND wnd = (HWND)window->winId();
|
||||
/* HWND wnd = (HWND)window->winId();
|
||||
|
||||
RECT rect;
|
||||
|
||||
@@ -404,5 +404,5 @@ WindowsRawInputFilter::mouse_handle(PRAWINPUT raw)
|
||||
int left = rect.left + (rect.right - rect.left) / 2;
|
||||
int top = rect.top + (rect.bottom - rect.top) / 2;
|
||||
|
||||
SetCursorPos(left, top);
|
||||
SetCursorPos(left, top); */
|
||||
}
|
||||
|
||||
@@ -894,7 +894,7 @@ fdc37c93x_kbc_handler(fdc37c93x_t *dev)
|
||||
dev->kbc_base = local_enable ? 0x0060 : 0x0000;
|
||||
|
||||
if (dev->kbc_base != old_base)
|
||||
kbc_at_handler(local_enable, dev->kbc);
|
||||
kbc_at_handler(local_enable, dev->kbc_base, dev->kbc);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,60 +8,97 @@
|
||||
*
|
||||
* Emulation of the NatSemi PC87309 Super I/O chip.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2020 Miran Grca.
|
||||
* Copyright 2020-2025 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/lpt.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/nvr.h>
|
||||
#include <86box/pci.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/serial.h>
|
||||
#include <86box/hdc.h>
|
||||
#include <86box/hdc_ide.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/sio.h>
|
||||
#include <86box/plat_fallthrough.h>
|
||||
#include "cpu.h"
|
||||
|
||||
typedef struct pc87309_t {
|
||||
uint8_t id;
|
||||
uint8_t baddr;
|
||||
uint8_t pm_idx;
|
||||
uint8_t regs[48];
|
||||
uint8_t ld_regs[256][208];
|
||||
uint8_t pm[8];
|
||||
uint8_t baddr;
|
||||
uint16_t superio_base;
|
||||
uint16_t pm_base;
|
||||
int cur_reg;
|
||||
void *kbc;
|
||||
fdc_t *fdc;
|
||||
serial_t *uart[2];
|
||||
} pc87309_t;
|
||||
|
||||
enum {
|
||||
LD_FDC = 0,
|
||||
LD_LPT,
|
||||
LD_UART2,
|
||||
LD_UART1,
|
||||
LD_PM,
|
||||
LD_KBD,
|
||||
LD_MOUSE
|
||||
} pc87309_ld_t;
|
||||
|
||||
#define LD_MIN LD_FDC
|
||||
#define LD_MAX LD_MOUSE
|
||||
|
||||
static void fdc_handler(pc87309_t *dev);
|
||||
static void lpt1_handler(pc87309_t *dev);
|
||||
static void serial_handler(pc87309_t *dev, int uart);
|
||||
|
||||
static void kbc_handler(pc87309_t *dev);
|
||||
static void pc87309_write(uint16_t port, uint8_t val, void *priv);
|
||||
static uint8_t pc87309_read(uint16_t port, void *priv);
|
||||
|
||||
#ifdef ENABLE_PC87309_LOG
|
||||
int pc87309_do_log = ENABLE_PC87309_LOG;
|
||||
|
||||
static void
|
||||
pc87309_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (pc87309_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define pc87309_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
static void
|
||||
pc87309_pm_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
pc87309_t *dev = (pc87309_t *) priv;
|
||||
|
||||
if (port & 1) {
|
||||
if (port & 1)
|
||||
dev->pm[dev->pm_idx] = val;
|
||||
else {
|
||||
dev->pm_idx = val & 0x07;
|
||||
|
||||
switch (dev->pm_idx) {
|
||||
case 0x00:
|
||||
@@ -74,8 +111,7 @@ pc87309_pm_write(uint16_t port, uint8_t val, void *priv)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else
|
||||
dev->pm_idx = val & 0x07;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
@@ -109,43 +145,48 @@ pc87309_pm_init(pc87309_t *dev, uint16_t addr)
|
||||
}
|
||||
|
||||
static void
|
||||
superio_handler(pc87309_t *dev)
|
||||
kbc_handler(pc87309_t *dev)
|
||||
{
|
||||
io_removehandler(0x15c, 0x0002,
|
||||
pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev);
|
||||
io_removehandler(0x02e, 0x0002,
|
||||
pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev);
|
||||
uint8_t active = (dev->ld_regs[LD_KBD][0x00] & 0x01) &&
|
||||
(dev->pm[0x00] & 0x01);
|
||||
uint8_t active_2 = dev->ld_regs[LD_MOUSE][0x00] & 0x01;
|
||||
uint8_t irq = (dev->ld_regs[LD_KBD][0x40] & 0x0f);
|
||||
uint8_t irq_2 = (dev->ld_regs[LD_MOUSE][0x40] & 0x0f);
|
||||
uint16_t addr = (dev->ld_regs[LD_KBD][0x30] << 8) |
|
||||
dev->ld_regs[LD_KBD][0x31];
|
||||
uint16_t addr_2 = (dev->ld_regs[LD_KBD][0x32] << 8) |
|
||||
dev->ld_regs[LD_KBD][0x33];
|
||||
|
||||
switch (dev->regs[0x21] & 0x0b) {
|
||||
case 0x02:
|
||||
case 0x08:
|
||||
case 0x0a:
|
||||
io_sethandler(0x15c, 0x0002,
|
||||
pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev);
|
||||
break;
|
||||
case 0x03:
|
||||
case 0x09:
|
||||
case 0x0b:
|
||||
io_sethandler(0x02e, 0x0002,
|
||||
pc87309_read, NULL, NULL, pc87309_write, NULL, NULL, dev);
|
||||
break;
|
||||
pc87309_log("%02X, %02X, %02X, %02X, %04X, %04X\n",
|
||||
active, active_2, irq, irq_2, addr, addr_2);
|
||||
|
||||
if (addr <= 0xfff8) {
|
||||
pc87309_log("Enabling KBC #1 on %04X...\n", addr);
|
||||
kbc_at_port_handler(0, active, addr, dev->kbc);
|
||||
}
|
||||
|
||||
if (addr_2 <= 0xfff8) {
|
||||
pc87309_log("Enabling KBC #2 on %04X...\n", addr_2);
|
||||
kbc_at_port_handler(1, active, addr_2, dev->kbc);
|
||||
}
|
||||
|
||||
kbc_at_set_irq(0, active ? irq : 0xffff, dev->kbc);
|
||||
kbc_at_set_irq(1, (active && active_2) ? irq_2 : 0xffff, dev->kbc);
|
||||
}
|
||||
|
||||
static void
|
||||
fdc_handler(pc87309_t *dev)
|
||||
{
|
||||
uint8_t irq;
|
||||
uint8_t active;
|
||||
uint16_t addr;
|
||||
|
||||
fdc_remove(dev->fdc);
|
||||
|
||||
active = (dev->ld_regs[0x00][0x00] & 0x01) && (dev->pm[0x00] & 0x08);
|
||||
addr = ((dev->ld_regs[0x00][0x30] << 8) | dev->ld_regs[0x00][0x31]) - 0x0002;
|
||||
irq = (dev->ld_regs[0x00][0x40] & 0x0f);
|
||||
uint8_t active = (dev->ld_regs[LD_FDC][0x00] & 0x01) &&
|
||||
(dev->pm[0x00] & 0x08);
|
||||
uint8_t irq = (dev->ld_regs[LD_FDC][0x40] & 0x0f);
|
||||
uint16_t addr = ((dev->ld_regs[LD_FDC][0x30] << 8) |
|
||||
dev->ld_regs[LD_FDC][0x31]) & 0xfff8;
|
||||
|
||||
if (active) {
|
||||
if (active && (addr <= 0xfff8)) {
|
||||
pc87309_log("Enabling FDC on %04X, IRQ %i...\n", addr, irq);
|
||||
fdc_set_base(dev->fdc, addr);
|
||||
fdc_set_irq(dev->fdc, irq);
|
||||
}
|
||||
@@ -154,222 +195,351 @@ fdc_handler(pc87309_t *dev)
|
||||
static void
|
||||
lpt1_handler(pc87309_t *dev)
|
||||
{
|
||||
uint8_t irq;
|
||||
uint8_t active;
|
||||
uint16_t addr;
|
||||
uint8_t active = (dev->ld_regs[LD_LPT][0x00] & 0x01) &&
|
||||
(dev->pm[0x00] & 0x10);
|
||||
uint8_t irq = (dev->ld_regs[LD_LPT][0x40] & 0x0f);
|
||||
uint16_t addr = (dev->ld_regs[LD_LPT][0x30] << 8) |
|
||||
dev->ld_regs[LD_LPT][0x31];
|
||||
|
||||
lpt1_remove();
|
||||
|
||||
active = (dev->ld_regs[0x01][0x00] & 0x01) && (dev->pm[0x00] & 0x10);
|
||||
addr = (dev->ld_regs[0x01][0x30] << 8) | dev->ld_regs[0x01][0x31];
|
||||
irq = (dev->ld_regs[0x01][0x40] & 0x0f);
|
||||
|
||||
if (active) {
|
||||
if (active && (addr <= 0xfffc)) {
|
||||
pc87309_log("Enabling LPT1 on %04X...\n", addr);
|
||||
lpt1_setup(addr);
|
||||
lpt1_irq(irq);
|
||||
}
|
||||
} else
|
||||
lpt1_setup(0xffff);
|
||||
|
||||
lpt1_irq(irq);
|
||||
}
|
||||
|
||||
static void
|
||||
serial_handler(pc87309_t *dev, int uart)
|
||||
{
|
||||
uint8_t irq;
|
||||
uint8_t active;
|
||||
uint16_t addr;
|
||||
|
||||
serial_remove(dev->uart[uart]);
|
||||
|
||||
active = (dev->ld_regs[0x03 - uart][0x00] & 0x01) && (dev->pm[0x00] & (1 << (6 - uart)));
|
||||
addr = (dev->ld_regs[0x03 - uart][0x30] << 8) | dev->ld_regs[0x03 - uart][0x31];
|
||||
irq = (dev->ld_regs[0x03 - uart][0x40] & 0x0f);
|
||||
uint8_t active = (dev->ld_regs[LD_UART1 - uart][0x00] & 0x01) &&
|
||||
(dev->pm[0x00] & (1 << (6 - uart)));
|
||||
uint8_t irq = (dev->ld_regs[LD_UART1 - uart][0x40] & 0x0f);
|
||||
uint16_t addr = (dev->ld_regs[LD_UART1 - uart][0x30] << 8) |
|
||||
dev->ld_regs[LD_UART1 - uart][0x31];
|
||||
|
||||
if (active)
|
||||
if (active && (addr <= 0xfff8)) {
|
||||
pc87309_log("Enabling COM%i on %04X...\n", uart + 1, addr);
|
||||
serial_setup(dev->uart[uart], addr, irq);
|
||||
} else
|
||||
serial_setup(dev->uart[uart], 0x0000, irq);
|
||||
}
|
||||
|
||||
static void
|
||||
pm_handler(pc87309_t *dev)
|
||||
{
|
||||
uint8_t active;
|
||||
uint16_t addr;
|
||||
|
||||
pc87309_pm_remove(dev);
|
||||
|
||||
active = (dev->ld_regs[0x04][0x00] & 0x01);
|
||||
addr = (dev->ld_regs[0x04][0x30] << 8) | dev->ld_regs[0x04][0x31];
|
||||
uint8_t active = (dev->ld_regs[LD_PM][0x00] & 0x01);
|
||||
uint16_t addr = (dev->ld_regs[LD_PM][0x30] << 8) |
|
||||
dev->ld_regs[LD_PM][0x31];
|
||||
|
||||
if (active)
|
||||
if (active) {
|
||||
pc87309_log("Enabling power management on %04X...\n", addr);
|
||||
pc87309_pm_init(dev, addr);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
superio_handler(pc87309_t *dev)
|
||||
{
|
||||
if (dev->superio_base != 0x0000)
|
||||
io_removehandler(dev->superio_base, 0x0002,
|
||||
pc87309_read, NULL, NULL,
|
||||
pc87309_write, NULL, NULL, dev);
|
||||
|
||||
switch (dev->regs[0x21] & 0x0b) {
|
||||
default:
|
||||
dev->superio_base = 0x0000;
|
||||
break;
|
||||
case 0x02:
|
||||
case 0x08: case 0x0a:
|
||||
dev->superio_base = 0x015c;
|
||||
break;
|
||||
case 0x03:
|
||||
case 0x09: case 0x0b:
|
||||
dev->superio_base = 0x002e;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dev->superio_base != 0x0000) {
|
||||
pc87309_log("Enabling Super I/O on %04X...\n", dev->superio_base);
|
||||
io_sethandler(dev->superio_base, 0x0002,
|
||||
pc87309_read, NULL, NULL,
|
||||
pc87309_write, NULL, NULL, dev);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pc87309_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
pc87309_t *dev = (pc87309_t *) priv;
|
||||
uint8_t index;
|
||||
|
||||
index = (port & 1) ? 0 : 1;
|
||||
pc87309_t *dev = (pc87309_t *) priv;
|
||||
uint8_t ld = dev->regs[0x07];
|
||||
uint8_t reg = dev->cur_reg - 0x30;
|
||||
uint8_t index = (port & 1) ? 0 : 1;
|
||||
uint8_t old = dev->regs[dev->cur_reg];
|
||||
|
||||
if (index) {
|
||||
dev->cur_reg = val;
|
||||
return;
|
||||
} else {
|
||||
#ifdef ENABLE_PC87309_LOG
|
||||
if (dev->cur_reg >= 0x30)
|
||||
pc87309_log("[%04X:%08X] [W] (%04X) %02X:%02X = %02X\n",
|
||||
CS, cpu_state.pc, port, ld, dev->cur_reg, val);
|
||||
else
|
||||
pc87309_log("[%04X:%08X] [W] (%04X) %02X = %02X\n",
|
||||
CS, cpu_state.pc, port, dev->cur_reg, val);
|
||||
#endif
|
||||
switch (dev->cur_reg) {
|
||||
case 0x00:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
case 0x02: case 0x03:
|
||||
case 0x06: case 0x07:
|
||||
dev->regs[dev->cur_reg] = val;
|
||||
break;
|
||||
case 0x21:
|
||||
dev->regs[dev->cur_reg] = val;
|
||||
fdc_toggle_flag(dev->fdc, FDC_FLAG_PS2_MCA, !(val & 0x04));
|
||||
superio_handler(dev);
|
||||
break;
|
||||
case 0x22:
|
||||
dev->regs[dev->cur_reg] = val & 0x7f;
|
||||
dev->regs[dev->cur_reg] = val;
|
||||
break;
|
||||
default:
|
||||
if (dev->cur_reg >= 0x30) {
|
||||
if ((dev->regs[0x07] != 0x06) || !(dev->regs[0x21] & 0x10))
|
||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val;
|
||||
}
|
||||
if (dev->cur_reg >= 0x30)
|
||||
old = dev->ld_regs[ld][reg];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (dev->cur_reg) {
|
||||
case 0x30:
|
||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x01;
|
||||
switch (dev->regs[0x07]) {
|
||||
case 0x00:
|
||||
switch (ld) {
|
||||
default:
|
||||
break;
|
||||
case LD_KBD: case LD_MOUSE:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
kbc_handler(dev);
|
||||
break;
|
||||
case LD_FDC:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
fdc_handler(dev);
|
||||
break;
|
||||
case 0x01:
|
||||
case LD_LPT:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
lpt1_handler(dev);
|
||||
break;
|
||||
case 0x02:
|
||||
case LD_UART2:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
serial_handler(dev, 1);
|
||||
break;
|
||||
case 0x03:
|
||||
case LD_UART1:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
serial_handler(dev, 0);
|
||||
break;
|
||||
case 0x04:
|
||||
case LD_PM:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
pm_handler(dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
/* I/O Range Check. */
|
||||
case 0x31:
|
||||
switch (ld) {
|
||||
default:
|
||||
break;
|
||||
case LD_MIN ... LD_MAX:
|
||||
if (ld != LD_MOUSE)
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
/* Base Address 0 MSB. */
|
||||
case 0x60:
|
||||
case 0x62:
|
||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x07;
|
||||
if (dev->cur_reg == 0x62)
|
||||
break;
|
||||
switch (dev->regs[0x07]) {
|
||||
case 0x00:
|
||||
switch (ld) {
|
||||
default:
|
||||
break;
|
||||
case LD_KBD:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
kbc_handler(dev);
|
||||
break;
|
||||
case LD_FDC:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
fdc_handler(dev);
|
||||
break;
|
||||
case 0x01:
|
||||
case LD_LPT:
|
||||
dev->ld_regs[ld][reg] = (old & 0xfc) | (val & 0x03);
|
||||
lpt1_handler(dev);
|
||||
break;
|
||||
case 0x02:
|
||||
case LD_UART2:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
serial_handler(dev, 1);
|
||||
break;
|
||||
case 0x03:
|
||||
case LD_UART1:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
serial_handler(dev, 0);
|
||||
break;
|
||||
case 0x04:
|
||||
case LD_PM:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
pm_handler(dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x63:
|
||||
if (dev->regs[0x07] == 0x06)
|
||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xf8) | 0x04;
|
||||
break;
|
||||
/* Base Address 0 LSB. */
|
||||
case 0x61:
|
||||
switch (dev->regs[0x07]) {
|
||||
case 0x00:
|
||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = (val & 0xfa) | 0x02;
|
||||
switch (ld) {
|
||||
default:
|
||||
break;
|
||||
case LD_KBD:
|
||||
dev->ld_regs[ld][reg] = (old & 0x04) | (val & 0xfb);
|
||||
kbc_handler(dev);
|
||||
break;
|
||||
case LD_FDC:
|
||||
dev->ld_regs[ld][reg] = (old & 0x07) | (val & 0xf8);
|
||||
fdc_handler(dev);
|
||||
break;
|
||||
case 0x01:
|
||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfc;
|
||||
case LD_LPT:
|
||||
dev->ld_regs[ld][reg] = (old & 0x03) | (val & 0xfc);
|
||||
lpt1_handler(dev);
|
||||
break;
|
||||
case 0x02:
|
||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8;
|
||||
case LD_UART2:
|
||||
dev->ld_regs[ld][reg] = (old & 0x07) | (val & 0xf8);
|
||||
serial_handler(dev, 1);
|
||||
break;
|
||||
case 0x03:
|
||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8;
|
||||
case LD_UART1:
|
||||
dev->ld_regs[ld][reg] = (old & 0x07) | (val & 0xf8);
|
||||
serial_handler(dev, 0);
|
||||
break;
|
||||
case 0x04:
|
||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xfe;
|
||||
case LD_PM:
|
||||
dev->ld_regs[ld][reg] = (old & 0x01) | (val & 0xfe);
|
||||
pm_handler(dev);
|
||||
break;
|
||||
case 0x06:
|
||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf8;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
/* Base Address 1 MSB (undocumented for Logical Device 7). */
|
||||
case 0x62:
|
||||
switch (ld) {
|
||||
default:
|
||||
break;
|
||||
case LD_KBD:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
kbc_handler(dev);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
/* Base Address 1 LSB (undocumented for Logical Device 7). */
|
||||
case 0x63:
|
||||
switch (ld) {
|
||||
default:
|
||||
break;
|
||||
case LD_KBD:
|
||||
dev->ld_regs[ld][reg] = (old & 0x04) | (val & 0xfb);
|
||||
kbc_handler(dev);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
/* Interrupt Select. */
|
||||
case 0x70:
|
||||
case 0x74:
|
||||
case 0x75:
|
||||
switch (dev->regs[0x07]) {
|
||||
case 0x00:
|
||||
switch (ld) {
|
||||
default:
|
||||
break;
|
||||
case LD_KBD: case LD_MOUSE:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
kbc_handler(dev);
|
||||
break;
|
||||
case LD_FDC:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
fdc_handler(dev);
|
||||
break;
|
||||
case 0x01:
|
||||
case LD_LPT:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
lpt1_handler(dev);
|
||||
break;
|
||||
case 0x02:
|
||||
case LD_UART2:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
serial_handler(dev, 1);
|
||||
break;
|
||||
case 0x03:
|
||||
case LD_UART1:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
serial_handler(dev, 0);
|
||||
break;
|
||||
case 0x04:
|
||||
pm_handler(dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
/* Interrupt Type. */
|
||||
case 0x71:
|
||||
switch (ld) {
|
||||
default:
|
||||
break;
|
||||
case LD_MIN ... LD_MAX:
|
||||
if ((ld == LD_KBD) || (ld == LD_MOUSE))
|
||||
dev->ld_regs[ld][reg] = (old & 0xfc) | (val & 0x03);
|
||||
else
|
||||
dev->ld_regs[ld][reg] = (old & 0xfd) | (val & 0x02);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
/* DMA Channel Select 0. */
|
||||
case 0x74:
|
||||
switch (ld) {
|
||||
default:
|
||||
break;
|
||||
case LD_FDC:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
fdc_handler(dev);
|
||||
break;
|
||||
case LD_LPT:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
lpt1_handler(dev);
|
||||
break;
|
||||
case LD_UART2:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
/* DMA Channel Select 1. */
|
||||
case 0x75:
|
||||
switch (ld) {
|
||||
default:
|
||||
break;
|
||||
case LD_UART2:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
/* Configuration Register 0. */
|
||||
case 0xf0:
|
||||
switch (dev->regs[0x07]) {
|
||||
case 0x00:
|
||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xe1;
|
||||
switch (ld) {
|
||||
default:
|
||||
break;
|
||||
case LD_KBD:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
break;
|
||||
case LD_FDC:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
fdc_update_densel_polarity(dev->fdc, (val & 0x20) ? 1 : 0);
|
||||
fdc_update_enh_mode(dev->fdc, (val & 0x40) ? 1 : 0);
|
||||
break;
|
||||
case 0x01:
|
||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xf3;
|
||||
case LD_LPT:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
lpt1_handler(dev);
|
||||
break;
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x87;
|
||||
break;
|
||||
case 0x06:
|
||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0xc1;
|
||||
break;
|
||||
|
||||
default:
|
||||
case LD_UART2: case LD_UART1:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
/* Configuration Register 1. */
|
||||
case 0xf1:
|
||||
if (dev->regs[0x07] == 0x00)
|
||||
dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30] = val & 0x0f;
|
||||
switch (ld) {
|
||||
default:
|
||||
break;
|
||||
case LD_FDC:
|
||||
dev->ld_regs[ld][reg] = val;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -377,30 +547,44 @@ pc87309_write(uint16_t port, uint8_t val, void *priv)
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
static uint8_t
|
||||
pc87309_read(uint16_t port, void *priv)
|
||||
{
|
||||
const pc87309_t *dev = (pc87309_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
uint8_t index;
|
||||
|
||||
index = (port & 1) ? 0 : 1;
|
||||
const pc87309_t *dev = (pc87309_t *) priv;
|
||||
uint8_t ld = dev->regs[0x07];
|
||||
uint8_t reg = dev->cur_reg - 0x30;
|
||||
uint8_t index = (port & 1) ? 0 : 1;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
if (index)
|
||||
ret = dev->cur_reg & 0x1f;
|
||||
ret = dev->cur_reg;
|
||||
else {
|
||||
if (dev->cur_reg >= 0x30)
|
||||
ret = dev->ld_regs[dev->regs[0x07]][dev->cur_reg - 0x30];
|
||||
ret = dev->ld_regs[ld][reg];
|
||||
/* Write-only registers. */
|
||||
else if ((dev->cur_reg == 0x00) ||
|
||||
(dev->cur_reg == 0x02) || (dev->cur_reg == 0x03))
|
||||
ret = 0x00;
|
||||
else
|
||||
ret = dev->regs[dev->cur_reg];
|
||||
#ifdef ENABLE_PC87309_LOG
|
||||
if (dev->cur_reg >= 0x30)
|
||||
pc87309_log("[%04X:%08X] [R] (%04X) %02X:%02X = %02X\n",
|
||||
CS, cpu_state.pc, port, ld, dev->cur_reg, ret);
|
||||
else
|
||||
pc87309_log("[%04X:%08X] [R] (%04X) %02X = %02X\n",
|
||||
CS, cpu_state.pc, port, dev->cur_reg, ret);
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
pc87309_reset(pc87309_t *dev)
|
||||
pc87309_reset(void *priv)
|
||||
{
|
||||
pc87309_t *dev = (pc87309_t *) priv;
|
||||
|
||||
memset(dev->regs, 0x00, 0x30);
|
||||
for (uint16_t i = 0; i < 256; i++)
|
||||
memset(dev->ld_regs[i], 0x00, 0xd0);
|
||||
@@ -409,65 +593,56 @@ pc87309_reset(pc87309_t *dev)
|
||||
dev->regs[0x20] = dev->id;
|
||||
dev->regs[0x21] = 0x04 | dev->baddr;
|
||||
|
||||
dev->ld_regs[0x00][0x01] = 0x01;
|
||||
dev->ld_regs[0x00][0x30] = 0x03;
|
||||
dev->ld_regs[0x00][0x31] = 0xf2;
|
||||
dev->ld_regs[0x00][0x40] = 0x06;
|
||||
dev->ld_regs[0x00][0x41] = 0x03;
|
||||
dev->ld_regs[0x00][0x44] = 0x02;
|
||||
dev->ld_regs[0x00][0x45] = 0x04;
|
||||
dev->ld_regs[0x00][0xc0] = 0x02;
|
||||
dev->ld_regs[LD_KBD ][0x00] = 0x01;
|
||||
dev->ld_regs[LD_KBD ][0x31] = 0x60;
|
||||
dev->ld_regs[LD_KBD ][0x33] = 0x64;
|
||||
dev->ld_regs[LD_KBD ][0x40] = 0x01;
|
||||
dev->ld_regs[LD_KBD ][0x41] = 0x02;
|
||||
dev->ld_regs[LD_KBD ][0x44] = 0x04;
|
||||
dev->ld_regs[LD_KBD ][0x45] = 0x04;
|
||||
dev->ld_regs[LD_KBD ][0xc0] = 0x40;
|
||||
|
||||
dev->ld_regs[0x01][0x30] = 0x02;
|
||||
dev->ld_regs[0x01][0x31] = 0x78;
|
||||
dev->ld_regs[0x01][0x40] = 0x07;
|
||||
dev->ld_regs[0x01][0x44] = 0x04;
|
||||
dev->ld_regs[0x01][0x45] = 0x04;
|
||||
dev->ld_regs[0x01][0xc0] = 0xf2;
|
||||
dev->ld_regs[LD_MOUSE][0x40] = 0x0c;
|
||||
dev->ld_regs[LD_MOUSE][0x41] = 0x02;
|
||||
dev->ld_regs[LD_MOUSE][0x44] = 0x04;
|
||||
dev->ld_regs[LD_MOUSE][0x45] = 0x04;
|
||||
|
||||
dev->ld_regs[0x02][0x30] = 0x02;
|
||||
dev->ld_regs[0x02][0x31] = 0xf8;
|
||||
dev->ld_regs[0x02][0x40] = 0x03;
|
||||
dev->ld_regs[0x02][0x41] = 0x03;
|
||||
dev->ld_regs[0x02][0x44] = 0x04;
|
||||
dev->ld_regs[0x02][0x45] = 0x04;
|
||||
dev->ld_regs[0x02][0xc0] = 0x02;
|
||||
dev->ld_regs[LD_FDC ][0x01] = 0x01;
|
||||
dev->ld_regs[LD_FDC ][0x30] = 0x03;
|
||||
dev->ld_regs[LD_FDC ][0x31] = 0xf0;
|
||||
dev->ld_regs[LD_FDC ][0x32] = 0x03;
|
||||
dev->ld_regs[LD_FDC ][0x33] = 0xf7;
|
||||
dev->ld_regs[LD_FDC ][0x40] = 0x06;
|
||||
dev->ld_regs[LD_FDC ][0x41] = 0x03;
|
||||
dev->ld_regs[LD_FDC ][0x44] = 0x02;
|
||||
dev->ld_regs[LD_FDC ][0x45] = 0x04;
|
||||
dev->ld_regs[LD_FDC ][0xc0] = 0x02;
|
||||
|
||||
dev->ld_regs[0x03][0x30] = 0x03;
|
||||
dev->ld_regs[0x03][0x31] = 0xf8;
|
||||
dev->ld_regs[0x03][0x40] = 0x04;
|
||||
dev->ld_regs[0x03][0x41] = 0x03;
|
||||
dev->ld_regs[0x03][0x44] = 0x04;
|
||||
dev->ld_regs[0x03][0x45] = 0x04;
|
||||
dev->ld_regs[0x03][0xc0] = 0x02;
|
||||
dev->ld_regs[LD_LPT ][0x30] = 0x02;
|
||||
dev->ld_regs[LD_LPT ][0x31] = 0x78;
|
||||
dev->ld_regs[LD_LPT ][0x40] = 0x07;
|
||||
dev->ld_regs[LD_LPT ][0x44] = 0x04;
|
||||
dev->ld_regs[LD_LPT ][0x45] = 0x04;
|
||||
dev->ld_regs[LD_LPT ][0xc0] = 0xf2;
|
||||
|
||||
dev->ld_regs[0x04][0x44] = 0x04;
|
||||
dev->ld_regs[0x04][0x45] = 0x04;
|
||||
dev->ld_regs[LD_UART2][0x30] = 0x02;
|
||||
dev->ld_regs[LD_UART2][0x31] = 0xf8;
|
||||
dev->ld_regs[LD_UART2][0x40] = 0x03;
|
||||
dev->ld_regs[LD_UART2][0x41] = 0x03;
|
||||
dev->ld_regs[LD_UART2][0x44] = 0x04;
|
||||
dev->ld_regs[LD_UART2][0x45] = 0x04;
|
||||
dev->ld_regs[LD_UART2][0xc0] = 0x02;
|
||||
|
||||
dev->ld_regs[0x05][0x40] = 0x0c;
|
||||
dev->ld_regs[0x05][0x41] = 0x02;
|
||||
dev->ld_regs[0x05][0x44] = 0x04;
|
||||
dev->ld_regs[0x05][0x45] = 0x04;
|
||||
dev->ld_regs[LD_UART1][0x30] = 0x03;
|
||||
dev->ld_regs[LD_UART1][0x31] = 0xf8;
|
||||
dev->ld_regs[LD_UART1][0x40] = 0x04;
|
||||
dev->ld_regs[LD_UART1][0x41] = 0x03;
|
||||
dev->ld_regs[LD_UART1][0x44] = 0x04;
|
||||
dev->ld_regs[LD_UART1][0x45] = 0x04;
|
||||
dev->ld_regs[LD_UART1][0xc0] = 0x02;
|
||||
|
||||
dev->ld_regs[0x06][0x01] = 0x01;
|
||||
dev->ld_regs[0x06][0x31] = 0x60;
|
||||
dev->ld_regs[0x06][0x33] = 0x64;
|
||||
dev->ld_regs[0x06][0x40] = 0x01;
|
||||
dev->ld_regs[0x06][0x41] = 0x02;
|
||||
dev->ld_regs[0x06][0x44] = 0x04;
|
||||
dev->ld_regs[0x06][0x45] = 0x04;
|
||||
dev->ld_regs[0x06][0xc0] = 0x40;
|
||||
|
||||
dev->regs[0x00] = 0x0B;
|
||||
dev->regs[0x01] = 0x01;
|
||||
dev->regs[0x03] = 0x01;
|
||||
dev->regs[0x05] = 0x0D;
|
||||
dev->regs[0x08] = 0x70;
|
||||
dev->regs[0x09] = 0xC0;
|
||||
dev->regs[0x0b] = 0x80;
|
||||
dev->regs[0x0f] = 0x1E;
|
||||
dev->regs[0x12] = 0x30;
|
||||
dev->regs[0x19] = 0xEF;
|
||||
dev->ld_regs[LD_PM ][0x44] = 0x04;
|
||||
dev->ld_regs[LD_PM ][0x45] = 0x04;
|
||||
|
||||
dev->pm[0] = 0x79;
|
||||
dev->pm[4] = 0x0e;
|
||||
@@ -478,11 +653,15 @@ pc87309_reset(pc87309_t *dev)
|
||||
0 = 360 rpm @ 500 kbps for 3.5"
|
||||
1 = Default, 300 rpm @ 500, 300, 250, 1000 kbps for 3.5"
|
||||
*/
|
||||
lpt1_remove();
|
||||
serial_remove(dev->uart[0]);
|
||||
serial_remove(dev->uart[1]);
|
||||
fdc_toggle_flag(dev->fdc, FDC_FLAG_PS2_MCA, 0);
|
||||
fdc_reset(dev->fdc);
|
||||
|
||||
kbc_handler(dev);
|
||||
fdc_handler(dev);
|
||||
lpt1_handler(dev);
|
||||
serial_handler(dev, 0);
|
||||
serial_handler(dev, 1);
|
||||
pm_handler(dev);
|
||||
superio_handler(dev);
|
||||
}
|
||||
|
||||
@@ -503,7 +682,27 @@ pc87309_init(const device_t *info)
|
||||
|
||||
dev->fdc = device_add(&fdc_at_nsc_device);
|
||||
|
||||
dev->baddr = (info->local & 0x100) ? 8 : 9;
|
||||
dev->uart[0] = device_add_inst(&ns16550_device, 1);
|
||||
dev->uart[1] = device_add_inst(&ns16550_device, 2);
|
||||
|
||||
switch (info->local & PCX730X_KBC) {
|
||||
default:
|
||||
case PCX730X_AMI:
|
||||
dev->kbc = device_add(&keyboard_ps2_intel_ami_pci_device);
|
||||
break;
|
||||
/* Optiplex! */
|
||||
case PCX730X_PHOENIX_42:
|
||||
dev->kbc = device_add(&keyboard_ps2_phoenix_device);
|
||||
break;
|
||||
case PCX730X_PHOENIX_42I:
|
||||
dev->kbc = device_add(&keyboard_ps2_phoenix_pci_device);
|
||||
break;
|
||||
}
|
||||
|
||||
if (info->local & PCX730X_15C)
|
||||
dev->baddr = 0x0a;
|
||||
else
|
||||
dev->baddr = 0x0b;
|
||||
|
||||
pc87309_reset(dev);
|
||||
|
||||
@@ -514,24 +713,10 @@ const device_t pc87309_device = {
|
||||
.name = "National Semiconductor PC87309 Super I/O",
|
||||
.internal_name = "pc87309",
|
||||
.flags = 0,
|
||||
.local = 0xe0,
|
||||
.local = 0,
|
||||
.init = pc87309_init,
|
||||
.close = pc87309_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t pc87309_15c_device = {
|
||||
.name = "National Semiconductor PC87309 Super I/O (Port 15Ch)",
|
||||
.internal_name = "pc87309_15c",
|
||||
.flags = 0,
|
||||
.local = 0x1e0,
|
||||
.init = pc87309_init,
|
||||
.close = pc87309_close,
|
||||
.reset = NULL,
|
||||
.reset = pc87309_reset,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
|
||||
@@ -8042,7 +8042,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
|
||||
|
||||
s3->accel.sy = s3->accel.maj_axis_pcnt;
|
||||
if ((s3->bpp == 0) && s3->color_16bit) {
|
||||
s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00);
|
||||
s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00) && rd_mask;
|
||||
if (s3->accel.rd_mask_16bit_check) {
|
||||
if ((s3->accel.cur_x_overflow & 0xc00) == 0xc00)
|
||||
s3->accel.start = 1;
|
||||
@@ -8353,7 +8353,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
|
||||
s3->accel.dest = dstbase + s3->accel.cy * s3->width;
|
||||
|
||||
if ((s3->bpp == 0) && s3->color_16bit) {
|
||||
s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00);
|
||||
s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00) && rd_mask;
|
||||
if (s3->accel.rd_mask_16bit_check) {
|
||||
if (s3->accel.cmd == 0x41b3) {
|
||||
if (frgd_mix == 0) {
|
||||
@@ -8478,9 +8478,10 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
|
||||
if ((s3_cpu_src(s3)) && !(s3->accel.cmd & 0x200)) {
|
||||
s3_log("FIXME: S3 911/924 15/16bpp documentation needed.\n");
|
||||
} else {
|
||||
if (!cpu_input && (s3->accel.cur_x & 0x400))
|
||||
if (!cpu_input && (s3->accel.cur_x & 0x400)) {
|
||||
s3_log("No Input.\n");
|
||||
break;
|
||||
else if (cpu_input && (s3->accel.cmd == 0x53b3) && (s3->accel.cur_x & 0x400))
|
||||
} else if (cpu_input && (s3->accel.cmd == 0x53b3) && (s3->accel.cur_x & 0x400))
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -8756,7 +8757,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
|
||||
s3->accel.cy = s3->accel.cur_y & 0xfff;
|
||||
|
||||
if ((s3->bpp == 0) && s3->color_16bit) {
|
||||
s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00);
|
||||
s3->accel.rd_mask_16bit_check = ((rd_mask & 0xff00) != 0xff00) && rd_mask;
|
||||
if (s3->accel.rd_mask_16bit_check) {
|
||||
if (!(clip_r & 0x400))
|
||||
s3->accel.start = 1;
|
||||
@@ -8805,7 +8806,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi
|
||||
s3_log("CMDFULL=%04x, FRGDSEL=%x, BKGDSEL=%x, FRGDMIX=%02x, BKGDMIX=%02x, MASKCHECK=%x, RDMASK=%04x, MINUS=%d, WRTMASK=%04X, MIX=%04x, CX=%d, CY=%d, DX=%d, DY=%d, SX=%d, SY=%d, PIXCNTL=%02x, 16BITCOLOR=%x, RDCHECK=%x, CLIPL=%d, CLIPR=%d, OVERFLOW=%d, pitch=%d.\n", s3->accel.cmd, frgd_mix, bkgd_mix, s3->accel.frgd_mix & 0x0f, s3->accel.bkgd_mix & 0x0f, s3->accel.rd_mask_16bit_check, rd_mask, s3->accel.minus, wrt_mask, mix_dat & 0xffff, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy, s3->accel.sx, s3->accel.sy, s3->accel.multifunc[0x0a] & 0xc4, s3->accel.color_16bit_check, s3->accel.rd_mask_16bit_check, clip_l, clip_r, (s3->accel.destx_overflow & 0xc00) == 0xc00, s3->width);
|
||||
|
||||
if (!cpu_input && (frgd_mix == 3) && !vram_mask && !(s3->accel.multifunc[0xe] & 0x100) && ((s3->accel.cmd & 0xa0) == 0xa0) && ((s3->accel.frgd_mix & 0xf) == 7) && ((s3->accel.bkgd_mix & 0xf) == 7)) {
|
||||
pclog("Special BitBLT.\n");
|
||||
s3_log("Special BitBLT.\n");
|
||||
while (1) {
|
||||
if ((s3->accel.dx >= clip_l) && (s3->accel.dx <= clip_r) && (s3->accel.dy >= clip_t) && (s3->accel.dy <= clip_b)) {
|
||||
READ(s3->accel.src + s3->accel.cx - s3->accel.minus, src_dat);
|
||||
|
||||
Reference in New Issue
Block a user