root/dev/pci/if_wi_pci.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wi_pci_lookup
  2. wi_pci_match
  3. wi_pci_attach
  4. wi_pci_power
  5. wi_pci_acex_attach
  6. wi_pci_plx_attach
  7. wi_pci_tmd_attach
  8. wi_pci_native_attach
  9. wi_pci_common_attach
  10. wi_pci_plx_print_cis

    1 /*      $OpenBSD: if_wi_pci.c,v 1.43 2006/11/26 19:46:28 deraadt Exp $  */
    2 
    3 /*
    4  * Copyright (c) 2001-2003 Todd C. Miller <Todd.Miller@courtesan.com>
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  *
   18  * Sponsored in part by the Defense Advanced Research Projects
   19  * Agency (DARPA) and Air Force Research Laboratory, Air Force
   20  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
   21  */
   22 
   23 /*
   24  * PCI attachment for the Wavelan driver.  There are two basic types
   25  * of PCI card supported:
   26  *
   27  * 1) Cards based on the Prism2.5 Mini-PCI chipset
   28  * 2) Cards that use a dumb PCMCIA->PCI bridge
   29  *
   30  * Only the first type are "true" PCI cards.
   31  *
   32  * The latter are simply PCMCIA cards (or the guts of same) with some
   33  * type of dumb PCMCIA->PCI bridge.  They are "dumb" in that they
   34  * are not true PCMCIA bridges and really just serve to deal with
   35  * the different interrupt types and timings of the ISA vs. PCI bus.
   36  *
   37  * The following bridge types are supported:
   38  *  o PLX 9052 (the most common)
   39  *  o TMD 7160 (found in some NDC/Sohoware NCP130 cards)
   40  *  o ACEX EP1K30 (really a PLD, found in Symbol cards and their OEMs)
   41  */
   42 
   43 #include <sys/param.h>
   44 #include <sys/systm.h>
   45 #include <sys/device.h>
   46 #include <sys/timeout.h>
   47 #include <sys/socket.h>
   48 #include <sys/tree.h>
   49 
   50 #include <net/if.h>
   51 #include <net/if_dl.h>
   52 #include <net/if_media.h>
   53 
   54 #ifdef INET
   55 #include <netinet/in.h>
   56 #include <netinet/if_ether.h>
   57 #endif
   58 
   59 #include <net80211/ieee80211_var.h>
   60 #include <net80211/ieee80211_ioctl.h>
   61 
   62 #include <machine/bus.h>
   63 
   64 #include <dev/pci/pcireg.h>
   65 #include <dev/pci/pcivar.h>
   66 #include <dev/pci/pcidevs.h>
   67 
   68 #include <dev/ic/if_wireg.h>
   69 #include <dev/ic/if_wi_ieee.h>
   70 #include <dev/ic/if_wivar.h>
   71 
   72 /* For printing CIS of the actual PCMCIA card */
   73 #define CIS_MFG_NAME_OFFSET     0x16
   74 #define CIS_INFO_SIZE           256
   75 
   76 const struct wi_pci_product *wi_pci_lookup(struct pci_attach_args *pa);
   77 int     wi_pci_match(struct device *, void *, void *);
   78 void    wi_pci_attach(struct device *, struct device *, void *);
   79 int     wi_pci_acex_attach(struct pci_attach_args *pa, struct wi_softc *sc);
   80 int     wi_pci_plx_attach(struct pci_attach_args *pa, struct wi_softc *sc);
   81 int     wi_pci_tmd_attach(struct pci_attach_args *pa, struct wi_softc *sc);
   82 int     wi_pci_native_attach(struct pci_attach_args *pa, struct wi_softc *sc);
   83 int     wi_pci_common_attach(struct pci_attach_args *pa, struct wi_softc *sc);
   84 void    wi_pci_plx_print_cis(struct wi_softc *);
   85 void    wi_pci_power(int, void *);
   86 
   87 struct wi_pci_softc {
   88         struct wi_softc          sc_wi;         /* real softc */
   89         void                    *sc_powerhook;
   90 };
   91 
   92 struct cfattach wi_pci_ca = {
   93         sizeof (struct wi_pci_softc), wi_pci_match, wi_pci_attach
   94 };
   95 
   96 static const struct wi_pci_product {
   97         pci_vendor_id_t pp_vendor;
   98         pci_product_id_t pp_product;
   99         int (*pp_attach)(struct pci_attach_args *pa, struct wi_softc *sc);
  100 } wi_pci_products[] = {
  101         { PCI_VENDOR_GLOBALSUN, PCI_PRODUCT_GLOBALSUN_GL24110P, wi_pci_plx_attach },
  102         { PCI_VENDOR_GLOBALSUN, PCI_PRODUCT_GLOBALSUN_GL24110P02, wi_pci_plx_attach },
  103         { PCI_VENDOR_GLOBALSUN, PCI_PRODUCT_GLOBALSUN_GL24110P03, wi_pci_plx_attach },
  104         { PCI_VENDOR_GLOBALSUN, PCI_PRODUCT_GLOBALSUN_8031, wi_pci_plx_attach },
  105         { PCI_VENDOR_EUMITCOM, PCI_PRODUCT_EUMITCOM_WL11000P, wi_pci_plx_attach },
  106         { PCI_VENDOR_USR2, PCI_PRODUCT_USR2_WL11000P, wi_pci_plx_attach },
  107         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CRWE777A, wi_pci_plx_attach },
  108         { PCI_VENDOR_NETGEAR, PCI_PRODUCT_NETGEAR_MA301, wi_pci_plx_attach },
  109         { PCI_VENDOR_EFFICIENTNETS, PCI_PRODUCT_EFFICIENTNETS_SS1023, wi_pci_plx_attach },
  110         { PCI_VENDOR_ADDTRON, PCI_PRODUCT_ADDTRON_AWA100, wi_pci_plx_attach },
  111         { PCI_VENDOR_BELKIN, PCI_PRODUCT_BELKIN_F5D6000, wi_pci_plx_attach },
  112         { PCI_VENDOR_NDC, PCI_PRODUCT_NDC_NCP130, wi_pci_plx_attach },
  113         { PCI_VENDOR_NDC, PCI_PRODUCT_NDC_NCP130A2, wi_pci_tmd_attach },
  114         { PCI_VENDOR_INTERSIL, PCI_PRODUCT_INTERSIL_MINI_PCI_WLAN, wi_pci_native_attach },
  115         { PCI_VENDOR_INTERSIL, PCI_PRODUCT_INTERSIL_ISL3872, wi_pci_native_attach },
  116         { PCI_VENDOR_SAMSUNG, PCI_PRODUCT_SAMSUNG_SWL2210P, wi_pci_native_attach },
  117         { PCI_VENDOR_NORTEL, PCI_PRODUCT_NORTEL_211818A, wi_pci_acex_attach },
  118         { PCI_VENDOR_SYMBOL, PCI_PRODUCT_SYMBOL_LA41X3, wi_pci_acex_attach },
  119         { 0, 0, 0 }
  120 };
  121 
  122 const struct wi_pci_product *
  123 wi_pci_lookup(struct pci_attach_args *pa)
  124 {
  125         const struct wi_pci_product *pp;
  126 
  127         for (pp = wi_pci_products; pp->pp_product != 0; pp++) {
  128                 if (PCI_VENDOR(pa->pa_id) == pp->pp_vendor && 
  129                     PCI_PRODUCT(pa->pa_id) == pp->pp_product)
  130                         return (pp);
  131         }
  132 
  133         return (NULL);
  134 }
  135 
  136 int
  137 wi_pci_match(struct device *parent, void *match, void *aux)
  138 {
  139         return (wi_pci_lookup(aux) != NULL);
  140 }
  141 
  142 void
  143 wi_pci_attach(struct device *parent, struct device *self, void *aux)
  144 {
  145         struct wi_pci_softc *psc = (struct wi_pci_softc *)self;
  146         struct wi_softc *sc = (struct wi_softc *)self;
  147         struct pci_attach_args *pa = aux;
  148         const struct wi_pci_product *pp;
  149 
  150         pp = wi_pci_lookup(pa);
  151         if (pp->pp_attach(pa, sc) != 0)
  152                 return;
  153         printf("\n");
  154         wi_attach(sc, &wi_func_io);
  155 
  156         psc->sc_powerhook = powerhook_establish(wi_pci_power, sc);
  157 }
  158 
  159 void
  160 wi_pci_power(int why, void *arg)
  161 {
  162         struct wi_softc *sc = (struct wi_softc *)arg;
  163 
  164         if (why == PWR_RESUME) {
  165                 if (sc->sc_ic.ic_if.if_flags & IFF_UP)
  166                         wi_init(sc);
  167         }
  168 }
  169 
  170 /*
  171  * ACEX EP1K30-based PCMCIA->PCI bridge attachment.
  172  *
  173  * The ACEX EP1K30 is a programmable logic device (PLD) used as a
  174  * PCMCIA->PCI bridge on the Symbol LA4123 and its OEM equivalents
  175  * (such as the Nortel E-mobility 211818-A).  There are 3 I/O ports:
  176  * BAR0 at 0x10 appears to be a command port.
  177  * BAR1 at 0x14 contains COR at offset 0xe0.
  178  * BAR2 at 0x18 maps the actual PCMCIA card.
  179  *
  180  * The datasheet for the ACEX EP1K30 is available from Altera but that
  181  * doesn't really help much since we don't know how it is programmed.
  182  * Details for this attachment were gleaned from a version of the
  183  * Linux orinoco driver modified by Tobias Hoffmann based on
  184  * what he discoverd from the Windows driver.
  185  */
  186 int
  187 wi_pci_acex_attach(struct pci_attach_args *pa, struct wi_softc *sc)
  188 {
  189         bus_space_handle_t commandh, localh, ioh;
  190         bus_space_tag_t commandt, localt;
  191         bus_space_tag_t iot = pa->pa_iot;
  192         bus_size_t commandsize, localsize, iosize;
  193         int i;
  194 
  195         if (pci_mapreg_map(pa, WI_ACEX_CMDRES, PCI_MAPREG_TYPE_IO,
  196             0, &commandt, &commandh, NULL, &commandsize, 0) != 0) {
  197                 printf(": can't map command I/O space\n");
  198                 return (ENXIO);
  199         }
  200 
  201         if (pci_mapreg_map(pa, WI_ACEX_LOCALRES, PCI_MAPREG_TYPE_IO,
  202             0, &localt, &localh, NULL, &localsize, 0) != 0) {
  203                 printf(": can't map local I/O space\n");
  204                 bus_space_unmap(commandt, commandh, commandsize);
  205                 return (ENXIO);
  206         }
  207         sc->wi_ltag = localt;
  208         sc->wi_lhandle = localh;
  209 
  210         if (pci_mapreg_map(pa, WI_TMD_IORES, PCI_MAPREG_TYPE_IO,
  211             0, &iot, &ioh, NULL, &iosize, 0) != 0) {
  212                 printf(": can't map I/O space\n");
  213                 bus_space_unmap(localt, localh, localsize);
  214                 bus_space_unmap(commandt, commandh, commandsize);
  215                 return (ENXIO);
  216         }
  217         sc->wi_btag = iot;
  218         sc->wi_bhandle = ioh;
  219 
  220         /*
  221          * Setup bridge chip.
  222          */
  223         if (bus_space_read_4(commandt, commandh, 0) & 1) {
  224                 printf(": bridge not ready\n");
  225                 bus_space_unmap(iot, ioh, iosize);
  226                 bus_space_unmap(localt, localh, localsize);
  227                 bus_space_unmap(commandt, commandh, commandsize);
  228                 return (ENXIO);
  229         }
  230         bus_space_write_4(commandt, commandh, 2, 0x118);
  231         bus_space_write_4(commandt, commandh, 2, 0x108);
  232         DELAY(30 * 1000);
  233         bus_space_write_4(commandt, commandh, 2, 0x8);
  234         for (i = 0; i < 30; i++) {
  235                 DELAY(30 * 1000);
  236                 if (bus_space_read_4(commandt, commandh, 0) & 0x10)
  237                         break;
  238         }
  239         if (i == 30) {
  240                 printf(": bridge timeout\n");
  241                 bus_space_unmap(iot, ioh, iosize);
  242                 bus_space_unmap(localt, localh, localsize);
  243                 bus_space_unmap(commandt, commandh, commandsize);
  244                 return (ENXIO);
  245         }
  246         if ((bus_space_read_4(localt, localh, 0xe0) & 1) ||
  247             (bus_space_read_4(localt, localh, 0xe2) & 1) ||
  248             (bus_space_read_4(localt, localh, 0xe4) & 1)) {
  249                 printf(": failed bridge setup\n");
  250                 bus_space_unmap(iot, ioh, iosize);
  251                 bus_space_unmap(localt, localh, localsize);
  252                 bus_space_unmap(commandt, commandh, commandsize);
  253                 return (ENXIO);
  254         }
  255 
  256         if (wi_pci_common_attach(pa, sc) != 0) {
  257                 bus_space_unmap(iot, ioh, iosize);
  258                 bus_space_unmap(localt, localh, localsize);
  259                 bus_space_unmap(commandt, commandh, commandsize);
  260                 return (ENXIO);
  261         }
  262 
  263         /* 
  264          * Enable I/O mode and level interrupts on the embedded PCMCIA
  265          * card.
  266          */
  267         bus_space_write_1(localt, localh, WI_ACEX_COR_OFFSET, WI_COR_IOMODE);
  268         sc->wi_cor_offset = WI_ACEX_COR_OFFSET;
  269 
  270         /* Unmap registers we no longer need access to. */
  271         bus_space_unmap(commandt, commandh, commandsize);
  272 
  273         return (0);
  274 }
  275 
  276 /*
  277  * PLX 9052-based PCMCIA->PCI bridge attachment.
  278  *
  279  * These are often sold as "PCI wireless card adapters" and are
  280  * sold by several vendors.  Most are simply rebadged versions of the
  281  * Eumitcom WL11000P or Global Sun Technology GL24110P02.
  282  * These cards use the PLX 9052 dumb bridge chip to connect a PCMCIA
  283  * wireless card to the PCI bus.  Because it is a dumb bridge and
  284  * not a true PCMCIA bridge, the PCMCIA subsystem is not involved
  285  * (or even required).  The PLX 9052 provides multiple PCI address
  286  * space mappings.  The primary mappings at PCI registers 0x10 (mem)
  287  * and 0x14 (I/O) are for the PLX chip itself, *NOT* the PCMCIA card.
  288  * The mem and I/O spaces for the PCMCIA card are mapped to 0x18 and
  289  * 0x1C respectively.
  290  * The PLX 9050/9052 datasheet may be downloaded from PLX at
  291  *      http://www.plxtech.com/products/toolbox/9050.htm
  292  */
  293 int
  294 wi_pci_plx_attach(struct pci_attach_args *pa, struct wi_softc *sc)
  295 {
  296         bus_space_handle_t localh, ioh, memh;
  297         bus_space_tag_t localt;
  298         bus_space_tag_t iot = pa->pa_iot;
  299         bus_space_tag_t memt = pa->pa_memt;
  300         bus_size_t localsize, memsize, iosize;
  301         u_int32_t intcsr;
  302 
  303         if (pci_mapreg_map(pa, WI_PLX_MEMRES, PCI_MAPREG_TYPE_MEM, 0,
  304             &memt, &memh, NULL, &memsize, 0) != 0) {
  305                 printf(": can't map mem space\n");
  306                 return (ENXIO);
  307         }
  308         sc->wi_ltag = memt;
  309         sc->wi_lhandle = memh;
  310 
  311         if (pci_mapreg_map(pa, WI_PLX_IORES,
  312             PCI_MAPREG_TYPE_IO, 0, &iot, &ioh, NULL, &iosize, 0) != 0) {
  313                 printf(": can't map I/O space\n");
  314                 bus_space_unmap(memt, memh, memsize);
  315                 return (ENXIO);
  316         }
  317         sc->wi_btag = iot;
  318         sc->wi_bhandle = ioh;
  319 
  320         /*
  321          * Some cards, such as the PLX version of the NDC NCP130,
  322          * don't have the PLX local registers mapped.  In general
  323          * this is OK since on those cards the serial EEPROM has
  324          * already set things up for us.
  325          * As such, we don't consider an error here to be fatal.
  326          */
  327         localsize = 0;
  328         if (pci_mapreg_type(pa->pa_pc, pa->pa_tag, WI_PLX_LOCALRES)
  329             == PCI_MAPREG_TYPE_IO) {
  330                 if (pci_mapreg_map(pa, WI_PLX_LOCALRES, PCI_MAPREG_TYPE_IO,
  331                     0, &localt, &localh, NULL, &localsize, 0) != 0)
  332                         printf(": can't map PLX I/O space\n");
  333         }
  334 
  335         if (wi_pci_common_attach(pa, sc) != 0) {
  336                 if (localsize)
  337                         bus_space_unmap(localt, localh, localsize);
  338                 bus_space_unmap(iot, ioh, iosize);
  339                 bus_space_unmap(memt, memh, memsize);
  340                 return (ENXIO);
  341         }
  342 
  343         if (localsize != 0) {
  344                 intcsr = bus_space_read_4(localt, localh,
  345                     WI_PLX_INTCSR);
  346 
  347                 /*
  348                  * The Netgear MA301 has local interrupt 1 active
  349                  * when there is no card in the adapter.  We bail
  350                  * early in this case since our attempt to check
  351                  * for the presence of a card later will hang the
  352                  * MA301.
  353                  */
  354                 if (intcsr & WI_PLX_LINT1STAT) {
  355                         printf("\n%s: no PCMCIA card detected in bridge card\n",
  356                             WI_PRT_ARG(sc));
  357                         pci_intr_disestablish(pa->pa_pc, sc->sc_ih);
  358                         if (localsize)
  359                                 bus_space_unmap(localt, localh, localsize);
  360                         bus_space_unmap(iot, ioh, iosize);
  361                         bus_space_unmap(memt, memh, memsize);
  362                         return (ENXIO);
  363                 }
  364 
  365                 /*
  366                  * Enable PCI interrupts on the PLX chip if they are
  367                  * not already enabled. On most adapters the serial
  368                  * EEPROM has done this for us but some (such as
  369                  * the Netgear MA301) do not.
  370                  */
  371                 if (!(intcsr & WI_PLX_INTEN)) {
  372                         intcsr |= WI_PLX_INTEN;
  373                         bus_space_write_4(localt, localh, WI_PLX_INTCSR,
  374                             intcsr);
  375                 }
  376         }
  377 
  378         /*
  379          * Enable I/O mode and level interrupts on the PCMCIA card.
  380          * The PCMCIA card's COR is the first byte after the CIS.
  381          */
  382         bus_space_write_1(memt, memh, WI_PLX_COR_OFFSET, WI_COR_IOMODE);
  383         sc->wi_cor_offset = WI_PLX_COR_OFFSET;
  384 
  385         if (localsize != 0) {
  386                 /*
  387                  * Test the presence of a wi(4) card by writing
  388                  * a magic number to the first software support
  389                  * register and then reading it back.
  390                  */
  391                 CSR_WRITE_2(sc, WI_SW0, WI_DRVR_MAGIC);
  392                 DELAY(1000);
  393                 if (CSR_READ_2(sc, WI_SW0) != WI_DRVR_MAGIC) {
  394                         printf("\n%s: no PCMCIA card detected in bridge card\n",
  395                             WI_PRT_ARG(sc));
  396                         pci_intr_disestablish(pa->pa_pc, sc->sc_ih);
  397                         if (localsize)
  398                                 bus_space_unmap(localt, localh, localsize);
  399                         bus_space_unmap(iot, ioh, iosize);
  400                         bus_space_unmap(memt, memh, memsize);
  401                         return (ENXIO);
  402                 }
  403 
  404                 /* Unmap registers we no longer need access to. */
  405                 bus_space_unmap(localt, localh, localsize);
  406 
  407                 /* Print PCMCIA card's CIS strings. */
  408                 wi_pci_plx_print_cis(sc);
  409         }
  410 
  411         return (0);
  412 }
  413 
  414 /*
  415  * TMD 7160-based PCMCIA->PCI bridge attachment.
  416  *
  417  * The TMD7160 dumb bridge chip is used on some versions of the
  418  * NDC/Sohoware NCP130.  The TMD7160 provides two PCI I/O registers.
  419  * The first, at 0x14, maps to the Prism2 COR.
  420  * The second, at 0x18, is for the Prism2 chip itself.
  421  *
  422  * The datasheet for the TMD7160 does not seem to be publicly available.
  423  * Details for this attachment were gleaned from a version of the
  424  * Linux WLAN driver modified by NDC.
  425  */
  426 int
  427 wi_pci_tmd_attach(struct pci_attach_args *pa, struct wi_softc *sc)
  428 {
  429         bus_space_handle_t localh, ioh;
  430         bus_space_tag_t localt;
  431         bus_space_tag_t iot = pa->pa_iot;
  432         bus_size_t localsize, iosize;
  433 
  434         if (pci_mapreg_map(pa, WI_TMD_LOCALRES, PCI_MAPREG_TYPE_IO,
  435             0, &localt, &localh, NULL, &localsize, 0) != 0) {
  436                 printf(": can't map TMD I/O space\n");
  437                 return (ENXIO);
  438         }
  439         sc->wi_ltag = localt;
  440         sc->wi_lhandle = localh;
  441 
  442         if (pci_mapreg_map(pa, WI_TMD_IORES, PCI_MAPREG_TYPE_IO,
  443             0, &iot, &ioh, NULL, &iosize, 0) != 0) {
  444                 printf(": can't map I/O space\n");
  445                 bus_space_unmap(localt, localh, localsize);
  446                 return (ENXIO);
  447         }
  448         sc->wi_btag = iot;
  449         sc->wi_bhandle = ioh;
  450 
  451         if (wi_pci_common_attach(pa, sc) != 0) {
  452                 bus_space_unmap(iot, ioh, iosize);
  453                 bus_space_unmap(localt, localh, localsize);
  454                 return (ENXIO);
  455         }
  456 
  457         /* 
  458          * Enable I/O mode and level interrupts on the embedded PCMCIA
  459          * card.  The PCMCIA card's COR is the first byte of BAR 0.
  460          */
  461         bus_space_write_1(localt, localh, 0, WI_COR_IOMODE);
  462         sc->wi_cor_offset = 0;
  463 
  464         return (0);
  465 }
  466 
  467 int
  468 wi_pci_native_attach(struct pci_attach_args *pa, struct wi_softc *sc)
  469 {
  470         bus_space_handle_t ioh;
  471         bus_space_tag_t iot = pa->pa_iot;
  472         bus_size_t iosize;
  473 
  474         if (pci_mapreg_map(pa, WI_PCI_CBMA, PCI_MAPREG_TYPE_MEM,
  475             0, &iot, &ioh, NULL, &iosize, 0) != 0) {
  476                 printf(": can't map mem space\n");
  477                 return (ENXIO);
  478         }
  479         sc->wi_ltag = iot;
  480         sc->wi_lhandle = ioh;
  481         sc->wi_btag = iot;
  482         sc->wi_bhandle = ioh;
  483         sc->sc_pci = 1;
  484 
  485         if (wi_pci_common_attach(pa, sc) != 0) {
  486                 bus_space_unmap(iot, ioh, iosize);
  487                 return (ENXIO);
  488         }
  489 
  490         /* Do a soft reset of the HFA3842 MAC core */
  491         bus_space_write_2(iot, ioh, WI_PCI_COR_OFFSET, WI_COR_SOFT_RESET);
  492         DELAY(100*1000); /* 100 m sec */
  493         bus_space_write_2(iot, ioh, WI_PCI_COR_OFFSET, WI_COR_CLEAR);
  494         DELAY(100*1000); /* 100 m sec */
  495         sc->wi_cor_offset = WI_PCI_COR_OFFSET;
  496 
  497         return (0);
  498 }
  499 
  500 int
  501 wi_pci_common_attach(struct pci_attach_args *pa, struct wi_softc *sc)
  502 {
  503         pci_intr_handle_t ih;
  504         pci_chipset_tag_t pc = pa->pa_pc;
  505         const char *intrstr;
  506 
  507         /* Make sure interrupts are disabled. */
  508         CSR_WRITE_2(sc, WI_INT_EN, 0);
  509         CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
  510 
  511         /* Map and establish the interrupt. */
  512         if (pci_intr_map(pa, &ih)) {
  513                 printf(": couldn't map interrupt\n");
  514                 return (ENXIO);
  515         }
  516         intrstr = pci_intr_string(pc, ih);
  517         sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, wi_intr, sc,
  518             sc->sc_dev.dv_xname);
  519         if (sc->sc_ih == NULL) {
  520                 printf(": couldn't establish interrupt");
  521                 if (intrstr != NULL)
  522                         printf(" at %s", intrstr);
  523                 printf("\n");
  524                 return (ENXIO);
  525         }
  526         printf(": %s", intrstr);
  527 
  528         return (0);
  529 }
  530 
  531 void
  532 wi_pci_plx_print_cis(struct wi_softc *sc)
  533 {
  534         int i, stringno;
  535         char cisbuf[CIS_INFO_SIZE];
  536         char *cis_strings[3];
  537         u_int8_t value;
  538         const u_int8_t cis_magic[] = {
  539                 0x01, 0x03, 0x00, 0x00, 0xff, 0x17, 0x04, 0x67
  540         };
  541 
  542         /* Make sure the CIS data is valid. */
  543         for (i = 0; i < 8; i++) {
  544                 value = bus_space_read_1(sc->wi_ltag, sc->wi_lhandle, i * 2);
  545                 if (value != cis_magic[i])
  546                         return;
  547         }
  548 
  549         cis_strings[0] = cisbuf;
  550         stringno = 0;
  551         for (i = 0; i < CIS_INFO_SIZE && stringno < 3; i++) {
  552                 cisbuf[i] = bus_space_read_1(sc->wi_ltag,
  553                     sc->wi_lhandle, (CIS_MFG_NAME_OFFSET + i) * 2);
  554                 if (cisbuf[i] == '\0' && ++stringno < 3)
  555                         cis_strings[stringno] = &cisbuf[i + 1];
  556         }
  557         cisbuf[CIS_INFO_SIZE - 1] = '\0';
  558         printf("\n%s: \"%s, %s, %s\"", WI_PRT_ARG(sc),
  559             cis_strings[0], cis_strings[1], cis_strings[2]);
  560 }

/* [<][>][^][v][top][bottom][index][help] */