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/mwl/if_mwl_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 /*-
    2  * Copyright (c) 2007-2009 Sam Leffler, Errno Consulting
    3  * Copyright (c) 2007-2009 Marvell Semiconductor, Inc.
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer,
   11  *    without modification.
   12  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   13  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
   14  *    redistribution must be conditioned upon including a substantially
   15  *    similar Disclaimer requirement for further binary redistribution.
   16  *
   17  * NO WARRANTY
   18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   20  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
   21  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
   22  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
   23  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
   26  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   28  * THE POSSIBILITY OF SUCH DAMAGES.
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 #ifdef __FreeBSD__
   33 __FBSDID("$FreeBSD: releng/9.2/sys/dev/mwl/if_mwl_pci.c 254364 2013-08-15 12:19:16Z scottl $");
   34 #endif
   35 
   36 /*
   37  * PCI front-end for the Marvell Wireless LAN controller driver.
   38  */
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h> 
   42 #include <sys/module.h>
   43 #include <sys/kernel.h>
   44 #include <sys/lock.h>
   45 #include <sys/mutex.h>
   46 #include <sys/errno.h>
   47 
   48 #include <machine/bus.h>
   49 #include <machine/resource.h>
   50 #include <sys/bus.h>
   51 #include <sys/rman.h>
   52 
   53 #include <sys/socket.h>
   54  
   55 #include <net/if.h>
   56 #include <net/if_media.h>
   57 #include <net/if_arp.h>
   58 
   59 #include <net80211/ieee80211_var.h>
   60 
   61 #include <dev/mwl/if_mwlvar.h>
   62 
   63 #include <dev/pci/pcivar.h>
   64 #include <dev/pci/pcireg.h>
   65 
   66 /*
   67  * PCI glue.
   68  */
   69 
   70 struct mwl_pci_softc {
   71         struct mwl_softc        sc_sc;
   72         struct resource         *sc_sr0;        /* BAR0 memory resource */
   73         struct resource         *sc_sr1;        /* BAR1 memory resource */
   74         struct resource         *sc_irq;        /* irq resource */
   75         void                    *sc_ih;         /* interrupt handler */
   76 };
   77 
   78 #define BS_BAR0 0x10
   79 #define BS_BAR1 0x14
   80 
   81 struct mwl_pci_ident {
   82         uint16_t        vendor;
   83         uint16_t        device;
   84         const char      *name;
   85 };
   86 
   87 static const struct mwl_pci_ident mwl_pci_ids[] = {
   88         { 0x11ab, 0x2a02, "Marvell 88W8363" },
   89         { 0x11ab, 0x2a03, "Marvell 88W8363" },
   90         { 0x11ab, 0x2a0a, "Marvell 88W8363" },
   91         { 0x11ab, 0x2a0b, "Marvell 88W8363" },
   92         { 0x11ab, 0x2a0c, "Marvell 88W8363" },
   93         { 0x11ab, 0x2a21, "Marvell 88W8363" },
   94         { 0x11ab, 0x2a24, "Marvell 88W8363" },
   95 
   96         { 0, 0, NULL }
   97 };
   98 
   99 const static struct mwl_pci_ident *
  100 mwl_pci_lookup(int vendor, int device)
  101 {
  102         const struct mwl_pci_ident *ident;
  103 
  104         for (ident = mwl_pci_ids; ident->name != NULL; ident++)
  105                 if (vendor == ident->vendor && device == ident->device)
  106                         return ident;
  107         return NULL;
  108 }
  109 
  110 static int
  111 mwl_pci_probe(device_t dev)
  112 {
  113         const struct mwl_pci_ident *ident;
  114 
  115         ident = mwl_pci_lookup(pci_get_vendor(dev), pci_get_device(dev));
  116         if (ident != NULL) {
  117                 device_set_desc(dev, ident->name);
  118                 return BUS_PROBE_DEFAULT;
  119         }
  120         return ENXIO;
  121 }
  122 
  123 static int
  124 mwl_pci_attach(device_t dev)
  125 {
  126         struct mwl_pci_softc *psc = device_get_softc(dev);
  127         struct mwl_softc *sc = &psc->sc_sc;
  128         int rid, error = ENXIO;
  129 
  130         sc->sc_dev = dev;
  131 
  132         pci_enable_busmaster(dev);
  133 
  134         /* 
  135          * Setup memory-mapping of PCI registers.
  136          */
  137         rid = BS_BAR0;
  138         psc->sc_sr0 = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  139                                             RF_ACTIVE);
  140         if (psc->sc_sr0 == NULL) {
  141                 device_printf(dev, "cannot map BAR0 register space\n");
  142                 goto bad;
  143         }
  144         rid = BS_BAR1;
  145         psc->sc_sr1 = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  146                                             RF_ACTIVE);
  147         if (psc->sc_sr1 == NULL) {
  148                 device_printf(dev, "cannot map BAR1 register space\n");
  149                 goto bad1;
  150         }
  151         sc->sc_invalid = 1;
  152 
  153         /*
  154          * Arrange interrupt line.
  155          */
  156         rid = 0;
  157         psc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
  158                                              RF_SHAREABLE|RF_ACTIVE);
  159         if (psc->sc_irq == NULL) {
  160                 device_printf(dev, "could not map interrupt\n");
  161                 goto bad2;
  162         }
  163         if (bus_setup_intr(dev, psc->sc_irq,
  164                            INTR_TYPE_NET | INTR_MPSAFE,
  165                            NULL, mwl_intr, sc, &psc->sc_ih)) {
  166                 device_printf(dev, "could not establish interrupt\n");
  167                 goto bad3;
  168         }
  169 
  170         /*
  171          * Setup DMA descriptor area.
  172          */
  173         if (bus_dma_tag_create(bus_get_dma_tag(dev),    /* parent */
  174                                1, 0,                    /* alignment, bounds */
  175                                BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
  176                                BUS_SPACE_MAXADDR,       /* highaddr */
  177                                NULL, NULL,              /* filter, filterarg */
  178                                BUS_SPACE_MAXADDR,       /* maxsize */
  179                                MWL_TXDESC,              /* nsegments */
  180                                BUS_SPACE_MAXADDR,       /* maxsegsize */
  181                                0,                       /* flags */
  182                                NULL,                    /* lockfunc */
  183                                NULL,                    /* lockarg */
  184                                &sc->sc_dmat)) {
  185                 device_printf(dev, "cannot allocate DMA tag\n");
  186                 goto bad4;
  187         }
  188 
  189         /*
  190          * Finish off the attach.
  191          */
  192         MWL_LOCK_INIT(sc);
  193         sc->sc_io0t = rman_get_bustag(psc->sc_sr0);
  194         sc->sc_io0h = rman_get_bushandle(psc->sc_sr0);
  195         sc->sc_io1t = rman_get_bustag(psc->sc_sr1);
  196         sc->sc_io1h = rman_get_bushandle(psc->sc_sr1);
  197         if (mwl_attach(pci_get_device(dev), sc) == 0)
  198                 return (0);
  199 
  200         MWL_LOCK_DESTROY(sc);
  201         bus_dma_tag_destroy(sc->sc_dmat);
  202 bad4:
  203         bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih);
  204 bad3:
  205         bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq);
  206 bad2:
  207         bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR1, psc->sc_sr1);
  208 bad1:
  209         bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR0, psc->sc_sr0);
  210 bad:
  211         return (error);
  212 }
  213 
  214 static int
  215 mwl_pci_detach(device_t dev)
  216 {
  217         struct mwl_pci_softc *psc = device_get_softc(dev);
  218         struct mwl_softc *sc = &psc->sc_sc;
  219 
  220         /* check if device was removed */
  221         sc->sc_invalid = !bus_child_present(dev);
  222 
  223         mwl_detach(sc);
  224 
  225         bus_generic_detach(dev);
  226         bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih);
  227         bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq);
  228 
  229         bus_dma_tag_destroy(sc->sc_dmat);
  230         bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR1, psc->sc_sr1);
  231         bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR0, psc->sc_sr0);
  232 
  233         MWL_LOCK_DESTROY(sc);
  234 
  235         return (0);
  236 }
  237 
  238 static int
  239 mwl_pci_shutdown(device_t dev)
  240 {
  241         struct mwl_pci_softc *psc = device_get_softc(dev);
  242 
  243         mwl_shutdown(&psc->sc_sc);
  244         return (0);
  245 }
  246 
  247 static int
  248 mwl_pci_suspend(device_t dev)
  249 {
  250         struct mwl_pci_softc *psc = device_get_softc(dev);
  251 
  252         mwl_suspend(&psc->sc_sc);
  253 
  254         return (0);
  255 }
  256 
  257 static int
  258 mwl_pci_resume(device_t dev)
  259 {
  260         struct mwl_pci_softc *psc = device_get_softc(dev);
  261 
  262         pci_enable_busmaster(dev);
  263 
  264         mwl_resume(&psc->sc_sc);
  265 
  266         return (0);
  267 }
  268 
  269 static device_method_t mwl_pci_methods[] = {
  270         /* Device interface */
  271         DEVMETHOD(device_probe,         mwl_pci_probe),
  272         DEVMETHOD(device_attach,        mwl_pci_attach),
  273         DEVMETHOD(device_detach,        mwl_pci_detach),
  274         DEVMETHOD(device_shutdown,      mwl_pci_shutdown),
  275         DEVMETHOD(device_suspend,       mwl_pci_suspend),
  276         DEVMETHOD(device_resume,        mwl_pci_resume),
  277 
  278         { 0,0 }
  279 };
  280 static driver_t mwl_pci_driver = {
  281         "mwl",
  282         mwl_pci_methods,
  283         sizeof (struct mwl_pci_softc)
  284 };
  285 static  devclass_t mwl_devclass;
  286 DRIVER_MODULE(mwl, pci, mwl_pci_driver, mwl_devclass, 0, 0);
  287 MODULE_VERSION(mwl, 1);
  288 MODULE_DEPEND(mwl, wlan, 1, 1, 1);              /* 802.11 media layer */
  289 MODULE_DEPEND(mwl, firmware, 1, 1, 1);

Cache object: 3ed8eeb6c9762c25fb42610ece48a3df


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