/* * Copyright (C) 2005 Sandvine Incorporated. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #define ICH_PMBASE 0x40 /* ACPI base address register */ #define INTEL_VENDORID 0x8086 #define INTEL_DEVICEID_ICH4 0x24c0 /* 82081CA (ICH3-S) LPC Interface bridge */ #define INTEL_DEVICEID_ICH3 0x2480 /* 82801EB/ER (ICH5) LPC Interface Bridge */ #define INTEL_DEVICEID_ICH5 0x24d0 int clearPeriodicBits(u_int pmbase) { u_int smi_en; smi_en = inl(pmbase + 0x30); /* This disables SMI for the entire system. * This may not be what you want for e.g. ACPI or APM */ smi_en = smi_en & (~((1<<14)| /* PERIODIC_EN */ (1<<13)| /* TCO_EN */ (1<<11)| /* MCSMI_EN */ (1<<6) | /* SWSMI_TMR_EN */ (1<<5) | /* APMC_EN */ (1<<4) | /* SLP_SMI_EN */ (1<<3) | /* LEGACY_USB_EN */ (1<<2) | /* BIOS_EN */ (1<<0))); /* GLBL_SMI_EN */ /* Disable the TCO counter to generate SMI */ outl(pmbase+0x30, smi_en); } int clearPeriodic(int fd, unsigned int vendorid, unsigned int deviceid) { u_int pmbase; struct pci_io io; struct pci_conf_io pciio; struct pci_match_conf mc; struct pci_conf match; memset(&pciio,0,sizeof(pciio)); memset(&mc, 0, sizeof(mc)); memset(&match, 0, sizeof(match)); mc.pc_vendor = vendorid; /* Intel */ mc.pc_device = deviceid; /* ICH3 LPC <-> PCI ISA bridge */ mc.flags = PCI_GETCONF_MATCH_VENDOR | PCI_GETCONF_MATCH_DEVICE; pciio.patterns = &mc; pciio.pat_buf_len = sizeof(mc); pciio.num_patterns = 1; pciio.matches = &match; pciio.match_buf_len = sizeof(match); if (ioctl(fd, PCIOCGETCONF, &pciio) < 0) { perror("PCIOCGETCONF"); return 1; } if (pciio.num_matches == 0) { return 1; } io.pi_sel = match.pc_sel; io.pi_reg = ICH_PMBASE; io.pi_width = 4; if (ioctl(fd, PCIOCREAD, &io) < 0) { perror("PCIOCREAD"); return 1; } pmbase = ((u_int )io.pi_data) / 2 * 2; printf("Found ICH device @ %u.%u.%u. pmbase = %08x\n", match.pc_sel.pc_bus, match.pc_sel.pc_dev, match.pc_sel.pc_func, pmbase); clearPeriodicBits(pmbase); } int main(int argc, char **argv) { int fd1, fd2; fd1 = open("/dev/pci", O_RDWR, 0); if (fd1 < 0) { perror("open /dev/pci"); } fd2 = open("/dev/io", O_RDWR, 0); if (fd2 < 0) { perror("open /dev/io"); } clearPeriodic(fd1, INTEL_VENDORID,INTEL_DEVICEID_ICH3); }