diff --git a/src/chipset/ali1543.c b/src/chipset/ali1543.c index 6227115fd..ccdaf0c46 100644 --- a/src/chipset/ali1543.c +++ b/src/chipset/ali1543.c @@ -1068,7 +1068,7 @@ ali7101_write(int func, int addr, uint8_t val, void *priv) case 0x40: dev->pmu_conf[addr] = val & 0x1f; - pic_set_smi_irq_mask(8, (dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x40] & 0x03)); + nvr_smi_enable((dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x40] & 0x08), dev->nvr); break; case 0x41: dev->pmu_conf[addr] = val & 0x10; @@ -1079,6 +1079,8 @@ ali7101_write(int func, int addr, uint8_t val, void *priv) /* TODO: Is the status R/W or R/WC? */ case 0x42: dev->pmu_conf[addr] &= ~(val & 0x1f); + if (val & 0x08) + nvr_smi_status_clear(dev->nvr); break; case 0x43: dev->pmu_conf[addr] &= ~(val & 0x10); @@ -1216,8 +1218,8 @@ ali7101_write(int func, int addr, uint8_t val, void *priv) case 0x77: /* TODO: If bit 1 is clear, then status bit is set even if SMI is disabled. */ dev->pmu_conf[addr] = val; - pic_set_smi_irq_mask(8, (dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x40] & 0x03)); ali1543_log("PMU77: %02X\n", val); + nvr_smi_enable((dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x40] & 0x08), dev->nvr); apm_set_do_smi(dev->acpi->apm, (dev->pmu_conf[0x77] & 0x08) && (dev->pmu_conf[0x41] & 0x10)); break; @@ -1422,14 +1424,23 @@ ali7101_read(int func, int addr, void *priv) return 0xff; /* TODO: C4, C5 = GPIREG (masks: 0D, 0E) */ - if (addr == 0x43) - ret = acpi_ali_soft_smi_status_read(dev->acpi) ? 0x10 : 0x00; - else if (addr == 0x7f) - ret = 0x80; - else if (addr == 0xbc) - ret = inb(0x70); - else - ret = dev->pmu_conf[addr]; + switch (addr) { + default: + ret = dev->pmu_conf[addr]; + break; + case 0x42: + ret = (dev->pmu_conf[addr] & 0xf7) | (nvr_smi_status(dev->nvr) ? 0x08 : 0x00); + break; + case 0x43: + ret = acpi_ali_soft_smi_status_read(dev->acpi) ? 0x10 : 0x00; + break; + case 0x7f: + ret = 0x80; + break; + case 0xbc: + ret = inb(0x70); + break; + } if (dev->pmu_conf[0x77] & 0x10) { switch (addr) { diff --git a/src/include/86box/nvr.h b/src/include/86box/nvr.h index 8f2b45041..d24ca903c 100644 --- a/src/include/86box/nvr.h +++ b/src/include/86box/nvr.h @@ -127,5 +127,8 @@ extern void nvr_via_wp_set(int set, int reg, nvr_t *nvr); extern void nvr_bank_set(int base, uint8_t bank, nvr_t *nvr); extern void nvr_lock_set(int base, int size, int lock, nvr_t *nvr); extern void nvr_irq_set(int irq, nvr_t *nvr); +extern void nvr_smi_enable(int enable, nvr_t *nvr); +extern uint8_t nvr_smi_status(nvr_t *nvr); +extern void nvr_smi_status_clear(nvr_t *nvr); #endif /*EMU_NVR_H*/ diff --git a/src/nvr_at.c b/src/nvr_at.c index 187e42a25..990d1f1e7 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -307,7 +307,7 @@ typedef struct local_t { uint8_t wp_0d; uint8_t wp_32; uint8_t irq_state; - uint8_t pad0; + uint8_t smi_status; uint8_t addr[8]; uint8_t wp[2]; @@ -317,6 +317,8 @@ typedef struct local_t { int16_t count; int16_t state; + int32_t smi_enable; + uint64_t ecount; uint64_t rtc_time; pc_timer_t update_timer; @@ -444,6 +446,10 @@ timer_update_irq(nvr_t *nvr) if (irq) { nvr->regs[RTC_REGC] |= REGC_IRQF; picintlevel(1 << nvr->irq, &local->irq_state); + if (local->smi_enable) { + smi_raise(); + local->smi_status = 1; + } } else { nvr->regs[RTC_REGC] &= ~REGC_IRQF; picintclevel(1 << nvr->irq, &local->irq_state); @@ -981,6 +987,33 @@ nvr_irq_set(int irq, nvr_t *nvr) nvr->irq = irq; } +void +nvr_smi_enable(int enable, nvr_t *nvr) +{ + local_t *local = (local_t *) nvr->data; + + local->smi_enable = enable; + + if (!enable) + local->smi_status = 0; +} + +uint8_t +nvr_smi_status(nvr_t *nvr) +{ + local_t *local = (local_t *) nvr->data; + + return local->smi_status; +} + +void +nvr_smi_status_clear(nvr_t *nvr) +{ + local_t *local = (local_t *) nvr->data; + + local->smi_status = 0; +} + static void nvr_at_reset(void *priv) {