The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/pci/pci.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: pci.c,v 1.103 2006/11/16 01:33:09 christos Exp $       */
    2 
    3 /*
    4  * Copyright (c) 1995, 1996, 1997, 1998
    5  *     Christopher G. Demetriou.  All rights reserved.
    6  * Copyright (c) 1994 Charles M. Hannum.  All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed by Charles M. Hannum.
   19  * 4. The name of the author may not be used to endorse or promote products
   20  *    derived from this software without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   32  */
   33 
   34 /*
   35  * PCI bus autoconfiguration.
   36  */
   37 
   38 #include <sys/cdefs.h>
   39 __KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.103 2006/11/16 01:33:09 christos Exp $");
   40 
   41 #include "opt_pci.h"
   42 
   43 #include <sys/param.h>
   44 #include <sys/systm.h>
   45 #include <sys/device.h>
   46 
   47 #include <dev/pci/pcireg.h>
   48 #include <dev/pci/pcivar.h>
   49 #include <dev/pci/pcidevs.h>
   50 
   51 #include <uvm/uvm_extern.h>
   52 
   53 #include "locators.h"
   54 
   55 #ifdef PCI_CONFIG_DUMP
   56 int pci_config_dump = 1;
   57 #else
   58 int pci_config_dump = 0;
   59 #endif
   60 
   61 int     pciprint(void *, const char *);
   62 
   63 #ifdef PCI_MACHDEP_ENUMERATE_BUS
   64 #define pci_enumerate_bus PCI_MACHDEP_ENUMERATE_BUS
   65 #else
   66 int pci_enumerate_bus(struct pci_softc *, const int *,
   67     int (*)(struct pci_attach_args *), struct pci_attach_args *);
   68 #endif
   69 
   70 /*
   71  * Important note about PCI-ISA bridges:
   72  *
   73  * Callbacks are used to configure these devices so that ISA/EISA bridges
   74  * can attach their child busses after PCI configuration is done.
   75  *
   76  * This works because:
   77  *      (1) there can be at most one ISA/EISA bridge per PCI bus, and
   78  *      (2) any ISA/EISA bridges must be attached to primary PCI
   79  *          busses (i.e. bus zero).
   80  *
   81  * That boils down to: there can only be one of these outstanding
   82  * at a time, it is cleared when configuring PCI bus 0 before any
   83  * subdevices have been found, and it is run after all subdevices
   84  * of PCI bus 0 have been found.
   85  *
   86  * This is needed because there are some (legacy) PCI devices which
   87  * can show up as ISA/EISA devices as well (the prime example of which
   88  * are VGA controllers).  If you attach ISA from a PCI-ISA/EISA bridge,
   89  * and the bridge is seen before the video board is, the board can show
   90  * up as an ISA device, and that can (bogusly) complicate the PCI device's
   91  * attach code, or make the PCI device not be properly attached at all.
   92  *
   93  * We use the generic config_defer() facility to achieve this.
   94  */
   95 
   96 static int
   97 pcirescan(struct device *sc, const char *ifattr, const int *locators)
   98 {
   99 
  100         KASSERT(ifattr && !strcmp(ifattr, "pci"));
  101         KASSERT(locators);
  102 
  103         pci_enumerate_bus((struct pci_softc *)sc, locators, NULL, NULL);
  104         return (0);
  105 }
  106 
  107 static int
  108 pcimatch(struct device *parent, struct cfdata *cf, void *aux)
  109 {
  110         struct pcibus_attach_args *pba = aux;
  111 
  112         /* Check the locators */
  113         if (cf->cf_loc[PCIBUSCF_BUS] != PCIBUSCF_BUS_DEFAULT &&
  114             cf->cf_loc[PCIBUSCF_BUS] != pba->pba_bus)
  115                 return (0);
  116 
  117         /* sanity */
  118         if (pba->pba_bus < 0 || pba->pba_bus > 255)
  119                 return (0);
  120 
  121         /*
  122          * XXX check other (hardware?) indicators
  123          */
  124 
  125         return (1);
  126 }
  127 
  128 static void
  129 pci_power_devices(struct pci_softc *sc, int why)
  130 {
  131         pci_chipset_tag_t pc;
  132         int device, function, nfunctions;
  133         pcitag_t tag;
  134         pcireg_t bhlcr, id;
  135         pcireg_t state;
  136 #ifdef __PCI_BUS_DEVORDER
  137         char devs[32];
  138         int i;
  139 #endif
  140 
  141         pc = sc->sc_pc;
  142         switch (why) {
  143         case PWR_STANDBY:
  144                 state = PCI_PMCSR_STATE_D1;
  145                 break;
  146         case PWR_SUSPEND:
  147                 state = PCI_PMCSR_STATE_D3;
  148                 break;
  149         case PWR_RESUME:
  150                 state = PCI_PMCSR_STATE_D0;
  151                 break;
  152         default:
  153                 /* we should never be called here */
  154 #ifdef DIAGNOSTIC
  155                 panic("pci_power_devices called with invalid reason %d\n",
  156                     why);
  157                 /* NOTREACHED */
  158 #endif
  159                 return;
  160         }
  161 
  162 #ifdef __PCI_BUS_DEVORDER
  163         pci_bus_devorder(sc->sc_pc, sc->sc_bus, devs);
  164         for (i = 0; (device = devs[i]) < 32 && device >= 0; i++)
  165 #else
  166         for (device = 0; device < sc->sc_maxndevs; device++)
  167 #endif
  168         {
  169                 tag = pci_make_tag(pc, sc->sc_bus, device, 0);
  170                 bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
  171                 if (PCI_HDRTYPE_TYPE(bhlcr) > 2)
  172                         continue;
  173                 id = pci_conf_read(pc, tag, PCI_ID_REG);
  174                 if (PCI_VENDOR(id) == PCI_VENDOR_INVALID ||
  175                     PCI_VENDOR(id) == 0x0000)
  176                         continue;
  177                 nfunctions = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1;
  178 
  179                 for (function = 0; function < nfunctions; function++) {
  180                         tag = pci_make_tag(pc, sc->sc_bus, device, function);
  181                         if (sc->PCI_SC_DEVICESC(device, function) != NULL)
  182                                 continue;
  183                         (void)pci_set_powerstate(pc, tag, state);
  184                 }
  185         }
  186 
  187         return;
  188 }
  189 
  190 static void
  191 pci_powerhook(int why, void *aux)
  192 {
  193         struct pci_softc *sc;
  194 
  195         sc = (struct pci_softc *)aux;
  196 
  197         switch (why) {
  198         case PWR_SUSPEND:
  199         case PWR_STANDBY:
  200         case PWR_RESUME:
  201                 pci_power_devices(sc, why);
  202                 break;
  203         }
  204 
  205         return;
  206 }
  207 
  208 static void
  209 pciattach(struct device *parent, struct device *self, void *aux)
  210 {
  211         struct pcibus_attach_args *pba = aux;
  212         struct pci_softc *sc = (struct pci_softc *)self;
  213         int io_enabled, mem_enabled, mrl_enabled, mrm_enabled, mwi_enabled;
  214         const char *sep = "";
  215         static const int wildcard[PCICF_NLOCS] = {
  216                 PCICF_DEV_DEFAULT, PCICF_FUNCTION_DEFAULT
  217         };
  218 
  219         pci_attach_hook(parent, self, pba);
  220 
  221         aprint_naive("\n");
  222         aprint_normal("\n");
  223 
  224         io_enabled = (pba->pba_flags & PCI_FLAGS_IO_ENABLED);
  225         mem_enabled = (pba->pba_flags & PCI_FLAGS_MEM_ENABLED);
  226         mrl_enabled = (pba->pba_flags & PCI_FLAGS_MRL_OKAY);
  227         mrm_enabled = (pba->pba_flags & PCI_FLAGS_MRM_OKAY);
  228         mwi_enabled = (pba->pba_flags & PCI_FLAGS_MWI_OKAY);
  229 
  230         if (io_enabled == 0 && mem_enabled == 0) {
  231                 aprint_error("%s: no spaces enabled!\n", self->dv_xname);
  232                 return;
  233         }
  234 
  235 #define PRINT(str)                                                      \
  236 do {                                                                    \
  237         aprint_normal("%s%s", sep, str);                                \
  238         sep = ", ";                                                     \
  239 } while (/*CONSTCOND*/0)
  240 
  241         aprint_normal("%s: ", self->dv_xname);
  242 
  243         if (io_enabled)
  244                 PRINT("i/o space");
  245         if (mem_enabled)
  246                 PRINT("memory space");
  247         aprint_normal(" enabled");
  248 
  249         if (mrl_enabled || mrm_enabled || mwi_enabled) {
  250                 if (mrl_enabled)
  251                         PRINT("rd/line");
  252                 if (mrm_enabled)
  253                         PRINT("rd/mult");
  254                 if (mwi_enabled)
  255                         PRINT("wr/inv");
  256                 aprint_normal(" ok");
  257         }
  258 
  259         aprint_normal("\n");
  260 
  261 #undef PRINT
  262 
  263         sc->sc_iot = pba->pba_iot;
  264         sc->sc_memt = pba->pba_memt;
  265         sc->sc_dmat = pba->pba_dmat;
  266         sc->sc_dmat64 = pba->pba_dmat64;
  267         sc->sc_pc = pba->pba_pc;
  268         sc->sc_bus = pba->pba_bus;
  269         sc->sc_bridgetag = pba->pba_bridgetag;
  270         sc->sc_maxndevs = pci_bus_maxdevs(pba->pba_pc, pba->pba_bus);
  271         sc->sc_intrswiz = pba->pba_intrswiz;
  272         sc->sc_intrtag = pba->pba_intrtag;
  273         sc->sc_flags = pba->pba_flags;
  274 
  275         sc->sc_powerhook = powerhook_establish(sc->sc_dev.dv_xname,
  276             pci_powerhook, sc);
  277         if (sc->sc_powerhook == NULL)
  278                 aprint_error("%s: can't establish powerhook\n",
  279                     sc->sc_dev.dv_xname);
  280 
  281         pcirescan(&sc->sc_dev, "pci", wildcard);
  282 }
  283 
  284 int
  285 pciprint(void *aux, const char *pnp)
  286 {
  287         struct pci_attach_args *pa = aux;
  288         char devinfo[256];
  289         const struct pci_quirkdata *qd;
  290 
  291         if (pnp) {
  292                 pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo, sizeof(devinfo));
  293                 aprint_normal("%s at %s", devinfo, pnp);
  294         }
  295         aprint_normal(" dev %d function %d", pa->pa_device, pa->pa_function);
  296         if (pci_config_dump) {
  297                 printf(": ");
  298                 pci_conf_print(pa->pa_pc, pa->pa_tag, NULL);
  299                 if (!pnp)
  300                         pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo, sizeof(devinfo));
  301                 printf("%s at %s", devinfo, pnp ? pnp : "?");
  302                 printf(" dev %d function %d (", pa->pa_device, pa->pa_function);
  303 #ifdef __i386__
  304                 printf("tag %#lx, intrtag %#lx, intrswiz %#lx, intrpin %#lx",
  305                     *(long *)&pa->pa_tag, *(long *)&pa->pa_intrtag,
  306                     (long)pa->pa_intrswiz, (long)pa->pa_intrpin);
  307 #else
  308                 printf("intrswiz %#lx, intrpin %#lx",
  309                     (long)pa->pa_intrswiz, (long)pa->pa_intrpin);
  310 #endif
  311                 printf(", i/o %s, mem %s,",
  312                     pa->pa_flags & PCI_FLAGS_IO_ENABLED ? "on" : "off",
  313                     pa->pa_flags & PCI_FLAGS_MEM_ENABLED ? "on" : "off");
  314                 qd = pci_lookup_quirkdata(PCI_VENDOR(pa->pa_id),
  315                     PCI_PRODUCT(pa->pa_id));
  316                 if (qd == NULL) {
  317                         printf(" no quirks");
  318                 } else {
  319                         bitmask_snprintf(qd->quirks,
  320                             "\002\001multifn\002singlefn\003skipfunc0"
  321                             "\004skipfunc1\005skipfunc2\006skipfunc3"
  322                             "\007skipfunc4\010skipfunc5\011skipfunc6"
  323                             "\012skipfunc7",
  324                             devinfo, sizeof (devinfo));
  325                         printf(" quirks %s", devinfo);
  326                 }
  327                 printf(")");
  328         }
  329         return (UNCONF);
  330 }
  331 
  332 int
  333 pci_probe_device(struct pci_softc *sc, pcitag_t tag,
  334     int (*match)(struct pci_attach_args *), struct pci_attach_args *pap)
  335 {
  336         pci_chipset_tag_t pc = sc->sc_pc;
  337         struct pci_attach_args pa;
  338         pcireg_t id, csr, class, intr, bhlcr;
  339         int ret, pin, bus, device, function;
  340         int locs[PCICF_NLOCS];
  341         struct device *subdev;
  342 
  343         pci_decompose_tag(pc, tag, &bus, &device, &function);
  344 
  345         /* a driver already attached? */
  346         if (sc->PCI_SC_DEVICESC(device, function) && !match)
  347                 return (0);
  348 
  349         bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
  350         if (PCI_HDRTYPE_TYPE(bhlcr) > 2)
  351                 return (0);
  352 
  353         id = pci_conf_read(pc, tag, PCI_ID_REG);
  354         csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
  355         class = pci_conf_read(pc, tag, PCI_CLASS_REG);
  356 
  357         /* Invalid vendor ID value? */
  358         if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
  359                 return (0);
  360         /* XXX Not invalid, but we've done this ~forever. */
  361         if (PCI_VENDOR(id) == 0)
  362                 return (0);
  363 
  364         pa.pa_iot = sc->sc_iot;
  365         pa.pa_memt = sc->sc_memt;
  366         pa.pa_dmat = sc->sc_dmat;
  367         pa.pa_dmat64 = sc->sc_dmat64;
  368         pa.pa_pc = pc;
  369         pa.pa_bus = bus;
  370         pa.pa_device = device;
  371         pa.pa_function = function;
  372         pa.pa_tag = tag;
  373         pa.pa_id = id;
  374         pa.pa_class = class;
  375 
  376         /*
  377          * Set up memory, I/O enable, and PCI command flags
  378          * as appropriate.
  379          */
  380         pa.pa_flags = sc->sc_flags;
  381         if ((csr & PCI_COMMAND_IO_ENABLE) == 0)
  382                 pa.pa_flags &= ~PCI_FLAGS_IO_ENABLED;
  383         if ((csr & PCI_COMMAND_MEM_ENABLE) == 0)
  384                 pa.pa_flags &= ~PCI_FLAGS_MEM_ENABLED;
  385 
  386         /*
  387          * If the cache line size is not configured, then
  388          * clear the MRL/MRM/MWI command-ok flags.
  389          */
  390         if (PCI_CACHELINE(bhlcr) == 0)
  391                 pa.pa_flags &= ~(PCI_FLAGS_MRL_OKAY|
  392                     PCI_FLAGS_MRM_OKAY|PCI_FLAGS_MWI_OKAY);
  393 
  394         if (sc->sc_bridgetag == NULL) {
  395                 pa.pa_intrswiz = 0;
  396                 pa.pa_intrtag = tag;
  397         } else {
  398                 pa.pa_intrswiz = sc->sc_intrswiz + device;
  399                 pa.pa_intrtag = sc->sc_intrtag;
  400         }
  401 
  402         intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
  403 
  404         pin = PCI_INTERRUPT_PIN(intr);
  405         pa.pa_rawintrpin = pin;
  406         if (pin == PCI_INTERRUPT_PIN_NONE) {
  407                 /* no interrupt */
  408                 pa.pa_intrpin = 0;
  409         } else {
  410                 /*
  411                  * swizzle it based on the number of busses we're
  412                  * behind and our device number.
  413                  */
  414                 pa.pa_intrpin =         /* XXX */
  415                     ((pin + pa.pa_intrswiz - 1) % 4) + 1;
  416         }
  417         pa.pa_intrline = PCI_INTERRUPT_LINE(intr);
  418 
  419         if (match != NULL) {
  420                 ret = (*match)(&pa);
  421                 if (ret != 0 && pap != NULL)
  422                         *pap = pa;
  423         } else {
  424                 locs[PCICF_DEV] = device;
  425                 locs[PCICF_FUNCTION] = function;
  426 
  427                 subdev = config_found_sm_loc(&sc->sc_dev, "pci", locs, &pa,
  428                                              pciprint, config_stdsubmatch);
  429                 sc->PCI_SC_DEVICESC(device, function) = subdev;
  430                 ret = (subdev != NULL);
  431         }
  432 
  433         return (ret);
  434 }
  435 
  436 static void
  437 pcidevdetached(struct device *sc, struct device *dev)
  438 {
  439         struct pci_softc *psc = (struct pci_softc *)sc;
  440         int d, f;
  441 
  442         d = device_locator(dev, PCICF_DEV);
  443         f = device_locator(dev, PCICF_FUNCTION);
  444 
  445         KASSERT(psc->PCI_SC_DEVICESC(d, f) == dev);
  446 
  447         psc->PCI_SC_DEVICESC(d, f) = 0;
  448 }
  449 
  450 int
  451 pci_get_capability(pci_chipset_tag_t pc, pcitag_t tag, int capid,
  452     int *offset, pcireg_t *value)
  453 {
  454         pcireg_t reg;
  455         unsigned int ofs;
  456 
  457         reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
  458         if (!(reg & PCI_STATUS_CAPLIST_SUPPORT))
  459                 return (0);
  460 
  461         /* Determine the Capability List Pointer register to start with. */
  462         reg = pci_conf_read(pc, tag, PCI_BHLC_REG);
  463         switch (PCI_HDRTYPE_TYPE(reg)) {
  464         case 0: /* standard device header */
  465                 ofs = PCI_CAPLISTPTR_REG;
  466                 break;
  467         case 2: /* PCI-CardBus Bridge header */
  468                 ofs = PCI_CARDBUS_CAPLISTPTR_REG;
  469                 break;
  470         default:
  471                 return (0);
  472         }
  473 
  474         ofs = PCI_CAPLIST_PTR(pci_conf_read(pc, tag, ofs));
  475         while (ofs != 0) {
  476 #ifdef DIAGNOSTIC
  477                 if ((ofs & 3) || (ofs < 0x40))
  478                         panic("pci_get_capability");
  479 #endif
  480                 reg = pci_conf_read(pc, tag, ofs);
  481                 if (PCI_CAPLIST_CAP(reg) == capid) {
  482                         if (offset)
  483                                 *offset = ofs;
  484                         if (value)
  485                                 *value = reg;
  486                         return (1);
  487                 }
  488                 ofs = PCI_CAPLIST_NEXT(reg);
  489         }
  490 
  491         return (0);
  492 }
  493 
  494 int
  495 pci_find_device(struct pci_attach_args *pa,
  496                 int (*match)(struct pci_attach_args *))
  497 {
  498         extern struct cfdriver pci_cd;
  499         struct device *pcidev;
  500         int i;
  501         static const int wildcard[2] = {
  502                 PCICF_DEV_DEFAULT,
  503                 PCICF_FUNCTION_DEFAULT
  504         };
  505 
  506         for (i = 0; i < pci_cd.cd_ndevs; i++) {
  507                 pcidev = pci_cd.cd_devs[i];
  508                 if (pcidev != NULL &&
  509                     pci_enumerate_bus((struct pci_softc *)pcidev, wildcard,
  510                                       match, pa) != 0)
  511                         return (1);
  512         }
  513         return (0);
  514 }
  515 
  516 #ifndef PCI_MACHDEP_ENUMERATE_BUS
  517 /*
  518  * Generic PCI bus enumeration routine.  Used unless machine-dependent
  519  * code needs to provide something else.
  520  */
  521 int
  522 pci_enumerate_bus(struct pci_softc *sc, const int *locators,
  523     int (*match)(struct pci_attach_args *), struct pci_attach_args *pap)
  524 {
  525         pci_chipset_tag_t pc = sc->sc_pc;
  526         int device, function, nfunctions, ret;
  527         const struct pci_quirkdata *qd;
  528         pcireg_t id, bhlcr;
  529         pcitag_t tag;
  530 #ifdef __PCI_BUS_DEVORDER
  531         char devs[32];
  532         int i;
  533 #endif
  534 
  535 #ifdef __PCI_BUS_DEVORDER
  536         pci_bus_devorder(sc->sc_pc, sc->sc_bus, devs);
  537         for (i = 0; (device = devs[i]) < 32 && device >= 0; i++)
  538 #else
  539         for (device = 0; device < sc->sc_maxndevs; device++)
  540 #endif
  541         {
  542                 if ((locators[PCICF_DEV] != PCICF_DEV_DEFAULT) &&
  543                     (locators[PCICF_DEV] != device))
  544                         continue;
  545 
  546                 tag = pci_make_tag(pc, sc->sc_bus, device, 0);
  547 
  548                 bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
  549                 if (PCI_HDRTYPE_TYPE(bhlcr) > 2)
  550                         continue;
  551 
  552                 id = pci_conf_read(pc, tag, PCI_ID_REG);
  553 
  554                 /* Invalid vendor ID value? */
  555                 if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
  556                         continue;
  557                 /* XXX Not invalid, but we've done this ~forever. */
  558                 if (PCI_VENDOR(id) == 0)
  559                         continue;
  560 
  561                 qd = pci_lookup_quirkdata(PCI_VENDOR(id), PCI_PRODUCT(id));
  562 
  563                 if (qd != NULL &&
  564                       (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0)
  565                         nfunctions = 8;
  566                 else if (qd != NULL &&
  567                       (qd->quirks & PCI_QUIRK_MONOFUNCTION) != 0)
  568                         nfunctions = 1;
  569                 else
  570                         nfunctions = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1;
  571 
  572                 for (function = 0; function < nfunctions; function++) {
  573                         if ((locators[PCICF_FUNCTION] != PCICF_FUNCTION_DEFAULT)
  574                             && (locators[PCICF_FUNCTION] != function))
  575                                 continue;
  576 
  577                         if (qd != NULL &&
  578                             (qd->quirks & PCI_QUIRK_SKIP_FUNC(function)) != 0)
  579                                 continue;
  580                         tag = pci_make_tag(pc, sc->sc_bus, device, function);
  581                         ret = pci_probe_device(sc, tag, match, pap);
  582                         if (match != NULL && ret != 0)
  583                                 return (ret);
  584                 }
  585         }
  586         return (0);
  587 }
  588 #endif /* PCI_MACHDEP_ENUMERATE_BUS */
  589 
  590 
  591 /*
  592  * Vital Product Data (PCI 2.2)
  593  */
  594 
  595 int
  596 pci_vpd_read(pci_chipset_tag_t pc, pcitag_t tag, int offset, int count,
  597     pcireg_t *data)
  598 {
  599         uint32_t reg;
  600         int ofs, i, j;
  601 
  602         KASSERT(data != NULL);
  603         KASSERT((offset + count) < 0x7fff);
  604 
  605         if (pci_get_capability(pc, tag, PCI_CAP_VPD, &ofs, &reg) == 0)
  606                 return (1);
  607 
  608         for (i = 0; i < count; offset += sizeof(*data), i++) {
  609                 reg &= 0x0000ffff;
  610                 reg &= ~PCI_VPD_OPFLAG;
  611                 reg |= PCI_VPD_ADDRESS(offset);
  612                 pci_conf_write(pc, tag, ofs, reg);
  613 
  614                 /*
  615                  * PCI 2.2 does not specify how long we should poll
  616                  * for completion nor whether the operation can fail.
  617                  */
  618                 j = 0;
  619                 do {
  620                         if (j++ == 20)
  621                                 return (1);
  622                         delay(4);
  623                         reg = pci_conf_read(pc, tag, ofs);
  624                 } while ((reg & PCI_VPD_OPFLAG) == 0);
  625                 data[i] = pci_conf_read(pc, tag, PCI_VPD_DATAREG(ofs));
  626         }
  627 
  628         return (0);
  629 }
  630 
  631 int
  632 pci_vpd_write(pci_chipset_tag_t pc, pcitag_t tag, int offset, int count,
  633     pcireg_t *data)
  634 {
  635         pcireg_t reg;
  636         int ofs, i, j;
  637 
  638         KASSERT(data != NULL);
  639         KASSERT((offset + count) < 0x7fff);
  640 
  641         if (pci_get_capability(pc, tag, PCI_CAP_VPD, &ofs, &reg) == 0)
  642                 return (1);
  643 
  644         for (i = 0; i < count; offset += sizeof(*data), i++) {
  645                 pci_conf_write(pc, tag, PCI_VPD_DATAREG(ofs), data[i]);
  646 
  647                 reg &= 0x0000ffff;
  648                 reg |= PCI_VPD_OPFLAG;
  649                 reg |= PCI_VPD_ADDRESS(offset);
  650                 pci_conf_write(pc, tag, ofs, reg);
  651 
  652                 /*
  653                  * PCI 2.2 does not specify how long we should poll
  654                  * for completion nor whether the operation can fail.
  655                  */
  656                 j = 0;
  657                 do {
  658                         if (j++ == 20)
  659                                 return (1);
  660                         delay(1);
  661                         reg = pci_conf_read(pc, tag, ofs);
  662                 } while (reg & PCI_VPD_OPFLAG);
  663         }
  664 
  665         return (0);
  666 }
  667 
  668 int
  669 pci_dma64_available(struct pci_attach_args *pa)
  670 {
  671 #ifdef _PCI_HAVE_DMA64
  672         if (BUS_DMA_TAG_VALID(pa->pa_dmat64) &&
  673                 ((uint64_t)physmem << PAGE_SHIFT) > 0xffffffffULL)
  674                         return 1;
  675 #endif
  676         return 0;
  677 }
  678 
  679 void
  680 pci_conf_capture(pci_chipset_tag_t pc, pcitag_t tag,
  681                   struct pci_conf_state *pcs)
  682 {
  683         int off;
  684 
  685         for (off = 0; off < 16; off++)
  686                 pcs->reg[off] = pci_conf_read(pc, tag, (off * 4));
  687 
  688         return;
  689 }
  690 
  691 void
  692 pci_conf_restore(pci_chipset_tag_t pc, pcitag_t tag,
  693                   struct pci_conf_state *pcs)
  694 {
  695         int off;
  696 
  697         for (off = 0; off < 16; off++)
  698                 pci_conf_write(pc, tag, (off * 4), pcs->reg[off]);
  699 
  700         return;
  701 }
  702 
  703 /*
  704  * Power Management Capability (Rev 2.2)
  705  */
  706 int
  707 pci_get_powerstate(pci_chipset_tag_t pc, pcitag_t tag , pcireg_t *state)
  708 {
  709         int offset;
  710         pcireg_t value, cap, now;
  711 
  712         if (!pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &offset, &value))
  713                 return EOPNOTSUPP;
  714 
  715         cap = value >> PCI_PMCR_SHIFT;
  716         value = pci_conf_read(pc, tag, offset + PCI_PMCSR);
  717         now = value & PCI_PMCSR_STATE_MASK;
  718         switch (now) {
  719         case PCI_PMCSR_STATE_D0:
  720         case PCI_PMCSR_STATE_D1:
  721         case PCI_PMCSR_STATE_D2:
  722         case PCI_PMCSR_STATE_D3:
  723                 *state = now;
  724                 return 0;
  725         default:
  726                 return EINVAL;
  727         }
  728 }
  729 
  730 int
  731 pci_set_powerstate(pci_chipset_tag_t pc, pcitag_t tag, pcireg_t state)
  732 {
  733         int offset;
  734         pcireg_t value, cap, now;
  735 
  736         if (!pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &offset, &value))
  737                 return EOPNOTSUPP;
  738 
  739         cap = value >> PCI_PMCR_SHIFT;
  740         value = pci_conf_read(pc, tag, offset + PCI_PMCSR);
  741         now = value & PCI_PMCSR_STATE_MASK;
  742         value &= ~PCI_PMCSR_STATE_MASK;
  743 
  744         if (now == state)
  745                 return 0;
  746         switch (state) {
  747         case PCI_PMCSR_STATE_D0:
  748                 value |= PCI_PMCSR_STATE_D0;
  749                 break;
  750         case PCI_PMCSR_STATE_D1:
  751                 if (now == PCI_PMCSR_STATE_D2 || now == PCI_PMCSR_STATE_D3)
  752                         return EINVAL;
  753                 if (!(cap & PCI_PMCR_D1SUPP))
  754                         return EOPNOTSUPP;
  755                 value |= PCI_PMCSR_STATE_D1;
  756                 break;
  757         case PCI_PMCSR_STATE_D2:
  758                 if (now == PCI_PMCSR_STATE_D3)
  759                         return EINVAL;
  760                 if (!(cap & PCI_PMCR_D2SUPP))
  761                         return EOPNOTSUPP;
  762                 value |= PCI_PMCSR_STATE_D2;
  763                 break;
  764         case PCI_PMCSR_STATE_D3:
  765                 if (now == PCI_PMCSR_STATE_D3)
  766                         return 0;
  767                 value |= PCI_PMCSR_STATE_D3;
  768                 break;
  769         default:
  770                 return EINVAL;
  771         }
  772         pci_conf_write(pc, tag, offset + PCI_PMCSR, value);
  773         DELAY(1000);
  774         return 0;
  775 }
  776 
  777 int
  778 pci_activate(pci_chipset_tag_t pc, pcitag_t tag, void *sc,
  779     int (*wakefun)(pci_chipset_tag_t, pcitag_t, void *, pcireg_t))
  780 {
  781         struct device *dv = sc;
  782         pcireg_t pmode;
  783         int error;
  784 
  785         if ((error = pci_get_powerstate(pc, tag, &pmode)))
  786                 return error;
  787 
  788         switch (pmode) {
  789         case PCI_PMCSR_STATE_D0:
  790                 break;
  791         case PCI_PMCSR_STATE_D3:
  792                 if (wakefun == NULL) {
  793                         /*
  794                          * The card has lost all configuration data in
  795                          * this state, so punt.
  796                          */
  797                         aprint_error(
  798                             "%s: unable to wake up from power state D3\n",
  799                             dv->dv_xname);
  800                         return EOPNOTSUPP;
  801                 }
  802                 /*FALLTHROUGH*/
  803         default:
  804                 if (wakefun) {
  805                         error = (*wakefun)(pc, tag, sc, pmode);
  806                         if (error)
  807                                 return error;
  808                 }
  809                 aprint_normal("%s: waking up from power state D%d\n",
  810                     dv->dv_xname, pmode);
  811                 if ((error = pci_set_powerstate(pc, tag, PCI_PMCSR_STATE_D0)))
  812                         return error;
  813         }
  814         return 0;
  815 }
  816 
  817 int
  818 pci_activate_null(pci_chipset_tag_t pc, pcitag_t tag,
  819     void *sc, pcireg_t state)
  820 {
  821         return 0;
  822 }
  823 
  824 CFATTACH_DECL2(pci, sizeof(struct pci_softc),
  825     pcimatch, pciattach, NULL, NULL, pcirescan, pcidevdetached);

Cache object: 3baaa70e05e9f04ea33cd99acdb132eb


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.