Add basic APM functionality for PIIX/PIIX3 and i430FX, i430VX, i430HX

and i440FX chipsets.
This commit is contained in:
SarahW 2020-11-01 14:46:56 +00:00
commit 38cee364d3
7 changed files with 233 additions and 8 deletions

View file

@ -106,6 +106,30 @@ void i430fx_write(int func, int addr, uint8_t val, void *priv)
i430fx_map(0xec000, 0x04000, val >> 4); i430fx_map(0xec000, 0x04000, val >> 4);
pclog("i430fx_write : PAM6 write %02X\n", val); pclog("i430fx_write : PAM6 write %02X\n", val);
break; break;
case 0x72: /*SMRAM*/
pclog("Write SMRAM %02x\n", val);
val = (val & 0x78) | 2; /*SMRAM always at A0000-BFFFF*/
val |= (card_i430fx[0x72] & 0x10); /*D_LCK can not be cleared by software*/
if (val & 0x10) /*D_LCK locks D_OPEN and G_SMRAME*/
{
val &= ~0x48; /*D_OPEN is forced to 0, G_SMRAME is read only*/
val |= (card_i430fx[0x72] & 0x08);
}
if ((card_i430fx[0x72] ^ val) & 0x40)
{
if (val & 0x40) /*SMRAM enabled*/
{
pclog("Enable SMRAM\n");
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
}
else
{
pclog("Disable SMRAM\n");
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
}
break;
} }
card_i430fx[addr] = val; card_i430fx[addr] = val;
@ -119,6 +143,17 @@ uint8_t i430fx_read(int func, int addr, void *priv)
return card_i430fx[addr]; return card_i430fx[addr];
} }
static void i430fx_smram_enable(void)
{
if (card_i430fx[0x72] & 8)
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
}
static void i430fx_smram_disable(void)
{
if (card_i430fx[0x72] & 8)
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
void i430fx_init() void i430fx_init()
{ {
pci_add_specific(0, i430fx_read, i430fx_write, NULL); pci_add_specific(0, i430fx_read, i430fx_write, NULL);
@ -141,6 +176,9 @@ void i430fx_init()
card_i430fx[0x72] = 0x02; card_i430fx[0x72] = 0x02;
// card_i430fx[0x74] = 0x0e; // card_i430fx[0x74] = 0x0e;
// card_i430fx[0x78] = 0x23; // card_i430fx[0x78] = 0x23;
smram_enable = i430fx_smram_enable;
smram_disable = i430fx_smram_disable;
} }
void i430fx_reset() void i430fx_reset()

View file

@ -106,6 +106,30 @@ void i430hx_write(int func, int addr, uint8_t val, void *priv)
i430hx_map(0xec000, 0x04000, val >> 4); i430hx_map(0xec000, 0x04000, val >> 4);
pclog("i430hx_write : PAM6 write %02X\n", val); pclog("i430hx_write : PAM6 write %02X\n", val);
break; break;
case 0x72: /*SMRAM*/
pclog("Write SMRAM %02x\n", val);
val = (val & 0x78) | 2; /*SMRAM always at A0000-BFFFF*/
val |= (card_i430hx[0x72] & 0x10); /*D_LCK can not be cleared by software*/
if (val & 0x10) /*D_LCK locks D_OPEN and G_SMRAME*/
{
val &= ~0x48; /*D_OPEN is forced to 0, G_SMRAME is read only*/
val |= (card_i430hx[0x72] & 0x08);
}
if ((card_i430hx[0x72] ^ val) & 0x40)
{
if (val & 0x40) /*SMRAM enabled*/
{
pclog("Enable SMRAM\n");
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
}
else
{
pclog("Disable SMRAM\n");
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
}
break;
} }
card_i430hx[addr] = val; card_i430hx[addr] = val;
@ -119,6 +143,16 @@ uint8_t i430hx_read(int func, int addr, void *priv)
return card_i430hx[addr]; return card_i430hx[addr];
} }
static void i430hx_smram_enable(void)
{
if (card_i430hx[0x72] & 8)
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
}
static void i430hx_smram_disable(void)
{
if (card_i430hx[0x72] & 8)
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
void i430hx_init() void i430hx_init()
{ {
@ -141,6 +175,9 @@ void i430hx_init()
card_i430hx[0x64] = card_i430hx[0x5F] = 0x02; card_i430hx[0x64] = card_i430hx[0x5F] = 0x02;
card_i430hx[0x65] = card_i430hx[0x66] = card_i430hx[0x67] = 0x02; card_i430hx[0x65] = card_i430hx[0x66] = card_i430hx[0x67] = 0x02;
card_i430hx[0x68] = 0x11; card_i430hx[0x68] = 0x11;
smram_enable = i430hx_smram_enable;
smram_disable = i430hx_smram_disable;
} }
void i430hx_reset() void i430hx_reset()

View file

@ -105,6 +105,30 @@ void i430vx_write(int func, int addr, uint8_t val, void *priv)
i430vx_map(0xec000, 0x04000, val >> 4); i430vx_map(0xec000, 0x04000, val >> 4);
pclog("i430vx_write : PAM6 write %02X\n", val); pclog("i430vx_write : PAM6 write %02X\n", val);
break; break;
case 0x72: /*SMRAM*/
pclog("Write SMRAM %02x\n", val);
val = (val & 0x78) | 2; /*SMRAM always at A0000-BFFFF*/
val |= (card_i430vx[0x72] & 0x10); /*D_LCK can not be cleared by software*/
if (val & 0x10) /*D_LCK locks D_OPEN and G_SMRAME*/
{
val &= ~0x48; /*D_OPEN is forced to 0, G_SMRAME is read only*/
val |= (card_i430vx[0x72] & 0x08);
}
if ((card_i430vx[0x72] ^ val) & 0x40)
{
if (val & 0x40) /*SMRAM enabled*/
{
pclog("Enable SMRAM\n");
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
}
else
{
pclog("Disable SMRAM\n");
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
}
break;
} }
card_i430vx[addr] = val; card_i430vx[addr] = val;
@ -118,6 +142,16 @@ uint8_t i430vx_read(int func, int addr, void *priv)
return card_i430vx[addr]; return card_i430vx[addr];
} }
static void i430vx_smram_enable(void)
{
if (card_i430vx[0x72] & 8)
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
}
static void i430vx_smram_disable(void)
{
if (card_i430vx[0x72] & 8)
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
void i430vx_init() void i430vx_init()
{ {
@ -141,6 +175,9 @@ void i430vx_init()
card_i430vx[0x72] = 0x02; card_i430vx[0x72] = 0x02;
card_i430vx[0x74] = 0x0e; card_i430vx[0x74] = 0x0e;
card_i430vx[0x78] = 0x23; card_i430vx[0x78] = 0x23;
smram_enable = i430vx_smram_enable;
smram_disable = i430vx_smram_disable;
} }
void i430vx_reset() void i430vx_reset()

View file

@ -106,6 +106,30 @@ void i440fx_write(int func, int addr, uint8_t val, void *priv)
i440fx_map(0xec000, 0x04000, val >> 4); i440fx_map(0xec000, 0x04000, val >> 4);
pclog("i440fx_write : PAM6 write %02X\n", val); pclog("i440fx_write : PAM6 write %02X\n", val);
break; break;
case 0x72: /*SMRAM*/
pclog("Write SMRAM %02x\n", val);
val = (val & 0x78) | 2; /*SMRAM always at A0000-BFFFF*/
val |= (card_i440fx[0x72] & 0x10); /*D_LCK can not be cleared by software*/
if (val & 0x10) /*D_LCK locks D_OPEN and G_SMRAME*/
{
val &= ~0x48; /*D_OPEN is forced to 0, G_SMRAME is read only*/
val |= (card_i440fx[0x72] & 0x08);
}
if ((card_i440fx[0x72] ^ val) & 0x40)
{
if (val & 0x40) /*SMRAM enabled*/
{
pclog("Enable SMRAM\n");
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
}
else
{
pclog("Disable SMRAM\n");
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
}
break;
} }
card_i440fx[addr] = val; card_i440fx[addr] = val;
@ -119,6 +143,17 @@ uint8_t i440fx_read(int func, int addr, void *priv)
return card_i440fx[addr]; return card_i440fx[addr];
} }
static void i440fx_smram_enable(void)
{
if (card_i440fx[0x72] & 8)
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
}
static void i440fx_smram_disable(void)
{
if (card_i440fx[0x72] & 8)
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
void i440fx_init() void i440fx_init()
{ {
pci_add_specific(0, i440fx_read, i440fx_write, NULL); pci_add_specific(0, i440fx_read, i440fx_write, NULL);
@ -137,6 +172,9 @@ void i440fx_init()
card_i440fx[0x60] = card_i440fx[0x61] = card_i440fx[0x62] = card_i440fx[0x63] = card_i440fx[0x64] = 0x01; card_i440fx[0x60] = card_i440fx[0x61] = card_i440fx[0x62] = card_i440fx[0x63] = card_i440fx[0x64] = 0x01;
card_i440fx[0x71] = 0x10; card_i440fx[0x71] = 0x10;
card_i440fx[0x72] = 0x02; card_i440fx[0x72] = 0x02;
smram_enable = i440fx_smram_enable;
smram_disable = i440fx_smram_disable;
} }
void i440fx_reset() void i440fx_reset()

View file

@ -127,7 +127,7 @@ uint8_t endeavor_brdconfig(uint16_t port, void *p)
temp = 0x10; temp = 0x10;
else else
temp = 0x10; // TODO: how are the overdrive processors configured? temp = 0x10; // TODO: how are the overdrive processors configured?
return 0xe2 | temp; return 0xe0 | temp;
} }
return 0; return 0;
} }

View file

@ -29,6 +29,12 @@ static sff_busmaster_t piix_busmaster[2];
static uint8_t piix_rc = 0; static uint8_t piix_rc = 0;
static void (*piix_nb_reset)(); static void (*piix_nb_reset)();
#define REG_SMIEN 0xa2
#define REG_SMIREQ 0xaa
#define SMIEN_APMC (1 << 7)
#define SMIREQ_RAPMC (1 << 7)
void piix_write(int func, int addr, uint8_t val, void *priv) void piix_write(int func, int addr, uint8_t val, void *priv)
{ {
@ -139,6 +145,21 @@ void piix_write(int func, int addr, uint8_t val, void *priv)
else else
pci_set_irq_routing(PCI_INTD, val & 0xf); pci_set_irq_routing(PCI_INTD, val & 0xf);
break; break;
case REG_SMIREQ:
if (piix.type <= TYPE_PIIX3)
{
card_piix[addr] &= val;
return;
}
break;
case REG_SMIREQ+1:
if (piix.type <= TYPE_PIIX3)
{
card_piix[addr] &= val;
return;
}
break;
} }
card_piix[addr] = val; card_piix[addr] = val;
} }
@ -179,8 +200,11 @@ void piix_rc_write(uint16_t port, uint8_t val, void *p)
keyboard_at_reset(); /*Reset keyboard controller to reset system flag*/ keyboard_at_reset(); /*Reset keyboard controller to reset system flag*/
ide_reset_devices(); ide_reset_devices();
piix.pm.timer_offset = tsc; piix.pm.timer_offset = tsc;
resetx86();
piix.pm.apmc = piix.pm.apms = 0;
} }
resetx86(); else
softresetx86();
} }
piix_rc = val & ~4; piix_rc = val & ~4;
@ -205,9 +229,53 @@ static void piix_92_write(uint16_t port, uint8_t val, void *p)
piix.port_92 = val; piix.port_92 = val;
} }
static uint8_t piix_apm_read(uint16_t port, void *p)
void piix_init(int card, int pci_a, int pci_b, int pci_c, int pci_d, void (*nb_reset)())
{ {
piix_t *piix = (piix_t *)p;
uint8_t ret = 0xff;
switch (port)
{
case 0xb2:
ret = piix->pm.apmc;
break;
case 0xb3:
ret = piix->pm.apms;
break;
}
// pclog("piix_apm_read: port=%04x ret=%02x\n", port, ret);
return ret;
}
static void piix_apm_write(uint16_t port, uint8_t val, void *p)
{
piix_t *piix = (piix_t *)p;
// pclog("piix_apm_write: port=%04x val=%02x\n", port, val);
switch (port)
{
case 0xb2:
piix->pm.apmc = val;
if (card_piix[REG_SMIEN] & SMIEN_APMC)
{
card_piix[REG_SMIREQ] |= SMIREQ_RAPMC;
// pclog("APMC write causes SMI\n");
x86_smi_trigger();
}
break;
case 0xb3:
piix->pm.apms = val;
break;
}
}
static void piix_common_init(int card, int pci_a, int pci_b, int pci_c, int pci_d, void (*nb_reset)())
{
memset(&piix, 0, sizeof(piix_t));
pci_add_specific(card, piix_read, piix_write, NULL); pci_add_specific(card, piix_read, piix_write, NULL);
memset(card_piix, 0, 256); memset(card_piix, 0, 256);
@ -263,6 +331,13 @@ void piix_init(int card, int pci_a, int pci_b, int pci_c, int pci_d, void (*nb_r
piix.type = TYPE_PIIX3; piix.type = TYPE_PIIX3;
} }
void piix_init(int card, int pci_a, int pci_b, int pci_c, int pci_d, void (*nb_reset)())
{
piix_common_init(card, pci_a, pci_b, pci_c, pci_d, nb_reset);
io_sethandler(0x00b2, 0x0002, piix_apm_read, NULL, NULL, piix_apm_write, NULL, NULL, &piix);
}
void piix4_init(int card, int pci_a, int pci_b, int pci_c, int pci_d, void (*nb_reset)()) void piix4_init(int card, int pci_a, int pci_b, int pci_c, int pci_d, void (*nb_reset)())
{ {
piix_init(card, pci_a, pci_b, pci_c, pci_d, nb_reset); piix_init(card, pci_a, pci_b, pci_c, pci_d, nb_reset);

View file

@ -291,7 +291,7 @@ static uint8_t piix_smbus_read(uint16_t port, void *p)
return ret; return ret;
} }
static uint8_t piix_apm_read(uint16_t port, void *p) static uint8_t piix4_apm_read(uint16_t port, void *p)
{ {
piix_t *piix = (piix_t *)p; piix_t *piix = (piix_t *)p;
uint8_t ret = 0xff; uint8_t ret = 0xff;
@ -309,7 +309,7 @@ static uint8_t piix_apm_read(uint16_t port, void *p)
// pclog("piix_apm_read: port=%04x ret=%02x\n", port, ret); // pclog("piix_apm_read: port=%04x ret=%02x\n", port, ret);
return ret; return ret;
} }
static void piix_apm_write(uint16_t port, uint8_t val, void *p) static void piix4_apm_write(uint16_t port, uint8_t val, void *p)
{ {
piix_t *piix = (piix_t *)p; piix_t *piix = (piix_t *)p;
@ -413,5 +413,5 @@ void piix_pm_init(piix_t *piix)
piix->pm.timer_offset = 0; piix->pm.timer_offset = 0;
piix->pm.gporeg = 0x7fffbfff; piix->pm.gporeg = 0x7fffbfff;
io_sethandler(0x00b2, 0x0002, piix_apm_read, NULL, NULL, piix_apm_write, NULL, NULL, piix); io_sethandler(0x00b2, 0x0002, piix4_apm_read, NULL, NULL, piix4_apm_write, NULL, NULL, piix);
} }