diff options
Diffstat (limited to 'src/dev-i440fx.c')
-rw-r--r-- | src/dev-i440fx.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/src/dev-i440fx.c b/src/dev-i440fx.c index 366a2db8..346f6d08 100644 --- a/src/dev-i440fx.c +++ b/src/dev-i440fx.c @@ -13,6 +13,7 @@ #include "util.h" // dprintf #include "ioport.h" // outb #include "pci.h" // pci_config_writeb +#include "pci_ids.h" #include "pci_regs.h" // PCI_INTERRUPT_LINE #include "acpi.h" #include "dev-i440fx.h" @@ -82,3 +83,34 @@ void piix4_fadt_init(u16 bdf, void *arg) fadt->gpe0_blk = cpu_to_le32(PIIX4_GPE0_BLK); fadt->gpe0_blk_len = PIIX4_GPE0_BLK_LEN; } + +#define I440FX_SMRAM 0x72 +#define PIIX_DEVACTB 0x58 +#define PIIX_APMC_EN (1 << 25) + +// This code is hardcoded for PIIX4 Power Management device. +void piix4_apmc_smm_init(u16 bdf, void *arg) +{ + int i440_bdf = pci_find_device(PCI_VENDOR_ID_INTEL + , PCI_DEVICE_ID_INTEL_82441); + if (i440_bdf < 0) + return; + + /* check if SMM init is already done */ + u32 value = pci_config_readl(bdf, PIIX_DEVACTB); + if (value & PIIX_APMC_EN) + return; + + /* enable the SMM memory window */ + pci_config_writeb(i440_bdf, I440FX_SMRAM, 0x02 | 0x48); + + smm_save_and_copy(); + + /* enable SMI generation when writing to the APMC register */ + pci_config_writel(bdf, PIIX_DEVACTB, value | PIIX_APMC_EN); + + smm_relocate_and_restore(); + + /* close the SMM memory window and enable normal SMM */ + pci_config_writeb(i440_bdf, I440FX_SMRAM, 0x02 | 0x08); +} |