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/cardbus/if_atw_cardbus.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: if_atw_cardbus.c,v 1.6 2004/02/17 21:20:55 dyoung Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 1999, 2000, 2003 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
    9  * NASA Ames Research Center.  This code was adapted for the ADMtek ADM8211
   10  * by David Young.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *      This product includes software developed by the NetBSD
   23  *      Foundation, Inc. and its contributors.
   24  * 4. Neither the name of The NetBSD Foundation nor the names of its
   25  *    contributors may be used to endorse or promote products derived
   26  *    from this software without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   38  * POSSIBILITY OF SUCH DAMAGE.
   39  */
   40 
   41 /*
   42  * CardBus bus front-end for the ADMtek ADM8211 802.11 MAC/BBP driver.
   43  */
   44 
   45 #include <sys/cdefs.h>
   46 __KERNEL_RCSID(0, "$NetBSD: if_atw_cardbus.c,v 1.6 2004/02/17 21:20:55 dyoung Exp $");
   47 
   48 #include "opt_inet.h"
   49 #include "opt_ns.h"
   50 #include "bpfilter.h"
   51 
   52 #include <sys/param.h>
   53 #include <sys/systm.h> 
   54 #include <sys/mbuf.h>   
   55 #include <sys/malloc.h>
   56 #include <sys/kernel.h>
   57 #include <sys/socket.h>
   58 #include <sys/ioctl.h>
   59 #include <sys/errno.h>
   60 #include <sys/device.h>
   61 
   62 #include <machine/endian.h>
   63  
   64 #include <net/if.h>
   65 #include <net/if_dl.h>
   66 #include <net/if_media.h>
   67 #include <net/if_ether.h>
   68 
   69 #include <net80211/ieee80211_compat.h>
   70 #include <net80211/ieee80211_radiotap.h>
   71 #include <net80211/ieee80211_var.h>
   72 
   73 #if NBPFILTER > 0 
   74 #include <net/bpf.h>
   75 #endif 
   76 
   77 #ifdef INET
   78 #include <netinet/in.h> 
   79 #include <netinet/if_inarp.h>
   80 #endif
   81 
   82 #ifdef NS
   83 #include <netns/ns.h>
   84 #include <netns/ns_if.h>
   85 #endif
   86 
   87 #include <machine/bus.h>
   88 #include <machine/intr.h>
   89 
   90 #include <dev/ic/atwreg.h>
   91 #include <dev/ic/rf3000reg.h>
   92 #include <dev/ic/si4136reg.h>
   93 #include <dev/ic/atwvar.h>
   94 
   95 #include <dev/pci/pcivar.h>
   96 #include <dev/pci/pcireg.h>
   97 #include <dev/pci/pcidevs.h>
   98 
   99 #include <dev/cardbus/cardbusvar.h>
  100 #include <dev/cardbus/cardbusdevs.h>
  101 
  102 /*
  103  * PCI configuration space registers used by the ADM8211.
  104  */
  105 #define ATW_PCI_IOBA            0x10    /* i/o mapped base */
  106 #define ATW_PCI_MMBA            0x14    /* memory mapped base */
  107 
  108 struct atw_cardbus_softc {
  109         struct atw_softc sc_atw;        /* real ADM8211 softc */
  110 
  111         /* CardBus-specific goo. */
  112         void    *sc_ih;                 /* interrupt handle */
  113         cardbus_devfunc_t sc_ct;        /* our CardBus devfuncs */
  114         cardbustag_t sc_tag;            /* our CardBus tag */
  115         int     sc_csr;                 /* CSR bits */
  116         bus_size_t sc_mapsize;          /* the size of mapped bus space
  117                                            region */
  118 
  119         int     sc_cben;                /* CardBus enables */
  120         int     sc_bar_reg;             /* which BAR to use */
  121         pcireg_t sc_bar_val;            /* value of the BAR */
  122 
  123         int     sc_intrline;            /* interrupt line */
  124 };
  125 
  126 int     atw_cardbus_match(struct device *, struct cfdata *, void *);
  127 void    atw_cardbus_attach(struct device *, struct device *, void *);
  128 int     atw_cardbus_detach(struct device *, int);
  129 
  130 CFATTACH_DECL(atw_cardbus, sizeof(struct atw_cardbus_softc),
  131     atw_cardbus_match, atw_cardbus_attach, atw_cardbus_detach, atw_activate);
  132 
  133 void    atw_cardbus_setup(struct atw_cardbus_softc *);
  134 
  135 int     atw_cardbus_enable(struct atw_softc *);
  136 void    atw_cardbus_disable(struct atw_softc *);
  137 void    atw_cardbus_power(struct atw_softc *, int);
  138 
  139 static void atw_cardbus_intr_ack(struct atw_softc *);
  140 
  141 const struct atw_cardbus_product *atw_cardbus_lookup
  142    (const struct cardbus_attach_args *);
  143 
  144 const struct atw_cardbus_product {
  145         u_int32_t        acp_vendor;    /* PCI vendor ID */
  146         u_int32_t        acp_product;   /* PCI product ID */
  147         const char      *acp_product_name;
  148 } atw_cardbus_products[] = {
  149         { PCI_VENDOR_ADMTEK,            PCI_PRODUCT_ADMTEK_ADM8211,
  150           "ADMtek ADM8211 802.11 MAC/BBP" },
  151 
  152         { 0,                            0,      NULL },
  153 };
  154 
  155 const struct atw_cardbus_product *
  156 atw_cardbus_lookup(const struct cardbus_attach_args *ca)
  157 {
  158         const struct atw_cardbus_product *acp;
  159 
  160         for (acp = atw_cardbus_products;
  161              acp->acp_product_name != NULL;
  162              acp++) {
  163                 if (PCI_VENDOR(ca->ca_id) == acp->acp_vendor &&
  164                     PCI_PRODUCT(ca->ca_id) == acp->acp_product)
  165                         return (acp);
  166         }
  167         return (NULL);
  168 }
  169 
  170 int
  171 atw_cardbus_match(struct device *parent, struct cfdata *match, void *aux)
  172 {
  173         struct cardbus_attach_args *ca = aux;
  174 
  175         if (atw_cardbus_lookup(ca) != NULL)
  176                 return (1);
  177 
  178         return (0);
  179 }
  180 
  181 void
  182 atw_cardbus_attach(struct device *parent, struct device *self, void *aux)
  183 {
  184         struct atw_cardbus_softc *csc = (void *)self;
  185         struct atw_softc *sc = &csc->sc_atw;
  186         struct cardbus_attach_args *ca = aux;
  187         cardbus_devfunc_t ct = ca->ca_ct;
  188         const struct atw_cardbus_product *acp;
  189         bus_addr_t adr;
  190         int rev;
  191 
  192         sc->sc_dmat = ca->ca_dmat;
  193         csc->sc_ct = ct;
  194         csc->sc_tag = ca->ca_tag;
  195 
  196         acp = atw_cardbus_lookup(ca);
  197         if (acp == NULL) {
  198                 printf("\n");
  199                 panic("atw_cardbus_attach: impossible");
  200         }
  201 
  202         /*
  203          * Power management hooks.
  204          */
  205         sc->sc_enable = atw_cardbus_enable;
  206         sc->sc_disable = atw_cardbus_disable;
  207         sc->sc_power = atw_cardbus_power;
  208 
  209         sc->sc_intr_ack = atw_cardbus_intr_ack;
  210 
  211         /* Get revision info. */
  212         rev = PCI_REVISION(ca->ca_class);
  213 
  214         printf(": %s\n", acp->acp_product_name);
  215 
  216 #if 0
  217         printf("%s: pass %d.%d signature %08x\n", sc->sc_dev.dv_xname,
  218             (rev >> 4) & 0xf, rev & 0xf,
  219             cardbus_conf_read(ct->ct_cc, ct->ct_cf, csc->sc_tag, 0x80));
  220 #endif
  221 
  222         /*
  223          * Map the device.
  224          */
  225         csc->sc_csr = CARDBUS_COMMAND_MASTER_ENABLE;
  226         if (Cardbus_mapreg_map(ct, ATW_PCI_MMBA,
  227             CARDBUS_MAPREG_TYPE_MEM, 0, &sc->sc_st, &sc->sc_sh, &adr,
  228             &csc->sc_mapsize) == 0) {
  229 #if 0
  230                 printf("%s: atw_cardbus_attach mapped %d bytes mem space\n",
  231                     sc->sc_dev.dv_xname, csc->sc_mapsize);
  232 #endif
  233 #if rbus
  234 #else
  235                 (*ct->ct_cf->cardbus_mem_open)(cc, 0, adr, adr+csc->sc_mapsize);
  236 #endif
  237                 csc->sc_cben = CARDBUS_MEM_ENABLE;
  238                 csc->sc_csr |= CARDBUS_COMMAND_MEM_ENABLE;
  239                 csc->sc_bar_reg = ATW_PCI_MMBA;
  240                 csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_MEM;
  241         } else if (Cardbus_mapreg_map(ct, ATW_PCI_IOBA,
  242             CARDBUS_MAPREG_TYPE_IO, 0, &sc->sc_st, &sc->sc_sh, &adr,
  243             &csc->sc_mapsize) == 0) {
  244 #if 0
  245                 printf("%s: atw_cardbus_attach mapped %d bytes I/O space\n",
  246                     sc->sc_dev.dv_xname, csc->sc_mapsize);
  247 #endif
  248 #if rbus
  249 #else
  250                 (*ct->ct_cf->cardbus_io_open)(cc, 0, adr, adr+csc->sc_mapsize);
  251 #endif
  252                 csc->sc_cben = CARDBUS_IO_ENABLE;
  253                 csc->sc_csr |= CARDBUS_COMMAND_IO_ENABLE;
  254                 csc->sc_bar_reg = ATW_PCI_IOBA;
  255                 csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_IO;
  256         } else {
  257                 printf("%s: unable to map device registers\n",
  258                     sc->sc_dev.dv_xname);
  259                 return;
  260         }
  261 
  262         /*
  263          * Bring the chip out of powersave mode and initialize the
  264          * configuration registers.
  265          */
  266         atw_cardbus_setup(csc);
  267 
  268         /* Remember which interrupt line. */
  269         csc->sc_intrline = ca->ca_intrline;
  270 
  271         printf("%s: interrupting at %d\n", sc->sc_dev.dv_xname,
  272             csc->sc_intrline);
  273 #if 0
  274         /*
  275          * The CardBus cards will make it to store-and-forward mode as
  276          * soon as you put them under any kind of load, so just start
  277          * out there.
  278          */
  279         sc->sc_txthresh = 3; /* TBD name constant */
  280 #endif
  281 
  282         /*
  283          * Finish off the attach.
  284          */
  285         atw_attach(sc);
  286 
  287         ATW_WRITE(sc, ATW_FER, ATW_FER_INTR);
  288 
  289         /*
  290          * Power down the socket.
  291          */
  292         Cardbus_function_disable(csc->sc_ct);
  293 }
  294 
  295 static void
  296 atw_cardbus_intr_ack(struct atw_softc *sc)
  297 {
  298         ATW_WRITE(sc, ATW_FER, ATW_FER_INTR);
  299 }
  300 
  301 int
  302 atw_cardbus_detach(struct device *self, int flags)
  303 {
  304         struct atw_cardbus_softc *csc = (void *)self;
  305         struct atw_softc *sc = &csc->sc_atw;
  306         struct cardbus_devfunc *ct = csc->sc_ct;
  307         int rv;
  308 
  309 #if defined(DIAGNOSTIC)
  310         if (ct == NULL)
  311                 panic("%s: data structure lacks", sc->sc_dev.dv_xname);
  312 #endif
  313 
  314         rv = atw_detach(sc);
  315         if (rv)
  316                 return (rv);
  317 
  318         /*
  319          * Unhook the interrupt handler.
  320          */
  321         if (csc->sc_ih != NULL)
  322                 cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);
  323 
  324         /*
  325          * Release bus space and close window.
  326          */
  327         if (csc->sc_bar_reg != 0)
  328                 Cardbus_mapreg_unmap(ct, csc->sc_bar_reg,
  329                     sc->sc_st, sc->sc_sh, csc->sc_mapsize);
  330 
  331         return (0);
  332 }
  333 
  334 int
  335 atw_cardbus_enable(struct atw_softc *sc)
  336 {
  337         struct atw_cardbus_softc *csc = (void *) sc;
  338         cardbus_devfunc_t ct = csc->sc_ct;
  339         cardbus_chipset_tag_t cc = ct->ct_cc;
  340         cardbus_function_tag_t cf = ct->ct_cf;
  341 
  342         /*
  343          * Power on the socket.
  344          */
  345         Cardbus_function_enable(ct);
  346 
  347         /*
  348          * Set up the PCI configuration registers.
  349          */
  350         atw_cardbus_setup(csc);
  351 
  352         /*
  353          * Map and establish the interrupt.
  354          */
  355         csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
  356             atw_intr, sc);
  357         if (csc->sc_ih == NULL) {
  358                 printf("%s: unable to establish interrupt at %d\n",
  359                     sc->sc_dev.dv_xname, csc->sc_intrline);
  360                 Cardbus_function_disable(csc->sc_ct);
  361                 return (1);
  362         }
  363 
  364         return (0);
  365 }
  366 
  367 void
  368 atw_cardbus_disable(struct atw_softc *sc)
  369 {
  370         struct atw_cardbus_softc *csc = (void *) sc;
  371         cardbus_devfunc_t ct = csc->sc_ct;
  372         cardbus_chipset_tag_t cc = ct->ct_cc;
  373         cardbus_function_tag_t cf = ct->ct_cf;
  374 
  375         /* Unhook the interrupt handler. */
  376         cardbus_intr_disestablish(cc, cf, csc->sc_ih);
  377         csc->sc_ih = NULL;
  378 
  379         /* Power down the socket. */
  380         Cardbus_function_disable(ct);
  381 }
  382 
  383 void
  384 atw_cardbus_power(struct atw_softc *sc, int why)
  385 {
  386         struct atw_cardbus_softc *csc = (void *) sc;
  387 
  388         printf("%s: atw_cardbus_power\n", sc->sc_dev.dv_xname);
  389 
  390         if (why == PWR_RESUME) {
  391                 /*
  392                  * Give the PCI configuration registers a kick
  393                  * in the head.
  394                  */
  395 #ifdef DIAGNOSTIC
  396                 if (ATW_IS_ENABLED(sc) == 0)
  397                         panic("atw_cardbus_power");
  398 #endif
  399                 atw_cardbus_setup(csc);
  400         }
  401 }
  402 
  403 void
  404 atw_cardbus_setup(struct atw_cardbus_softc *csc)
  405 {
  406         struct atw_softc *sc = &csc->sc_atw;
  407         cardbus_devfunc_t ct = csc->sc_ct;
  408         cardbus_chipset_tag_t cc = ct->ct_cc;
  409         cardbus_function_tag_t cf = ct->ct_cf;
  410         pcireg_t reg;
  411         int pmreg;
  412 
  413         if (cardbus_get_capability(cc, cf, csc->sc_tag,
  414             PCI_CAP_PWRMGMT, &pmreg, 0)) {
  415                 reg = cardbus_conf_read(cc, cf, csc->sc_tag, pmreg + 4) & 0x03;
  416 #if 1 /* XXX Probably not right for CardBus. */
  417                 if (reg == 3) {
  418                         /*
  419                          * The card has lost all configuration data in
  420                          * this state, so punt.
  421                          */
  422                         printf("%s: unable to wake up from power state D3\n",
  423                             sc->sc_dev.dv_xname);
  424                         return;
  425                 }
  426 #endif
  427                 if (reg != 0) {
  428                         printf("%s: waking up from power state D%d\n",
  429                             sc->sc_dev.dv_xname, reg);
  430                         cardbus_conf_write(cc, cf, csc->sc_tag,
  431                             pmreg + 4, 0);
  432                 }
  433         }
  434 
  435         /* Make sure the right access type is on the CardBus bridge. */
  436         (*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben);
  437         (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
  438 
  439         /* Program the BAR. */
  440         cardbus_conf_write(cc, cf, csc->sc_tag, csc->sc_bar_reg,
  441             csc->sc_bar_val);
  442 
  443         /* Enable the appropriate bits in the PCI CSR. */
  444         reg = cardbus_conf_read(cc, cf, csc->sc_tag,
  445             CARDBUS_COMMAND_STATUS_REG);
  446         reg &= ~(CARDBUS_COMMAND_IO_ENABLE|CARDBUS_COMMAND_MEM_ENABLE);
  447         reg |= csc->sc_csr;
  448         cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_COMMAND_STATUS_REG,
  449             reg);
  450 
  451         /*
  452          * Make sure the latency timer is set to some reasonable
  453          * value.
  454          */
  455         reg = cardbus_conf_read(cc, cf, csc->sc_tag, CARDBUS_BHLC_REG);
  456         if (CARDBUS_LATTIMER(reg) < 0x20) {
  457                 reg &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT);
  458                 reg |= (0x20 << CARDBUS_LATTIMER_SHIFT);
  459                 cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_BHLC_REG, reg);
  460         }
  461 }

Cache object: 532bbcd539208be2e697e6c363b8a267


[ 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.