Multiple fixes for the SiS 85C50x

- Fixed the PCI IRQ setting
- Added a missing register needed to trigger an APM SMI
- Registers with reserved bits are now safe
- The ISA controller is properly implemented
This commit is contained in:
Panagiotis
2020-12-17 09:19:51 +02:00
committed by GitHub
parent fbab9d8643
commit 4b0b03e056

View File

@@ -53,7 +53,7 @@ sis_85c50x_log(const char *fmt, ...)
typedef struct sis_85c50x_t typedef struct sis_85c50x_t
{ {
uint8_t pci_conf[256], pci_conf_sb[256], regs[256]; uint8_t pci_conf[256], pci_conf_sb[256], regs[256], index;
apm_t *apm; apm_t *apm;
smram_t *smram; smram_t *smram;
@@ -113,25 +113,42 @@ sis_85c50x_write(int func, int addr, uint8_t val, void *priv)
dev->pci_conf[addr] = val; dev->pci_conf[addr] = val;
switch (addr) switch (addr)
{ {
case 0x51: case 0x04: /* Command */
dev->pci_conf[addr] = (val & 0xcf);
break;
case 0x07: /* Status */
dev->pci_conf[addr] = (val & 0xfe);
break;
case 0x51: /* Cache */
cpu_cache_ext_enabled = (val & 0x40); cpu_cache_ext_enabled = (val & 0x40);
break; break;
case 0x53: case 0x53: /* Shadow RAM */
case 0x54: case 0x54:
case 0x55: case 0x55:
case 0x56: case 0x56:
sis_85c50x_shadow_recalc(dev); sis_85c50x_shadow_recalc(dev);
break; break;
case 0x60: case 0x5f:
apm_set_do_smi(dev->apm, (val & 0x02)); dev->pci_conf[addr] = (val & 0xfe);
break; break;
case 0x64: case 0x60: /* SMI */
apm_set_do_smi(dev->apm, ((val & 0x02) && (dev->pci_conf[0x68] & 0x01)));
if (val & 0x02)
dev->pci_conf[0x69] &= 0x01;
break;
case 0x64: /* SMM/SMRAM */
case 0x65: case 0x65:
sis_85c50x_smm_recalc(dev); sis_85c50x_smm_recalc(dev);
break; break;
case 0x66:
dev->pci_conf[addr] = (val & 0x7f);
break;
} }
sis_85c50x_log("85C501: dev->pci_conf[%02x] = %02x", addr, val); sis_85c50x_log("85C501: dev->pci_conf[%02x] = %02x", addr, val);
} }
@@ -154,17 +171,29 @@ sis_85c50x_sb_write(int func, int addr, uint8_t val, void *priv)
switch (addr) switch (addr)
{ {
case 0x41: case 0x07: /* Status */
pci_set_irq_routing(PCI_INTA, (val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED); dev->pci_conf_sb[addr] = (val & 0x36);
break; break;
case 0x42:
pci_set_irq_routing(PCI_INTB, (val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED); case 0x40:
dev->pci_conf_sb[addr] = (val & 0x3f);
break; break;
case 0x43:
pci_set_irq_routing(PCI_INTC, (val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED); case 0x41: /* PCI INTA IRQ */
dev->pci_conf_sb[addr] = (val & 0x8f);
pci_set_irq_routing(PCI_INTA, !(val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED);
break; break;
case 0x44: case 0x42: /* PCI INTB IRQ */
pci_set_irq_routing(PCI_INTD, (val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED); dev->pci_conf_sb[addr] = (val & 0x8f);
pci_set_irq_routing(PCI_INTB, !(val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED);
break;
case 0x43: /* PCI INTC IRQ */
dev->pci_conf_sb[addr] = (val & 0x8f);
pci_set_irq_routing(PCI_INTC, !(val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED);
break;
case 0x44: /* PCI INTD IRQ */
dev->pci_conf_sb[addr] = (val & 0x8f);
pci_set_irq_routing(PCI_INTD, !(val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED);
break; break;
} }
sis_85c50x_log("85C503: dev->pci_conf_sb[%02x] = %02x", addr, val); sis_85c50x_log("85C503: dev->pci_conf_sb[%02x] = %02x", addr, val);
@@ -182,11 +211,23 @@ static void
sis_85c50x_isa_write(uint16_t addr, uint8_t val, void *priv) sis_85c50x_isa_write(uint16_t addr, uint8_t val, void *priv)
{ {
sis_85c50x_t *dev = (sis_85c50x_t *)priv; sis_85c50x_t *dev = (sis_85c50x_t *)priv;
dev->regs[addr] = val;
if (addr == 0x81) switch (addr)
cpu_update_waitstates(); {
case 0x22:
dev->index = val;
break;
case 0x23:
dev->regs[dev->index] = val;
switch (dev->index)
{
case 0x81:
dev->regs[dev->index] = (val & 0xf4);
cpu_update_waitstates();
break;
}
}
sis_85c50x_log("85C501-ISA: dev->regs[%02x] = %02x", addr, val); sis_85c50x_log("85C501-ISA: dev->regs[%02x] = %02x", addr, val);
} }
@@ -194,8 +235,8 @@ static uint8_t
sis_85c50x_isa_read(uint16_t addr, void *priv) sis_85c50x_isa_read(uint16_t addr, void *priv)
{ {
sis_85c50x_t *dev = (sis_85c50x_t *)priv; sis_85c50x_t *dev = (sis_85c50x_t *)priv;
return dev->regs[addr]; return dev->regs[dev->index];
sis_85c50x_log("85C501-ISA: dev->regs[%02x] (%02x)", addr, dev->regs[addr]); sis_85c50x_log("85C501-ISA: dev->regs[%02x] (%02x)", dev->index, dev->regs[dev->index]);
} }
static void static void
@@ -203,7 +244,7 @@ sis_85c50x_reset(void *priv)
{ {
sis_85c50x_t *dev = (sis_85c50x_t *)priv; sis_85c50x_t *dev = (sis_85c50x_t *)priv;
/* North Bridge */ /* North Bridge (SiS 85C501/502) */
dev->pci_conf[0x00] = 0x39; dev->pci_conf[0x00] = 0x39;
dev->pci_conf[0x01] = 0x10; dev->pci_conf[0x01] = 0x10;
dev->pci_conf[0x02] = 0x06; dev->pci_conf[0x02] = 0x06;
@@ -230,7 +271,7 @@ sis_85c50x_reset(void *priv)
sis_85c50x_write(0, 0x64, 0x00, dev); sis_85c50x_write(0, 0x64, 0x00, dev);
sis_85c50x_write(0, 0x65, 0x00, dev); sis_85c50x_write(0, 0x65, 0x00, dev);
/* South Bridge */ /* South Bridge (SiS 85C503) */
dev->pci_conf_sb[0x00] = 0x39; dev->pci_conf_sb[0x00] = 0x39;
dev->pci_conf_sb[0x01] = 0x10; dev->pci_conf_sb[0x01] = 0x10;
dev->pci_conf_sb[0x02] = 0x08; dev->pci_conf_sb[0x02] = 0x08;
@@ -247,10 +288,10 @@ sis_85c50x_reset(void *priv)
dev->pci_conf_sb[0x0d] = 0x00; dev->pci_conf_sb[0x0d] = 0x00;
dev->pci_conf_sb[0x0e] = 0x00; dev->pci_conf_sb[0x0e] = 0x00;
dev->pci_conf_sb[0x0f] = 0x00; dev->pci_conf_sb[0x0f] = 0x00;
sis_85c50x_write(0, 0x41, 0x00, dev); sis_85c50x_write(0, 0x41, 0x80, dev);
sis_85c50x_write(0, 0x42, 0x00, dev); sis_85c50x_write(0, 0x42, 0x80, dev);
sis_85c50x_write(0, 0x43, 0x00, dev); sis_85c50x_write(0, 0x43, 0x80, dev);
sis_85c50x_write(0, 0x44, 0x00, dev); sis_85c50x_write(0, 0x44, 0x80, dev);
} }
static void static void