/* * 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 #define ICH_PMBASE 0x40 #define SMI_CTRL 0x30 #define INTEL_VENDORID 0x8086 #define INTEL_DEVICEID_82801AA 0x2410 #define INTEL_DEVICEID_82801AB 0x2420 #define INTEL_DEVICEID_82801BA 0x2440 #define INTEL_DEVICEID_82801CA 0x2480 #define INTEL_DEVICEID_82801DB 0x24c0 #define INTEL_DEVICEID_82801DBM 0x24cc #define INTEL_DEVICEID_82801EB 0x24d0 struct pciids { u_int16_t vendorid; u_int16_t deviceid; int has_usb2; }; static struct pciids ich_devs[] = { { INTEL_VENDORID, INTEL_DEVICEID_82801AA, 0 }, { INTEL_VENDORID, INTEL_DEVICEID_82801AB, 0 }, { INTEL_VENDORID, INTEL_DEVICEID_82801BA, 0 }, { INTEL_VENDORID, INTEL_DEVICEID_82801CA, 0 }, { INTEL_VENDORID, INTEL_DEVICEID_82801DB, 1 }, { INTEL_VENDORID, INTEL_DEVICEID_82801DBM, 1 }, { INTEL_VENDORID, INTEL_DEVICEID_82801EB, 1 }, }; #define NUM_ICH_DEVS (sizeof(ich_devs) / sizeof(struct pciids)) int clearPeriodicBits(u_int pmbase, int has_usb2) { int fd; u_int smi_en; if ((fd = open("/dev/io", O_RDWR, 0)) < 0) { perror("open /dev/io"); return (-1); } /* * This disables SMI for the entire system. * This may not be what you want for e.g. ACPI or APM. */ smi_en = inl(pmbase + SMI_CTRL); printf("Setting SMI_EN = 0x%08x", smi_en); smi_en = smi_en & (~((has_usb2 ? (1 << 18) | /* INTEL_USB2_EN */ (1 << 17) : 0) | /* LEGACY_USB2_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 */ printf(" -> 0x%08x\n", smi_en); outl(pmbase + SMI_CTRL, smi_en); close(fd); return (0); } int clearPeriodic(int fd) { int i, has_usb2; u_int pmbase; struct pci_io io; struct pci_conf_io pciio; struct pci_match_conf *mc; struct pci_conf match; mc = (struct pci_match_conf *)calloc(NUM_ICH_DEVS, sizeof(struct pci_match_conf)); if (mc == NULL) { perror("malloc"); return (-1); } for (i = 0; i < NUM_ICH_DEVS; i++) { mc[i].pc_vendor = ich_devs[i].vendorid; mc[i].pc_device = ich_devs[i].deviceid; mc[i].flags = PCI_GETCONF_MATCH_VENDOR | PCI_GETCONF_MATCH_DEVICE; } pciio.pat_buf_len = sizeof(struct pci_match_conf) * NUM_ICH_DEVS; pciio.num_patterns = NUM_ICH_DEVS; pciio.patterns = mc; pciio.match_buf_len = sizeof(match); pciio.matches = &match; pciio.offset = 0; if (ioctl(fd, PCIOCGETCONF, &pciio) < 0) { perror("PCIOCGETCONF"); free(mc); return (-1); } free(mc); if (pciio.num_matches == 0) { fprintf(stderr, "Cannot find supported ICH\n"); return (-1); } has_usb2 = 0; for (i = 0; i < NUM_ICH_DEVS; i++) if (match.pc_vendor == ich_devs[i].vendorid && match.pc_device == ich_devs[i].deviceid) { has_usb2 = ich_devs[i].has_usb2; break; } io.pi_sel = match.pc_sel; io.pi_reg = ICH_PMBASE; io.pi_width = 2; if (ioctl(fd, PCIOCREAD, &io) < 0) { perror("PCIOCREAD"); return (-1); } close(fd); pmbase = (u_int)io.pi_data & 0xff80; printf("Found 0x%04x%04x@pci%u:%u:%u, pmbase = 0x%08x\n", match.pc_device, match.pc_vendor, match.pc_sel.pc_bus, match.pc_sel.pc_dev, match.pc_sel.pc_func, pmbase); return (clearPeriodicBits(pmbase, has_usb2)); } int main(int argc, char *argv[]) { int fd; if ((fd = open("/dev/pci", O_RDWR, 0)) < 0) { perror("open /dev/pci"); return (-1); } return (clearPeriodic(fd)); }