Implement APM on i430LX and SIO chipset.

This commit is contained in:
SarahW 2020-11-01 16:55:21 +00:00
commit 82b1486f6b
2 changed files with 109 additions and 1 deletions

View file

@ -6,6 +6,7 @@
#include "keyboard_at.h"
#include "mem.h"
#include "pci.h"
#include "sio.h"
#include "x86.h"
#include "i430lx.h"
@ -107,6 +108,30 @@ void i430lx_write(int func, int addr, uint8_t val, void *priv)
i430lx_map(0xec000, 0x04000, val >> 4);
pclog("i430lx_write : PAM6 write %02X\n", val);
break;
case 0x72: /*SMRAM*/
pclog("Write SMRAM %02x\n", val);
val = (val & 0x38) | 2; /*SMRAM always at A0000-BFFFF*/
val |= (card_i430lx[0x72] & 0x08); /*D_LCK can not be cleared by software*/
if (val & 0x08) /*D_LCK locks D_OPEN*/
{
val &= ~0x20; /*D_OPEN is forced to 0*/
}
val |= (card_i430lx[0x72] & 0x08);
if ((card_i430lx[0x72] ^ val) & 0x20)
{
if (val & 0x20) /*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_i430lx[addr] = val;
@ -134,15 +159,27 @@ void i430lx_trc_write(uint16_t port, uint8_t val, void *p)
if (val & 2) /*Hard reset*/
{
i430lx_write(0, 0x59, 0xf, NULL); /*Should reset all PCI devices, but just set PAM0 to point to ROM for now*/
card_i430lx[0x72] = 0; /*Also clear SMRAM register so BIOS will relocate SMBASE*/
keyboard_at_reset(); /*Reset keyboard controller to reset system flag*/
ide_reset_devices();
resetx86();
}
resetx86();
else
softresetx86();
}
trc = val;
}
static void i430lx_smram_enable(void)
{
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
}
static void i430lx_smram_disable(void)
{
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
void i430lx_init()
{
pci_add_specific(0, i430lx_read, i430lx_write, NULL);
@ -168,4 +205,7 @@ void i430lx_init()
// card_i430lx[0x78] = 0x23;
io_sethandler(0x0cf9, 0x0001, i430lx_trc_read, NULL, NULL, i430lx_trc_write, NULL, NULL, NULL);
smram_enable = i430lx_smram_enable;
smram_disable = i430lx_smram_disable;
}

View file

@ -8,9 +8,23 @@
#include "sio.h"
typedef struct sio_t
{
struct
{
uint8_t apmc, apms;
} pm;
} sio_t;
static sio_t sio;
static uint8_t card_sio[256];
//static int pci_cards_ids[4];
#define REG_SMIEN 0xa2
#define REG_SMIREQ 0xaa
#define SMIEN_APMC (1 << 7)
#define SMIREQ_RAPMC (1 << 7)
void sio_write(int func, int addr, uint8_t val, void *priv)
{
// pclog("sio_write: func=%d addr=%02x val=%02x %04x:%08x\n", func, addr, val, CS, cpu_state.pc);
@ -70,6 +84,13 @@ void sio_write(int func, int addr, uint8_t val, void *priv)
else
pci_set_irq_routing(PCI_INTD, val & 0xf);
break;
case REG_SMIREQ:
card_sio[addr] &= val;
return;
case REG_SMIREQ+1:
card_sio[addr] &= val;
return;
}
card_sio[addr] = val;
}
@ -83,8 +104,53 @@ uint8_t sio_read(int func, int addr, void *priv)
return card_sio[addr];
}
static uint8_t sio_apm_read(uint16_t port, void *p)
{
sio_t *sio = (sio_t *)p;
uint8_t ret = 0xff;
switch (port)
{
case 0xb2:
ret = sio->pm.apmc;
break;
case 0xb3:
ret = sio->pm.apms;
break;
}
// pclog("sio_apm_read: port=%04x ret=%02x\n", port, ret);
return ret;
}
static void sio_apm_write(uint16_t port, uint8_t val, void *p)
{
sio_t *sio = (sio_t *)p;
// pclog("sio_apm_write: port=%04x val=%02x\n", port, val);
switch (port)
{
case 0xb2:
sio->pm.apmc = val;
if (card_sio[REG_SMIEN] & SMIEN_APMC)
{
card_sio[REG_SMIREQ] |= SMIREQ_RAPMC;
// pclog("APMC write causes SMI\n");
x86_smi_trigger();
}
break;
case 0xb3:
sio->pm.apms = val;
break;
}
}
void sio_init(int card, int pci_a, int pci_b, int pci_c, int pci_d)
{
memset(&sio, 0, sizeof(sio_t));
pci_add_specific(card, sio_read, sio_write, NULL);
memset(card_sio, 0, 256);
@ -116,4 +182,6 @@ void sio_init(int card, int pci_a, int pci_b, int pci_c, int pci_d)
pci_set_card_routing(pci_c, PCI_INTC);
if (pci_d)
pci_set_card_routing(pci_d, PCI_INTD);
io_sethandler(0x00b2, 0x0002, sio_apm_read, NULL, NULL, sio_apm_write, NULL, NULL, &sio);
}