diff --git a/src/acpi.c b/src/acpi.c index 8664bf743..0f361384e 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -63,17 +63,19 @@ acpi_update_irq(void *priv) int sci_level; 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); + if (sci_level) { - if (dev->regs.irq_mode == 1) - pci_set_irq(dev->regs.slot, dev->regs.irq_pin); + if (dev->irq_mode == 1) + pci_set_irq(dev->slot, dev->irq_pin); else - picintlevel(1 << 9); + picintlevel(1 << dev->irq_line); } else { - if (dev->regs.irq_mode == 1) - pci_clear_irq(dev->regs.slot, dev->regs.irq_pin); + if (dev->irq_mode == 1) + pci_clear_irq(dev->slot, dev->irq_pin); else - picintc(1 << 9); + picintc(1 << dev->irq_line); } } @@ -88,12 +90,15 @@ acpi_raise_smi(void *priv) smi_line = 1; dev->regs.smi_active = 1; } - } else { + } else if (dev->vendor == VEN_INTEL) { if (dev->regs.glbctl & 0x01) { smi_line = 1; /* Clear bit 16 of GLBCTL. */ dev->regs.glbctl &= ~0x00010000; } + } else if (dev->vendor == VEN_SMC) { + if (dev->regs.glbctl & 0x01) + smi_line = 1; } } @@ -307,17 +312,67 @@ acpi_reg_read_via(int size, uint16_t addr, void *p) } +static uint32_t +acpi_reg_read_smc(int size, uint16_t addr, void *p) +{ + uint32_t ret = 0x00000000; + + addr &= 0x0f; + + ret = acpi_reg_read_common_regs(size, addr, p); + + acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); + return ret; +} + + +static uint32_t +acpi_aux_reg_read_smc(int size, uint16_t addr, void *p) +{ + acpi_t *dev = (acpi_t *) p; + uint32_t ret = 0x00000000; + int shift16; + + addr &= 0x07; + shift16 = (addr & 1) << 3; + + switch (addr) { + case 0x00: case 0x01: + /* SCI Status Register */ + ret = (dev->regs.pcntrl >> shift16) & 0xff; + break; + case 0x02: case 0x03: + /* SCI Enable Register */ + ret = (dev->regs.gpscien >> shift16) & 0xff; + break; + case 0x04: case 0x05: + /* Miscellaneous Status Register */ + ret = (dev->regs.glbsts >> shift16) & 0xff; + break; + case 0x06: + /* Miscellaneous Enable Register */ + ret = dev->regs.glben & 0xff; + break; + case 0x07: + /* Miscellaneous Control Register */ + ret = dev->regs.glbctl & 0xff; + break; + } + + acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret); + return ret; +} + + static void acpi_reg_write_common_regs(int size, uint16_t addr, uint8_t val, void *p) { acpi_t *dev = (acpi_t *) p; - int shift16, shift32; - int sus_typ; + int shift16, sus_typ; addr &= 0x3f; 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 0x00: case 0x01: @@ -377,7 +432,6 @@ acpi_reg_write_intel(int size, uint16_t addr, uint8_t val, void *p) { acpi_t *dev = (acpi_t *) p; int shift16, shift32; - int sus_typ; addr &= 0x3f; acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val); @@ -431,7 +485,9 @@ acpi_reg_write_intel(int size, uint16_t addr, uint8_t val, void *p) default: acpi_reg_write_common_regs(size, addr, val, p); /* Setting GBL_RLS also sets BIOS_STS and generates SMI. */ - if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { + if ((addr == 0x00) && !(dev->regs.pmsts & 0x20)) + dev->regs.glbctl &= ~0x0002; + else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { dev->regs.glbsts |= 0x01; if (dev->regs.glben & 0x02) acpi_raise_smi(dev); @@ -446,7 +502,6 @@ acpi_reg_write_via(int size, uint16_t addr, uint8_t val, void *p) { acpi_t *dev = (acpi_t *) p; int shift16, shift32; - int sus_typ; addr &= 0xff; acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val); @@ -549,6 +604,72 @@ acpi_reg_write_via(int size, uint16_t addr, uint8_t val, void *p) } +static void +acpi_reg_write_smc(int size, uint16_t addr, uint8_t val, void *p) +{ + acpi_t *dev = (acpi_t *) p; + + addr &= 0x0f; + acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val); + + acpi_reg_write_common_regs(size, addr, val, p); + /* Setting GBL_RLS also sets BIOS_STS and generates SMI. */ + if ((addr == 0x00) && !(dev->regs.pmsts & 0x20)) + dev->regs.glbctl &= ~0x0001; + else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) { + dev->regs.glbsts |= 0x01; + if (dev->regs.glben & 0x01) + acpi_raise_smi(dev); + } +} + + +static void +acpi_aux_reg_write_smc(int size, uint16_t addr, uint8_t val, void *p) +{ + acpi_t *dev = (acpi_t *) p; + int shift16; + + addr &= 0x07; + acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val); + shift16 = (addr & 1) << 3; + + switch (addr) { + case 0x00: case 0x01: + /* SCI Status Register */ + dev->regs.gpscists &= ~((val << shift16) & 0x000c); + break; + case 0x02: case 0x03: + /* SCI Enable Register */ + dev->regs.gpscien = ((dev->regs.gpscien & ~(0xff << shift16)) | (val << shift16)) & 0x3fff; + break; + case 0x04: case 0x05: + /* Miscellanous Status Register */ + dev->regs.glbsts &= ~((val << shift16) & 0x001f); + break; + case 0x06: + /* Miscellaneous Enable Register */ + dev->regs.glben = (uint16_t) (val & 0x03); + break; + case 0x07: + /* Miscellaneous Control Register */ + dev->regs.glbctl = (uint16_t) (val & 0x03); + /* Setting BIOS_RLS also sets GBL_STS and generates SMI. */ + if (dev->regs.glbctl & 0x0001) { + dev->regs.pmsts |= 0x20; + if (dev->regs.pmen & 0x20) + acpi_update_irq(dev); + } + if (dev->regs.glbctl & 0x0002) { + dev->regs.pmsts |= 0x10; + if (dev->regs.pmcntrl & 0x02) + acpi_update_irq(dev); + } + break; + } +} + + static uint32_t acpi_reg_read_common(int size, uint16_t addr, void *p) { @@ -557,8 +678,10 @@ acpi_reg_read_common(int size, uint16_t addr, void *p) if (dev->vendor == VEN_VIA) ret = acpi_reg_read_via(size, addr, p); - else + else if (dev->vendor == VEN_INTEL) ret = acpi_reg_read_intel(size, addr, p); + else if (dev->vendor == VEN_SMC) + ret = acpi_reg_read_smc(size, addr, p); return ret; } @@ -571,8 +694,33 @@ acpi_reg_write_common(int size, uint16_t addr, uint8_t val, void *p) if (dev->vendor == VEN_VIA) acpi_reg_write_via(size, addr, val, p); - else + else if (dev->vendor == VEN_INTEL) acpi_reg_write_intel(size, addr, val, p); + else if (dev->vendor == VEN_SMC) + acpi_reg_write_smc(size, addr, val, p); +} + + +static uint32_t +acpi_aux_reg_read_common(int size, uint16_t addr, void *p) +{ + acpi_t *dev = (acpi_t *) p; + uint8_t ret = 0xff; + + if (dev->vendor == VEN_SMC) + ret = acpi_aux_reg_read_smc(size, addr, p); + + return ret; +} + + +static void +acpi_aux_reg_write_common(int size, uint16_t addr, uint8_t val, void *p) +{ + acpi_t *dev = (acpi_t *) p; + + if (dev->vendor == VEN_SMC) + acpi_aux_reg_write_smc(size, addr, val, p); } @@ -617,6 +765,47 @@ acpi_reg_read(uint16_t addr, void *p) } +static uint32_t +acpi_aux_read_readl(uint16_t addr, void *p) +{ + uint32_t ret = 0x00000000; + + ret = acpi_aux_reg_read_common(4, addr, p); + ret |= (acpi_aux_reg_read_common(4, addr + 1, p) << 8); + ret |= (acpi_aux_reg_read_common(4, addr + 2, p) << 16); + ret |= (acpi_aux_reg_read_common(4, addr + 3, p) << 24); + + acpi_log("ACPI: Read L %08X from %04X\n", ret, addr); + + return ret; +} + + +static uint16_t +acpi_aux_read_readw(uint16_t addr, void *p) +{ + uint16_t ret = 0x0000; + + ret = acpi_aux_reg_read_common(2, addr, p); + ret |= (acpi_aux_reg_read_common(2, addr + 1, p) << 8); + + acpi_log("ACPI: Read W %08X from %04X\n", ret, addr); + + return ret; +} + + +static uint8_t +acpi_aux_read_read(uint16_t addr, void *p) +{ + uint8_t ret = 0x00; + + ret = acpi_aux_reg_read_common(1, addr, p); + + return ret; +} + + static void acpi_reg_writel(uint16_t addr, uint32_t val, void *p) { @@ -642,25 +831,71 @@ acpi_reg_write(uint16_t addr, uint8_t val, void *p) } +static void +acpi_aux_reg_writel(uint16_t addr, uint32_t val, void *p) +{ + acpi_aux_reg_write_common(4, addr, val & 0xff, p); + acpi_aux_reg_write_common(4, addr + 1, (val >> 8) & 0xff, p); + acpi_aux_reg_write_common(4, addr + 1, (val >> 16) & 0xff, p); + acpi_aux_reg_write_common(4, addr + 1, (val >> 24) & 0xff, p); +} + + +static void +acpi_aux_reg_writew(uint16_t addr, uint16_t val, void *p) +{ + acpi_aux_reg_write_common(2, addr, val & 0xff, p); + acpi_aux_reg_write_common(2, addr + 1, (val >> 8) & 0xff, p); +} + + +static void +acpi_aux_reg_write(uint16_t addr, uint8_t val, void *p) +{ + acpi_aux_reg_write_common(1, addr, val, p); +} + + void acpi_update_io_mapping(acpi_t *dev, uint32_t base, int chipset_en) { - if (dev->regs.io_base != 0x0000) { - io_removehandler(dev->regs.io_base, 0x40, + int size = (dev->vendor == VEN_SMC) ? 0x10 : 0x40; + + if (dev->io_base != 0x0000) { + io_removehandler(dev->io_base, size, acpi_reg_read, acpi_reg_readw, acpi_reg_readl, acpi_reg_write, acpi_reg_writew, acpi_reg_writel, dev); } - dev->regs.io_base = base; + dev->io_base = base; - if (chipset_en && (dev->regs.io_base != 0x0000)) { - io_sethandler(dev->regs.io_base, 0x40, + if (chipset_en && (dev->io_base != 0x0000)) { + io_sethandler(dev->io_base, size, acpi_reg_read, acpi_reg_readw, acpi_reg_readl, acpi_reg_write, acpi_reg_writew, acpi_reg_writel, dev); } } +void +acpi_update_aux_io_mapping(acpi_t *dev, uint32_t base, int chipset_en) +{ + if (dev->aux_io_base != 0x0000) { + io_removehandler(dev->aux_io_base, 0x08, + acpi_aux_read_read, acpi_aux_read_readw, acpi_aux_read_readl, + acpi_aux_reg_write, acpi_aux_reg_writew, acpi_aux_reg_writel, dev); + } + + dev->aux_io_base = base; + + if (chipset_en && (dev->aux_io_base != 0x0000)) { + io_sethandler(dev->aux_io_base, 0x08, + acpi_aux_read_read, acpi_aux_read_readw, acpi_aux_read_readl, + acpi_aux_reg_write, acpi_aux_reg_writew, acpi_aux_reg_writel, dev); + } +} + + static void acpi_timer_count(void *priv) { @@ -711,21 +946,28 @@ acpi_set_timer32(acpi_t *dev, uint8_t timer32) void acpi_set_slot(acpi_t *dev, int slot) { - dev->regs.slot = slot; + dev->slot = slot; } void acpi_set_irq_mode(acpi_t *dev, int irq_mode) { - dev->regs.irq_mode = irq_mode; + dev->irq_mode = irq_mode; } void acpi_set_irq_pin(acpi_t *dev, int irq_pin) { - dev->regs.irq_pin = irq_pin; + dev->irq_pin = irq_pin; +} + + +void +acpi_set_irq_line(acpi_t *dev, int irq_line) +{ + dev->irq_line = irq_line; } @@ -821,6 +1063,8 @@ acpi_init(const device_t *info) dev->vendor = info->local; + dev->irq_line = 9; + if (dev->vendor == VEN_INTEL) { dev->apm = device_add(&apm_pci_acpi_device); io_sethandler(0x00b2, 0x0002, acpi_apm_in, NULL, NULL, acpi_apm_out, NULL, NULL, dev); @@ -837,7 +1081,7 @@ acpi_init(const device_t *info) const device_t acpi_intel_device = { - "ACPI v1.0", + "Intel ACPI", DEVICE_PCI, VEN_INTEL, acpi_init, @@ -852,7 +1096,7 @@ const device_t acpi_intel_device = const device_t acpi_via_device = { - "ACPI v1.2", + "VIA ACPI", DEVICE_PCI, VEN_VIA, acpi_init, @@ -863,3 +1107,18 @@ const device_t acpi_via_device = NULL, NULL }; + + +const device_t acpi_smc_device = +{ + "SMC FDC73C931APM ACPI", + DEVICE_PCI, + VEN_SMC, + acpi_init, + acpi_close, + acpi_reset, + NULL, + acpi_speed_changed, + NULL, + NULL +}; diff --git a/src/include/86box/acpi.h b/src/include/86box/acpi.h index fa10aaa2f..3f9ea76e3 100644 --- a/src/include/86box/acpi.h +++ b/src/include/86box/acpi.h @@ -27,6 +27,9 @@ extern "C" { #define RSM_STS (1 << 15) #define PWRBTN_STS (1 << 8) +#define GBL_STS (1 << 5) +#define BM_STS (1 << 4) +#define TMROF_STS (1 << 0) #define RTC_EN (1 << 10) #define PWRBTN_EN (1 << 8) @@ -40,6 +43,7 @@ extern "C" { #define ACPI_DISABLE 0xf0 #define VEN_INTEL 0x8086 +#define VEN_SMC 0x1055 #define VEN_VIA 0x1106 @@ -52,13 +56,11 @@ typedef struct gpireg[3], gporeg[4]; uint16_t pmsts, pmen, pmcntrl, gpsts, - gpen, io_base, - gpscien, gpsmien, - pscntrl, gpo_val, - gpi_val; - int slot, irq_mode, - irq_pin, smi_lock, - smi_active; + gpen, gpscien, + gpsmien, pscntrl, + gpo_val, gpi_val, + gpscists; + int smi_lock, smi_active; uint32_t pcntrl, glbsts, devsts, glben, glbctl, devctl, @@ -72,7 +74,10 @@ typedef struct { acpi_regs_t regs; uint8_t gporeg_default[4]; - int vendor; + uint16_t io_base, aux_io_base; + int vendor, + slot, irq_mode, + irq_pin, irq_line; pc_timer_t timer; nvr_t *nvr; apm_t *apm; @@ -81,16 +86,19 @@ typedef struct /* Global variables. */ extern const device_t acpi_intel_device; +extern const device_t acpi_smc_device; extern const device_t acpi_via_device; /* Functions. */ 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); extern void acpi_set_timer32(acpi_t *dev, uint8_t timer32); extern void acpi_set_slot(acpi_t *dev, int slot); extern void acpi_set_irq_mode(acpi_t *dev, int irq_mode); 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_nvr(acpi_t *dev, nvr_t *nvr); #ifdef __cplusplus diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index 0fcdb965a..b66b600de 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -22,6 +22,7 @@ extern const device_t fdc37c663_device; extern const device_t fdc37c665_device; extern const device_t fdc37c666_device; extern const device_t fdc37c669_device; +extern const device_t fdc37c931apm_device; extern const device_t fdc37c932fr_device; extern const device_t fdc37c932qf_device; extern const device_t fdc37c935_device; diff --git a/src/sio/sio_fdc37c93x.c b/src/sio/sio_fdc37c93x.c index 2f6a4a61b..89038d51d 100644 --- a/src/sio/sio_fdc37c93x.c +++ b/src/sio/sio_fdc37c93x.c @@ -31,6 +31,8 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/nvr.h> +#include <86box/apm.h> +#include <86box/acpi.h> #include <86box/sio.h> @@ -47,10 +49,11 @@ typedef struct { } access_bus_t; typedef struct { - uint8_t chip_id, tries, + uint8_t chip_id, is_apm, + tries, gpio_regs[2], auxio_reg, regs[48], - ld_regs[10][256]; + ld_regs[11][256]; uint16_t gpio_base, /* Set to EA */ auxio_base, nvr_sec_base; int locked, @@ -59,6 +62,7 @@ typedef struct { serial_t *uart[2]; access_bus_t *access_bus; nvr_t *nvr; + acpi_t *acpi; } fdc37c93x_t; @@ -223,7 +227,8 @@ fdc37c93x_auxio_handler(fdc37c93x_t *dev) } -static void fdc37c93x_gpio_handler(fdc37c93x_t *dev) +static void +fdc37c93x_gpio_handler(fdc37c93x_t *dev) { uint16_t ld_port = 0; uint8_t local_enable; @@ -256,7 +261,7 @@ static void fdc37c93x_gpio_handler(fdc37c93x_t *dev) static uint8_t -fdc37c932fr_access_bus_read(uint16_t port, void *priv) +fdc37c93x_access_bus_read(uint16_t port, void *priv) { access_bus_t *dev = (access_bus_t *) priv; uint8_t ret = 0xff; @@ -281,7 +286,7 @@ fdc37c932fr_access_bus_read(uint16_t port, void *priv) static void -fdc37c932fr_access_bus_write(uint16_t port, uint8_t val, void *priv) +fdc37c93x_access_bus_write(uint16_t port, uint8_t val, void *priv) { access_bus_t *dev = (access_bus_t *) priv; @@ -303,23 +308,49 @@ fdc37c932fr_access_bus_write(uint16_t port, uint8_t val, void *priv) } -static void fdc37c932fr_access_bus_handler(fdc37c93x_t *dev) +static void +fdc37c93x_access_bus_handler(fdc37c93x_t *dev) { uint16_t ld_port = 0; uint8_t global_enable = !!(dev->regs[0x22] & (1 << 6)); uint8_t local_enable = !!dev->ld_regs[9][0x30]; io_removehandler(dev->access_bus->base, 0x0004, - fdc37c932fr_access_bus_read, NULL, NULL, fdc37c932fr_access_bus_write, NULL, NULL, dev->access_bus); + fdc37c93x_access_bus_read, NULL, NULL, fdc37c93x_access_bus_write, NULL, NULL, dev->access_bus); if (global_enable && local_enable) { dev->access_bus->base = ld_port = make_port(dev, 9); if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) io_sethandler(dev->access_bus->base, 0x0004, - fdc37c932fr_access_bus_read, NULL, NULL, fdc37c932fr_access_bus_write, NULL, NULL, dev->access_bus); + fdc37c93x_access_bus_read, NULL, NULL, fdc37c93x_access_bus_write, NULL, NULL, dev->access_bus); } } +static void +fdc37c93x_acpi_handler(fdc37c93x_t *dev) +{ + uint16_t ld_port = 0; + uint8_t local_enable = !!dev->ld_regs[0x0a][0x30]; + uint8_t sci_irq = dev->ld_regs[0x0a][0x70]; + + acpi_update_io_mapping(dev->acpi, 0x0000, local_enable); + if (local_enable) { + ld_port = make_port(dev, 0x0a); + if ((ld_port >= 0x0100) && (ld_port <= 0x0FF0)) + acpi_update_io_mapping(dev->acpi, ld_port, local_enable); + } + + acpi_update_aux_io_mapping(dev->acpi, 0x0000, local_enable); + if (local_enable) { + ld_port = make_port_sec(dev, 0x0a); + if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) + acpi_update_aux_io_mapping(dev->acpi, ld_port, local_enable); + } + + acpi_set_irq_line(dev->acpi, sci_irq); +} + + static void fdc37c93x_write(uint16_t port, uint8_t val, void *priv) { @@ -361,17 +392,23 @@ fdc37c93x_write(uint16_t port, uint8_t val, void *priv) if (((dev->cur_reg & 0xF0) == 0x70) && (dev->regs[7] < 4)) return; /* Block writes to some logical devices. */ - if (dev->regs[7] > 9) + if (dev->regs[7] > 0x0a) return; else switch (dev->regs[7]) { - case 1: - case 2: - case 7: + case 0x01: + case 0x02: + case 0x07: return; - case 9: + case 0x09: /* If we're on the FDC37C935, return as this is not a valid logical device there. */ - if (dev->chip_id == 0x02) + if (!dev->is_apm && (dev->chip_id == 0x02)) + return; + break; + case 0x0a: + /* If we're not on the FDC37C931APM, return as this is not a + valid logical device there. */ + if (!dev->is_apm) return; break; } @@ -398,7 +435,7 @@ fdc37c93x_write(uint16_t port, uint8_t val, void *priv) if (valxor & 0x20) fdc37c93x_serial_handler(dev, 1); if ((valxor & 0x40) && (dev->chip_id != 0x02)) - fdc37c932fr_access_bus_handler(dev); + fdc37c93x_access_bus_handler(dev); break; } @@ -564,7 +601,7 @@ fdc37c93x_write(uint16_t port, uint8_t val, void *priv) } break; case 9: - /* Access bus (FDC37C932FR only) */ + /* Access bus (FDC37C932FR and FDC37C931APM only) */ switch(dev->cur_reg) { case 0x30: case 0x60: @@ -573,7 +610,21 @@ fdc37c93x_write(uint16_t port, uint8_t val, void *priv) if ((dev->cur_reg == 0x30) && (val & 0x01)) dev->regs[0x22] |= 0x40; if (valxor) - fdc37c932fr_access_bus_handler(dev); + fdc37c93x_access_bus_handler(dev); + break; + } + break; + case 10: + /* Access bus (FDC37C931APM only) */ + switch(dev->cur_reg) { + case 0x30: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x70: + if (valxor) + fdc37c93x_acpi_handler(dev); break; } break; @@ -694,13 +745,17 @@ fdc37c93x_reset(fdc37c93x_t *dev) /* Logical device 9: ACCESS.bus */ + /* Logical device A: ACPI */ + fdc37c93x_gpio_handler(dev); fdc37c93x_lpt_handler(dev); fdc37c93x_serial_handler(dev, 0); fdc37c93x_serial_handler(dev, 1); fdc37c93x_auxio_handler(dev); - if (dev->chip_id == 0x03) - fdc37c932fr_access_bus_handler(dev); + if (dev->is_apm || (dev->chip_id == 0x03)) + fdc37c93x_access_bus_handler(dev); + if (dev->is_apm) + fdc37c93x_acpi_handler(dev); fdc_reset(dev->fdc); fdc37c93x_fdc_handler(dev); @@ -758,7 +813,8 @@ fdc37c93x_init(const device_t *info) dev->uart[0] = device_add_inst(&ns16550_device, 1); dev->uart[1] = device_add_inst(&ns16550_device, 2); - dev->chip_id = info->local; + dev->chip_id = info->local & 0xff; + dev->is_apm = info->local >> 8; dev->gpio_regs[0] = 0xff; dev->gpio_regs[1] = 0xfd; @@ -773,6 +829,9 @@ fdc37c93x_init(const device_t *info) if (dev->chip_id == 0x03) dev->access_bus = device_add(&access_bus_device); + if (dev->is_apm) + dev->acpi = device_add(&acpi_smc_device); + io_sethandler(0x370, 0x0002, fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); io_sethandler(0x3f0, 0x0002, @@ -784,6 +843,15 @@ fdc37c93x_init(const device_t *info) } +const device_t fdc37c931apm_device = { + "SMC FDC37C932QF Super I/O", + 0, + 0x130, /* Share the same ID with the 932QF. */ + fdc37c93x_init, fdc37c93x_close, NULL, + NULL, NULL, NULL, + NULL +}; + const device_t fdc37c932fr_device = { "SMC FDC37C932FR Super I/O", 0, @@ -796,7 +864,7 @@ const device_t fdc37c932fr_device = { const device_t fdc37c932qf_device = { "SMC FDC37C932QF Super I/O", 0, - 0x30, /* Share the same ID with the 935. */ + 0x30, fdc37c93x_init, fdc37c93x_close, NULL, NULL, NULL, NULL, NULL