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/netif/ndis/if_ndis_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) 2003
    3  *      Bill Paul <wpaul@windriver.com>.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *      This product includes software developed by Bill Paul.
   16  * 4. Neither the name of the author nor the names of any co-contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
   24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   30  * THE POSSIBILITY OF SUCH DAMAGE.
   31  *
   32  * $FreeBSD: src/sys/dev/if_ndis/if_ndis_pci.c,v 1.26 2010/12/19 11:14:34 tijl Exp $
   33  */
   34 
   35 #include "use_usb4bsd.h"
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/kernel.h>
   40 #include <sys/module.h>
   41 #include <sys/socket.h>
   42 #include <sys/queue.h>
   43 #include <sys/sysctl.h>
   44 #include <sys/lock.h>
   45 
   46 #include <net/if.h>
   47 #include <net/if_arp.h>
   48 #include <net/if_media.h>
   49 
   50 #include <sys/bus.h>
   51 #include <sys/rman.h>
   52 
   53 #include <netproto/802_11/ieee80211_var.h>
   54 
   55 #include <bus/pci/pcireg.h>
   56 #include <bus/pci/pcivar.h>
   57 #if NUSB4BSD > 0
   58 #include <bus/u4b/usb.h>
   59 #include <bus/u4b/usbdi.h>
   60 #else
   61 #include <bus/usb/usb.h>
   62 #include <bus/usb/usbdi.h>
   63 #endif
   64 
   65 #include <emulation/ndis/pe_var.h>
   66 #include <emulation/ndis/cfg_var.h>
   67 #include <emulation/ndis/resource_var.h>
   68 #include <emulation/ndis/ntoskrnl_var.h>
   69 #include <emulation/ndis/ndis_var.h>
   70 #include <dev/netif/ndis/if_ndisvar.h>
   71 
   72 MODULE_DEPEND(if_ndis, pci, 1, 1, 1);
   73 
   74 static int ndis_probe_pci       (device_t);
   75 static int ndis_attach_pci      (device_t);
   76 static int ndis_detach_pci      (device_t);
   77 static struct resource_list *ndis_get_resource_list
   78                                 (device_t, device_t);
   79 static int ndis_devcompare      (interface_type,
   80                                  struct ndis_pci_type *, device_t);
   81 extern int ndisdrv_modevent     (module_t, int, void *);
   82 extern int ndis_attach          (device_t);
   83 extern int ndis_shutdown        (device_t);
   84 extern int ndis_detach          (device_t);
   85 extern int ndis_suspend         (device_t);
   86 extern int ndis_resume          (device_t);
   87 
   88 static device_method_t ndis_methods[] = {
   89         /* Device interface */
   90         DEVMETHOD(device_probe,         ndis_probe_pci),
   91         DEVMETHOD(device_attach,        ndis_attach_pci),
   92         DEVMETHOD(device_detach,        ndis_detach_pci),
   93         DEVMETHOD(device_shutdown,      ndis_shutdown),
   94         DEVMETHOD(device_suspend,       ndis_suspend),
   95         DEVMETHOD(device_resume,        ndis_resume),
   96 
   97         /* Bus interface */
   98         DEVMETHOD(bus_get_resource_list, ndis_get_resource_list),
   99 
  100         DEVMETHOD_END
  101 };
  102 
  103 static driver_t ndis_driver = {
  104         "ndis",
  105         ndis_methods,
  106         sizeof(struct ndis_softc)
  107 };
  108 
  109 static devclass_t ndis_devclass;
  110 
  111 DRIVER_MODULE(if_ndis, pci, ndis_driver, ndis_devclass, ndisdrv_modevent, NULL);
  112 DRIVER_MODULE(if_ndis, cardbus, ndis_driver, ndis_devclass, ndisdrv_modevent, NULL);
  113 
  114 static int
  115 ndis_devcompare(interface_type bustype, struct ndis_pci_type *t, device_t dev)
  116 {
  117         uint16_t                vid, did;
  118         uint32_t                subsys;
  119 
  120         if (bustype != PCIBus)
  121                 return(FALSE);
  122 
  123         vid = pci_get_vendor(dev);
  124         did = pci_get_device(dev);
  125         subsys = pci_get_subdevice(dev);
  126         subsys = (subsys << 16) | pci_get_subvendor(dev);
  127 
  128         while(t->ndis_name != NULL) {
  129                 if ((t->ndis_vid == vid) && (t->ndis_did == did) &&
  130                     (t->ndis_subsys == subsys || t->ndis_subsys == 0)) {
  131                         device_set_desc(dev, t->ndis_name);
  132                         return(TRUE);
  133                 }
  134                 t++;
  135         }
  136 
  137         return(FALSE);
  138 }
  139 
  140 /*
  141  * Probe for an NDIS device. Check the PCI vendor and device
  142  * IDs against our list and return a device name if we find a match.
  143  */
  144 static int
  145 ndis_probe_pci(device_t dev)
  146 {
  147         driver_object           *drv;
  148         struct drvdb_ent        *db;
  149 
  150         drv = windrv_lookup(0, "PCI Bus");
  151 
  152         if (drv == NULL)
  153                 return(ENXIO);
  154 
  155         db = windrv_match((matchfuncptr)ndis_devcompare, dev);
  156 
  157         if (db != NULL) {
  158                 /* Create PDO for this device instance */
  159                 windrv_create_pdo(drv, dev);
  160                 return(0);
  161         }
  162 
  163         return(ENXIO);
  164 }
  165 
  166 /*
  167  * Attach the interface. Allocate softc structures, do ifmedia
  168  * setup and ethernet/BPF attach.
  169  */
  170 static int
  171 ndis_attach_pci(device_t dev)
  172 {
  173         struct ndis_softc       *sc;
  174         int                     error = 0, rid;
  175         struct ndis_pci_type    *t;
  176         int                     devidx = 0, defidx = 0;
  177         struct resource_list    *rl;
  178         struct resource_list_entry      *rle;
  179         struct drvdb_ent        *db;
  180         uint16_t                vid, did;
  181         uint32_t                subsys;
  182 
  183         wlan_serialize_enter();
  184 
  185         sc = device_get_softc(dev);
  186         sc->ndis_dev = dev;
  187 
  188         db = windrv_match((matchfuncptr)ndis_devcompare, dev);
  189         if (db == NULL) {
  190                 wlan_serialize_exit();
  191                 return (ENXIO);
  192         }
  193         sc->ndis_dobj = db->windrv_object;
  194         sc->ndis_regvals = db->windrv_regvals;
  195 
  196         /*
  197          * Map control/status registers.
  198          */
  199 
  200         pci_enable_busmaster(dev);
  201 
  202         rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
  203         if (rl != NULL) {
  204                 SLIST_FOREACH(rle, rl, link) {
  205                         switch (rle->type) {
  206                         case SYS_RES_IOPORT:
  207                                 sc->ndis_io_rid = rle->rid;
  208                                 sc->ndis_res_io = bus_alloc_resource_any(dev,
  209                                     SYS_RES_IOPORT, &sc->ndis_io_rid,
  210                                     RF_ACTIVE);
  211                                 if (sc->ndis_res_io == NULL) {
  212                                         device_printf(dev,
  213                                             "couldn't map iospace\n");
  214                                         error = ENXIO;
  215                                         goto fail;
  216                                 }
  217                                 break;
  218                         case SYS_RES_MEMORY:
  219                                 if (sc->ndis_res_altmem != NULL &&
  220                                     sc->ndis_res_mem != NULL) {
  221                                         device_printf(dev,
  222                                             "too many memory resources\n");
  223                                         error = ENXIO;
  224                                         goto fail;
  225                                 }
  226                                 if (sc->ndis_res_mem) {
  227                                         sc->ndis_altmem_rid = rle->rid;
  228                                         sc->ndis_res_altmem =
  229                                             bus_alloc_resource_any(dev,
  230                                                 SYS_RES_MEMORY,
  231                                                 &sc->ndis_altmem_rid,
  232                                                 RF_ACTIVE);
  233                                         if (sc->ndis_res_altmem == NULL) {
  234                                                 device_printf(dev,
  235                                                     "couldn't map alt "
  236                                                     "memory\n");
  237                                                 error = ENXIO;
  238                                                 goto fail;
  239                                         }
  240                                 } else {
  241                                         sc->ndis_mem_rid = rle->rid;
  242                                         sc->ndis_res_mem =
  243                                             bus_alloc_resource_any(dev,
  244                                                 SYS_RES_MEMORY,
  245                                                 &sc->ndis_mem_rid,
  246                                                 RF_ACTIVE);
  247                                         if (sc->ndis_res_mem == NULL) {
  248                                                 device_printf(dev,
  249                                                     "couldn't map memory\n");
  250                                                 error = ENXIO;
  251                                                 goto fail;
  252                                         }
  253                                 }
  254                                 break;
  255                         case SYS_RES_IRQ:
  256                                 rid = rle->rid;
  257                                 sc->ndis_irq = bus_alloc_resource_any(dev,
  258                                     SYS_RES_IRQ, &rid,
  259                                     RF_SHAREABLE | RF_ACTIVE);
  260                                 if (sc->ndis_irq == NULL) {
  261                                         device_printf(dev,
  262                                             "couldn't map interrupt\n");
  263                                         error = ENXIO;
  264                                         goto fail;
  265                                 }
  266                                 break;
  267                         default:
  268                                 break;
  269                         }
  270                         sc->ndis_rescnt++;
  271                 }
  272         }
  273 
  274         /*
  275          * If the BIOS did not set up an interrupt for this device,
  276          * the resource traversal code above will fail to set up
  277          * an IRQ resource. This is usually a bad thing, so try to
  278          * force the allocation of an interrupt here. If one was
  279          * not assigned to us by the BIOS, bus_alloc_resource()
  280          * should route one for us.
  281          */
  282         if (sc->ndis_irq == NULL) {
  283                 rid = 0;
  284                 sc->ndis_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
  285                     &rid, RF_SHAREABLE | RF_ACTIVE);
  286                 if (sc->ndis_irq == NULL) {
  287                         device_printf(dev, "couldn't route interrupt\n");
  288                         error = ENXIO;
  289                         goto fail;
  290                 }
  291                 sc->ndis_rescnt++;
  292         }
  293 
  294         /*
  295          * Allocate the parent bus DMA tag appropriate for PCI.
  296          */
  297 #define NDIS_NSEG_NEW 32
  298         error = bus_dma_tag_create(NULL,        /* parent */
  299                         1, 0,                   /* alignment, boundary */
  300                         BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
  301                         BUS_SPACE_MAXADDR,      /* highaddr */
  302                         NULL, NULL,             /* filter, filterarg */
  303                         MAXBSIZE, NDIS_NSEG_NEW,/* maxsize, nsegments */
  304                         BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
  305                         BUS_DMA_ALLOCNOW,       /* flags */
  306                         &sc->ndis_parent_tag);
  307 
  308         if (error)
  309                 goto fail;
  310 
  311         sc->ndis_iftype = PCIBus;
  312 
  313         /* Figure out exactly which device we matched. */
  314 
  315         vid = pci_get_vendor(dev);
  316         did = pci_get_device(dev);
  317         subsys = pci_get_subdevice(dev);
  318         subsys = (subsys << 16) | pci_get_subvendor(dev);
  319 
  320         t = db->windrv_devlist;
  321 
  322         while(t->ndis_name != NULL) {
  323                 if (t->ndis_vid == vid && t->ndis_did == did) {
  324                         if (t->ndis_subsys == 0)
  325                                 defidx = devidx;
  326                         else if (t->ndis_subsys == subsys)
  327                                 break;
  328                 }
  329                 t++;
  330                 devidx++;
  331         }
  332 
  333         if (t->ndis_name == NULL)
  334                 sc->ndis_devidx = defidx;
  335         else
  336                 sc->ndis_devidx = devidx;
  337 
  338         error = ndis_attach(dev);
  339 
  340 fail:
  341         wlan_serialize_exit();
  342         return(error);
  343 }
  344 
  345 static int
  346 ndis_detach_pci(device_t dev)
  347 {
  348         int error = 0;
  349 
  350         wlan_serialize_enter();
  351         error = ndis_detach(dev);
  352         wlan_serialize_exit();
  353         return(error);
  354 }
  355 
  356 static struct resource_list *
  357 ndis_get_resource_list(device_t dev, device_t child)
  358 {
  359         struct ndis_softc       *sc;
  360 
  361         sc = device_get_softc(dev);
  362         return (BUS_GET_RESOURCE_LIST(device_get_parent(sc->ndis_dev), dev));
  363 }

Cache object: 25dd54ae4db54a100ec52af46d2db1fa


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