diff --git a/src/i430lx.c b/src/i430lx.c index d051e96..4d2bb74 100644 --- a/src/i430lx.c +++ b/src/i430lx.c @@ -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; } diff --git a/src/sio.c b/src/sio.c index bc2dc33..65c8980 100644 --- a/src/sio.c +++ b/src/sio.c @@ -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); }