Reimplemented ALi M1543(C) NVR SMI# handling, fixes #3278.
This commit is contained in:
@@ -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) {
|
||||
|
@@ -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*/
|
||||
|
35
src/nvr_at.c
35
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)
|
||||
{
|
||||
|
Reference in New Issue
Block a user