diff options
Diffstat (limited to 'sys/arch/i386')
-rw-r--r-- | sys/arch/i386/conf/files.i386 | 9 | ||||
-rw-r--r-- | sys/arch/i386/pci/ichpcib.c | 222 | ||||
-rw-r--r-- | sys/arch/i386/pci/pcib.c | 140 |
3 files changed, 231 insertions, 140 deletions
diff --git a/sys/arch/i386/conf/files.i386 b/sys/arch/i386/conf/files.i386 index ae614753b5a..6634d08dff2 100644 --- a/sys/arch/i386/conf/files.i386 +++ b/sys/arch/i386/conf/files.i386 @@ -1,4 +1,4 @@ -# $OpenBSD: files.i386,v 1.113 2004/04/11 18:12:10 deraadt Exp $ +# $OpenBSD: files.i386,v 1.114 2004/05/06 19:47:03 grange Exp $ # $NetBSD: files.i386,v 1.73 1996/05/07 00:58:36 thorpej Exp $ # # new style config file for i386 architecture @@ -122,7 +122,12 @@ file arch/i386/pci/geodesc.c geodesc # PCI-ISA bridge chipsets device pcib: isabus attach pcib at pci -file arch/i386/pci/pcib.c pcib +file arch/i386/pci/pcib.c pcib | ichpcib + +# Intel ICHx/ICHx-M LPC bridges +device ichpcib: isabus +attach ichpcib at pci +file arch/i386/pci/ichpcib.c ichpcib device hme: ether, ifnet, mii, ifmedia file dev/ic/hme.c hme diff --git a/sys/arch/i386/pci/ichpcib.c b/sys/arch/i386/pci/ichpcib.c new file mode 100644 index 00000000000..7e2aaa69bd4 --- /dev/null +++ b/sys/arch/i386/pci/ichpcib.c @@ -0,0 +1,222 @@ +/* $OpenBSD: ichpcib.c,v 1.1 2004/05/06 19:47:03 grange Exp $ */ +/* + * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Special driver for the Intel ICHx/ICHx-M LPC bridges that attaches + * instead of pcib(4). In addition to the core pcib(4) functionality this + * driver provides support for the Intel SpeedStep technology. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/sysctl.h> + +#include <machine/bus.h> + +#include <dev/pci/pcidevs.h> +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> + +#include <dev/pci/ichreg.h> + +struct ichpcib_softc { + struct device sc_dev; + + bus_space_tag_t sc_pm_iot; + bus_space_handle_t sc_pm_ioh; +}; + +int ichpcib_match(struct device *, void *, void *); +void ichpcib_attach(struct device *, struct device *, void *); + +int ichss_present(struct pci_attach_args *); +int ichss_setperf(int); + +/* arch/i386/pci/pcib.c */ +void pcibattach(struct device *, struct device *, void *); + +struct cfattach ichpcib_ca = { + sizeof(struct ichpcib_softc), + ichpcib_match, + ichpcib_attach +}; + +struct cfdriver ichpcib_cd = { + NULL, "ichpcib", DV_DULL +}; + +#ifndef SMALL_KERNEL +static void *ichss_cookie; /* XXX */ +extern int setperf_prio; +#endif /* !SMALL_KERNEL */ + +int +ichpcib_match(struct device *parent, void *match, void *aux) +{ + struct pci_attach_args *pa = aux; + + if (PCI_CLASS(pa->pa_class) != PCI_CLASS_BRIDGE || + PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_BRIDGE_ISA) { + return (0); + } + + if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL) { + switch (PCI_PRODUCT(pa->pa_id)) { + case PCI_PRODUCT_INTEL_82801AA_LPC: /* ICH */ + case PCI_PRODUCT_INTEL_82801AB_LPC: /* ICH0 */ + case PCI_PRODUCT_INTEL_82801BA_LPC: /* ICH2 */ + case PCI_PRODUCT_INTEL_82801BAM_LPC: /* ICH2-M */ + case PCI_PRODUCT_INTEL_82801CA_LPC: /* ICH3-S */ + case PCI_PRODUCT_INTEL_82801CAM_LPC: /* ICH3-M */ + case PCI_PRODUCT_INTEL_82801DB_LPC: /* ICH4 */ + case PCI_PRODUCT_INTEL_82801DBM_LPC: /* ICH4-M */ + case PCI_PRODUCT_INTEL_82801EB_LPC: /* ICH5 */ + return (2); /* supersede pcib(4) */ + } + } + + return (0); +} + +void +ichpcib_attach(struct device *parent, struct device *self, void *aux) +{ +#ifndef SMALL_KERNEL + struct ichpcib_softc *sc = (struct ichpcib_softc *)self; + struct pci_attach_args *pa = aux; + pcireg_t pmbase; + + /* Map power management I/O space */ + sc->sc_pm_iot = pa->pa_iot; + pmbase = pci_conf_read(pa->pa_pc, pa->pa_tag, ICH_PMBASE); + if (bus_space_map(sc->sc_pm_iot, PCI_MAPREG_IO_ADDR(pmbase), + ICH_PMSIZE, 0, &sc->sc_pm_ioh) != 0) { + printf(": failed to map I/O space"); + goto corepcib; + } + + /* Check for SpeedStep */ + if (ichss_present(pa)) { + printf(": SpeedStep"); + + /* Enable SpeedStep */ + pci_conf_write(pa->pa_pc, pa->pa_tag, ICH_GEN_PMCON1, + pci_conf_read(pa->pa_pc, pa->pa_tag, ICH_GEN_PMCON1) | + ICH_GEN_PMCON1_SS_EN); + + /* Hook into hw.setperf sysctl */ + ichss_cookie = sc; + cpu_setperf = ichss_setperf; + setperf_prio = 2; + } + +corepcib: +#endif /* !SMALL_KERNEL */ + /* Provide core pcib(4) functionality */ + pcibattach(parent, self, aux); +} + +#ifndef SMALL_KERNEL +int +ichss_present(struct pci_attach_args *pa) +{ + pcitag_t br_tag; + pcireg_t br_id, br_class; + + if (setperf_prio > 2) + return (0); + + if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801DBM_LPC || + PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801CAM_LPC) + return (1); + if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801BAM_LPC) { + /* + * Old revisions of the 82815 hostbridge found on + * Dell Inspirons 8000 and 8100 don't support + * SpeedStep. + */ + /* + * XXX: dev 0 func 0 is not always a hostbridge, + * should be converted to use pchb(4) hook. + */ + br_tag = pci_make_tag(pa->pa_pc, pa->pa_bus, 0, 0); + br_id = pci_conf_read(pa->pa_pc, br_tag, PCI_ID_REG); + br_class = pci_conf_read(pa->pa_pc, br_tag, PCI_CLASS_REG); + + if (PCI_PRODUCT(br_id) == PCI_PRODUCT_INTEL_82815_FULL_HUB && + PCI_REVISION(br_class) < 5) + return (0); + return (1); + } + + return (0); +} + +int +ichss_setperf(int level) +{ + struct ichpcib_softc *sc = ichss_cookie; + u_int8_t state, ostate, cntl; + int s; + +#ifdef DIAGNOSTIC + if (sc == NULL) { + printf("%s: no cookie", __func__); + return (EFAULT); + } +#endif + + s = splhigh(); + state = bus_space_read_1(sc->sc_pm_iot, sc->sc_pm_ioh, ICH_PM_SS_CNTL); + ostate = state; + + /* Only two states are available */ + if (level <= 50) + state |= ICH_PM_SS_STATE_LOW; + else + state &= ~ICH_PM_SS_STATE_LOW; + + /* + * An Intel SpeedStep technology transition _always_ occur on + * writes to the ICH_PM_SS_CNTL register, even if the value + * written is the same as the previous value. So do the write + * only if the state has changed. + */ + if (state != ostate) { + /* Disable bus mastering arbitration */ + cntl = bus_space_read_1(sc->sc_pm_iot, sc->sc_pm_ioh, + ICH_PM_CNTL); + bus_space_write_1(sc->sc_pm_iot, sc->sc_pm_ioh, ICH_PM_CNTL, + cntl | ICH_PM_ARB_DIS); + + /* Do the transition */ + bus_space_write_1(sc->sc_pm_iot, sc->sc_pm_ioh, ICH_PM_SS_CNTL, + state); + + /* Restore bus mastering arbitration state */ + bus_space_write_1(sc->sc_pm_iot, sc->sc_pm_ioh, ICH_PM_CNTL, + cntl); + + if (update_cpuspeed != NULL) + update_cpuspeed(); + } + splx(s); + + return (0); +} +#endif /* !SMALL_KERNEL */ diff --git a/sys/arch/i386/pci/pcib.c b/sys/arch/i386/pci/pcib.c index 38a13ed68a6..6e4dd57e669 100644 --- a/sys/arch/i386/pci/pcib.c +++ b/sys/arch/i386/pci/pcib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pcib.c,v 1.14 2004/02/27 21:46:44 grange Exp $ */ +/* $OpenBSD: pcib.c,v 1.15 2004/05/06 19:47:03 grange Exp $ */ /* $NetBSD: pcib.c,v 1.6 1997/06/06 23:29:16 thorpej Exp $ */ /*- @@ -41,7 +41,6 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> -#include <sys/sysctl.h> #include <machine/bus.h> #include <dev/isa/isavar.h> @@ -51,8 +50,6 @@ #include <dev/pci/pcidevs.h> -#include <dev/pci/ichreg.h> - #include "isa.h" #include "pcibios.h" #if NPCIBIOS > 0 @@ -64,28 +61,14 @@ void pcibattach(struct device *, struct device *, void *); void pcib_callback(struct device *); int pcib_print(void *, const char *); -int ichss_match(void *); -int ichss_attach(struct device *, void *); -int ichss_setperf(int); - -struct pcib_softc { - struct device sc_dev; - - /* For power management capable bridges */ - bus_space_tag_t sc_pmt; - bus_space_handle_t sc_pmh; -}; - struct cfattach pcib_ca = { - sizeof(struct pcib_softc), pcibmatch, pcibattach + sizeof(struct device), pcibmatch, pcibattach }; struct cfdriver pcib_cd = { NULL, "pcib", DV_DULL }; -extern int setperf_prio; - int pcibmatch(parent, match, aux) struct device *parent; @@ -123,15 +106,6 @@ pcibattach(parent, self, aux) struct device *parent, *self; void *aux; { -#ifndef SMALL_KERNEL - /* - * Detect and activate SpeedStep on ICHx-M chipsets. - */ - if (setperf_prio < 2 && ichss_match(aux) && - ichss_attach(self, aux) == 0) - printf(": SpeedStep"); -#endif - /* * Cannot attach isa bus now; must postpone for various reasons */ @@ -173,113 +147,3 @@ pcib_print(aux, pnp) printf("isa at %s", pnp); return (UNCONF); } - -#ifndef SMALL_KERNEL -static void *ichss_cookie; /* XXX */ - -int -ichss_match(void *aux) -{ - struct pci_attach_args *pa = aux; - pcitag_t br_tag; - pcireg_t br_id, br_class; - - if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801DBM_LPC || - PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801CAM_LPC) - return (1); - if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801BAM_LPC) { - /* - * Old revisions of the 82815 hostbridge found on - * Dell Inspirons 8000 and 8100 don't support - * SpeedStep. - */ - /* XXX: dev 0 func 0 is not always a hostbridge */ - br_tag = pci_make_tag(pa->pa_pc, pa->pa_bus, 0, 0); - br_id = pci_conf_read(pa->pa_pc, br_tag, PCI_ID_REG); - br_class = pci_conf_read(pa->pa_pc, br_tag, PCI_CLASS_REG); - - if (PCI_PRODUCT(br_id) == PCI_PRODUCT_INTEL_82815_FULL_HUB && - PCI_REVISION(br_class) < 5) - return (0); - return (1); - } - - return (0); -} - -int -ichss_attach(struct device *self, void *aux) -{ - struct pcib_softc *sc = (struct pcib_softc *)self; - struct pci_attach_args *pa = aux; - pcireg_t pmbase; - - /* Map power management I/O space */ - sc->sc_pmt = pa->pa_iot; - pmbase = pci_conf_read(pa->pa_pc, pa->pa_tag, ICH_PMBASE); - if (bus_space_map(sc->sc_pmt, PCI_MAPREG_IO_ADDR(pmbase), - ICH_PMSIZE, 0, &sc->sc_pmh) != 0) - return (1); - - /* Enable SpeedStep */ - pci_conf_write(pa->pa_pc, pa->pa_tag, ICH_GEN_PMCON1, - pci_conf_read(pa->pa_pc, pa->pa_tag, ICH_GEN_PMCON1) | - ICH_GEN_PMCON1_SS_EN); - - /* Hook into hw.setperf sysctl */ - ichss_cookie = sc; - cpu_setperf = ichss_setperf; - setperf_prio = 2; - - return (0); -} - -int -ichss_setperf(int level) -{ - struct pcib_softc *sc = ichss_cookie; - u_int8_t state, ostate, cntl; - int s; - -#ifdef DIAGNOSTIC - if (sc == NULL) { - printf("%s: no cookie", __func__); - return (EFAULT); - } -#endif - - s = splhigh(); - state = bus_space_read_1(sc->sc_pmt, sc->sc_pmh, ICH_PM_SS_CNTL); - ostate = state; - - /* Only two states are available */ - if (level <= 50) - state |= ICH_PM_SS_STATE_LOW; - else - state &= ~ICH_PM_SS_STATE_LOW; - - /* - * An Intel SpeedStep technology transition _always_ occur on - * writes to the ICH_PM_SS_CNTL register, even if the value - * written is the same as the previous value. So do the write - * only if the state has changed. - */ - if (state != ostate) { - /* Disable bus mastering arbitration */ - cntl = bus_space_read_1(sc->sc_pmt, sc->sc_pmh, ICH_PM_CNTL); - bus_space_write_1(sc->sc_pmt, sc->sc_pmh, ICH_PM_CNTL, - cntl | ICH_PM_ARB_DIS); - - /* Do the transition */ - bus_space_write_1(sc->sc_pmt, sc->sc_pmh, ICH_PM_SS_CNTL, - state); - - /* Restore bus mastering arbitration state */ - bus_space_write_1(sc->sc_pmt, sc->sc_pmh, ICH_PM_CNTL, - cntl); - } - splx(s); - - return (0); -} -#endif /* !SMALL_KERNEL */ |