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/mpt/mpt_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  * PCI specific probe and attach routines for LSI Fusion Adapters
    3  * FreeBSD Version.
    4  *
    5  * Copyright (c) 2000, 2001 by Greg Ansley
    6  * Partially derived from Matt Jacob's ISP driver.
    7  * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002 by Matthew Jacob
    8  * Feral Software
    9  * All rights reserved.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice immediately at the beginning of the file, without modification,
   16  *    this list of conditions, and the following disclaimer.
   17  * 2. The name of the author may not be used to endorse or promote products
   18  *    derived from this software without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   24  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  */
   32 /*-
   33  * Copyright (c) 2002, 2006 by Matthew Jacob
   34  * All rights reserved.
   35  * 
   36  * Redistribution and use in source and binary forms, with or without
   37  * modification, are permitted provided that the following conditions are
   38  * met:
   39  * 1. Redistributions of source code must retain the above copyright
   40  *    notice, this list of conditions and the following disclaimer.
   41  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   42  *    substantially similar to the "NO WARRANTY" disclaimer below
   43  *    ("Disclaimer") and any redistribution must be conditioned upon including
   44  *    a substantially similar Disclaimer requirement for further binary
   45  *    redistribution.
   46  * 3. Neither the names of the above listed copyright holders nor the names
   47  *    of any contributors may be used to endorse or promote products derived
   48  *    from this software without specific prior written permission.
   49  * 
   50  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   51  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   52  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   53  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   54  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   55  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   56  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   57  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   58  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   59  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT
   60  * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   61  *
   62  * Support from Chris Ellsworth in order to make SAS adapters work
   63  * is gratefully acknowledged.
   64  *
   65  * Support from LSI-Logic has also gone a great deal toward making this a
   66  * workable subsystem and is gratefully acknowledged.
   67  */
   68 /*
   69  * Copyright (c) 2004, Avid Technology, Inc. and its contributors.
   70  * Copyright (c) 2005, WHEEL Sp. z o.o.
   71  * Copyright (c) 2004, 2005 Justin T. Gibbs
   72  * All rights reserved.
   73  * 
   74  * Redistribution and use in source and binary forms, with or without
   75  * modification, are permitted provided that the following conditions are
   76  * met:
   77  * 1. Redistributions of source code must retain the above copyright
   78  *    notice, this list of conditions and the following disclaimer.
   79  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   80  *    substantially similar to the "NO WARRANTY" disclaimer below
   81  *    ("Disclaimer") and any redistribution must be conditioned upon including
   82  *    a substantially similar Disclaimer requirement for further binary
   83  *    redistribution.
   84  * 3. Neither the names of the above listed copyright holders nor the names
   85  *    of any contributors may be used to endorse or promote products derived
   86  *    from this software without specific prior written permission.
   87  * 
   88  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   89  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   90  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   91  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   92  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   93  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   94  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   95  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   96  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   97  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT
   98  * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   99  */
  100 
  101 #include <sys/cdefs.h>
  102 __FBSDID("$FreeBSD$");
  103 
  104 #include <dev/mpt/mpt.h>
  105 #include <dev/mpt/mpt_cam.h>
  106 #include <dev/mpt/mpt_raid.h>
  107 
  108 #if __FreeBSD_version < 700000
  109 #define pci_msix_count(x)       0
  110 #define pci_msi_count(x)        0
  111 #define pci_alloc_msi(x, y)     1
  112 #define pci_alloc_msix(x, y)    1
  113 #define pci_release_msi(x)      do { ; } while (0)
  114 #endif
  115 
  116 #ifndef PCI_VENDOR_LSI
  117 #define PCI_VENDOR_LSI                  0x1000
  118 #endif
  119 
  120 #ifndef PCI_PRODUCT_LSI_FC909
  121 #define PCI_PRODUCT_LSI_FC909           0x0620
  122 #endif
  123 
  124 #ifndef PCI_PRODUCT_LSI_FC909A
  125 #define PCI_PRODUCT_LSI_FC909A          0x0621
  126 #endif
  127 
  128 #ifndef PCI_PRODUCT_LSI_FC919
  129 #define PCI_PRODUCT_LSI_FC919           0x0624
  130 #endif
  131 
  132 #ifndef PCI_PRODUCT_LSI_FC929
  133 #define PCI_PRODUCT_LSI_FC929           0x0622
  134 #endif
  135 
  136 #ifndef PCI_PRODUCT_LSI_FC929X
  137 #define PCI_PRODUCT_LSI_FC929X          0x0626
  138 #endif
  139 
  140 #ifndef PCI_PRODUCT_LSI_FC919X
  141 #define PCI_PRODUCT_LSI_FC919X          0x0628
  142 #endif
  143 
  144 #ifndef PCI_PRODUCT_LSI_FC7X04X
  145 #define PCI_PRODUCT_LSI_FC7X04X         0x0640
  146 #endif
  147 
  148 #ifndef PCI_PRODUCT_LSI_FC646
  149 #define PCI_PRODUCT_LSI_FC646           0x0646
  150 #endif
  151 
  152 #ifndef PCI_PRODUCT_LSI_1030
  153 #define PCI_PRODUCT_LSI_1030            0x0030
  154 #endif
  155 
  156 #ifndef PCI_PRODUCT_LSI_SAS1064
  157 #define PCI_PRODUCT_LSI_SAS1064         0x0050
  158 #endif
  159 
  160 #ifndef PCI_PRODUCT_LSI_SAS1064A
  161 #define PCI_PRODUCT_LSI_SAS1064A        0x005C
  162 #endif
  163 
  164 #ifndef PCI_PRODUCT_LSI_SAS1064E
  165 #define PCI_PRODUCT_LSI_SAS1064E        0x0056
  166 #endif
  167 
  168 #ifndef PCI_PRODUCT_LSI_SAS1066
  169 #define PCI_PRODUCT_LSI_SAS1066         0x005E
  170 #endif
  171 
  172 #ifndef PCI_PRODUCT_LSI_SAS1066E
  173 #define PCI_PRODUCT_LSI_SAS1066E        0x005A
  174 #endif
  175 
  176 #ifndef PCI_PRODUCT_LSI_SAS1068
  177 #define PCI_PRODUCT_LSI_SAS1068         0x0054
  178 #endif
  179 
  180 #ifndef PCI_PRODUCT_LSI_SAS1068E
  181 #define PCI_PRODUCT_LSI_SAS1068E        0x0058
  182 #endif
  183 
  184 #ifndef PCI_PRODUCT_LSI_SAS1078
  185 #define PCI_PRODUCT_LSI_SAS1078         0x0060
  186 #endif
  187 
  188 #ifndef PCI_PRODUCT_LSI_SAS1078DE
  189 #define PCI_PRODUCT_LSI_SAS1078DE       0x007C
  190 #endif
  191 
  192 #ifndef PCIM_CMD_SERRESPEN
  193 #define PCIM_CMD_SERRESPEN      0x0100
  194 #endif
  195 
  196 
  197 #define MPT_IO_BAR      0
  198 #define MPT_MEM_BAR     1
  199 
  200 static int mpt_pci_probe(device_t);
  201 static int mpt_pci_attach(device_t);
  202 static void mpt_free_bus_resources(struct mpt_softc *mpt);
  203 static int mpt_pci_detach(device_t);
  204 static int mpt_pci_shutdown(device_t);
  205 static int mpt_dma_mem_alloc(struct mpt_softc *mpt);
  206 static void mpt_dma_mem_free(struct mpt_softc *mpt);
  207 static void mpt_read_config_regs(struct mpt_softc *mpt);
  208 static void mpt_pci_intr(void *);
  209 
  210 static device_method_t mpt_methods[] = {
  211         /* Device interface */
  212         DEVMETHOD(device_probe,         mpt_pci_probe),
  213         DEVMETHOD(device_attach,        mpt_pci_attach),
  214         DEVMETHOD(device_detach,        mpt_pci_detach),
  215         DEVMETHOD(device_shutdown,      mpt_pci_shutdown),
  216         { 0, 0 }
  217 };
  218 
  219 static driver_t mpt_driver = {
  220         "mpt", mpt_methods, sizeof(struct mpt_softc)
  221 };
  222 static devclass_t mpt_devclass;
  223 DRIVER_MODULE(mpt, pci, mpt_driver, mpt_devclass, 0, 0);
  224 MODULE_DEPEND(mpt, pci, 1, 1, 1);
  225 MODULE_VERSION(mpt, 1);
  226 
  227 static int
  228 mpt_pci_probe(device_t dev)
  229 {
  230         char *desc;
  231 
  232         if (pci_get_vendor(dev) != PCI_VENDOR_LSI) {
  233                 return (ENXIO);
  234         }
  235 
  236         switch ((pci_get_device(dev) & ~1)) {
  237         case PCI_PRODUCT_LSI_FC909:
  238                 desc = "LSILogic FC909 FC Adapter";
  239                 break;
  240         case PCI_PRODUCT_LSI_FC909A:
  241                 desc = "LSILogic FC909A FC Adapter";
  242                 break;
  243         case PCI_PRODUCT_LSI_FC919:
  244                 desc = "LSILogic FC919 FC Adapter";
  245                 break;
  246         case PCI_PRODUCT_LSI_FC929:
  247                 desc = "Dual LSILogic FC929 FC Adapter";
  248                 break;
  249         case PCI_PRODUCT_LSI_FC919X:
  250                 desc = "LSILogic FC919 FC PCI-X Adapter";
  251                 break;
  252         case PCI_PRODUCT_LSI_FC929X:
  253                 desc = "Dual LSILogic FC929X 2Gb/s FC PCI-X Adapter";
  254                 break;
  255         case PCI_PRODUCT_LSI_FC646:
  256                 desc = "Dual LSILogic FC7X04X 4Gb/s FC PCI-Express Adapter";
  257                 break;
  258         case PCI_PRODUCT_LSI_FC7X04X:
  259                 desc = "Dual LSILogic FC7X04X 4Gb/s FC PCI-X Adapter";
  260                 break;
  261         case PCI_PRODUCT_LSI_1030:
  262                 desc = "LSILogic 1030 Ultra4 Adapter";
  263                 break;
  264         case PCI_PRODUCT_LSI_SAS1064:
  265         case PCI_PRODUCT_LSI_SAS1064A:
  266         case PCI_PRODUCT_LSI_SAS1064E:
  267         case PCI_PRODUCT_LSI_SAS1066:
  268         case PCI_PRODUCT_LSI_SAS1066E:
  269         case PCI_PRODUCT_LSI_SAS1068:
  270         case PCI_PRODUCT_LSI_SAS1068E:
  271         case PCI_PRODUCT_LSI_SAS1078:
  272         case PCI_PRODUCT_LSI_SAS1078DE:
  273                 desc = "LSILogic SAS/SATA Adapter";
  274                 break;
  275         default:
  276                 return (ENXIO);
  277         }
  278 
  279         device_set_desc(dev, desc);
  280         return (0);
  281 }
  282 
  283 #if     __FreeBSD_version < 500000  
  284 static void
  285 mpt_set_options(struct mpt_softc *mpt)
  286 {
  287         int bitmap;
  288 
  289         bitmap = 0;
  290         if (getenv_int("mpt_disable", &bitmap)) {
  291                 if (bitmap & (1 << mpt->unit)) {
  292                         mpt->disabled = 1;
  293                 }
  294         }
  295         bitmap = 0;
  296         if (getenv_int("mpt_debug", &bitmap)) {
  297                 if (bitmap & (1 << mpt->unit)) {
  298                         mpt->verbose = MPT_PRT_DEBUG;
  299                 }
  300         }
  301         bitmap = 0;
  302         if (getenv_int("mpt_debug1", &bitmap)) {
  303                 if (bitmap & (1 << mpt->unit)) {
  304                         mpt->verbose = MPT_PRT_DEBUG1;
  305                 }
  306         }
  307         bitmap = 0;
  308         if (getenv_int("mpt_debug2", &bitmap)) {
  309                 if (bitmap & (1 << mpt->unit)) {
  310                         mpt->verbose = MPT_PRT_DEBUG2;
  311                 }
  312         }
  313         bitmap = 0;
  314         if (getenv_int("mpt_debug3", &bitmap)) {
  315                 if (bitmap & (1 << mpt->unit)) {
  316                         mpt->verbose = MPT_PRT_DEBUG3;
  317                 }
  318         }
  319 
  320         mpt->cfg_role = MPT_ROLE_DEFAULT;
  321         bitmap = 0;
  322         if (getenv_int("mpt_nil_role", &bitmap)) {
  323                 if (bitmap & (1 << mpt->unit)) {
  324                         mpt->cfg_role = 0;
  325                 }
  326                 mpt->do_cfg_role = 1;
  327         }
  328         bitmap = 0;
  329         if (getenv_int("mpt_tgt_role", &bitmap)) {
  330                 if (bitmap & (1 << mpt->unit)) {
  331                         mpt->cfg_role |= MPT_ROLE_TARGET;
  332                 }
  333                 mpt->do_cfg_role = 1;
  334         }
  335         bitmap = 0;
  336         if (getenv_int("mpt_ini_role", &bitmap)) {
  337                 if (bitmap & (1 << mpt->unit)) {
  338                         mpt->cfg_role |= MPT_ROLE_INITIATOR;
  339                 }
  340                 mpt->do_cfg_role = 1;
  341         }
  342         mpt->msi_enable = 0;
  343 }
  344 #else
  345 static void
  346 mpt_set_options(struct mpt_softc *mpt)
  347 {
  348         int tval;
  349 
  350         tval = 0;
  351         if (resource_int_value(device_get_name(mpt->dev),
  352             device_get_unit(mpt->dev), "disable", &tval) == 0 && tval != 0) {
  353                 mpt->disabled = 1;
  354         }
  355         tval = 0;
  356         if (resource_int_value(device_get_name(mpt->dev),
  357             device_get_unit(mpt->dev), "debug", &tval) == 0 && tval != 0) {
  358                 mpt->verbose = tval;
  359         }
  360         tval = -1;
  361         if (resource_int_value(device_get_name(mpt->dev),
  362             device_get_unit(mpt->dev), "role", &tval) == 0 && tval >= 0 &&
  363             tval <= 3) {
  364                 mpt->cfg_role = tval;
  365                 mpt->do_cfg_role = 1;
  366         }
  367 
  368         tval = 0;
  369         mpt->msi_enable = 0;
  370         if (resource_int_value(device_get_name(mpt->dev),
  371             device_get_unit(mpt->dev), "msi_enable", &tval) == 0 && tval == 1) {
  372                 mpt->msi_enable = 1;
  373         }
  374 }
  375 #endif
  376 
  377 
  378 static void
  379 mpt_link_peer(struct mpt_softc *mpt)
  380 {
  381         struct mpt_softc *mpt2;
  382 
  383         if (mpt->unit == 0) {
  384                 return;
  385         }
  386         /*
  387          * XXX: depends on probe order
  388          */
  389         mpt2 = (struct mpt_softc *)devclass_get_softc(mpt_devclass,mpt->unit-1);
  390 
  391         if (mpt2 == NULL) {
  392                 return;
  393         }
  394         if (pci_get_vendor(mpt2->dev) != pci_get_vendor(mpt->dev)) {
  395                 return;
  396         }
  397         if (pci_get_device(mpt2->dev) != pci_get_device(mpt->dev)) {
  398                 return;
  399         }
  400         mpt->mpt2 = mpt2;
  401         mpt2->mpt2 = mpt;
  402         if (mpt->verbose >= MPT_PRT_DEBUG) {
  403                 mpt_prt(mpt, "linking with peer (mpt%d)\n",
  404                     device_get_unit(mpt2->dev));
  405         }
  406 }
  407 
  408 static void
  409 mpt_unlink_peer(struct mpt_softc *mpt)
  410 {
  411         if (mpt->mpt2) {
  412                 mpt->mpt2->mpt2 = NULL;
  413         }
  414 }
  415 
  416 
  417 static int
  418 mpt_pci_attach(device_t dev)
  419 {
  420         struct mpt_softc *mpt;
  421         int               iqd;
  422         uint32_t          data, cmd;
  423 
  424         /* Allocate the softc structure */
  425         mpt  = (struct mpt_softc*)device_get_softc(dev);
  426         if (mpt == NULL) {
  427                 device_printf(dev, "cannot allocate softc\n");
  428                 return (ENOMEM);
  429         }
  430         memset(mpt, 0, sizeof(struct mpt_softc));
  431         switch ((pci_get_device(dev) & ~1)) {
  432         case PCI_PRODUCT_LSI_FC909:
  433         case PCI_PRODUCT_LSI_FC909A:
  434         case PCI_PRODUCT_LSI_FC919:
  435         case PCI_PRODUCT_LSI_FC929:
  436         case PCI_PRODUCT_LSI_FC919X:
  437         case PCI_PRODUCT_LSI_FC646:
  438         case PCI_PRODUCT_LSI_FC7X04X:
  439                 mpt->is_fc = 1;
  440                 break;
  441         case PCI_PRODUCT_LSI_SAS1064:
  442         case PCI_PRODUCT_LSI_SAS1064A:
  443         case PCI_PRODUCT_LSI_SAS1064E:
  444         case PCI_PRODUCT_LSI_SAS1066:
  445         case PCI_PRODUCT_LSI_SAS1066E:
  446         case PCI_PRODUCT_LSI_SAS1068:
  447         case PCI_PRODUCT_LSI_SAS1068E:
  448         case PCI_PRODUCT_LSI_SAS1078:
  449         case PCI_PRODUCT_LSI_SAS1078DE:
  450                 mpt->is_sas = 1;
  451                 break;
  452         default:
  453                 mpt->is_spi = 1;
  454                 break;
  455         }
  456         mpt->dev = dev;
  457         mpt->unit = device_get_unit(dev);
  458         mpt->raid_resync_rate = MPT_RAID_RESYNC_RATE_DEFAULT;
  459         mpt->raid_mwce_setting = MPT_RAID_MWCE_DEFAULT;
  460         mpt->raid_queue_depth = MPT_RAID_QUEUE_DEPTH_DEFAULT;
  461         mpt->verbose = MPT_PRT_NONE;
  462         mpt->role = MPT_ROLE_NONE;
  463         mpt_set_options(mpt);
  464         if (mpt->verbose == MPT_PRT_NONE) {
  465                 mpt->verbose = MPT_PRT_WARN;
  466                 /* Print INFO level (if any) if bootverbose is set */
  467                 mpt->verbose += (bootverbose != 0)? 1 : 0;
  468         }
  469         /* Make sure memory access decoders are enabled */
  470         cmd = pci_read_config(dev, PCIR_COMMAND, 2);
  471         if ((cmd & PCIM_CMD_MEMEN) == 0) {
  472                 device_printf(dev, "Memory accesses disabled");
  473                 return (ENXIO);
  474         }
  475 
  476         /*
  477          * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER are set.
  478          */
  479         cmd |=
  480             PCIM_CMD_SERRESPEN | PCIM_CMD_PERRESPEN |
  481             PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN;
  482         pci_write_config(dev, PCIR_COMMAND, cmd, 2);
  483 
  484         /*
  485          * Make sure we've disabled the ROM.
  486          */
  487         data = pci_read_config(dev, PCIR_BIOS, 4);
  488         data &= ~1;
  489         pci_write_config(dev, PCIR_BIOS, data, 4);
  490 
  491         /*
  492          * Is this part a dual?
  493          * If so, link with our partner (around yet)
  494          */
  495         if ((pci_get_device(dev) & ~1) == PCI_PRODUCT_LSI_FC929 ||
  496             (pci_get_device(dev) & ~1) == PCI_PRODUCT_LSI_FC646 ||
  497             (pci_get_device(dev) & ~1) == PCI_PRODUCT_LSI_FC7X04X ||
  498             (pci_get_device(dev) & ~1) == PCI_PRODUCT_LSI_1030) {
  499                 mpt_link_peer(mpt);
  500         }
  501 
  502         /*
  503          * Set up register access.  PIO mode is required for
  504          * certain reset operations (but must be disabled for
  505          * some cards otherwise).
  506          */
  507         mpt->pci_pio_rid = PCIR_BAR(MPT_IO_BAR);
  508         mpt->pci_pio_reg = bus_alloc_resource(dev, SYS_RES_IOPORT,
  509                             &mpt->pci_pio_rid, 0, ~0, 0, RF_ACTIVE);
  510         if (mpt->pci_pio_reg == NULL) {
  511                 device_printf(dev, "unable to map registers in PIO mode\n");
  512                 goto bad;
  513         }
  514         mpt->pci_pio_st = rman_get_bustag(mpt->pci_pio_reg);
  515         mpt->pci_pio_sh = rman_get_bushandle(mpt->pci_pio_reg);
  516 
  517         /* Allocate kernel virtual memory for the 9x9's Mem0 region */
  518         mpt->pci_mem_rid = PCIR_BAR(MPT_MEM_BAR);
  519         mpt->pci_reg = bus_alloc_resource(dev, SYS_RES_MEMORY,
  520                         &mpt->pci_mem_rid, 0, ~0, 0, RF_ACTIVE);
  521         if (mpt->pci_reg == NULL) {
  522                 device_printf(dev, "Unable to memory map registers.\n");
  523                 if (mpt->is_sas) {
  524                         device_printf(dev, "Giving Up.\n");
  525                         goto bad;
  526                 }
  527                 device_printf(dev, "Falling back to PIO mode.\n");
  528                 mpt->pci_st = mpt->pci_pio_st;
  529                 mpt->pci_sh = mpt->pci_pio_sh;
  530         } else {
  531                 mpt->pci_st = rman_get_bustag(mpt->pci_reg);
  532                 mpt->pci_sh = rman_get_bushandle(mpt->pci_reg);
  533         }
  534 
  535         /* Get a handle to the interrupt */
  536         iqd = 0;
  537         if (mpt->msi_enable) {
  538                 /*
  539                  * First try to alloc an MSI-X message.  If that
  540                  * fails, then try to alloc an MSI message instead.
  541                  */
  542                 if (pci_msix_count(dev) == 1) {
  543                         mpt->pci_msi_count = 1;
  544                         if (pci_alloc_msix(dev, &mpt->pci_msi_count) == 0) {
  545                                 iqd = 1;
  546                         } else {
  547                                 mpt->pci_msi_count = 0;
  548                         }
  549                 }
  550                 if (iqd == 0 && pci_msi_count(dev) == 1) {
  551                         mpt->pci_msi_count = 1;
  552                         if (pci_alloc_msi(dev, &mpt->pci_msi_count) == 0) {
  553                                 iqd = 1;
  554                         } else {
  555                                 mpt->pci_msi_count = 0;
  556                         }
  557                 }
  558         }
  559         mpt->pci_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd,
  560             RF_ACTIVE | RF_SHAREABLE);
  561         if (mpt->pci_irq == NULL) {
  562                 device_printf(dev, "could not allocate interrupt\n");
  563                 goto bad;
  564         }
  565 
  566         MPT_LOCK_SETUP(mpt);
  567 
  568         /* Disable interrupts at the part */
  569         mpt_disable_ints(mpt);
  570 
  571         /* Register the interrupt handler */
  572         if (mpt_setup_intr(dev, mpt->pci_irq, MPT_IFLAGS, NULL, mpt_pci_intr,
  573             mpt, &mpt->ih)) {
  574                 device_printf(dev, "could not setup interrupt\n");
  575                 goto bad;
  576         }
  577 
  578         /* Allocate dma memory */
  579 /* XXX JGibbs -Should really be done based on IOCFacts. */
  580         if (mpt_dma_mem_alloc(mpt)) {
  581                 mpt_prt(mpt, "Could not allocate DMA memory\n");
  582                 goto bad;
  583         }
  584 
  585         /*
  586          * Save the PCI config register values
  587          *
  588          * Hard resets are known to screw up the BAR for diagnostic
  589          * memory accesses (Mem1).
  590          *
  591          * Using Mem1 is known to make the chip stop responding to 
  592          * configuration space transfers, so we need to save it now
  593          */
  594 
  595         mpt_read_config_regs(mpt);
  596 
  597         /*
  598          * Disable PIO until we need it
  599          */
  600         if (mpt->is_sas) {
  601                 pci_disable_io(dev, SYS_RES_IOPORT);
  602         }
  603 
  604         /* Initialize the hardware */
  605         if (mpt->disabled == 0) {
  606                 MPT_LOCK(mpt);
  607                 if (mpt_attach(mpt) != 0) {
  608                         MPT_UNLOCK(mpt);
  609                         goto bad;
  610                 }
  611                 MPT_UNLOCK(mpt);
  612         } else {
  613                 mpt_prt(mpt, "device disabled at user request\n");
  614                 goto bad;
  615         }
  616 
  617         mpt->eh = EVENTHANDLER_REGISTER(shutdown_post_sync, mpt_pci_shutdown,
  618             dev, SHUTDOWN_PRI_DEFAULT);
  619 
  620         if (mpt->eh == NULL) {
  621                 mpt_prt(mpt, "shutdown event registration failed\n");
  622                 MPT_LOCK(mpt);
  623                 (void) mpt_detach(mpt);
  624                 MPT_UNLOCK(mpt);
  625                 goto bad;
  626         }
  627         KASSERT(MPT_OWNED(mpt) == 0, ("leaving attach with device locked"));
  628         return (0);
  629 
  630 bad:
  631         mpt_dma_mem_free(mpt);
  632         mpt_free_bus_resources(mpt);
  633         mpt_unlink_peer(mpt);
  634 
  635         MPT_LOCK_DESTROY(mpt);
  636 
  637         /*
  638          * but return zero to preserve unit numbering
  639          */
  640         return (0);
  641 }
  642 
  643 /*
  644  * Free bus resources
  645  */
  646 static void
  647 mpt_free_bus_resources(struct mpt_softc *mpt)
  648 {
  649         if (mpt->ih) {
  650                 bus_teardown_intr(mpt->dev, mpt->pci_irq, mpt->ih);
  651                 mpt->ih = 0;
  652         }
  653 
  654         if (mpt->pci_irq) {
  655                 bus_release_resource(mpt->dev, SYS_RES_IRQ,
  656                     mpt->pci_msi_count ? 1 : 0, mpt->pci_irq);
  657                 mpt->pci_irq = 0;
  658         }
  659 
  660         if (mpt->pci_msi_count) {
  661                 pci_release_msi(mpt->dev);
  662                 mpt->pci_msi_count = 0;
  663         }
  664                 
  665         if (mpt->pci_pio_reg) {
  666                 bus_release_resource(mpt->dev, SYS_RES_IOPORT, mpt->pci_pio_rid,
  667                         mpt->pci_pio_reg);
  668                 mpt->pci_pio_reg = 0;
  669         }
  670         if (mpt->pci_reg) {
  671                 bus_release_resource(mpt->dev, SYS_RES_MEMORY, mpt->pci_mem_rid,
  672                         mpt->pci_reg);
  673                 mpt->pci_reg = 0;
  674         }
  675         MPT_LOCK_DESTROY(mpt);
  676 }
  677 
  678 
  679 /*
  680  * Disconnect ourselves from the system.
  681  */
  682 static int
  683 mpt_pci_detach(device_t dev)
  684 {
  685         struct mpt_softc *mpt;
  686 
  687         mpt  = (struct mpt_softc*)device_get_softc(dev);
  688 
  689         if (mpt) {
  690                 MPT_LOCK(mpt);
  691                 mpt_disable_ints(mpt);
  692                 mpt_detach(mpt);
  693                 mpt_reset(mpt, /*reinit*/FALSE);
  694                 mpt_dma_mem_free(mpt);
  695                 mpt_free_bus_resources(mpt);
  696                 mpt_raid_free_mem(mpt);
  697                 if (mpt->eh != NULL) {
  698                         EVENTHANDLER_DEREGISTER(shutdown_final, mpt->eh);
  699                 }
  700                 MPT_UNLOCK(mpt);
  701         }
  702         return(0);
  703 }
  704 
  705 
  706 /*
  707  * Disable the hardware
  708  */
  709 static int
  710 mpt_pci_shutdown(device_t dev)
  711 {
  712         struct mpt_softc *mpt;
  713 
  714         mpt = (struct mpt_softc *)device_get_softc(dev);
  715         if (mpt) {
  716                 int r;
  717                 MPT_LOCK(mpt);
  718                 r = mpt_shutdown(mpt);
  719                 MPT_UNLOCK(mpt);
  720                 return (r);
  721         }
  722         return(0);
  723 }
  724 
  725 static int
  726 mpt_dma_mem_alloc(struct mpt_softc *mpt)
  727 {
  728         int i, error, nsegs;
  729         uint8_t *vptr;
  730         uint32_t pptr, end;
  731         size_t len;
  732         struct mpt_map_info mi;
  733 
  734         /* Check if we alreay have allocated the reply memory */
  735         if (mpt->reply_phys != 0) {
  736                 return 0;
  737         }
  738 
  739         len = sizeof (request_t) * MPT_MAX_REQUESTS(mpt);
  740 #ifdef  RELENG_4
  741         mpt->request_pool = (request_t *)malloc(len, M_DEVBUF, M_WAITOK);
  742         if (mpt->request_pool == NULL) {
  743                 mpt_prt(mpt, "cannot allocate request pool\n");
  744                 return (1);
  745         }
  746         memset(mpt->request_pool, 0, len);
  747 #else
  748         mpt->request_pool = (request_t *)malloc(len, M_DEVBUF, M_WAITOK|M_ZERO);
  749         if (mpt->request_pool == NULL) {
  750                 mpt_prt(mpt, "cannot allocate request pool\n");
  751                 return (1);
  752         }
  753 #endif
  754 
  755         /*
  756          * Create a parent dma tag for this device.
  757          *
  758          * Align at byte boundaries,
  759          * Limit to 32-bit addressing for request/reply queues.
  760          */
  761         if (mpt_dma_tag_create(mpt, /*parent*/bus_get_dma_tag(mpt->dev),
  762             /*alignment*/1, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR,
  763             /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL,
  764             /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
  765             /*nsegments*/BUS_SPACE_MAXSIZE_32BIT,
  766             /*maxsegsz*/BUS_SPACE_UNRESTRICTED, /*flags*/0,
  767             &mpt->parent_dmat) != 0) {
  768                 mpt_prt(mpt, "cannot create parent dma tag\n");
  769                 return (1);
  770         }
  771 
  772         /* Create a child tag for reply buffers */
  773         if (mpt_dma_tag_create(mpt, mpt->parent_dmat, PAGE_SIZE, 0,
  774             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
  775             NULL, NULL, 2 * PAGE_SIZE, 1, BUS_SPACE_MAXSIZE_32BIT, 0,
  776             &mpt->reply_dmat) != 0) {
  777                 mpt_prt(mpt, "cannot create a dma tag for replies\n");
  778                 return (1);
  779         }
  780 
  781         /* Allocate some DMA accessable memory for replies */
  782         if (bus_dmamem_alloc(mpt->reply_dmat, (void **)&mpt->reply,
  783             BUS_DMA_NOWAIT, &mpt->reply_dmap) != 0) {
  784                 mpt_prt(mpt, "cannot allocate %lu bytes of reply memory\n",
  785                     (u_long) (2 * PAGE_SIZE));
  786                 return (1);
  787         }
  788 
  789         mi.mpt = mpt;
  790         mi.error = 0;
  791 
  792         /* Load and lock it into "bus space" */
  793         bus_dmamap_load(mpt->reply_dmat, mpt->reply_dmap, mpt->reply,
  794             2 * PAGE_SIZE, mpt_map_rquest, &mi, 0);
  795 
  796         if (mi.error) {
  797                 mpt_prt(mpt, "error %d loading dma map for DMA reply queue\n",
  798                     mi.error);
  799                 return (1);
  800         }
  801         mpt->reply_phys = mi.phys;
  802 
  803         /* Create a child tag for data buffers */
  804 
  805         /*
  806          * XXX: we should say that nsegs is 'unrestricted, but that
  807          * XXX: tickles a horrible bug in the busdma code. Instead,
  808          * XXX: we'll derive a reasonable segment limit from MAXPHYS
  809          */
  810         nsegs = (MAXPHYS / PAGE_SIZE) + 1;
  811         if (mpt_dma_tag_create(mpt, mpt->parent_dmat, 1,
  812             0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
  813             NULL, NULL, MAXBSIZE, nsegs, BUS_SPACE_MAXSIZE_32BIT, 0,
  814             &mpt->buffer_dmat) != 0) {
  815                 mpt_prt(mpt, "cannot create a dma tag for data buffers\n");
  816                 return (1);
  817         }
  818 
  819         /* Create a child tag for request buffers */
  820         if (mpt_dma_tag_create(mpt, mpt->parent_dmat, PAGE_SIZE, 0,
  821             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
  822             NULL, NULL, MPT_REQ_MEM_SIZE(mpt), 1, BUS_SPACE_MAXSIZE_32BIT, 0,
  823             &mpt->request_dmat) != 0) {
  824                 mpt_prt(mpt, "cannot create a dma tag for requests\n");
  825                 return (1);
  826         }
  827 
  828         /* Allocate some DMA accessable memory for requests */
  829         if (bus_dmamem_alloc(mpt->request_dmat, (void **)&mpt->request,
  830             BUS_DMA_NOWAIT, &mpt->request_dmap) != 0) {
  831                 mpt_prt(mpt, "cannot allocate %d bytes of request memory\n",
  832                     MPT_REQ_MEM_SIZE(mpt));
  833                 return (1);
  834         }
  835 
  836         mi.mpt = mpt;
  837         mi.error = 0;
  838 
  839         /* Load and lock it into "bus space" */
  840         bus_dmamap_load(mpt->request_dmat, mpt->request_dmap, mpt->request,
  841             MPT_REQ_MEM_SIZE(mpt), mpt_map_rquest, &mi, 0);
  842 
  843         if (mi.error) {
  844                 mpt_prt(mpt, "error %d loading dma map for DMA request queue\n",
  845                     mi.error);
  846                 return (1);
  847         }
  848         mpt->request_phys = mi.phys;
  849 
  850         /*
  851          * Now create per-request dma maps
  852          */
  853         i = 0;
  854         pptr =  mpt->request_phys;
  855         vptr =  mpt->request;
  856         end = pptr + MPT_REQ_MEM_SIZE(mpt);
  857         while(pptr < end) {
  858                 request_t *req = &mpt->request_pool[i];
  859                 req->index = i++;
  860 
  861                 /* Store location of Request Data */
  862                 req->req_pbuf = pptr;
  863                 req->req_vbuf = vptr;
  864 
  865                 pptr += MPT_REQUEST_AREA;
  866                 vptr += MPT_REQUEST_AREA;
  867 
  868                 req->sense_pbuf = (pptr - MPT_SENSE_SIZE);
  869                 req->sense_vbuf = (vptr - MPT_SENSE_SIZE);
  870 
  871                 error = bus_dmamap_create(mpt->buffer_dmat, 0, &req->dmap);
  872                 if (error) {
  873                         mpt_prt(mpt, "error %d creating per-cmd DMA maps\n",
  874                             error);
  875                         return (1);
  876                 }
  877         }
  878 
  879         return (0);
  880 }
  881 
  882 
  883 
  884 /* Deallocate memory that was allocated by mpt_dma_mem_alloc 
  885  */
  886 static void
  887 mpt_dma_mem_free(struct mpt_softc *mpt)
  888 {
  889         int i;
  890 
  891         /* Make sure we aren't double destroying */
  892         if (mpt->reply_dmat == 0) {
  893                 mpt_lprt(mpt, MPT_PRT_DEBUG, "already released dma memory\n");
  894                 return;
  895         }
  896                 
  897         for (i = 0; i < MPT_MAX_REQUESTS(mpt); i++) {
  898                 bus_dmamap_destroy(mpt->buffer_dmat, mpt->request_pool[i].dmap);
  899         }
  900         bus_dmamap_unload(mpt->request_dmat, mpt->request_dmap);
  901         bus_dmamem_free(mpt->request_dmat, mpt->request, mpt->request_dmap);
  902         bus_dma_tag_destroy(mpt->request_dmat);
  903         bus_dma_tag_destroy(mpt->buffer_dmat);
  904         bus_dmamap_unload(mpt->reply_dmat, mpt->reply_dmap);
  905         bus_dmamem_free(mpt->reply_dmat, mpt->reply, mpt->reply_dmap);
  906         bus_dma_tag_destroy(mpt->reply_dmat);
  907         bus_dma_tag_destroy(mpt->parent_dmat);
  908         mpt->reply_dmat = 0;
  909         free(mpt->request_pool, M_DEVBUF);
  910         mpt->request_pool = 0;
  911 
  912 }
  913 
  914 
  915 
  916 /* Reads modifiable (via PCI transactions) config registers */
  917 static void
  918 mpt_read_config_regs(struct mpt_softc *mpt)
  919 {
  920         mpt->pci_cfg.Command = pci_read_config(mpt->dev, PCIR_COMMAND, 2);
  921         mpt->pci_cfg.LatencyTimer_LineSize =
  922             pci_read_config(mpt->dev, PCIR_CACHELNSZ, 2);
  923         mpt->pci_cfg.IO_BAR = pci_read_config(mpt->dev, PCIR_BAR(0), 4);
  924         mpt->pci_cfg.Mem0_BAR[0] = pci_read_config(mpt->dev, PCIR_BAR(1), 4);
  925         mpt->pci_cfg.Mem0_BAR[1] = pci_read_config(mpt->dev, PCIR_BAR(2), 4);
  926         mpt->pci_cfg.Mem1_BAR[0] = pci_read_config(mpt->dev, PCIR_BAR(3), 4);
  927         mpt->pci_cfg.Mem1_BAR[1] = pci_read_config(mpt->dev, PCIR_BAR(4), 4);
  928         mpt->pci_cfg.ROM_BAR = pci_read_config(mpt->dev, PCIR_BIOS, 4);
  929         mpt->pci_cfg.IntLine = pci_read_config(mpt->dev, PCIR_INTLINE, 1);
  930         mpt->pci_cfg.PMCSR = pci_read_config(mpt->dev, 0x44, 4);
  931 }
  932 
  933 /* Sets modifiable config registers */
  934 void
  935 mpt_set_config_regs(struct mpt_softc *mpt)
  936 {
  937         uint32_t val;
  938 
  939 #define MPT_CHECK(reg, offset, size)                                    \
  940         val = pci_read_config(mpt->dev, offset, size);                  \
  941         if (mpt->pci_cfg.reg != val) {                                  \
  942                 mpt_prt(mpt,                                            \
  943                     "Restoring " #reg " to 0x%X from 0x%X\n",           \
  944                     mpt->pci_cfg.reg, val);                             \
  945         }
  946 
  947         if (mpt->verbose >= MPT_PRT_DEBUG) {
  948                 MPT_CHECK(Command, PCIR_COMMAND, 2);
  949                 MPT_CHECK(LatencyTimer_LineSize, PCIR_CACHELNSZ, 2);
  950                 MPT_CHECK(IO_BAR, PCIR_BAR(0), 4);
  951                 MPT_CHECK(Mem0_BAR[0], PCIR_BAR(1), 4);
  952                 MPT_CHECK(Mem0_BAR[1], PCIR_BAR(2), 4);
  953                 MPT_CHECK(Mem1_BAR[0], PCIR_BAR(3), 4);
  954                 MPT_CHECK(Mem1_BAR[1], PCIR_BAR(4), 4);
  955                 MPT_CHECK(ROM_BAR, PCIR_BIOS, 4);
  956                 MPT_CHECK(IntLine, PCIR_INTLINE, 1);
  957                 MPT_CHECK(PMCSR, 0x44, 4);
  958         }
  959 #undef MPT_CHECK
  960 
  961         pci_write_config(mpt->dev, PCIR_COMMAND, mpt->pci_cfg.Command, 2);
  962         pci_write_config(mpt->dev, PCIR_CACHELNSZ,
  963             mpt->pci_cfg.LatencyTimer_LineSize, 2);
  964         pci_write_config(mpt->dev, PCIR_BAR(0), mpt->pci_cfg.IO_BAR, 4);
  965         pci_write_config(mpt->dev, PCIR_BAR(1), mpt->pci_cfg.Mem0_BAR[0], 4);
  966         pci_write_config(mpt->dev, PCIR_BAR(2), mpt->pci_cfg.Mem0_BAR[1], 4);
  967         pci_write_config(mpt->dev, PCIR_BAR(3), mpt->pci_cfg.Mem1_BAR[0], 4);
  968         pci_write_config(mpt->dev, PCIR_BAR(4), mpt->pci_cfg.Mem1_BAR[1], 4);
  969         pci_write_config(mpt->dev, PCIR_BIOS, mpt->pci_cfg.ROM_BAR, 4);
  970         pci_write_config(mpt->dev, PCIR_INTLINE, mpt->pci_cfg.IntLine, 1);
  971         pci_write_config(mpt->dev, 0x44, mpt->pci_cfg.PMCSR, 4);
  972 }
  973 
  974 static void
  975 mpt_pci_intr(void *arg)
  976 {
  977         struct mpt_softc *mpt;
  978 
  979         mpt = (struct mpt_softc *)arg;
  980         MPT_LOCK(mpt);
  981         mpt_intr(mpt);
  982         MPT_UNLOCK(mpt);
  983 }

Cache object: 883eaa6f350925ebf679981cf6bdf0ae


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