From 61f0ae79548172f42040259f70d4c14095aada9a Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 13 Apr 2020 20:01:47 +0200 Subject: [PATCH] Better ACPI implementation (currently only on PIIX4/PIIX4E/SMSC southbridges), finished the SMSC southbridge (but the Atrend BIOS still hangs, need to figure out why), and fixed Tandy EEPROM saving. --- src/chipset/intel_4x0.c | 4 - src/cpu_common/386_common.c | 7 + src/cpu_common/cpu.c | 20 +- src/disk/hdc_ide_sff8038i.c | 26 +- src/include/86box/hdc_ide_sff8038i.h | 7 +- src/include/86box/nvr.h | 1 + src/include/86box/pit.h | 2 +- src/intel_piix.c | 517 +++++++++++++++------------ src/machine/m_at_slot1.c | 2 +- src/machine/m_tandy.c | 2 +- src/nvr_at.c | 129 ++++--- src/pit.c | 3 +- src/sound/snd_sb_dsp.c | 18 +- src/via_vt82c586b.c | 30 +- src/via_vt82c596b.c | 31 +- src/win/Makefile.mingw | 2 +- src/win/Makefile_ndr.mingw | 2 +- 17 files changed, 472 insertions(+), 331 deletions(-) diff --git a/src/chipset/intel_4x0.c b/src/chipset/intel_4x0.c index b21b6cb1c..14cfa55f3 100644 --- a/src/chipset/intel_4x0.c +++ b/src/chipset/intel_4x0.c @@ -1101,8 +1101,6 @@ i4x0_reset(void *priv) for (i = 0; i <= dev->max_func; i++) memset(dev->regs_locked[i], 0x00, 256 * sizeof(uint8_t)); } - - // smbase = 0xa0000; } @@ -1315,8 +1313,6 @@ static void i4x0_write(regs[0x5f], 0x5f, 0x00, dev); i4x0_write(regs[0x72], 0x72, 0x00, dev); - // smbase = 0xa0000; - if (((dev->type == INTEL_440BX) || (dev->type == INTEL_440ZX)) && (dev->max_func == 1)) { regs = (uint8_t *) dev->regs[1]; diff --git a/src/cpu_common/386_common.c b/src/cpu_common/386_common.c index f3ba15edb..0c38818a7 100644 --- a/src/cpu_common/386_common.c +++ b/src/cpu_common/386_common.c @@ -1077,6 +1077,9 @@ enter_smm(int in_hlt) smm_in_hlt = in_hlt; CPU_BLOCK_END(); + + // if (smbase == 0x000a0000) + // leave_smm(); } @@ -1132,6 +1135,10 @@ leave_smm(void) else if (is_p6) /* Intel P6 (Pentium Pro, Pentium II, Celeron) */ smram_restore_state_p6(saved_state); + /* Maybe we need this? */ + if (smbase == 0x00030000) + smbase = 0x000a0000; + in_smm = 0; mem_mapping_recalc(0x00030000, 0x00020000); mem_mapping_recalc(0x000a0000, 0x00060000); diff --git a/src/cpu_common/cpu.c b/src/cpu_common/cpu.c index 39b6e6158..f8a39ca67 100644 --- a/src/cpu_common/cpu.c +++ b/src/cpu_common/cpu.c @@ -2202,9 +2202,15 @@ cpu_CPUID(void) EAX = CPUID; EBX = ECX = 0; EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_CMPXCHG8B | CPUID_MTRR/* | CPUID_SEP*/ | CPUID_CMOV; +#ifdef USE_SEP + EDX |= CPUID_SEP; +#endif } else if (EAX == 2) { + EAX = 0x00000001; + EBX = ECX = 0; + EDX = 0x00000000; } else EAX = EBX = ECX = EDX = 0; @@ -2223,12 +2229,15 @@ cpu_CPUID(void) EAX = CPUID; EBX = ECX = 0; EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR/* | CPUID_SEP*/ | CPUID_CMOV; +#ifdef USE_SEP + EDX |= CPUID_SEP; +#endif } else if (EAX == 2) { - EAX = 0x03020101; + EAX = 0x00000001; EBX = ECX = 0; - EDX = 0x0C040843; + EDX = 0x00000000; } else EAX = EBX = ECX = EDX = 0; @@ -2247,12 +2256,15 @@ cpu_CPUID(void) EAX = CPUID; EBX = ECX = 0; EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR/* | CPUID_SEP*/ | CPUID_FXSR | CPUID_CMOV; +#ifdef USE_SEP + EDX |= CPUID_SEP; +#endif } else if (EAX == 2) { - EAX = 0x03020101; + EAX = 0x00000001; EBX = ECX = 0; - EDX = 0x0C040844; + EDX = 0x00000000; } else EAX = EBX = ECX = EDX = 0; diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index c8ff3617d..e5292e3b0 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -374,17 +374,21 @@ sff_bus_master_set_irq(int channel, void *priv) channel &= 0x01; if (dev->status & 0x04) { sff_log("SFF8038i: Channel %i IRQ raise\n", channel); - if ((dev->irq_mode == 2) && channel && pci_use_mirq(0)) + if (dev->irq_mode[channel] == 3) + picintlevel(1 << dev->irq_line); + else if ((dev->irq_mode[channel] == 2) && channel && pci_use_mirq(0)) pci_set_mirq(0, 0); - else if (dev->irq_mode == 1) + else if (dev->irq_mode[channel] == 1) pci_set_irq(dev->slot, dev->irq_pin); else picint(1 << (14 + channel)); } else { sff_log("SFF8038i: Channel %i IRQ lower\n", channel); - if ((dev->irq_mode == 2) && channel && pci_use_mirq(0)) + if (dev->irq_mode[channel] == 3) + picintc(1 << dev->irq_line); + else if ((dev->irq_mode[channel] == 2) && channel && pci_use_mirq(0)) pci_clear_mirq(0, 0); - else if (dev->irq_mode == 1) + else if (dev->irq_mode[channel] == 1) pci_clear_irq(dev->slot, dev->irq_pin); else picintc(1 << (14 + channel)); @@ -449,9 +453,16 @@ sff_set_slot(sff8038i_t *dev, int slot) void -sff_set_irq_mode(sff8038i_t *dev, int irq_mode) +sff_set_irq_line(sff8038i_t *dev, int irq_line) { - dev->irq_mode = irq_mode; + dev->irq_line = irq_line; +} + + +void +sff_set_irq_mode(sff8038i_t *dev, int channel, int irq_mode) +{ + dev->irq_mode[channel] = irq_mode; } @@ -488,8 +499,9 @@ static void ide_set_bus_master(next_id, sff_bus_master_dma, sff_bus_master_set_irq, dev); dev->slot = 7; - dev->irq_mode = 2; + dev->irq_mode[0] = dev->irq_mode[1] = 2; dev->irq_pin = PCI_INTA; + dev->irq_line = 14; next_id++; diff --git a/src/include/86box/hdc_ide_sff8038i.h b/src/include/86box/hdc_ide_sff8038i.h index 72a68a6ba..43288aa99 100644 --- a/src/include/86box/hdc_ide_sff8038i.h +++ b/src/include/86box/hdc_ide_sff8038i.h @@ -25,7 +25,8 @@ typedef struct addr; int count, eot, slot, - irq_mode, irq_pin; + irq_mode[2], irq_pin, + irq_line; } sff8038i_t; @@ -42,5 +43,7 @@ extern void sff_bus_master_reset(sff8038i_t *dev, uint16_t old_base); extern void sff_set_slot(sff8038i_t *dev, int slot); -extern void sff_set_irq_mode(sff8038i_t *dev, int irq_mode); +extern void sff_set_irq_line(sff8038i_t *dev, int irq_line); + +extern void sff_set_irq_mode(sff8038i_t *dev, int channel, int irq_mode); extern void sff_set_irq_pin(sff8038i_t *dev, int irq_pin); diff --git a/src/include/86box/nvr.h b/src/include/86box/nvr.h index f923200e7..9c0413f09 100644 --- a/src/include/86box/nvr.h +++ b/src/include/86box/nvr.h @@ -112,6 +112,7 @@ extern int nvr_get_days(int month, int year); extern void nvr_time_get(struct tm *); extern void nvr_time_set(struct tm *); +extern void nvr_reg_write(uint16_t reg, uint8_t val, void *priv); extern void nvr_at_handler(int set, uint16_t base, nvr_t *nvr); extern void nvr_at_sec_handler(int set, uint16_t base, nvr_t *nvr); extern void nvr_wp_set(int set, int h, nvr_t *nvr); diff --git a/src/include/86box/pit.h b/src/include/86box/pit.h index 7b8ac98b7..3ec389cf1 100644 --- a/src/include/86box/pit.h +++ b/src/include/86box/pit.h @@ -57,7 +57,7 @@ extern uint64_t PITCONST, ISACONST, HERCCONST, VGACONST1, VGACONST2, - RTCCONST; + RTCCONST, ACPICONST; /* Gets a counter's count. */ diff --git a/src/intel_piix.c b/src/intel_piix.c index 8b429fa17..44daf3842 100644 --- a/src/intel_piix.c +++ b/src/intel_piix.c @@ -39,6 +39,7 @@ #include <86box/mem.h> #include <86box/timer.h> #include <86box/nvr.h> +#include <86box/acpi.h> #include <86box/pci.h> #include <86box/pic.h> #include <86box/port_92.h> @@ -51,24 +52,6 @@ #include <86box/piix.h> -#define ACPI_TIMER_FREQ 3579545 -#define PM_FREQ ACPI_TIMER_FREQ - -#define RSM_STS (1 << 15) -#define PWRBTN_STS (1 << 8) - -#define RTC_EN (1 << 10) -#define PWRBTN_EN (1 << 8) -#define GBL_EN (1 << 5) -#define TMROF_EN (1 << 0) - -#define SCI_EN (1 << 0) -#define SUS_EN (1 << 13) - -#define ACPI_ENABLE 0xf1 -#define ACPI_DISABLE 0xf0 - - typedef struct { uint16_t io_base; @@ -76,17 +59,6 @@ typedef struct } ddma_t; -typedef struct -{ - uint8_t gpireg[3], gporeg[4]; - uint16_t pmsts, pmen, - pmcntrl; - uint32_t glbctl; - uint64_t tmr_overflow_time; - int timer_index; -} power_t; - - typedef struct { uint8_t cur_readout_reg, rev, @@ -96,15 +68,16 @@ typedef struct readout_regs[256], board_config[2]; uint16_t func0_id, nvr_io_base, - usb_io_base, power_io_base; + usb_io_base, acpi_io_base; uint8_t *usb_smsc_mmio; - mem_mapping_t *usb_smsc_mmio_mapping; + mem_mapping_t usb_smsc_mmio_mapping; sff8038i_t *bm[2]; ddma_t ddma[2]; - power_t power; smbus_piix4_t * smbus; apm_t * apm; nvr_t * nvr; + acpi_t * acpi; + port_92_t * port_92; } piix_t; @@ -128,28 +101,88 @@ piix_log(const char *fmt, ...) #endif -static -void do_irq(piix_t *dev, int func, int level) +static void +smsc_ide_handlers(piix_t *dev) { - if ((dev == NULL) || (func > dev->max_func) /*|| - (dev->regs[func][0x3d] < PCI_INTA) || (dev->regs[func][0x3d] < PCI_INTD)*/) - return; + uint16_t main, side; - if (level) { -#ifdef WRONG_SPEC - pci_set_irq(dev->pci_slot, dev->regs[func][0x3d]); -#else - picintlevel(1 << 9); -#endif - piix_log("Raising IRQ...\n"); + ide_pri_disable(); + ide_sec_disable(); + + if (dev->regs[1][0x09] & 0x01) { + main = (dev->regs[1][0x11] << 8) | (dev->regs[1][0x10] & 0xf8); + side = ((dev->regs[1][0x15] << 8) | (dev->regs[1][0x14] & 0xfc)) + 2; } else { -#ifdef WRONG_SPEC - pci_clear_irq(dev->pci_slot, dev->regs[func][0x3d]); -#else - picintc(1 << 9); -#endif - piix_log("Lowering IRQ...\n"); + main = 0x1f0; + side = 0x3f6; } + ide_set_base(0, main); + ide_set_side(0, side); + + if (dev->regs[1][0x09] & 0x04) { + main = (dev->regs[1][0x19] << 8) | (dev->regs[1][0x18] & 0xf8); + side = ((dev->regs[1][0x1d] << 8) | (dev->regs[1][0x1c] & 0xfc)) + 2; + } else { + main = 0x170; + side = 0x376; + } + ide_set_base(1, main); + ide_set_side(1, side); + + if (dev->regs[1][0x04] & PCI_COMMAND_IO) { + if (dev->regs[1][0x41] & 0x80) + ide_pri_enable(); + if (dev->regs[1][0x43] & 0x80) + ide_sec_enable(); + } +} + + +static void +smsc_ide_irqs(piix_t *dev) +{ + int irq_line = 3, irq_mode[2] = { 0, 0 }; + + if (dev->regs[1][0x09] & 0x01) + irq_mode[0] = (dev->regs[0][0xe0] & 0x01) ? 3 : 1; + + if (dev->regs[1][0x09] & 0x04) + irq_mode[1] = (dev->regs[0][0xe0] & 0x01) ? 3 : 1; + + switch ((dev->regs[0][0xe0] >> 1) & 0x07) { + case 0x00: + irq_line = 3; + break; + case 0x01: + irq_line = 5; + break; + case 0x02: + irq_line = 7; + break; + case 0x03: + irq_line = 8; + break; + case 0x04: + irq_line = 11; + break; + case 0x05: + irq_line = 12; + break; + case 0x06: + irq_line = 14; + break; + case 0x07: + irq_line = 15; + break; + } + + sff_set_irq_line(dev->bm[0], irq_line); + sff_set_irq_mode(dev->bm[0], 0, irq_mode[0]); + sff_set_irq_mode(dev->bm[0], 1, irq_mode[1]); + + sff_set_irq_line(dev->bm[1], irq_line); + sff_set_irq_mode(dev->bm[1], 0, irq_mode[0]); + sff_set_irq_mode(dev->bm[1], 1, irq_mode[1]); } @@ -356,23 +389,14 @@ usb_update_io_mapping(piix_t *dev) static void usb_smsc_update_mem_mapping(piix_t *dev) { - uint8_t *fregs; uint32_t usb_bar; - if (!dev->usb_smsc_mmio_mapping) - return; + mem_mapping_disable(&dev->usb_smsc_mmio_mapping); - mem_mapping_disable(dev->usb_smsc_mmio_mapping); + usb_bar = ((dev->regs[2][0x11] << 8) | (dev->regs[2][0x12] << 16) | (dev->regs[2][0x13] << 24)) & 0xfffff000; - if (!dev->usb_smsc_mmio) - return; - - fregs = (uint8_t *) dev->regs[2]; - usb_bar = fregs[0x10] | (fregs[0x11] << 8) | (fregs[0x12] << 16) | (fregs[0x13] << 24); - piix_log("smsc usb bar %08x\n", usb_bar); - - if ((usb_bar != 0x00000000) && (usb_bar < 0xFF000000)) - mem_mapping_set_addr(dev->usb_smsc_mmio_mapping, usb_bar, 0x1000); + if ((dev->regs[2][0x04] & 0x02) && (usb_bar != 0x00000000)) + mem_mapping_set_addr(&dev->usb_smsc_mmio_mapping, usb_bar, 0x1000); } @@ -380,10 +404,12 @@ static uint8_t usb_smsc_mmio_read(uint32_t addr, void *p) { piix_t *dev = (piix_t *) p; - uint8_t ret; - ret = dev->usb_smsc_mmio[addr & 0xFFF]; + uint8_t ret = 0x00; + + /* addr &= 0x00000fff; + + ret = dev->usb_smsc_mmio[addr]; */ - piix_log("usb_smsc_mmio_read(%08x) = %02x\n", addr, ret); return ret; } @@ -393,127 +419,22 @@ usb_smsc_mmio_write(uint32_t addr, uint8_t val, void *p) { piix_t *dev = (piix_t *) p; - switch (addr & 0xFFF) { + addr &= 0x00000fff; + + switch (addr) { case 0x08: /* HCCOMMANDSTATUS */ /* bit HostControllerReset must be cleared for the controller to be seen as initialized */ - val = val & ~(0x01); + val &= ~0x01; /* bit OwnershipChangeRequest triggers an ownership change (SMM <-> OS) */ - if (val & 0x0F) { - dev->usb_smsc_mmio[0x0F] = 0x40; + if (val & 0x0f) { + dev->usb_smsc_mmio[0x0f] = 0x40; dev->usb_smsc_mmio[0x05] &= ~(dev->usb_smsc_mmio[0x05] & 0x01); } break; } - dev->usb_smsc_mmio[addr & 0xFFF] = val; - - piix_log("usb_smsc_mmio_write(%08x, %02x)\n", addr, val); -} - - -static uint32_t -power_reg_readl(uint16_t addr, void *p) -{ - piix_t *dev = (piix_t *) p; - uint32_t timer; - uint32_t ret = 0xffffffff; - - switch (addr & 0x3c) { - case 0x08: - /* ACPI timer */ - timer = (tsc * ACPI_TIMER_FREQ) / machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed; - timer &= 0x00ffffff; - ret = timer; - break; - } - - piix_log("ACPI: Read L %08X from %04X\n", ret, addr); - - return ret; -} - - -static uint16_t -power_reg_readw(uint16_t addr, void *p) -{ - piix_t *dev = (piix_t *) p; - uint16_t ret = 0xffff; - uint32_t ret32; - - switch (addr & 0x3c) { - case 0x00: - break; - default: - ret32 = power_reg_readl(addr, p); - if (addr & 0x02) - ret = (ret32 >> 16) & 0xffff; - else - ret = ret32 & 0xffff; - break; - } - - piix_log("ACPI: Read W %08X from %04X\n", ret, addr); - - return ret; -} - - -static uint8_t -power_reg_read(uint16_t addr, void *p) -{ - piix_t *dev = (piix_t *) p; - uint32_t timer; - uint8_t ret = 0xff; - uint16_t ret16; - - switch (addr & 0x3f) { - case 0x30: case 0x31: case 0x32: - ret = dev->power.gporeg[addr & 0x03]; - piix_log("ACPI: Read B %02X from GPIREG %01X\n", ret, addr & 0x03); - break; - case 0x34: case 0x35: case 0x36: case 0x37: - ret = dev->power.gporeg[addr & 0x03]; - piix_log("ACPI: Read B %02X from GPOREG %01X\n", ret, addr & 0x03); - break; - default: - ret16 = power_reg_readw(addr, p); - if (addr & 0x01) - ret = (ret16 >> 8) & 0xff; - else - ret = ret16 & 0xff; - break; - } - - return ret; -} - - -static void -power_reg_write(uint16_t addr, uint8_t val, void *p) -{ - piix_t *dev = (piix_t *) p; - - piix_log("ACPI: Write %02X to %04X\n", val, addr); - - switch (addr & 0x3f) { - case 0x34: case 0x35: case 0x36: case 0x37: - dev->power.gporeg[addr & 0x03] = val; - break; - } -} - - -static void -power_update_io_mapping(piix_t *dev) -{ - if (dev->power_io_base != 0x0000) - io_removehandler(dev->power_io_base, 0x40, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, dev); - - dev->power_io_base = (dev->regs[3][0x41] << 8) | (dev->regs[3][0x40] & 0xc0); - - if ((dev->regs[3][0x80] & 0x01) && (dev->power_io_base != 0x0000)) - io_sethandler(dev->power_io_base, 0x40, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, dev); + dev->usb_smsc_mmio[addr] = val; } @@ -527,24 +448,29 @@ smbus_update_io_mapping(piix_t *dev) static void nvr_update_io_mapping(piix_t *dev) { + int enabled2 = 1; + if (dev->nvr_io_base != 0x0000) { nvr_at_handler(0, dev->nvr_io_base, dev->nvr); nvr_at_handler(0, dev->nvr_io_base + 0x0002, dev->nvr); nvr_at_handler(0, dev->nvr_io_base + 0x0004, dev->nvr); - nvr_at_handler(0, dev->nvr_io_base + 0x0006, dev->nvr); } if (dev->type == 5) - dev->power_io_base = (dev->regs[0][0xd5] << 8) | (dev->regs[3][0xd4] & 0xf0); + dev->nvr_io_base = (dev->regs[0][0xd5] << 8) | (dev->regs[0][0xd4] & 0xf0); else - dev->power_io_base = 0x70; + dev->nvr_io_base = 0x70; + pclog("New NVR I/O base: %04X\n", dev->nvr_io_base); - if ((dev->regs[0][0xcb] & 0x01) && (dev->regs[2][0xff] & 0x10)) + /* if (dev->type == 4) + enabled2 = (dev->regs[2][0xff] & 0x10); */ + + if ((dev->regs[0][0xcb] & 0x01) && enabled2) { nvr_at_handler(1, dev->nvr_io_base, dev->nvr); + nvr_at_handler(1, dev->nvr_io_base + 0x0004, dev->nvr); + } if (dev->regs[0][0xcb] & 0x04) nvr_at_handler(1, dev->nvr_io_base + 0x0002, dev->nvr); - nvr_at_handler(1, dev->nvr_io_base + 0x0004, dev->nvr); - nvr_at_handler(1, dev->nvr_io_base + 0x0006, dev->nvr); } @@ -563,6 +489,10 @@ piix_write(int func, int addr, uint8_t val, void *priv) return; } + /* Ignore the new IDE BAR's on the Intel chips. */ + if ((dev->type < 5) && (func == 1) && (addr >= 0x10) && (addr <= 0x1f)) + return; + piix_log("PIIX function %i write: %02X to %02X\n", func, val, addr); fregs = (uint8_t *) dev->regs[func]; @@ -628,9 +558,9 @@ piix_write(int func, int addr, uint8_t val, void *priv) if (dev->type > 4) fregs[0x65] = val; break; - case 0x68: + case 0x66: if (dev->type > 4) - fregs[0x68] = val & 0x81; + fregs[0x66] = val & 0x81; break; case 0x69: if (dev->type > 1) @@ -791,15 +721,23 @@ piix_write(int func, int addr, uint8_t val, void *priv) break; case 0xe1: case 0xe4: case 0xe5: case 0xe6: case 0xe7: case 0xe8: case 0xe9: case 0xea: case 0xeb: - if (dev->type > 4) + if (dev->type > 4) { fregs[addr] = val; + if ((dev->type == 5) && (addr == 0xe1)) { + smsc_ide_irqs(dev); + port_92_set_features(dev->port_92, !!(val & 0x40), !!(val & 0x40)); + } + } break; } else if (func == 1) switch(addr) { /* IDE */ case 0x04: fregs[0x04] = (val & 5); if (dev->type < 3) fregs[0x04] |= 0x02; - piix_ide_legacy_handlers(dev, 0x03); + if (dev->type == 5) + smsc_ide_handlers(dev); + else + piix_ide_legacy_handlers(dev, 0x03); piix_ide_bm_handlers(dev); break; case 0x07: @@ -810,9 +748,48 @@ piix_write(int func, int addr, uint8_t val, void *priv) if (val & 0x08) fregs[0x07] &= 0xf7; break; + case 0x09: + if (dev->type == 5) { + fregs[0x09] = (fregs[0x09] & 0xfa) | (val & 0x05); + smsc_ide_handlers(dev); + smsc_ide_irqs(dev); + } + break; case 0x0d: fregs[0x0d] = val & 0xf0; break; + case 0x10: + fregs[0x10] = (val & 0xf8) | 1; + smsc_ide_handlers(dev); + break; + case 0x11: + fregs[0x11] = val; + smsc_ide_handlers(dev); + break; + case 0x14: + fregs[0x14] = (val & 0xfc) | 1; + smsc_ide_handlers(dev); + break; + case 0x15: + fregs[0x15] = val; + smsc_ide_handlers(dev); + break; + case 0x18: + fregs[0x18] = (val & 0xf8) | 1; + smsc_ide_handlers(dev); + break; + case 0x19: + fregs[0x19] = val; + smsc_ide_handlers(dev); + break; + case 0x1c: + fregs[0x1c] = (val & 0xfc) | 1; + smsc_ide_handlers(dev); + break; + case 0x1d: + fregs[0x1d] = val; + smsc_ide_handlers(dev); + break; case 0x20: fregs[0x20] = (val & 0xf0) | 1; piix_ide_bm_handlers(dev); @@ -822,7 +799,6 @@ piix_write(int func, int addr, uint8_t val, void *priv) piix_ide_bm_handlers(dev); break; case 0x3c: - piix_log("IDE IRQ write: %02X\n", val); fregs[0x3c] = val; break; case 0x40: case 0x42: @@ -830,26 +806,52 @@ piix_write(int func, int addr, uint8_t val, void *priv) break; case 0x41: case 0x43: fregs[addr] = val & ((dev->type > 1) ? 0xf3 : 0xb3); - piix_ide_legacy_handlers(dev, 1 << !!(addr & 0x02)); + if (dev->type == 5) + smsc_ide_handlers(dev); + else + piix_ide_legacy_handlers(dev, 1 << !!(addr & 0x02)); break; case 0x44: if (dev->type > 1) fregs[0x44] = val; break; + case 0x45: + if (dev->type > 4) + fregs[0x45] = val; + break; + case 0x46: + if (dev->type > 4) + fregs[0x46] = val & 0x03; + break; case 0x48: if (dev->type > 3) fregs[0x48] = val & 0x0f; break; case 0x4a: case 0x4b: - if (dev->type > 4) + if (dev->type > 3) fregs[addr] = val & 0x33; break; + case 0x5c: case 0x5d: + if (dev->type > 4) + fregs[addr] = val; + break; } else if (func == 2) switch(addr) { /* USB */ case 0x04: - fregs[0x04] = (val & 5); - usb_update_io_mapping(dev); + if (dev->type > 4) { + fregs[0x04] = (val & 7); + usb_smsc_update_mem_mapping(dev); + } else { + fregs[0x04] = (val & 5); + usb_update_io_mapping(dev); + } break; case 0x07: + if (dev->type > 4) { + if (val & 0x80) + fregs[0x07] &= 0x7f; + if (val & 0x40) + fregs[0x07] &= 0xbf; + } if (val & 0x20) fregs[0x07] &= 0xdf; if (val & 0x10) @@ -857,40 +859,68 @@ piix_write(int func, int addr, uint8_t val, void *priv) if (val & 0x08) fregs[0x07] &= 0xf7; break; + case 0x0c: + if (dev->type > 4) + fregs[0x0c] = val; + break; case 0x0d: - fregs[0x0d] = val & 0xf0; + if (dev->type <= 4) + fregs[0x0d] = val & 0xf0; break; case 0x11: - fregs[addr] = val & ~(0x10); - usb_smsc_update_mem_mapping(dev); + if (dev->type > 4) { + fregs[addr] = val & 0xf0; + usb_smsc_update_mem_mapping(dev); + } break; case 0x12: case 0x13: - fregs[addr] = val; - usb_smsc_update_mem_mapping(dev); + if (dev->type > 4) { + fregs[addr] = val; + usb_smsc_update_mem_mapping(dev); + } break; case 0x20: - fregs[0x20] = (val & 0xe0) | 1; - usb_update_io_mapping(dev); + if (dev->type < 5) { + fregs[0x20] = (val & 0xe0) | 1; + usb_update_io_mapping(dev); + } break; case 0x21: - fregs[0x21] = val; - usb_update_io_mapping(dev); + if (dev->type < 5) { + fregs[0x21] = val; + usb_update_io_mapping(dev); + } break; case 0x3c: fregs[0x3c] = val; break; + case 0x3e: case 0x3f: + case 0x40: case 0x41: case 0x43: + if (dev->type > 4) + fregs[addr] = val; + break; + case 0x42: + if (dev->type > 4) + fregs[addr] = val & 0x8f; + break; + case 0x44: case 0x45: + if (dev->type > 4) + fregs[addr] = val & 0x01; + break; case 0x6a: - if (dev->type < 4) + if (dev->type == 4) fregs[0x6a] = val & 0x01; break; case 0xc0: - fregs[0xc0] = val; + if (dev->type == 4) + fregs[0xc0] = val; break; case 0xc1: - fregs[0xc1] = val & 0xbf; + if (dev->type == 4) + fregs[0xc1] = val & 0xbf; break; case 0xff: - if (dev->type >= 4) { + if (dev->type == 4) { fregs[addr] = val & 0x10; nvr_at_handler(0, 0x0070, dev->nvr); if ((dev->regs[0][0xcb] & 0x01) && (dev->regs[2][0xff] & 0x10)) @@ -900,7 +930,6 @@ piix_write(int func, int addr, uint8_t val, void *priv) } else if (func == 3) switch(addr) { /* Power Management */ case 0x04: fregs[0x04] = (val & 0x01); - power_update_io_mapping(dev); smbus_update_io_mapping(dev); apm_set_do_smi(dev->apm, !!(fregs[0x5b] & 0x02) && !!(val & 0x01)); break; @@ -915,11 +944,13 @@ piix_write(int func, int addr, uint8_t val, void *priv) #endif case 0x40: fregs[0x40] = (val & 0xc0) | 1; - power_update_io_mapping(dev); + dev->acpi_io_base = (dev->regs[3][0x41] << 8) | (dev->regs[3][0x40] & 0xc0); + acpi_update_io_mapping(dev->acpi, dev->acpi_io_base, (dev->regs[3][0x80] & 0x01)); break; case 0x41: fregs[0x41] = val; - power_update_io_mapping(dev); + dev->acpi_io_base = (dev->regs[3][0x41] << 8) | (dev->regs[3][0x40] & 0xc0); + acpi_update_io_mapping(dev->acpi, dev->acpi_io_base, (dev->regs[3][0x80] & 0x01)); break; case 0x44: case 0x45: case 0x46: case 0x47: case 0x48: case 0x49: @@ -947,7 +978,7 @@ piix_write(int func, int addr, uint8_t val, void *priv) case 0x4f: case 0x80: case 0xd2: fregs[addr] = val & 0x0f; if (addr == 0x80) - power_update_io_mapping(dev); + acpi_update_io_mapping(dev->acpi, dev->acpi_io_base, (dev->regs[3][0x80] & 0x01)); else if (addr == 0xd2) smbus_update_io_mapping(dev); break; @@ -1056,8 +1087,17 @@ piix_reset_hard(piix_t *dev) sff_bus_master_reset(dev->bm[1], old_base + 8); if (dev->type >= 4) { - sff_set_irq_mode(dev->bm[0], 0); - sff_set_irq_mode(dev->bm[1], 0); + sff_set_slot(dev->bm[0], dev->pci_slot); + sff_set_irq_pin(dev->bm[0], PCI_INTA); + sff_set_irq_line(dev->bm[0], 14); + sff_set_irq_mode(dev->bm[0], 0, 0); + sff_set_irq_mode(dev->bm[0], 1, 0); + + 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_mode(dev->bm[1], 0, 0); + sff_set_irq_mode(dev->bm[1], 1, 0); } #ifdef ENABLE_PIIX_LOG @@ -1071,7 +1111,6 @@ piix_reset_hard(piix_t *dev) nvr_wp_set(0, 0, dev->nvr); nvr_wp_set(0, 1, dev->nvr); nvr_at_handler(1, 0x0074, dev->nvr); - nvr_at_handler(1, 0x0076, dev->nvr); dev->nvr_io_base = 0x0070; } @@ -1140,9 +1179,16 @@ piix_reset_hard(piix_t *dev) fregs[0x08] = dev->rev & 0x07; else fregs[0x08] = dev->rev; - fregs[0x09] = 0x80; + if (dev->type == 5) + fregs[0x09] = 0x8a; + else + fregs[0x09] = 0x80; fregs[0x0a] = 0x01; fregs[0x0b] = 0x01; fregs[0x20] = 0x01; + if (dev->type == 5) { + fregs[0x3c] = 0x0e; + fregs[0x3d] = 0x01; + } dev->max_func = 0; /* It starts with IDE disabled, then enables it. */ /* Function 2: USB */ @@ -1153,8 +1199,10 @@ piix_reset_hard(piix_t *dev) fregs[0x06] = 0x80; fregs[0x07] = 0x02; if (dev->type == 4) fregs[0x08] = dev->rev & 0x07; - else + else if (dev->type < 4) fregs[0x08] = dev->rev; + else + fregs[0x08] = 0x02; if (dev->type == 5) fregs[0x09] = 0x10; /* SMSC has OHCI rather than UHCI */ fregs[0x0a] = 0x03; fregs[0x0b] = 0x0c; @@ -1180,11 +1228,15 @@ piix_reset_hard(piix_t *dev) fregs = (uint8_t *) dev->regs[3]; piix_log("PIIX Function 3: %02X%02X:%02X%02X\n", fregs[0x01], fregs[0x00], fregs[0x03], fregs[0x02]); fregs[0x06] = 0x80; fregs[0x07] = 0x02; - fregs[0x08] = (dev->rev & 0x08) ? 0x02 : (dev->rev & 0x07); + if (dev->type > 4) + fregs[0x08] = 0x02; + else + fregs[0x08] = (dev->rev & 0x08) ? 0x02 : (dev->rev & 0x07); fregs[0x0a] = 0x80; fregs[0x0b] = 0x06; /* NOTE: The Specification Update says this should default to 0x00 and be read-only. */ #ifdef WRONG_SPEC - fregs[0x3d] = 0x01; + if (dev->type == 4) + fregs[0x3d] = 0x01; #endif fregs[0x40] = 0x01; fregs[0x90] = 0x01; @@ -1201,12 +1253,8 @@ piix_reset_hard(piix_t *dev) if (dev->type < 3) pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); - if (dev->type == 4) { - dev->power.gporeg[0] = 0xff; - dev->power.gporeg[1] = 0xbf; - dev->power.gporeg[2] = 0xff; - dev->power.gporeg[3] = 0x7f; - } + if (dev->type >= 4) + acpi_init_gporeg(dev->acpi, 0xff, 0xbf, 0xff, 0x7f); } @@ -1222,7 +1270,6 @@ piix_close(void *p) static void *piix_init(const device_t *info) { - int i; CPU *cpu_s = &machines[machine].cpu[cpu_manufacturer].cpus[cpu]; piix_t *dev = (piix_t *) malloc(sizeof(piix_t)); @@ -1240,26 +1287,30 @@ static void dev->bm[0] = device_add_inst(&sff8038i_device, 1); dev->bm[1] = device_add_inst(&sff8038i_device, 2); - if (dev->type > 3) + if (dev->type > 3) { dev->nvr = device_add(&piix4_nvr_device); + dev->smbus = device_add(&piix4_smbus_device); + + dev->acpi = device_add(&acpi_device); + acpi_set_slot(dev->acpi, dev->pci_slot); + acpi_set_nvr(dev->acpi, dev->nvr); + } if (dev->type == 5) { - dev->usb_smsc_mmio = malloc(4096); + dev->usb_smsc_mmio = (uint8_t *) malloc(4096); + memset(dev->usb_smsc_mmio, 0x00, 4096); - dev->usb_smsc_mmio_mapping = malloc(sizeof(mem_mapping_t)); - mem_mapping_add(dev->usb_smsc_mmio_mapping, 0, 0, + mem_mapping_add(&dev->usb_smsc_mmio_mapping, 0, 0, usb_smsc_mmio_read, NULL, NULL, usb_smsc_mmio_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, dev); - mem_mapping_disable(dev->usb_smsc_mmio_mapping); + mem_mapping_disable(&dev->usb_smsc_mmio_mapping); } piix_reset_hard(dev); - dev->smbus = device_add(&piix4_smbus_device); - dev->apm = device_add(&apm_device); - device_add(&port_92_pci_device); + dev->port_92 = device_add(&port_92_pci_device); dma_alias_set(); @@ -1299,7 +1350,7 @@ static void dev->readout_regs[1] |= 0x80; io_sethandler(0x0078, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, dev); - // io_sethandler(0x00e0, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, dev); + io_sethandler(0x00e0, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, dev); dev->board_config[0] = 0xff; dev->board_config[0] = 0x00; diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index 11191608c..7ad3e2b66 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -97,7 +97,7 @@ machine_at_p2bls_init(const machine_t *model) device_add(&i440bx_device); device_add(&piix4e_device); device_add(&keyboard_ps2_pci_device); - device_add(&w83977ef_device); + // device_add(&w83977ef_device); device_add(&sst_flash_39sf020_device); spd_register(SPD_TYPE_SDRAM, 0xF, 256); diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index ab1260804..3fee77bba 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -1309,7 +1309,7 @@ eep_close(void *priv) t1keep_t *eep = (t1keep_t *)priv; FILE *f = NULL; - f = nvr_fopen(eep->path, L"rb"); + f = nvr_fopen(eep->path, L"wb"); if (f != NULL) { (void)fwrite(eep->store, 128, 1, f); (void)fclose(f); diff --git a/src/nvr_at.c b/src/nvr_at.c index 4e19e6b96..37c8f2ec0 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -553,78 +553,89 @@ timer_tick(nvr_t *nvr) } +/* This must be exposed because ACPI uses it. */ +void +nvr_reg_write(uint16_t reg, uint8_t val, void *priv) +{ + nvr_t *nvr = (nvr_t *)priv; + local_t *local = (local_t *)nvr->data; + struct tm tm; + uint8_t old, i; + uint16_t checksum = 0x0000; + + old = nvr->regs[reg]; + switch(reg) { + case RTC_REGA: + nvr->regs[RTC_REGA] = val; + timer_load_count(nvr); + break; + + case RTC_REGB: + nvr->regs[RTC_REGB] = val; + if (((old^val) & REGB_SET) && (val®B_SET)) { + /* According to the datasheet... */ + nvr->regs[RTC_REGA] &= ~REGA_UIP; + nvr->regs[RTC_REGB] &= ~REGB_UIE; + } + break; + + case RTC_REGC: /* R/O */ + case RTC_REGD: /* R/O */ + break; + + case 0x2e: + case 0x2f: + if (local->flags & FLAG_LS_HACK) { + /* 2E and 2F are a simple sum of the values of 0E to 2D. */ + for (i = 0x0e; i < 0x2e; i++) + checksum += (uint16_t) nvr->regs[i]; + nvr->regs[0x2e] = checksum >> 8; + nvr->regs[0x2f] = checksum & 0xff; + break; + } + /*FALLTHROUGH*/ + + default: /* non-RTC registers are just NVRAM */ + if ((reg >= 0x38) && (reg <= 0x3f) && local->wp[0]) + break; + if ((reg >= 0xb8) && (reg <= 0xbf) && local->wp[1]) + break; + if (local->lock[reg]) + break; + if (nvr->regs[reg] != val) { + nvr->regs[reg] = val; + nvr_dosave = 1; + } + break; + } + + if ((reg < RTC_REGA) || ((local->cent != 0xff) && (reg == local->cent))) { + if ((reg != 1) && (reg != 3) && (reg != 5)) { + if ((old != val) && !(time_sync & TIME_SYNC_ENABLED)) { + /* Update internal clock. */ + time_get(nvr, &tm); + nvr_time_set(&tm); + nvr_dosave = 1; + } + } + } +} + + /* Write to one of the NVR registers. */ static void nvr_write(uint16_t addr, uint8_t val, void *priv) { nvr_t *nvr = (nvr_t *)priv; local_t *local = (local_t *)nvr->data; - struct tm tm; - uint8_t old, i; uint8_t addr_id = (addr & 0x0e) >> 1; - uint16_t checksum = 0x0000; sub_cycles(ISA_CYCLES(8)); if (addr & 1) { if (local->bank[addr_id] == 0xff) return; - old = nvr->regs[local->addr[addr_id]]; - switch(local->addr[addr_id]) { - case RTC_REGA: - nvr->regs[RTC_REGA] = val; - timer_load_count(nvr); - break; - - case RTC_REGB: - nvr->regs[RTC_REGB] = val; - if (((old^val) & REGB_SET) && (val®B_SET)) { - /* According to the datasheet... */ - nvr->regs[RTC_REGA] &= ~REGA_UIP; - nvr->regs[RTC_REGB] &= ~REGB_UIE; - } - break; - - case RTC_REGC: /* R/O */ - case RTC_REGD: /* R/O */ - break; - - case 0x2e: - case 0x2f: - if (local->flags & FLAG_LS_HACK) { - /* 2E and 2F are a simple sum of the values of 0E to 2D. */ - for (i = 0x0e; i < 0x2e; i++) - checksum += (uint16_t) nvr->regs[i]; - nvr->regs[0x2e] = checksum >> 8; - nvr->regs[0x2f] = checksum & 0xff; - break; - } - /*FALLTHROUGH*/ - - default: /* non-RTC registers are just NVRAM */ - if ((local->addr[addr_id] >= 0x38) && (local->addr[addr_id] <= 0x3f) && local->wp[0]) - break; - if ((local->addr[addr_id] >= 0xb8) && (local->addr[addr_id] <= 0xbf) && local->wp[1]) - break; - if (local->lock[local->addr[addr_id]]) - break; - if (nvr->regs[local->addr[addr_id]] != val) { - nvr->regs[local->addr[addr_id]] = val; - nvr_dosave = 1; - } - break; - } - - if ((local->addr[addr_id] < RTC_REGA) || ((local->cent != 0xff) && (local->addr[addr_id] == local->cent))) { - if ((local->addr[addr_id] != 1) && (local->addr[addr_id] != 3) && (local->addr[addr_id] != 5)) { - if ((old != val) && !(time_sync & TIME_SYNC_ENABLED)) { - /* Update internal clock. */ - time_get(nvr, &tm); - nvr_time_set(&tm); - nvr_dosave = 1; - } - } - } + nvr_reg_write(local->addr[addr_id], val, priv); } else { local->addr[addr_id] = (val & (nvr->size - 1)); /* Some chipsets use a 256 byte NVRAM but ports 70h and 71h always access only 128 bytes. */ diff --git a/src/pit.c b/src/pit.c index c12108f36..d07b38c72 100644 --- a/src/pit.c +++ b/src/pit.c @@ -50,7 +50,7 @@ uint64_t PITCONST, ISACONST, CGACONST, MDACONST, HERCCONST, VGACONST1, VGACONST2, - RTCCONST; + RTCCONST, ACPICONST; int io_delay = 5; @@ -1021,6 +1021,7 @@ pit_set_clock(int clock) VGACONST1 = (uint64_t) (cpuclock / 25175000.0 * (double)(1ull << 32)); VGACONST2 = (uint64_t) (cpuclock / 28322000.0 * (double)(1ull << 32)); RTCCONST = (uint64_t) (cpuclock / 32768.0 * (double)(1ull << 32)); + ACPICONST = (uint64_t) (cpuclock / 3579545.0 * (double)(1ull << 32)); TIMER_USEC = (uint64_t)((cpuclock / 1000000.0) * (double)(1ull << 32)); diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index 5a8c239f8..d9d1c3f5a 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -810,14 +810,16 @@ sb_exec_command(sb_dsp_t *dsp) break; case 0x09: /*AZTECH mode set*/ - if (dsp->sb_data[0] == 0x00) { - sb_dsp_log("AZT2316A: WSS MODE!\n"); - azt2316a_enable_wss(1, dsp->parent); - } else if (dsp->sb_data[0] == 0x01) { - sb_dsp_log("AZT2316A: SB8PROV2 MODE!\n"); - azt2316a_enable_wss(0, dsp->parent); - } else - sb_dsp_log("AZT2316A: UNKNOWN MODE! = %02x\n", dsp->sb_data[0]); // sequences 0x02->0xFF, 0x04->0xFF seen + if (IS_AZTECH(dsp)) { + if (dsp->sb_data[0] == 0x00) { + sb_dsp_log("AZT2316A: WSS MODE!\n"); + azt2316a_enable_wss(1, dsp->parent); + } else if (dsp->sb_data[0] == 0x01) { + sb_dsp_log("AZT2316A: SB8PROV2 MODE!\n"); + azt2316a_enable_wss(0, dsp->parent); + } else + sb_dsp_log("AZT2316A: UNKNOWN MODE! = %02x\n", dsp->sb_data[0]); // sequences 0x02->0xFF, 0x04->0xFF seen + } break; /* TODO: Some more data about the DSP registeres diff --git a/src/via_vt82c586b.c b/src/via_vt82c586b.c index a2ff6f4d1..b2721c5d4 100644 --- a/src/via_vt82c586b.c +++ b/src/via_vt82c586b.c @@ -220,6 +220,25 @@ via_vt82c586b_ide_handlers(via_vt82c586b_t *dev) } +static void +via_vt82c586b_ide_irqs(via_vt82c586b_t *dev) +{ + int irq_mode[2] = { 0, 0 }; + + if (dev->ide_regs[0x09] & 0x01) + irq_mode[0] = (dev->ide_regs[0x3d] & 0x01); + + if (dev->ide_regs[0x09] & 0x04) + irq_mode[1] = (dev->ide_regs[0x3d] & 0x01); + + sff_set_irq_mode(dev->bm[0], 0, irq_mode[0]); + sff_set_irq_mode(dev->bm[0], 1, irq_mode[1]); + + sff_set_irq_mode(dev->bm[1], 0, irq_mode[0]); + sff_set_irq_mode(dev->bm[1], 1, irq_mode[1]); +} + + static void via_vt82c586b_bus_master_handlers(via_vt82c586b_t *dev) { @@ -466,6 +485,7 @@ via_vt82c586b_write(int func, int addr, uint8_t val, void *priv) case 0x09: dev->ide_regs[0x09] = (val & 0x05) | 0x8a; via_vt82c586b_ide_handlers(dev); + via_vt82c586b_ide_irqs(dev); break; case 0x10: @@ -514,8 +534,8 @@ via_vt82c586b_write(int func, int addr, uint8_t val, void *priv) break; case 0x3d: - sff_set_irq_mode(dev->bm[0], val); - sff_set_irq_mode(dev->bm[1], val); + dev->ide_regs[0x3d] = val & 0x01; + via_vt82c586b_ide_irqs(dev); break; case 0x40: @@ -591,12 +611,14 @@ static void dev->bm[0] = device_add_inst(&sff8038i_device, 1); sff_set_slot(dev->bm[0], dev->slot); - sff_set_irq_mode(dev->bm[0], 0); + sff_set_irq_mode(dev->bm[0], 0, 0); + sff_set_irq_mode(dev->bm[0], 1, 0); sff_set_irq_pin(dev->bm[0], PCI_INTA); dev->bm[1] = device_add_inst(&sff8038i_device, 2); sff_set_slot(dev->bm[1], dev->slot); - sff_set_irq_mode(dev->bm[1], 0); + sff_set_irq_mode(dev->bm[1], 0, 0); + sff_set_irq_mode(dev->bm[1], 1, 0); sff_set_irq_pin(dev->bm[1], PCI_INTA); dev->nvr = device_add(&via_nvr_device); diff --git a/src/via_vt82c596b.c b/src/via_vt82c596b.c index 4aa548d34..e982e4e05 100644 --- a/src/via_vt82c596b.c +++ b/src/via_vt82c596b.c @@ -263,6 +263,7 @@ via_vt82c596b_reset(void *priv) ide_sec_disable(); } + // IDE CONTROLLER static void ide_handlers(via_vt82c596b_t *dev) @@ -307,6 +308,25 @@ ide_handlers(via_vt82c596b_t *dev) } +static void +ide_irqs(via_vt82c596b_t *dev) +{ + int irq_mode[2] = { 0, 0 }; + + if (dev->ide_regs[0x09] & 0x01) + irq_mode[0] = (dev->ide_regs[0x3d] & 0x01); + + if (dev->ide_regs[0x09] & 0x04) + irq_mode[1] = (dev->ide_regs[0x3d] & 0x01); + + sff_set_irq_mode(dev->bm[0], 0, irq_mode[0]); + sff_set_irq_mode(dev->bm[0], 1, irq_mode[1]); + + sff_set_irq_mode(dev->bm[1], 0, irq_mode[0]); + sff_set_irq_mode(dev->bm[1], 1, irq_mode[1]); +} + + static void bus_master_handlers(via_vt82c596b_t *dev) { @@ -581,6 +601,7 @@ via_vt82c596b_write(int func, int addr, uint8_t val, void *priv) case 0x09: dev->ide_regs[0x09] = (val & 0x05) | 0x8a; ide_handlers(dev); + ide_irqs(dev); break; case 0x10: @@ -629,8 +650,8 @@ via_vt82c596b_write(int func, int addr, uint8_t val, void *priv) break; case 0x3d: - sff_set_irq_mode(dev->bm[0], val); - sff_set_irq_mode(dev->bm[1], val); + dev->ide_regs[0x3d] = val & 0x01; + ide_irqs(dev); break; case 0x40: @@ -717,12 +738,14 @@ via_vt82c596b_init(const device_t *info) dev->bm[0] = device_add_inst(&sff8038i_device, 1); sff_set_slot(dev->bm[0], dev->slot); - sff_set_irq_mode(dev->bm[0], 0); + sff_set_irq_mode(dev->bm[0], 0, 0); + sff_set_irq_mode(dev->bm[0], 1, 0); sff_set_irq_pin(dev->bm[0], PCI_INTA); dev->bm[1] = device_add_inst(&sff8038i_device, 2); sff_set_slot(dev->bm[1], dev->slot); - sff_set_irq_mode(dev->bm[1], 0); + sff_set_irq_mode(dev->bm[1], 0, 0); + sff_set_irq_mode(dev->bm[1], 1, 0); sff_set_irq_pin(dev->bm[1], PCI_INTA); dev->nvr = device_add(&via_nvr_device); diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index de4990cfc..d92d028ec 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -549,7 +549,7 @@ CXXFLAGS := $(CFLAGS) ######################################################################### # Create the (final) list of objects to build. # ######################################################################### -MAINOBJ := pc.o config.o random.o timer.o io.o apm.o dma.o nmi.o \ +MAINOBJ := pc.o config.o random.o timer.o io.o acpi.o apm.o dma.o nmi.o \ pic.o pit.o port_92.o ppi.o pci.o mca.o mcr.o mem.o \ rom.o device.o nvr.o nvr_at.o nvr_ps2.o sst_flash.o via_vt82c586b.o \ via_vt82c596b.o $(VNCOBJ) $(RDPOBJ) diff --git a/src/win/Makefile_ndr.mingw b/src/win/Makefile_ndr.mingw index 952f51587..ccc00515c 100644 --- a/src/win/Makefile_ndr.mingw +++ b/src/win/Makefile_ndr.mingw @@ -553,7 +553,7 @@ CXXFLAGS := $(CFLAGS) ######################################################################### # Create the (final) list of objects to build. # ######################################################################### -MAINOBJ := pc.o config.o random.o timer.o io.o apm.o dma.o nmi.o \ +MAINOBJ := pc.o config.o random.o timer.o io.o acpi.o apm.o dma.o nmi.o \ pic.o pit.o port_92.o ppi.o pci.o mca.o mcr.o mem.o \ rom.o device.o nvr.o nvr_at.o nvr_ps2.o sst_flash.o via_vt82c586b.o \ via_vt82c596b.o $(VNCOBJ) $(RDPOBJ)