Implement I/O port traps on PIIX and VIA ACPI
This commit is contained in:
103
src/acpi.c
103
src/acpi.c
@@ -63,13 +63,10 @@ acpi_log(const char *fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
acpi_update_irq(void *priv)
|
||||
void
|
||||
acpi_update_irq(acpi_t *dev)
|
||||
{
|
||||
acpi_t *dev = (acpi_t *) priv;
|
||||
int sci_level;
|
||||
|
||||
sci_level = (dev->regs.pmsts & dev->regs.pmen) & (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN);
|
||||
int sci_level = (dev->regs.pmsts & dev->regs.pmen) & (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN);
|
||||
if (dev->vendor == VEN_SMC)
|
||||
sci_level |= (dev->regs.pmsts & BM_STS);
|
||||
|
||||
@@ -87,11 +84,9 @@ acpi_update_irq(void *priv)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
acpi_raise_smi(void *priv)
|
||||
void
|
||||
acpi_raise_smi(acpi_t *dev)
|
||||
{
|
||||
acpi_t *dev = (acpi_t *) priv;
|
||||
|
||||
if (dev->regs.glbctl & 0x01) {
|
||||
if ((dev->vendor == VEN_VIA) || (dev->vendor == VEN_VIA_596B)) {
|
||||
if ((!dev->regs.smi_lock || !dev->regs.smi_active)) {
|
||||
@@ -530,10 +525,11 @@ acpi_reg_read_via_596b(int size, uint16_t addr, void *p)
|
||||
shift32 = (addr & 3) << 3;
|
||||
|
||||
switch (addr) {
|
||||
case 0x42:
|
||||
/* GPIO port Output Value */
|
||||
if (size == 1)
|
||||
ret = dev->regs.gpio_val & 0x13;
|
||||
case 0x40: /* Extended I/O Trap Status (686A/B) */
|
||||
ret = dev->regs.extiotrapsts;
|
||||
break;
|
||||
case 0x42: /* Extended I/O Trap Enable (686A/B) */
|
||||
ret = dev->regs.extiotrapen;
|
||||
break;
|
||||
case 0x44: case 0x45:
|
||||
/* External SMI Input Value */
|
||||
@@ -817,6 +813,8 @@ acpi_reg_write_intel(int size, uint16_t addr, uint8_t val, void *p)
|
||||
case 0x2c: case 0x2d: case 0x2e: case 0x2f:
|
||||
/* DEVCTL - Device Control Register (IO) */
|
||||
dev->regs.devctl = ((dev->regs.devctl & ~(0xff << shift32)) | (val << shift32)) & 0x0fffffff;
|
||||
if (dev->trap_update)
|
||||
dev->trap_update(dev->trap_priv);
|
||||
break;
|
||||
case 0x34: case 0x35: case 0x36: case 0x37:
|
||||
/* GPOREG - General Purpose Output Register (IO) */
|
||||
@@ -957,14 +955,6 @@ acpi_reg_write_via_common(int size, uint16_t addr, uint8_t val, void *p)
|
||||
/* Power Supply Control */
|
||||
dev->regs.pscntrl = ((dev->regs.pscntrl & ~(0xff << shift16)) | (val << shift16)) & 0x0701;
|
||||
break;
|
||||
case 0x28: case 0x29:
|
||||
/* GLBSTS - Global Status Register (IO) */
|
||||
dev->regs.glbsts &= ~((val << shift16) & 0x007f);
|
||||
break;
|
||||
case 0x2a: case 0x2b:
|
||||
/* GLBEN - Global Enable Register (IO) */
|
||||
dev->regs.glben = ((dev->regs.glben & ~(0xff << shift16)) | (val << shift16)) & 0x007f;
|
||||
break;
|
||||
case 0x2c:
|
||||
/* GLBCTL - Global Control Register (IO) */
|
||||
dev->regs.glbctl = (dev->regs.glbctl & ~0xff) | (val & 0xff);
|
||||
@@ -991,14 +981,6 @@ acpi_reg_write_via_common(int size, uint16_t addr, uint8_t val, void *p)
|
||||
acpi_raise_smi(dev);
|
||||
}
|
||||
break;
|
||||
case 0x30: case 0x31: case 0x32: case 0x33:
|
||||
/* Primary Activity Detect Status */
|
||||
dev->regs.padsts &= ~((val << shift32) & 0x000000fd);
|
||||
break;
|
||||
case 0x34: case 0x35: case 0x36: case 0x37:
|
||||
/* Primary Activity Detect Enable */
|
||||
dev->regs.paden = ((dev->regs.paden & ~(0xff << shift32)) | (val << shift32)) & 0x000000fd;
|
||||
break;
|
||||
case 0x38: case 0x39: case 0x3a: case 0x3b:
|
||||
/* GP Timer Reload Enable */
|
||||
dev->regs.gptren = ((dev->regs.gptren & ~(0xff << shift32)) | (val << shift32)) & 0x000000d9;
|
||||
@@ -1030,13 +1012,32 @@ static void
|
||||
acpi_reg_write_via(int size, uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
acpi_t *dev = (acpi_t *) p;
|
||||
int shift16;
|
||||
int shift16, shift32;
|
||||
|
||||
addr &= 0xff;
|
||||
acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val);
|
||||
shift16 = (addr & 1) << 3;
|
||||
shift32 = (addr & 3) << 3;
|
||||
|
||||
switch (addr) {
|
||||
case 0x28: case 0x29:
|
||||
/* GLBSTS - Global Status Register (IO) */
|
||||
dev->regs.glbsts &= ~((val << shift16) & 0x007f);
|
||||
break;
|
||||
case 0x2a: case 0x2b:
|
||||
/* GLBEN - Global Enable Register (IO) */
|
||||
dev->regs.glben = ((dev->regs.glben & ~(0xff << shift16)) | (val << shift16)) & 0x007f;
|
||||
break;
|
||||
case 0x30: case 0x31: case 0x32: case 0x33:
|
||||
/* Primary Activity Detect Status */
|
||||
dev->regs.padsts &= ~((val << shift32) & 0x000000fd);
|
||||
break;
|
||||
case 0x34: case 0x35: case 0x36: case 0x37:
|
||||
/* Primary Activity Detect Enable */
|
||||
dev->regs.paden = ((dev->regs.paden & ~(0xff << shift32)) | (val << shift32)) & 0x000000fd;
|
||||
if (dev->trap_update)
|
||||
dev->trap_update(dev->trap_priv);
|
||||
break;
|
||||
case 0x40:
|
||||
/* GPIO Direction Control */
|
||||
if (size == 1) {
|
||||
@@ -1066,17 +1067,37 @@ static void
|
||||
acpi_reg_write_via_596b(int size, uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
acpi_t *dev = (acpi_t *) p;
|
||||
int shift32;
|
||||
int shift16, shift32;
|
||||
|
||||
addr &= 0x7f;
|
||||
acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val);
|
||||
shift16 = (addr & 1) << 3;
|
||||
shift32 = (addr & 3) << 3;
|
||||
|
||||
switch (addr) {
|
||||
case 0x42:
|
||||
/* GPIO port Output Value */
|
||||
if (size == 1)
|
||||
dev->regs.gpio_val = val & 0x13;
|
||||
case 0x28: case 0x29:
|
||||
/* GLBSTS - Global Status Register (IO) */
|
||||
dev->regs.glbsts &= ~((val << shift16) & 0xfdff);
|
||||
break;
|
||||
case 0x2a: case 0x2b:
|
||||
/* GLBEN - Global Enable Register (IO) */
|
||||
dev->regs.glben = ((dev->regs.glben & ~(0xff << shift16)) | (val << shift16)) & 0xfdff;
|
||||
break;
|
||||
case 0x30: case 0x31: case 0x32: case 0x33:
|
||||
/* Primary Activity Detect Status */
|
||||
dev->regs.padsts &= ~((val << shift32) & 0x000007ff);
|
||||
break;
|
||||
case 0x34: case 0x35: case 0x36: case 0x37:
|
||||
/* Primary Activity Detect Enable */
|
||||
dev->regs.paden = ((dev->regs.paden & ~(0xff << shift32)) | (val << shift32)) & 0x000007ff;
|
||||
if (dev->trap_update)
|
||||
dev->trap_update(dev->trap_priv);
|
||||
break;
|
||||
case 0x40: /* Extended I/O Trap Status (686A/B) */
|
||||
dev->regs.extiotrapsts &= ~(val & 0x13);
|
||||
break;
|
||||
case 0x42: /* Extended I/O Trap Enable (686A/B) */
|
||||
dev->regs.extiotrapen = val & 0x13;
|
||||
break;
|
||||
case 0x4c: case 0x4d: case 0x4e: case 0x4f:
|
||||
/* GPO Port Output Value */
|
||||
@@ -1534,6 +1555,14 @@ acpi_set_nvr(acpi_t *dev, nvr_t *nvr)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
acpi_set_trap_update(acpi_t *dev, void (*update)(void *priv), void *priv)
|
||||
{
|
||||
dev->trap_update = update;
|
||||
dev->trap_priv = priv;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
acpi_apm_out(uint16_t port, uint8_t val, void *p)
|
||||
{
|
||||
@@ -1771,7 +1800,7 @@ const device_t acpi_via_device =
|
||||
|
||||
const device_t acpi_via_596b_device =
|
||||
{
|
||||
"VIA ACPI (VT82C596B)",
|
||||
"VIA VT82C596 ACPI",
|
||||
DEVICE_PCI,
|
||||
VEN_VIA_596B,
|
||||
acpi_init,
|
||||
|
@@ -49,8 +49,14 @@
|
||||
#include <86box/chipset.h>
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
struct _piix_ *dev;
|
||||
void *trap;
|
||||
uint8_t dev_id;
|
||||
uint32_t *sts_reg, *en_reg, sts_mask, en_mask;
|
||||
} piix_io_trap_t;
|
||||
|
||||
typedef struct _piix_ {
|
||||
uint8_t cur_readout_reg, rev,
|
||||
type, func_shift,
|
||||
max_func, pci_slot,
|
||||
@@ -66,6 +72,7 @@ typedef struct
|
||||
ddma_t * ddma;
|
||||
usb_t * usb;
|
||||
acpi_t * acpi;
|
||||
piix_io_trap_t io_traps[26];
|
||||
port_92_t * port_92;
|
||||
pc_timer_t fast_off_timer;
|
||||
} piix_t;
|
||||
@@ -265,6 +272,148 @@ nvr_update_io_mapping(piix_t *dev)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
piix_trap_io(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv)
|
||||
{
|
||||
piix_io_trap_t *trap = (piix_io_trap_t *) priv;
|
||||
|
||||
if (*(trap->en_reg) & trap->en_mask) {
|
||||
*(trap->sts_reg) |= trap->sts_mask;
|
||||
acpi_raise_smi(trap->dev->acpi);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
piix_trap_update_devctl(piix_t *dev, uint8_t trap_id, uint8_t dev_id,
|
||||
uint32_t devctl_mask, uint8_t enable,
|
||||
uint16_t addr, uint16_t size)
|
||||
{
|
||||
piix_io_trap_t *trap = &dev->io_traps[trap_id];
|
||||
enable = (dev->acpi->regs.devctl & devctl_mask) && enable;
|
||||
|
||||
/* Set up Device I/O traps dynamically. */
|
||||
if (enable && !trap->trap) {
|
||||
trap->dev = dev;
|
||||
trap->trap = io_trap_add(piix_trap_io, trap);
|
||||
trap->dev_id = dev_id;
|
||||
trap->sts_reg = &dev->acpi->regs.devsts;
|
||||
trap->sts_mask = 0x00010000 << dev_id;
|
||||
trap->en_reg = &dev->acpi->regs.devctl;
|
||||
trap->en_mask = devctl_mask;
|
||||
}
|
||||
|
||||
//#ifdef ENABLE_PIIX_LOG
|
||||
if ((dev_id == 9) || (dev_id == 10) || (dev_id == 12) || (dev_id == 13))
|
||||
pclog("PIIX: Mapping trap device %d to %04X-%04X (enable %d)\n", dev_id, addr, addr + size - 1, enable);
|
||||
//#endif
|
||||
|
||||
/* Remap I/O trap. */
|
||||
io_trap_remap(trap->trap, enable, addr, size);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
piix_trap_update(void *priv)
|
||||
{
|
||||
piix_t *dev = (piix_t *) priv;
|
||||
uint8_t trap_id = 0, *fregs = dev->regs[3];
|
||||
uint16_t temp;
|
||||
|
||||
piix_trap_update_devctl(dev, trap_id++, 0, 0x00000002, 1, 0x1f0, 8);
|
||||
piix_trap_update_devctl(dev, trap_id++, 0, 0x00000002, 1, 0x3f6, 1);
|
||||
|
||||
piix_trap_update_devctl(dev, trap_id++, 1, 0x00000008, 1, 0x1f0, 8);
|
||||
piix_trap_update_devctl(dev, trap_id++, 1, 0x00000008, 1, 0x3f6, 1);
|
||||
|
||||
piix_trap_update_devctl(dev, trap_id++, 2, 0x00000020, 1, 0x170, 8);
|
||||
piix_trap_update_devctl(dev, trap_id++, 2, 0x00000020, 1, 0x376, 1);
|
||||
|
||||
piix_trap_update_devctl(dev, trap_id++, 3, 0x00000080, 1, 0x170, 8);
|
||||
piix_trap_update_devctl(dev, trap_id++, 3, 0x00000080, 1, 0x376, 1);
|
||||
|
||||
piix_trap_update_devctl(dev, trap_id++, 4, 0x00000200, fregs[0x5c] & 0x08, 0x220 + (0x20 * ((fregs[0x5c] >> 5) & 0x03)), 20);
|
||||
piix_trap_update_devctl(dev, trap_id++, 4, 0x00000200, fregs[0x5c] & 0x10, 0x200, 8);
|
||||
piix_trap_update_devctl(dev, trap_id++, 4, 0x00000200, fregs[0x5c] & 0x08, 0x388, 4);
|
||||
switch (fregs[0x5d] & 0x03) {
|
||||
case 0x00: temp = 0x530; break;
|
||||
case 0x01: temp = 0x604; break;
|
||||
case 0x02: temp = 0xe80; break;
|
||||
default: temp = 0xf40; break;
|
||||
}
|
||||
piix_trap_update_devctl(dev, trap_id++, 4, 0x00000200, fregs[0x5c] & 0x80, temp, 8);
|
||||
piix_trap_update_devctl(dev, trap_id++, 4, 0x00000200, fregs[0x5c] & 0x01, 0x300 + (0x10 * ((fregs[0x5c] >> 1) & 0x03)), 4);
|
||||
|
||||
piix_trap_update_devctl(dev, trap_id++, 5, 0x00000800, fregs[0x51] & 0x10, 0x370 + (0x80 * !(fregs[0x63] & 0x10)), 6);
|
||||
piix_trap_update_devctl(dev, trap_id++, 5, 0x00000800, fregs[0x51] & 0x10, 0x377 + (0x80 * !(fregs[0x63] & 0x10)), 1);
|
||||
|
||||
switch (fregs[0x67] & 0x07) {
|
||||
case 0x00: temp = 0x3f8; break;
|
||||
case 0x01: temp = 0x2f8; break;
|
||||
case 0x02: temp = 0x220; break;
|
||||
case 0x03: temp = 0x228; break;
|
||||
case 0x04: temp = 0x238; break;
|
||||
case 0x05: temp = 0x2e8; break;
|
||||
case 0x06: temp = 0x338; break;
|
||||
default: temp = 0x3e8; break;
|
||||
}
|
||||
piix_trap_update_devctl(dev, trap_id++, 6, 0x00002000, fregs[0x51] & 0x40, temp, 8);
|
||||
|
||||
switch (fregs[0x67] & 0x70) {
|
||||
case 0x00: temp = 0x3f8; break;
|
||||
case 0x10: temp = 0x2f8; break;
|
||||
case 0x20: temp = 0x220; break;
|
||||
case 0x30: temp = 0x228; break;
|
||||
case 0x40: temp = 0x238; break;
|
||||
case 0x50: temp = 0x2e8; break;
|
||||
case 0x60: temp = 0x338; break;
|
||||
default: temp = 0x3e8; break;
|
||||
}
|
||||
piix_trap_update_devctl(dev, trap_id++, 7, 0x00008000, fregs[0x52] & 0x01, temp, 8);
|
||||
|
||||
switch (fregs[0x63] & 0x06) {
|
||||
case 0x00:
|
||||
piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0x3bc, 4);
|
||||
piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0x7bc, 3);
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0x378, 8);
|
||||
piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0x778, 3);
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0x278, 8);
|
||||
piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0x678, 3);
|
||||
break;
|
||||
|
||||
default:
|
||||
piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0, 0);
|
||||
piix_trap_update_devctl(dev, trap_id++, 8, 0x00020000, fregs[0x52] & 0x04, 0, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
temp = fregs[0x62] & 0x0f;
|
||||
piix_trap_update_devctl(dev, trap_id++, 9, 0x00080000, fregs[0x62] & 0x20, (fregs[0x60] | (fregs[0x61] << 8)) & ~temp, temp + 1);
|
||||
|
||||
temp = fregs[0x66] & 0x0f;
|
||||
piix_trap_update_devctl(dev, trap_id++, 10, 0x00200000, fregs[0x66] & 0x20, (fregs[0x64] | (fregs[0x65] << 8)) & ~temp, temp + 1);
|
||||
|
||||
piix_trap_update_devctl(dev, trap_id++, 11, 0x00800000, fregs[0x5f] & 0x04, 0x3b0, 48);
|
||||
piix_trap_update_devctl(dev, trap_id++, 11, 0x00800000, fregs[0x5f] & 0x10, 0x60, 1);
|
||||
piix_trap_update_devctl(dev, trap_id++, 11, 0x00800000, fregs[0x5f] & 0x10, 0x64, 1);
|
||||
/* [A0000:BFFFF] memory trap not implemented. */
|
||||
|
||||
temp = fregs[0x6a] & 0x0f;
|
||||
piix_trap_update_devctl(dev, trap_id++, 12, 0x01000000, fregs[0x6a] & 0x10, (fregs[0x68] | (fregs[0x69] << 8)) & ~temp, temp + 1);
|
||||
/* Programmable memory trap not implemented. */
|
||||
|
||||
temp = fregs[0x72] & 0x0f;
|
||||
piix_trap_update_devctl(dev, trap_id++, 13, 0x02000000, fregs[0x72] & 0x10, (fregs[0x70] | (fregs[0x71] << 8)) & ~temp, temp + 1);
|
||||
/* Programmable memory trap not implemented. */
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
piix_write(int func, int addr, uint8_t val, void *priv)
|
||||
{
|
||||
@@ -835,6 +984,10 @@ piix_write(int func, int addr, uint8_t val, void *priv)
|
||||
case 0xd3: case 0xd4:
|
||||
case 0xd5:
|
||||
fregs[addr] = val;
|
||||
if ((addr == 0x5c) || (addr == 0x60) || (addr == 0x61) || (addr == 0x62) ||
|
||||
(addr == 0x64) || (addr == 0x65) || (addr == 0x68) || (addr == 0x69) ||
|
||||
(addr == 0x70) || (addr == 0x71))
|
||||
piix_trap_update(dev);
|
||||
break;
|
||||
case 0x4a:
|
||||
fregs[addr] = val & 0x73;
|
||||
@@ -854,9 +1007,11 @@ piix_write(int func, int addr, uint8_t val, void *priv)
|
||||
break;
|
||||
case 0x51:
|
||||
fregs[addr] = val & 0x58;
|
||||
piix_trap_update(dev);
|
||||
break;
|
||||
case 0x52:
|
||||
fregs[addr] = val & 0x7f;
|
||||
piix_trap_update(dev);
|
||||
break;
|
||||
case 0x58:
|
||||
fregs[addr] = val & 0x77;
|
||||
@@ -867,12 +1022,16 @@ piix_write(int func, int addr, uint8_t val, void *priv)
|
||||
break;
|
||||
case 0x63:
|
||||
fregs[addr] = val & 0xf7;
|
||||
piix_trap_update(dev);
|
||||
break;
|
||||
case 0x66:
|
||||
fregs[addr] = val & 0xef;
|
||||
piix_trap_update(dev);
|
||||
break;
|
||||
case 0x6a: case 0x72: case 0x7a: case 0x7e:
|
||||
fregs[addr] = val & 0x1f;
|
||||
if ((addr == 0x6a) || (addr == 0x72))
|
||||
piix_trap_update(dev);
|
||||
break;
|
||||
case 0x6d: case 0x75:
|
||||
fregs[addr] = val & 0x80;
|
||||
@@ -1297,6 +1456,7 @@ static void
|
||||
acpi_set_slot(dev->acpi, dev->pci_slot);
|
||||
acpi_set_nvr(dev->acpi, dev->nvr);
|
||||
acpi_set_gpireg2_default(dev->acpi, (dev->type > 4) ? 0xf1 : 0xdd);
|
||||
acpi_set_trap_update(dev->acpi, piix_trap_update, dev);
|
||||
|
||||
dev->ddma = device_add(&ddma_device);
|
||||
} else
|
||||
|
@@ -67,23 +67,69 @@
|
||||
#define VIA_PIPC_8231 0x82311000
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
enum {
|
||||
TRAP_DRQ = 0,
|
||||
TRAP_PIRQ,
|
||||
TRAP_PIDE_MAIN,
|
||||
TRAP_PIDE_SIDE,
|
||||
TRAP_SIDE_MAIN,
|
||||
TRAP_SIDE_SIDE,
|
||||
TRAP_FLP_MAIN,
|
||||
TRAP_FLP_SIDE,
|
||||
TRAP_COM1,
|
||||
TRAP_COM3,
|
||||
TRAP_COM2,
|
||||
TRAP_COM4,
|
||||
TRAP_LPT_LPT1,
|
||||
TRAP_LPT_LPT2,
|
||||
TRAP_VGA,
|
||||
TRAP_KBC,
|
||||
TRAP_AUD_MIDI_0,
|
||||
TRAP_AUD_MIDI_1,
|
||||
TRAP_AUD_MIDI_2,
|
||||
TRAP_AUD_MIDI_3,
|
||||
TRAP_AUD_SB_0,
|
||||
TRAP_AUD_SB_1,
|
||||
TRAP_AUD_SB_2,
|
||||
TRAP_AUD_SB_3,
|
||||
TRAP_AUD_GAME,
|
||||
TRAP_AUD_WSS_0,
|
||||
TRAP_AUD_WSS_1,
|
||||
TRAP_AUD_WSS_2,
|
||||
TRAP_AUD_WSS_3,
|
||||
TRAP_GR0,
|
||||
TRAP_GR1,
|
||||
TRAP_GR2,
|
||||
TRAP_GR3,
|
||||
TRAP_MAX
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
struct _pipc_ *dev;
|
||||
void *trap;
|
||||
uint32_t *sts_reg, *en_reg, mask;
|
||||
} pipc_io_trap_t;
|
||||
|
||||
typedef struct _pipc_ {
|
||||
uint32_t local;
|
||||
uint8_t max_func;
|
||||
uint8_t max_func, max_pcs;
|
||||
|
||||
uint8_t pci_isa_regs[256],
|
||||
ide_regs[256],
|
||||
usb_regs[2][256],
|
||||
power_regs[256],
|
||||
ac97_regs[2][256], fmnmi_regs[4];
|
||||
|
||||
sff8038i_t *bm[2];
|
||||
nvr_t *nvr;
|
||||
int nvr_enabled, slot;
|
||||
ddma_t *ddma;
|
||||
smbus_piix4_t *smbus;
|
||||
usb_t *usb[2];
|
||||
|
||||
acpi_t *acpi;
|
||||
pipc_io_trap_t io_traps[TRAP_MAX];
|
||||
|
||||
void *gameport, *ac97;
|
||||
sb_t *sb;
|
||||
uint16_t midigame_base, sb_base, fmnmi_base;
|
||||
@@ -117,6 +163,32 @@ static uint8_t pipc_read(int func, int addr, void *priv);
|
||||
static void pipc_write(int func, int addr, uint8_t val, void *priv);
|
||||
|
||||
|
||||
static void
|
||||
pipc_trap_io_pact(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv)
|
||||
{
|
||||
pipc_io_trap_t *trap = (pipc_io_trap_t *) priv;
|
||||
|
||||
if (*(trap->en_reg) & trap->mask) {
|
||||
*(trap->sts_reg) |= trap->mask;
|
||||
trap->dev->acpi->regs.glbsts |= 0x0001;
|
||||
if (trap->dev->acpi->regs.glben & 0x0001)
|
||||
acpi_raise_smi(trap->dev->acpi);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pipc_io_trap_glb(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv)
|
||||
{
|
||||
pipc_io_trap_t *trap = (pipc_io_trap_t *) priv;
|
||||
|
||||
if (*(trap->en_reg) & trap->mask) {
|
||||
*(trap->sts_reg) |= trap->mask;
|
||||
acpi_raise_smi(trap->dev->acpi);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pipc_reset_hard(void *priv)
|
||||
{
|
||||
@@ -136,7 +208,7 @@ pipc_reset_hard(void *priv)
|
||||
memset(dev->power_regs, 0, 256);
|
||||
memset(dev->ac97_regs, 0, 512);
|
||||
|
||||
/* PCI-ISA bridge registers */
|
||||
/* PCI-ISA bridge registers. */
|
||||
dev->pci_isa_regs[0x00] = 0x06; dev->pci_isa_regs[0x01] = 0x11;
|
||||
dev->pci_isa_regs[0x02] = dev->local >> 16;
|
||||
dev->pci_isa_regs[0x03] = dev->local >> 24;
|
||||
@@ -164,7 +236,9 @@ pipc_reset_hard(void *priv)
|
||||
|
||||
pic_set_shadow(0);
|
||||
|
||||
/* IDE registers */
|
||||
dev->max_pcs = (dev->local >= VIA_PIPC_686A) ? 3 : 1;
|
||||
|
||||
/* IDE registers. */
|
||||
dev->max_func++;
|
||||
dev->ide_regs[0x00] = 0x06; dev->ide_regs[0x01] = 0x11;
|
||||
dev->ide_regs[0x02] = 0x71; dev->ide_regs[0x03] = 0x05;
|
||||
@@ -212,7 +286,7 @@ pipc_reset_hard(void *priv)
|
||||
dev->ide_regs[0xc2] = 0x02;
|
||||
}
|
||||
|
||||
/* USB registers */
|
||||
/* USB registers. */
|
||||
for (i = 0; i <= (dev->local >= VIA_PIPC_686A); i++) {
|
||||
dev->max_func++;
|
||||
dev->usb_regs[i][0x00] = 0x06; dev->usb_regs[i][0x01] = 0x11;
|
||||
@@ -260,7 +334,7 @@ pipc_reset_hard(void *priv)
|
||||
dev->usb_regs[i][0xc1] = 0x20;
|
||||
}
|
||||
|
||||
/* power management registers */
|
||||
/* Power management registers. */
|
||||
if (dev->acpi) {
|
||||
dev->max_func++;
|
||||
dev->power_regs[0x00] = 0x06; dev->power_regs[0x01] = 0x11;
|
||||
@@ -317,9 +391,26 @@ pipc_reset_hard(void *priv)
|
||||
dev->power_regs[0x80] = 0x01;
|
||||
else if (dev->local >= VIA_PIPC_596B)
|
||||
dev->power_regs[0x90] = 0x01;
|
||||
|
||||
/* Set up PCS I/O traps. */
|
||||
pipc_io_trap_t *trap;
|
||||
for (i = 0; i <= dev->max_pcs; i++) {
|
||||
trap = &dev->io_traps[TRAP_GR0 + i];
|
||||
trap->dev = dev;
|
||||
trap->trap = io_trap_add(pipc_io_trap_glb, trap);
|
||||
if (i & 2) {
|
||||
trap->sts_reg = (uint32_t *) &dev->acpi->regs.extiotrapsts;
|
||||
trap->en_reg = (uint32_t *) &dev->acpi->regs.extiotrapen;
|
||||
trap->mask = 0x01 << (i & 1);
|
||||
} else {
|
||||
trap->sts_reg = &dev->acpi->regs.glbsts;
|
||||
trap->en_reg = &dev->acpi->regs.glben;
|
||||
trap->mask = 0x4000 << i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* AC97/MC97 registers */
|
||||
/* AC97/MC97 registers. */
|
||||
if (dev->local >= VIA_PIPC_686A) {
|
||||
for (i = 0; i <= 1; i++) {
|
||||
dev->max_func++;
|
||||
@@ -459,6 +550,139 @@ pipc_bus_master_handlers(pipc_t *dev)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pipc_pcs_update(pipc_t *dev)
|
||||
{
|
||||
uint8_t i, io_base_reg, io_mask_reg, io_mask_shift, enable;
|
||||
uint16_t io_base, io_mask;
|
||||
|
||||
for (i = 0; i <= dev->max_pcs; i++) {
|
||||
if (i & 2) {
|
||||
io_base_reg = 0x8c;
|
||||
io_mask_reg = 0x8a;
|
||||
} else {
|
||||
io_base_reg = 0x78;
|
||||
io_mask_reg = 0x80;
|
||||
}
|
||||
io_base_reg |= (i & 1) << 1;
|
||||
io_mask_shift = (i & 1) << 2;
|
||||
|
||||
if (dev->local <= VIA_PIPC_596B)
|
||||
enable = dev->pci_isa_regs[0x76] & (0x10 << i);
|
||||
else
|
||||
enable = dev->pci_isa_regs[0x8b] & (0x01 << i);
|
||||
|
||||
io_base = dev->pci_isa_regs[io_base_reg] | (dev->pci_isa_regs[io_base_reg | 1] << 8);
|
||||
io_mask = (dev->pci_isa_regs[io_mask_reg] >> io_mask_shift) & 0x000f;
|
||||
|
||||
pipc_log("PIPC: Mapping PCS%d to %04X-%04X (enable %d)\n", i, io_base, io_base + io_mask, enable);
|
||||
io_trap_remap(dev->io_traps[TRAP_GR0 + i].trap, enable, io_base & ~io_mask, io_mask + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pipc_trap_update_paden(pipc_t *dev, uint8_t trap_id,
|
||||
uint32_t paden_mask, uint8_t enable,
|
||||
uint16_t addr, uint16_t size)
|
||||
{
|
||||
pipc_io_trap_t *trap = &dev->io_traps[trap_id];
|
||||
enable = (dev->acpi->regs.paden & paden_mask) && enable;
|
||||
|
||||
/* Set up Primary Activity Detect I/O traps dynamically. */
|
||||
if (enable && !trap->trap) {
|
||||
trap->dev = dev;
|
||||
trap->trap = io_trap_add(pipc_trap_io_pact, trap);
|
||||
trap->sts_reg = &dev->acpi->regs.padsts;
|
||||
trap->en_reg = &dev->acpi->regs.paden;
|
||||
trap->mask = paden_mask;
|
||||
}
|
||||
|
||||
/* Remap I/O trap. */
|
||||
io_trap_remap(trap->trap, enable, addr, size);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pipc_trap_update_586(void *priv)
|
||||
{
|
||||
pipc_t *dev = (pipc_t *) priv;
|
||||
|
||||
/* TRAP_DRQ (00000001) and TRAP_PIRQ (00000002) not implemented. */
|
||||
|
||||
pipc_trap_update_paden(dev, TRAP_PIDE_MAIN, 0x00000008, 1, 0x1f0, 8);
|
||||
pipc_trap_update_paden(dev, TRAP_SIDE_MAIN, 0x00000008, 1, 0x170, 8);
|
||||
pipc_trap_update_paden(dev, TRAP_FLP_MAIN, 0x00000008, 1, 0x3f5, 1);
|
||||
|
||||
pipc_trap_update_paden(dev, TRAP_VGA, 0x00000010, 1, 0x3b0, 48);
|
||||
/* [A0000:BFFFF] memory trap not implemented. */
|
||||
|
||||
pipc_trap_update_paden(dev, TRAP_LPT_LPT1, 0x00000020, 1, 0x378, 8);
|
||||
pipc_trap_update_paden(dev, TRAP_LPT_LPT2, 0x00000020, 1, 0x278, 8);
|
||||
|
||||
pipc_trap_update_paden(dev, TRAP_COM1, 0x00000040, 1, 0x3f8, 8);
|
||||
pipc_trap_update_paden(dev, TRAP_COM2, 0x00000040, 1, 0x2f8, 8);
|
||||
pipc_trap_update_paden(dev, TRAP_COM3, 0x00000040, 1, 0x3e8, 8);
|
||||
pipc_trap_update_paden(dev, TRAP_COM4, 0x00000040, 1, 0x2e8, 8);
|
||||
|
||||
pipc_trap_update_paden(dev, TRAP_KBC, 0x00000080, 1, 0x60, 1);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pipc_trap_update_596(void *priv)
|
||||
{
|
||||
pipc_t *dev = (pipc_t *) priv;
|
||||
int i;
|
||||
|
||||
/* TRAP_DRQ (00000001) and TRAP_PIRQ (00000002) not implemented. */
|
||||
|
||||
pipc_trap_update_paden(dev, TRAP_PIDE_MAIN, 0x00000004, 1, 0x1f0, 8);
|
||||
pipc_trap_update_paden(dev, TRAP_PIDE_SIDE, 0x00000004, 1, 0x3f6, 1);
|
||||
|
||||
pipc_trap_update_paden(dev, TRAP_SIDE_MAIN, 0x00000008, 1, 0x170, 8);
|
||||
pipc_trap_update_paden(dev, TRAP_SIDE_SIDE, 0x00000008, 1, 0x376, 1);
|
||||
|
||||
pipc_trap_update_paden(dev, TRAP_FLP_MAIN, 0x00000010, 1, 0x3f0, 6);
|
||||
pipc_trap_update_paden(dev, TRAP_FLP_SIDE, 0x00000010, 1, 0x3f7, 1);
|
||||
|
||||
pipc_trap_update_paden(dev, TRAP_COM1, 0x00000020, 1, 0x3f8, 8);
|
||||
pipc_trap_update_paden(dev, TRAP_COM3, 0x00000020, 1, 0x3e8, 8);
|
||||
|
||||
pipc_trap_update_paden(dev, TRAP_COM2, 0x00000040, 1, 0x2f8, 8);
|
||||
pipc_trap_update_paden(dev, TRAP_COM4, 0x00000040, 1, 0x2e8, 8);
|
||||
|
||||
pipc_trap_update_paden(dev, TRAP_LPT_LPT1, 0x00000080, 1, 0x378, 8);
|
||||
pipc_trap_update_paden(dev, TRAP_LPT_LPT2, 0x00000080, 1, 0x278, 8);
|
||||
|
||||
pipc_trap_update_paden(dev, TRAP_VGA, 0x00000100, 1, 0x3b0, 48);
|
||||
/* [A0000:BFFFF] memory trap not implemented. */
|
||||
|
||||
pipc_trap_update_paden(dev, TRAP_KBC, 0x00000200, 1, 0x60, 1);
|
||||
|
||||
/* The following traps are poorly documented and assumed to operate on all ranges allowed
|
||||
by the Positive Decoding Control registers. I couldn't probe this behavior on hardware.
|
||||
It's better to be safe and cover all of them than to assume Intel-like behavior (one range). */
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
pipc_trap_update_paden(dev, TRAP_AUD_MIDI_0 + i,
|
||||
0x00000400, (dev->local <= VIA_PIPC_596B) || (dev->power_regs[0x40] & 0x01),
|
||||
0x300 + (0x10 * i), 4);
|
||||
|
||||
pipc_trap_update_paden(dev, TRAP_AUD_SB_0 + i,
|
||||
0x00000400, (dev->local <= VIA_PIPC_596B) || (dev->power_regs[0x40] & 0x02),
|
||||
0x220 + (0x20 * i), 20);
|
||||
}
|
||||
|
||||
pipc_trap_update_paden(dev, TRAP_AUD_GAME, 0x00000400, (dev->local <= VIA_PIPC_596B) || (dev->power_regs[0x40] & 0x04), 0x200, 8);
|
||||
|
||||
pipc_trap_update_paden(dev, TRAP_AUD_WSS_0, 0x00000400, (dev->local <= VIA_PIPC_596B) || (dev->power_regs[0x40] & 0x08), 0x530, 8);
|
||||
pipc_trap_update_paden(dev, TRAP_AUD_WSS_1, 0x00000400, (dev->local <= VIA_PIPC_596B) || (dev->power_regs[0x40] & 0x08), 0x604, 8);
|
||||
pipc_trap_update_paden(dev, TRAP_AUD_WSS_2, 0x00000400, (dev->local <= VIA_PIPC_596B) || (dev->power_regs[0x40] & 0x08), 0xe80, 8);
|
||||
pipc_trap_update_paden(dev, TRAP_AUD_WSS_3, 0x00000400, (dev->local <= VIA_PIPC_596B) || (dev->power_regs[0x40] & 0x08), 0xf40, 8);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pipc_sgd_handlers(pipc_t *dev, uint8_t modem)
|
||||
{
|
||||
@@ -882,17 +1106,21 @@ pipc_write(int func, int addr, uint8_t val, void *priv)
|
||||
dev->pci_isa_regs[(addr - 0x44)] = val;
|
||||
break;
|
||||
|
||||
case 0x74: case 0x8b:
|
||||
case 0x78: case 0x79: case 0x7a: case 0x7b:
|
||||
case 0x8c: case 0x8d: case 0x8e: case 0x8f:
|
||||
case 0x80: case 0x8a:
|
||||
dev->pci_isa_regs[addr] = val;
|
||||
pipc_pcs_update(dev);
|
||||
break;
|
||||
|
||||
case 0x77:
|
||||
if (val & 0x10)
|
||||
if ((dev->local >= VIA_PIPC_686A) && (val & 0x10))
|
||||
pclog("PIPC: Warning: Internal I/O APIC enabled.\n");
|
||||
nvr_via_wp_set(!!(val & 0x04), 0x32, dev->nvr);
|
||||
nvr_via_wp_set(!!(val & 0x02), 0x0d, dev->nvr);
|
||||
break;
|
||||
|
||||
case 0x80: case 0x86: case 0x87:
|
||||
dev->pci_isa_regs[addr] &= ~(val);
|
||||
break;
|
||||
|
||||
default:
|
||||
dev->pci_isa_regs[addr] = val;
|
||||
break;
|
||||
@@ -1326,10 +1554,13 @@ pipc_init(const device_t *info)
|
||||
else if (dev->local >= VIA_PIPC_596A)
|
||||
dev->smbus = device_add(&piix4_smbus_device);
|
||||
|
||||
if (dev->local >= VIA_PIPC_596A)
|
||||
if (dev->local >= VIA_PIPC_596A) {
|
||||
dev->acpi = device_add(&acpi_via_596b_device);
|
||||
else if (dev->local >= VIA_PIPC_586B)
|
||||
acpi_set_trap_update(dev->acpi, pipc_trap_update_596, dev);
|
||||
} else if (dev->local >= VIA_PIPC_586B) {
|
||||
dev->acpi = device_add(&acpi_via_device);
|
||||
acpi_set_trap_update(dev->acpi, pipc_trap_update_586, dev);
|
||||
}
|
||||
|
||||
dev->usb[0] = device_add_inst(&usb_device, 1);
|
||||
if (dev->local >= VIA_PIPC_686A) {
|
||||
@@ -1383,6 +1614,9 @@ pipc_close(void *p)
|
||||
|
||||
pipc_log("PIPC: close()\n");
|
||||
|
||||
for (int i = 0; i < TRAP_MAX; i++)
|
||||
io_trap_remove(dev->io_traps[i].trap);
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
@@ -63,7 +63,8 @@ typedef struct
|
||||
smicmd, gpio_dir,
|
||||
gpio_val, muxcntrl, pad,
|
||||
timer32, smireg,
|
||||
gpireg[3], gporeg[4];
|
||||
gpireg[3], gporeg[4],
|
||||
extiotrapsts, extiotrapen;
|
||||
uint16_t pmsts, pmen,
|
||||
pmcntrl, gpsts, gpsts1,
|
||||
gpen, gpen1, gpscien,
|
||||
@@ -95,7 +96,8 @@ typedef struct
|
||||
pc_timer_t timer;
|
||||
nvr_t *nvr;
|
||||
apm_t *apm;
|
||||
void *i2c;
|
||||
void *i2c,
|
||||
(*trap_update)(void *priv), *trap_priv;
|
||||
} acpi_t;
|
||||
|
||||
|
||||
@@ -111,6 +113,8 @@ extern const device_t acpi_via_596b_device;
|
||||
|
||||
|
||||
/* Functions */
|
||||
extern void acpi_update_irq(acpi_t *dev);
|
||||
extern void acpi_raise_smi(acpi_t *dev);
|
||||
extern void acpi_update_io_mapping(acpi_t *dev, uint32_t base, int chipset_en);
|
||||
extern void acpi_update_aux_io_mapping(acpi_t *dev, uint32_t base, int chipset_en);
|
||||
extern void acpi_init_gporeg(acpi_t *dev, uint8_t val0, uint8_t val1, uint8_t val2, uint8_t val3);
|
||||
@@ -121,6 +125,7 @@ extern void acpi_set_irq_pin(acpi_t *dev, int irq_pin);
|
||||
extern void acpi_set_irq_line(acpi_t *dev, int irq_line);
|
||||
extern void acpi_set_gpireg2_default(acpi_t *dev, uint8_t gpireg2_default);
|
||||
extern void acpi_set_nvr(acpi_t *dev, nvr_t *nvr);
|
||||
extern void acpi_set_trap_update(acpi_t *dev, void (*update)(void *priv), void *priv);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -111,5 +111,10 @@ extern void outw(uint16_t port, uint16_t val);
|
||||
extern uint32_t inl(uint16_t port);
|
||||
extern void outl(uint16_t port, uint32_t val);
|
||||
|
||||
extern void *io_trap_add(void (*func)(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv),
|
||||
void *priv);
|
||||
extern void io_trap_remap(void *handle, int enable, uint16_t addr, uint16_t size);
|
||||
extern void io_trap_remove(void *handle);
|
||||
|
||||
|
||||
#endif /*EMU_IO_H*/
|
||||
|
136
src/io.c
136
src/io.c
@@ -35,19 +35,26 @@
|
||||
|
||||
|
||||
typedef struct _io_ {
|
||||
uint8_t (*inb)(uint16_t addr, void *priv);
|
||||
uint16_t (*inw)(uint16_t addr, void *priv);
|
||||
uint32_t (*inl)(uint16_t addr, void *priv);
|
||||
uint8_t (*inb)(uint16_t addr, void *priv);
|
||||
uint16_t (*inw)(uint16_t addr, void *priv);
|
||||
uint32_t (*inl)(uint16_t addr, void *priv);
|
||||
|
||||
void (*outb)(uint16_t addr, uint8_t val, void *priv);
|
||||
void (*outw)(uint16_t addr, uint16_t val, void *priv);
|
||||
void (*outl)(uint16_t addr, uint32_t val, void *priv);
|
||||
void (*outb)(uint16_t addr, uint8_t val, void *priv);
|
||||
void (*outw)(uint16_t addr, uint16_t val, void *priv);
|
||||
void (*outl)(uint16_t addr, uint32_t val, void *priv);
|
||||
|
||||
void *priv;
|
||||
void *priv;
|
||||
|
||||
struct _io_ *prev, *next;
|
||||
struct _io_ *prev, *next;
|
||||
} io_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t enable;
|
||||
uint16_t base, size;
|
||||
void (*func)(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv),
|
||||
*priv;
|
||||
} io_trap_t;
|
||||
|
||||
int initialized = 0;
|
||||
io_t *io[NPORTS], *io_last[NPORTS];
|
||||
|
||||
@@ -583,3 +590,116 @@ outl(uint16_t port, uint32_t val)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
io_trap_readb(uint16_t addr, void *priv)
|
||||
{
|
||||
io_trap_t *trap = (io_trap_t *) priv;
|
||||
trap->func(1, addr, 0, 0, trap->priv);
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
|
||||
static uint16_t
|
||||
io_trap_readw(uint16_t addr, void *priv)
|
||||
{
|
||||
io_trap_t *trap = (io_trap_t *) priv;
|
||||
trap->func(2, addr, 0, 0, trap->priv);
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
io_trap_readl(uint16_t addr, void *priv)
|
||||
{
|
||||
io_trap_t *trap = (io_trap_t *) priv;
|
||||
trap->func(4, addr, 0, 0, trap->priv);
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
io_trap_writeb(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
io_trap_t *trap = (io_trap_t *) priv;
|
||||
trap->func(1, addr, 1, val, trap->priv);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
io_trap_writew(uint16_t addr, uint16_t val, void *priv)
|
||||
{
|
||||
io_trap_t *trap = (io_trap_t *) priv;
|
||||
trap->func(2, addr, 1, val, trap->priv);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
io_trap_writel(uint16_t addr, uint32_t val, void *priv)
|
||||
{
|
||||
io_trap_t *trap = (io_trap_t *) priv;
|
||||
trap->func(4, addr, 1, val, trap->priv);
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
io_trap_add(void (*func)(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv),
|
||||
void *priv)
|
||||
{
|
||||
/* Instantiate new I/O trap. */
|
||||
io_trap_t *trap = (io_trap_t *) malloc(sizeof(io_trap_t));
|
||||
trap->enable = 0;
|
||||
trap->base = trap->size = 0;
|
||||
trap->func = func;
|
||||
trap->priv = priv;
|
||||
|
||||
return trap;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
io_trap_remap(void *handle, int enable, uint16_t addr, uint16_t size)
|
||||
{
|
||||
io_trap_t *trap = (io_trap_t *) handle;
|
||||
if (!trap)
|
||||
return;
|
||||
|
||||
io_log("I/O: Remapping trap from %04X-%04X (enable %d) to %04X-%04X (enable %d)\n",
|
||||
trap->base, trap->base + trap->size, trap->enable, addr, addr + size, enable);
|
||||
|
||||
/* Remove old I/O mapping. */
|
||||
if (trap->enable && trap->base && trap->size) {
|
||||
io_removehandler(trap->base, trap->size,
|
||||
io_trap_readb, io_trap_readw, io_trap_readl,
|
||||
io_trap_writeb, io_trap_writew, io_trap_writel,
|
||||
trap);
|
||||
}
|
||||
|
||||
/* Set trap enable flag, base address and size. */
|
||||
trap->enable = !!enable;
|
||||
trap->base = addr;
|
||||
trap->size = size;
|
||||
|
||||
/* Add new I/O mapping. */
|
||||
if (trap->enable && trap->base && trap->size) {
|
||||
io_sethandler(trap->base, trap->size,
|
||||
io_trap_readb, io_trap_readw, io_trap_readl,
|
||||
io_trap_writeb, io_trap_writew, io_trap_writel,
|
||||
trap);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
io_trap_remove(void *handle)
|
||||
{
|
||||
io_trap_t *trap = (io_trap_t *) handle;
|
||||
if (!trap)
|
||||
return;
|
||||
|
||||
/* Unmap I/O trap before freeing it. */
|
||||
io_trap_remap(trap, 0, 0, 0);
|
||||
|
||||
free(trap);
|
||||
}
|
||||
|
Reference in New Issue
Block a user