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/8.2/sys/dev/mwl/if_mwl_pci.c 212818 2010-09-18 08:23:45Z bschmidt $");
   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 u_int32_t
  124 mwl_pci_setup(device_t dev)
  125 {
  126         u_int32_t cmd;
  127 
  128         /*
  129          * Enable memory mapping and bus mastering.
  130          */
  131         cmd = pci_read_config(dev, PCIR_COMMAND, 4);
  132         cmd |= PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN;
  133         pci_write_config(dev, PCIR_COMMAND, cmd, 4);
  134         cmd = pci_read_config(dev, PCIR_COMMAND, 4);
  135         if ((cmd & PCIM_CMD_MEMEN) == 0) {
  136                 device_printf(dev, "failed to enable memory mapping\n");
  137                 return 0;
  138         }
  139         if ((cmd & PCIM_CMD_BUSMASTEREN) == 0) {
  140                 device_printf(dev, "failed to enable bus mastering\n");
  141                 return 0;
  142         }
  143         return 1;
  144 }
  145 
  146 static int
  147 mwl_pci_attach(device_t dev)
  148 {
  149         struct mwl_pci_softc *psc = device_get_softc(dev);
  150         struct mwl_softc *sc = &psc->sc_sc;
  151         int rid, error = ENXIO;
  152 
  153         sc->sc_dev = dev;
  154 
  155         /*
  156          * Enable memory mapping and bus mastering.
  157          */
  158         if (!mwl_pci_setup(dev))
  159                 return 0;
  160         /* 
  161          * Setup memory-mapping of PCI registers.
  162          */
  163         rid = BS_BAR0;
  164         psc->sc_sr0 = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  165                                             RF_ACTIVE);
  166         if (psc->sc_sr0 == NULL) {
  167                 device_printf(dev, "cannot map BAR0 register space\n");
  168                 goto bad;
  169         }
  170         rid = BS_BAR1;
  171         psc->sc_sr1 = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  172                                             RF_ACTIVE);
  173         if (psc->sc_sr1 == NULL) {
  174                 device_printf(dev, "cannot map BAR1 register space\n");
  175                 goto bad1;
  176         }
  177         sc->sc_invalid = 1;
  178 
  179         /*
  180          * Arrange interrupt line.
  181          */
  182         rid = 0;
  183         psc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
  184                                              RF_SHAREABLE|RF_ACTIVE);
  185         if (psc->sc_irq == NULL) {
  186                 device_printf(dev, "could not map interrupt\n");
  187                 goto bad2;
  188         }
  189         if (bus_setup_intr(dev, psc->sc_irq,
  190                            INTR_TYPE_NET | INTR_MPSAFE,
  191                            NULL, mwl_intr, sc, &psc->sc_ih)) {
  192                 device_printf(dev, "could not establish interrupt\n");
  193                 goto bad3;
  194         }
  195 
  196         /*
  197          * Setup DMA descriptor area.
  198          */
  199         if (bus_dma_tag_create(bus_get_dma_tag(dev),    /* parent */
  200                                1, 0,                    /* alignment, bounds */
  201                                BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
  202                                BUS_SPACE_MAXADDR,       /* highaddr */
  203                                NULL, NULL,              /* filter, filterarg */
  204                                BUS_SPACE_MAXADDR,       /* maxsize */
  205                                MWL_TXDESC,              /* nsegments */
  206                                BUS_SPACE_MAXADDR,       /* maxsegsize */
  207                                0,                       /* flags */
  208                                NULL,                    /* lockfunc */
  209                                NULL,                    /* lockarg */
  210                                &sc->sc_dmat)) {
  211                 device_printf(dev, "cannot allocate DMA tag\n");
  212                 goto bad4;
  213         }
  214 
  215         /*
  216          * Finish off the attach.
  217          */
  218         MWL_LOCK_INIT(sc);
  219         sc->sc_io0t = rman_get_bustag(psc->sc_sr0);
  220         sc->sc_io0h = rman_get_bushandle(psc->sc_sr0);
  221         sc->sc_io1t = rman_get_bustag(psc->sc_sr1);
  222         sc->sc_io1h = rman_get_bushandle(psc->sc_sr1);
  223         if (mwl_attach(pci_get_device(dev), sc) == 0)
  224                 return (0);
  225 
  226         MWL_LOCK_DESTROY(sc);
  227         bus_dma_tag_destroy(sc->sc_dmat);
  228 bad4:
  229         bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih);
  230 bad3:
  231         bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq);
  232 bad2:
  233         bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR1, psc->sc_sr1);
  234 bad1:
  235         bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR0, psc->sc_sr0);
  236 bad:
  237         return (error);
  238 }
  239 
  240 static int
  241 mwl_pci_detach(device_t dev)
  242 {
  243         struct mwl_pci_softc *psc = device_get_softc(dev);
  244         struct mwl_softc *sc = &psc->sc_sc;
  245 
  246         /* check if device was removed */
  247         sc->sc_invalid = !bus_child_present(dev);
  248 
  249         mwl_detach(sc);
  250 
  251         bus_generic_detach(dev);
  252         bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih);
  253         bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq);
  254 
  255         bus_dma_tag_destroy(sc->sc_dmat);
  256         bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR1, psc->sc_sr1);
  257         bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR0, psc->sc_sr0);
  258 
  259         MWL_LOCK_DESTROY(sc);
  260 
  261         return (0);
  262 }
  263 
  264 static int
  265 mwl_pci_shutdown(device_t dev)
  266 {
  267         struct mwl_pci_softc *psc = device_get_softc(dev);
  268 
  269         mwl_shutdown(&psc->sc_sc);
  270         return (0);
  271 }
  272 
  273 static int
  274 mwl_pci_suspend(device_t dev)
  275 {
  276         struct mwl_pci_softc *psc = device_get_softc(dev);
  277 
  278         mwl_suspend(&psc->sc_sc);
  279 
  280         return (0);
  281 }
  282 
  283 static int
  284 mwl_pci_resume(device_t dev)
  285 {
  286         struct mwl_pci_softc *psc = device_get_softc(dev);
  287 
  288         if (!mwl_pci_setup(dev))
  289                 return ENXIO;
  290 
  291         mwl_resume(&psc->sc_sc);
  292 
  293         return (0);
  294 }
  295 
  296 static device_method_t mwl_pci_methods[] = {
  297         /* Device interface */
  298         DEVMETHOD(device_probe,         mwl_pci_probe),
  299         DEVMETHOD(device_attach,        mwl_pci_attach),
  300         DEVMETHOD(device_detach,        mwl_pci_detach),
  301         DEVMETHOD(device_shutdown,      mwl_pci_shutdown),
  302         DEVMETHOD(device_suspend,       mwl_pci_suspend),
  303         DEVMETHOD(device_resume,        mwl_pci_resume),
  304 
  305         { 0,0 }
  306 };
  307 static driver_t mwl_pci_driver = {
  308         "mwl",
  309         mwl_pci_methods,
  310         sizeof (struct mwl_pci_softc)
  311 };
  312 static  devclass_t mwl_devclass;
  313 DRIVER_MODULE(mwl, pci, mwl_pci_driver, mwl_devclass, 0, 0);
  314 MODULE_VERSION(mwl, 1);
  315 MODULE_DEPEND(mwl, wlan, 1, 1, 1);              /* 802.11 media layer */
  316 MODULE_DEPEND(mwl, firmware, 1, 1, 1);

Cache object: 29df45600386afe1c9dffdf8398c47d7


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