Reimplemented ALi M1543(C) NVR SMI# handling, fixes #3278.

This commit is contained in:
OBattler
2023-08-19 01:39:30 +02:00
parent 250b756af7
commit 274b44ab00
3 changed files with 58 additions and 11 deletions

View File

@@ -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) {

View File

@@ -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*/

View File

@@ -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)
{