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/aac/aac_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) 2000 Michael Smith
    3  * Copyright (c) 2001 Scott Long
    4  * Copyright (c) 2000 BSDi
    5  * Copyright (c) 2001 Adaptec, Inc.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 /*
   34  * PCI bus interface and resource allocation.
   35  */
   36 
   37 #include "opt_aac.h"
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/kernel.h>
   42 #include <sys/module.h>
   43 
   44 #include <sys/bio.h>
   45 #include <sys/bus.h>
   46 #include <sys/conf.h>
   47 #include <sys/disk.h>
   48 
   49 #include <machine/bus_memio.h>
   50 #include <machine/bus.h>
   51 #include <machine/resource.h>
   52 #include <sys/rman.h>
   53 
   54 #include <dev/pci/pcireg.h>
   55 #include <dev/pci/pcivar.h>
   56 
   57 #include <dev/aac/aacreg.h>
   58 #include <sys/aac_ioctl.h>
   59 #include <dev/aac/aacvar.h>
   60 
   61 static int      aac_pci_probe(device_t dev);
   62 static int      aac_pci_attach(device_t dev);
   63 
   64 static device_method_t aac_methods[] = {
   65         /* Device interface */
   66         DEVMETHOD(device_probe,         aac_pci_probe),
   67         DEVMETHOD(device_attach,        aac_pci_attach),
   68         DEVMETHOD(device_detach,        aac_detach),
   69         DEVMETHOD(device_suspend,       aac_suspend),
   70         DEVMETHOD(device_resume,        aac_resume),
   71 
   72         DEVMETHOD(bus_print_child,      bus_generic_print_child),
   73         DEVMETHOD(bus_driver_added,     bus_generic_driver_added),
   74         { 0, 0 }
   75 };
   76 
   77 static driver_t aac_pci_driver = {
   78         "aac",
   79         aac_methods,
   80         sizeof(struct aac_softc)
   81 };
   82 
   83 static devclass_t       aac_devclass;
   84 
   85 DRIVER_MODULE(aac, pci, aac_pci_driver, aac_devclass, 0, 0);
   86 
   87 struct aac_ident
   88 {
   89         u_int16_t               vendor;
   90         u_int16_t               device;
   91         u_int16_t               subvendor;
   92         u_int16_t               subdevice;
   93         int                     hwif;
   94         int                     quirks;
   95         char                    *desc;
   96 } aac_identifiers[] = {
   97         {0x1028, 0x0001, 0x1028, 0x0001, AAC_HWIF_I960RX, 0,
   98         "Dell PERC 2/Si"},
   99         {0x1028, 0x0002, 0x1028, 0x0002, AAC_HWIF_I960RX, 0,
  100         "Dell PERC 3/Di"},
  101         {0x1028, 0x0003, 0x1028, 0x0003, AAC_HWIF_I960RX, 0,
  102         "Dell PERC 3/Si"},
  103         {0x1028, 0x0004, 0x1028, 0x00d0, AAC_HWIF_I960RX, 0,
  104         "Dell PERC 3/Si"},
  105         {0x1028, 0x0002, 0x1028, 0x00d1, AAC_HWIF_I960RX, 0,
  106         "Dell PERC 3/Di"},
  107         {0x1028, 0x0002, 0x1028, 0x00d9, AAC_HWIF_I960RX, 0,
  108         "Dell PERC 3/Di"},
  109         {0x1028, 0x000a, 0x1028, 0x0106, AAC_HWIF_I960RX, 0,
  110         "Dell PERC 3/Di"},
  111         {0x1028, 0x000a, 0x1028, 0x011b, AAC_HWIF_I960RX, 0,
  112         "Dell PERC 3/Di"},
  113         {0x1028, 0x000a, 0x1028, 0x0121, AAC_HWIF_I960RX, 0,
  114         "Dell PERC 3/Di"},
  115         {0x1011, 0x0046, 0x9005, 0x0364, AAC_HWIF_STRONGARM, 0,
  116         "Adaptec AAC-364"},
  117         {0x1011, 0x0046, 0x9005, 0x0365, AAC_HWIF_STRONGARM,
  118          AAC_FLAGS_BROKEN_MEMMAP, "Adaptec SCSI RAID 5400S"},
  119         {0x1011, 0x0046, 0x9005, 0x1364, AAC_HWIF_STRONGARM, AAC_FLAGS_PERC2QC,
  120          "Dell PERC 2/QC"},
  121         {0x1011, 0x0046, 0x103c, 0x10c2, AAC_HWIF_STRONGARM, 0,
  122          "HP NetRaid-4M"},
  123         {0x9005, 0x0285, 0x9005, 0x0285, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB |
  124          AAC_FLAGS_256FIBS, "Adaptec SCSI RAID 2200S"},
  125         {0x9005, 0x0285, 0x1028, 0x0287, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB |
  126          AAC_FLAGS_256FIBS, "Dell PERC 320/DC"},
  127         {0x9005, 0x0285, 0x9005, 0x0286, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB |
  128          AAC_FLAGS_256FIBS, "Adaptec SCSI RAID 2120S"},
  129         {0x9005, 0x0285, 0x9005, 0x0290, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB,
  130          "Adaptec SCSI RAID 2410SA"},
  131         {0x9005, 0x0285, 0x1028, 0x0291, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB,
  132          "Dell CERC SATA RAID 2"},
  133         {0x9005, 0x0285, 0x9005, 0x0292, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB,
  134          "Adaptec SCSI RAID 2810SA"},
  135         {0x9005, 0x0285, 0x9005, 0x0293, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB,
  136          "Adaptec SCSI RAID 21610SA"},
  137         {0x9005, 0x0286, 0x9005, 0x028c, AAC_HWIF_RKT, 0,
  138          "Adaptec SCSI RAID 2230S"},
  139         {0x9005, 0x0286, 0x9005, 0x028d, AAC_HWIF_RKT, 0,
  140          "Adaptec SCSI RAID 2130S"},
  141         {0, 0, 0, 0, 0, 0, 0}
  142 };
  143 
  144 /*
  145  * Determine whether this is one of our supported adapters.
  146  */
  147 static int
  148 aac_pci_probe(device_t dev)
  149 {
  150         struct aac_ident *m;
  151 
  152         debug_called(1);
  153 
  154         for (m = aac_identifiers; m->vendor != 0; m++) {
  155                 if ((m->vendor == pci_get_vendor(dev)) &&
  156                     (m->device == pci_get_device(dev)) &&
  157                     ((m->subvendor == 0) || (m->subvendor ==
  158                                              pci_get_subvendor(dev))) &&
  159                     ((m->subdevice == 0) || ((m->subdevice ==
  160                                               pci_get_subdevice(dev))))) {
  161                 
  162                         device_set_desc(dev, m->desc);
  163                         return(-10);    /* allow room to be overridden */
  164                 }
  165         }
  166         return(ENXIO);
  167 }
  168 
  169 /*
  170  * Allocate resources for our device, set up the bus interface.
  171  */
  172 static int
  173 aac_pci_attach(device_t dev)
  174 {
  175         struct aac_softc *sc;
  176         int i, error;
  177         u_int32_t command;
  178 
  179         debug_called(1);
  180 
  181         /*
  182          * Initialise softc.
  183          */
  184         sc = device_get_softc(dev);
  185         bzero(sc, sizeof(*sc));
  186         sc->aac_dev = dev;
  187 
  188         /* assume failure is 'not configured' */
  189         error = ENXIO;
  190 
  191         /* 
  192          * Verify that the adapter is correctly set up in PCI space.
  193          */
  194         command = pci_read_config(sc->aac_dev, PCIR_COMMAND, 2);
  195         command |= PCIM_CMD_BUSMASTEREN;
  196         pci_write_config(dev, PCIR_COMMAND, command, 2);
  197         command = pci_read_config(sc->aac_dev, PCIR_COMMAND, 2);
  198         if (!(command & PCIM_CMD_BUSMASTEREN)) {
  199                 device_printf(sc->aac_dev, "can't enable bus-master feature\n");
  200                 goto out;
  201         }
  202         if ((command & PCIM_CMD_MEMEN) == 0) {
  203                 device_printf(sc->aac_dev, "memory window not available\n");
  204                 goto out;
  205         }
  206 
  207         /*
  208          * Allocate the PCI register window.
  209          */
  210         sc->aac_regs_rid = PCIR_BAR(0);
  211         if ((sc->aac_regs_resource = bus_alloc_resource_any(sc->aac_dev,
  212                                                             SYS_RES_MEMORY,
  213                                                             &sc->aac_regs_rid,
  214                                                             RF_ACTIVE)) ==
  215                                                             NULL) {
  216                 device_printf(sc->aac_dev,
  217                               "couldn't allocate register window\n");
  218                 goto out;
  219         }
  220         sc->aac_btag = rman_get_bustag(sc->aac_regs_resource);
  221         sc->aac_bhandle = rman_get_bushandle(sc->aac_regs_resource);
  222 
  223         /* 
  224          * Allocate and connect our interrupt.
  225          */
  226         sc->aac_irq_rid = 0;
  227         if ((sc->aac_irq = bus_alloc_resource_any(sc->aac_dev, SYS_RES_IRQ,
  228                                                   &sc->aac_irq_rid,
  229                                                   RF_SHAREABLE |
  230                                                   RF_ACTIVE)) == NULL) {
  231                 device_printf(sc->aac_dev, "can't allocate interrupt\n");
  232                 goto out;
  233         }
  234         if (bus_setup_intr(sc->aac_dev, sc->aac_irq,
  235                            INTR_FAST|INTR_TYPE_BIO, aac_intr,
  236                            sc, &sc->aac_intr)) {
  237                 device_printf(sc->aac_dev, "can't set up FAST interrupt\n");
  238                 if (bus_setup_intr(sc->aac_dev, sc->aac_irq,
  239                                    INTR_MPSAFE|INTR_ENTROPY|INTR_TYPE_BIO,
  240                                    aac_intr, sc, &sc->aac_intr)) {
  241                         device_printf(sc->aac_dev,
  242                                       "can't set up MPSAFE interrupt\n");
  243                         goto out;
  244                 }
  245         }
  246 
  247         /* assume failure is 'out of memory' */
  248         error = ENOMEM;
  249 
  250         /*
  251          * Allocate the parent bus DMA tag appropriate for our PCI interface.
  252          * 
  253          * Note that some of these controllers are 64-bit capable.
  254          */
  255         if (bus_dma_tag_create(NULL,                    /* parent */
  256                                PAGE_SIZE, 0,            /* algnmnt, boundary */
  257                                BUS_SPACE_MAXADDR,       /* lowaddr */
  258                                BUS_SPACE_MAXADDR,       /* highaddr */
  259                                NULL, NULL,              /* filter, filterarg */
  260                                BUS_SPACE_MAXSIZE_32BIT, /* maxsize */
  261                                AAC_MAXSGENTRIES,        /* nsegments */
  262                                BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
  263                                0,                       /* flags */
  264                                NULL, NULL,              /* No locking needed */
  265                                &sc->aac_parent_dmat)) {
  266                 device_printf(sc->aac_dev, "can't allocate parent DMA tag\n");
  267                 goto out;
  268         }
  269 
  270         /* 
  271          * Detect the hardware interface version, set up the bus interface
  272          * indirection.
  273          */
  274         for (i = 0; aac_identifiers[i].vendor != 0; i++) {
  275                 if ((aac_identifiers[i].vendor == pci_get_vendor(dev)) &&
  276                     (aac_identifiers[i].device == pci_get_device(dev)) &&
  277                     (aac_identifiers[i].subvendor == pci_get_subvendor(dev)) &&
  278                     (aac_identifiers[i].subdevice == pci_get_subdevice(dev))) {
  279                         sc->aac_hwif = aac_identifiers[i].hwif;
  280                         switch(sc->aac_hwif) {
  281                         case AAC_HWIF_I960RX:
  282                                 debug(2, "set hardware up for i960Rx");
  283                                 sc->aac_if = aac_rx_interface;
  284                                 break;
  285                         case AAC_HWIF_STRONGARM:
  286                                 debug(2, "set hardware up for StrongARM");
  287                                 sc->aac_if = aac_sa_interface;
  288                                 break;
  289                         case AAC_HWIF_FALCON:
  290                                 debug(2, "set hardware up for Falcon/PPC");
  291                                 sc->aac_if = aac_fa_interface;
  292                                 break;
  293                         case AAC_HWIF_RKT:
  294                                 debug(2, "setu hardware up for Rocket/MIPS");
  295                                 sc->aac_if = aac_rkt_interface;
  296                                 break;
  297                         default:
  298                                 sc->aac_hwif = AAC_HWIF_UNKNOWN;
  299                                 break;
  300                         }
  301 
  302                         /* Set up quirks */
  303                         sc->flags = aac_identifiers[i].quirks;
  304 
  305                         break;
  306                 }
  307         }
  308         if (sc->aac_hwif == AAC_HWIF_UNKNOWN) {
  309                 device_printf(sc->aac_dev, "unknown hardware type\n");
  310                 error = ENXIO;
  311                 goto out;
  312         }
  313 
  314 
  315         /*
  316          * Do bus-independent initialisation.
  317          */
  318         error = aac_attach(sc);
  319         
  320 out:
  321         if (error)
  322                 aac_free(sc);
  323         return(error);
  324 }
  325 
  326 /*
  327  * Do nothing driver that will attach to the SCSI channels of a Dell PERC
  328  * controller.  This is needed to keep the power management subsystem from
  329  * trying to power down these devices.
  330  */
  331 static int aacch_probe(device_t dev);
  332 static int aacch_attach(device_t dev);
  333 static int aacch_detach(device_t dev);
  334 
  335 static device_method_t aacch_methods[] = {
  336         /* Device interface */
  337         DEVMETHOD(device_probe,         aacch_probe),
  338         DEVMETHOD(device_attach,        aacch_attach),
  339         DEVMETHOD(device_detach,        aacch_detach),
  340         { 0, 0 }
  341 };
  342 
  343 struct aacch_softc {
  344         device_t        dev;
  345 };
  346 
  347 static driver_t aacch_driver = {
  348         "aacch",
  349         aacch_methods,
  350         sizeof(struct aacch_softc)
  351 };
  352 
  353 static devclass_t       aacch_devclass;
  354 DRIVER_MODULE(aacch, pci, aacch_driver, aacch_devclass, 0, 0);
  355 
  356 static int
  357 aacch_probe(device_t dev)
  358 {
  359 
  360         if ((pci_get_subvendor(dev) != 0x9005) ||
  361             (pci_get_subdevice(dev) != 0x00c5))
  362                 return (ENXIO);
  363 
  364         device_set_desc(dev, "AAC RAID Channel");
  365         return (-10);
  366 }
  367 
  368 static int
  369 aacch_attach(device_t dev)
  370 {
  371         struct aacch_softc *sc;
  372 
  373         sc = device_get_softc(dev);
  374 
  375         sc->dev = dev;
  376 
  377         return (0);
  378 }
  379 
  380 static int
  381 aacch_detach(device_t dev)
  382 {
  383 
  384         return (0);
  385 }
  386 

Cache object: 4bea2b0191914749d7926e72d877ded4


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