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/mps/mps_config.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) 2011, 2012 LSI Corp.
    3  * 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  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * LSI MPT-Fusion Host Adapter FreeBSD
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD: releng/8.4/sys/dev/mps/mps_config.c 237877 2012-07-01 05:23:59Z ken $");
   31 
   32 /* TODO Move headers to mpsvar */
   33 #include <sys/types.h>
   34 #include <sys/param.h>
   35 #include <sys/lock.h>
   36 #include <sys/mutex.h>
   37 #include <sys/systm.h>
   38 #include <sys/kernel.h>
   39 #include <sys/malloc.h>
   40 #include <sys/kthread.h>
   41 #include <sys/taskqueue.h>
   42 #include <sys/bus.h>
   43 #include <sys/endian.h>
   44 #include <sys/sysctl.h>
   45 #include <sys/eventhandler.h>
   46 #include <sys/uio.h>
   47 #include <machine/bus.h>
   48 #include <machine/resource.h>
   49 #include <dev/mps/mpi/mpi2_type.h>
   50 #include <dev/mps/mpi/mpi2.h>
   51 #include <dev/mps/mpi/mpi2_ioc.h>
   52 #include <dev/mps/mpi/mpi2_sas.h>
   53 #include <dev/mps/mpi/mpi2_cnfg.h>
   54 #include <dev/mps/mpi/mpi2_init.h>
   55 #include <dev/mps/mpi/mpi2_tool.h>
   56 #include <dev/mps/mps_ioctl.h>
   57 #include <dev/mps/mpsvar.h>
   58 
   59 /**
   60  * mps_config_get_ioc_pg8 - obtain ioc page 8
   61  * @sc: per adapter object
   62  * @mpi_reply: reply mf payload returned from firmware
   63  * @config_page: contents of the config page
   64  * Context: sleep.
   65  *
   66  * Returns 0 for success, non-zero for failure.
   67  */
   68 int
   69 mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
   70     Mpi2IOCPage8_t *config_page)
   71 {
   72         MPI2_CONFIG_REQUEST *request;
   73         MPI2_CONFIG_REPLY *reply;
   74         struct mps_command *cm;
   75         MPI2_CONFIG_PAGE_IOC_8 *page = NULL;
   76         int error = 0;
   77         u16 ioc_status;
   78 
   79         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
   80 
   81         if ((cm = mps_alloc_command(sc)) == NULL) {
   82                 printf("%s: command alloc failed @ line %d\n", __func__,
   83                     __LINE__);
   84                 error = EBUSY;
   85                 goto out;
   86         }
   87         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
   88         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
   89         request->Function = MPI2_FUNCTION_CONFIG;
   90         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
   91         request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
   92         request->Header.PageNumber = 8;
   93         request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
   94         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
   95         cm->cm_data = NULL;
   96         error = mps_request_polled(sc, cm);
   97         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
   98         if (error || (reply == NULL)) {
   99                 /* FIXME */
  100                 /* If the poll returns error then we need to do diag reset */ 
  101                 printf("%s: poll for header completed with error %d",
  102                     __func__, error);
  103                 error = ENXIO;
  104                 goto out;
  105         }
  106         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  107         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  108         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  109                 /* FIXME */
  110                 /* If the poll returns error then we need to do diag reset */ 
  111                 printf("%s: header read with error; iocstatus = 0x%x\n",
  112                     __func__, ioc_status);
  113                 error = ENXIO;
  114                 goto out;
  115         }
  116         /* We have to do free and alloc for the reply-free and reply-post
  117          * counters to match - Need to review the reply FIFO handling.
  118          */
  119         mps_free_command(sc, cm);
  120         
  121         if ((cm = mps_alloc_command(sc)) == NULL) {
  122                 printf("%s: command alloc failed @ line %d\n", __func__,
  123                     __LINE__);
  124                 error = EBUSY;
  125                 goto out;
  126         }
  127         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
  128         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
  129         request->Function = MPI2_FUNCTION_CONFIG;
  130         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  131         request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
  132         request->Header.PageNumber = 8;
  133         request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
  134         request->Header.PageLength = mpi_reply->Header.PageLength;
  135         cm->cm_length =  le16toh(mpi_reply->Header.PageLength) * 4;
  136         cm->cm_sge = &request->PageBufferSGE;
  137         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
  138         cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
  139         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  140         page = malloc((cm->cm_length), M_MPT2, M_ZERO | M_NOWAIT);
  141         if (!page) {
  142                 printf("%s: page alloc failed\n", __func__);
  143                 error = ENOMEM;
  144                 goto out;
  145         }
  146         cm->cm_data = page;
  147         error = mps_request_polled(sc, cm);
  148         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  149         if (error || (reply == NULL)) {
  150                 /* FIXME */
  151                 /* If the poll returns error then we need to do diag reset */ 
  152                 printf("%s: poll for page completed with error %d",
  153                     __func__, error);
  154                 error = ENXIO;
  155                 goto out;
  156         }
  157         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  158         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  159         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  160                 /* FIXME */
  161                 /* If the poll returns error then we need to do diag reset */ 
  162                 printf("%s: page read with error; iocstatus = 0x%x\n",
  163                     __func__, ioc_status);
  164                 error = ENXIO;
  165                 goto out;
  166         }
  167         bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t))));
  168 
  169 out:
  170         free(page, M_MPT2);
  171         if (cm)
  172                 mps_free_command(sc, cm);
  173         return (error);
  174 }
  175 
  176 /**
  177  * mps_config_get_man_pg10 - obtain Manufacturing Page 10 data and set flags
  178  *   accordingly.  Currently, this page does not need to return to caller.
  179  * @sc: per adapter object
  180  * @mpi_reply: reply mf payload returned from firmware
  181  * Context: sleep.
  182  *
  183  * Returns 0 for success, non-zero for failure.
  184  */
  185 int
  186 mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply)
  187 {
  188         MPI2_CONFIG_REQUEST *request;
  189         MPI2_CONFIG_REPLY *reply;
  190         struct mps_command *cm;
  191         pMpi2ManufacturingPagePS_t page = NULL;
  192         uint32_t *pPS_info;
  193         uint8_t OEM_Value = 0;
  194         int error = 0;
  195         u16 ioc_status;
  196 
  197         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
  198 
  199         if ((cm = mps_alloc_command(sc)) == NULL) {
  200                 printf("%s: command alloc failed @ line %d\n", __func__,
  201                     __LINE__);
  202                 error = EBUSY;
  203                 goto out;
  204         }
  205         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
  206         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
  207         request->Function = MPI2_FUNCTION_CONFIG;
  208         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  209         request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
  210         request->Header.PageNumber = 10;
  211         request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
  212         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  213         cm->cm_data = NULL;
  214         error = mps_request_polled(sc, cm);
  215         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  216         if (error || (reply == NULL)) {
  217                 /* FIXME */
  218                 /* If the poll returns error then we need to do diag reset */ 
  219                 printf("%s: poll for header completed with error %d",
  220                     __func__, error);
  221                 error = ENXIO;
  222                 goto out;
  223         }
  224         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  225         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  226         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  227                 /* FIXME */
  228                 /* If the poll returns error then we need to do diag reset */ 
  229                 printf("%s: header read with error; iocstatus = 0x%x\n",
  230                     __func__, ioc_status);
  231                 error = ENXIO;
  232                 goto out;
  233         }
  234         /* We have to do free and alloc for the reply-free and reply-post
  235          * counters to match - Need to review the reply FIFO handling.
  236          */
  237         mps_free_command(sc, cm);
  238         
  239         if ((cm = mps_alloc_command(sc)) == NULL) {
  240                 printf("%s: command alloc failed @ line %d\n", __func__,
  241                     __LINE__);
  242                 error = EBUSY;
  243                 goto out;
  244         }
  245         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
  246         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
  247         request->Function = MPI2_FUNCTION_CONFIG;
  248         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  249         request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
  250         request->Header.PageNumber = 10;
  251         request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
  252         request->Header.PageLength = mpi_reply->Header.PageLength;
  253         cm->cm_length =  le16toh(mpi_reply->Header.PageLength) * 4;
  254         cm->cm_sge = &request->PageBufferSGE;
  255         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
  256         cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
  257         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  258         page = malloc(MPS_MAN_PAGE10_SIZE, M_MPT2, M_ZERO | M_NOWAIT);
  259         if (!page) {
  260                 printf("%s: page alloc failed\n", __func__);
  261                 error = ENOMEM;
  262                 goto out;
  263         }
  264         cm->cm_data = page;
  265         error = mps_request_polled(sc, cm);
  266         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  267         if (error || (reply == NULL)) {
  268                 /* FIXME */
  269                 /* If the poll returns error then we need to do diag reset */ 
  270                 printf("%s: poll for page completed with error %d",
  271                     __func__, error);
  272                 error = ENXIO;
  273                 goto out;
  274         }
  275         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  276         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  277         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  278                 /* FIXME */
  279                 /* If the poll returns error then we need to do diag reset */ 
  280                 printf("%s: page read with error; iocstatus = 0x%x\n",
  281                     __func__, ioc_status);
  282                 error = ENXIO;
  283                 goto out;
  284         }
  285 
  286         /*
  287          * If OEM ID is unknown, fail the request.
  288          */
  289         sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
  290         OEM_Value = (uint8_t)(page->ProductSpecificInfo & 0x000000FF);
  291         if (OEM_Value != MPS_WD_LSI_OEM) {
  292                 mps_dprint(sc, MPS_FAULT, "Unknown OEM value for WarpDrive "
  293                     "(0x%x)\n", OEM_Value);
  294                 error = ENXIO;
  295                 goto out;
  296         }
  297 
  298         /*
  299          * Set the phys disks hide/expose value.
  300          */
  301         pPS_info = &page->ProductSpecificInfo;
  302         sc->WD_hide_expose = (uint8_t)(pPS_info[5]);
  303         sc->WD_hide_expose &= MPS_WD_HIDE_EXPOSE_MASK;
  304         if ((sc->WD_hide_expose != MPS_WD_HIDE_ALWAYS) &&
  305             (sc->WD_hide_expose != MPS_WD_EXPOSE_ALWAYS) &&
  306             (sc->WD_hide_expose != MPS_WD_HIDE_IF_VOLUME)) {
  307                 mps_dprint(sc, MPS_FAULT, "Unknown value for WarpDrive "
  308                     "hide/expose: 0x%x\n", sc->WD_hide_expose);
  309                 error = ENXIO;
  310                 goto out;
  311         }
  312 
  313 out:
  314         free(page, M_MPT2);
  315         if (cm)
  316                 mps_free_command(sc, cm);
  317         return (error);
  318 }
  319 
  320 /**
  321  * mps_base_static_config_pages - static start of day config pages.
  322  * @sc: per adapter object
  323  *
  324  * Return nothing.
  325  */
  326 void
  327 mps_base_static_config_pages(struct mps_softc *sc)
  328 {
  329         Mpi2ConfigReply_t       mpi_reply;
  330         int                     retry;
  331 
  332         retry = 0;
  333         while (mps_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
  334                 retry++;
  335                 if (retry > 5) {
  336                         /* We need to Handle this situation */
  337                         /*FIXME*/
  338                         break;
  339                 }
  340         }
  341 }
  342 
  343 /**
  344  * mps_wd_config_pages - get info required to support WarpDrive.  This needs to
  345  *    be called after discovery is complete to guarentee that IR info is there.
  346  * @sc: per adapter object
  347  *
  348  * Return nothing.
  349  */
  350 void
  351 mps_wd_config_pages(struct mps_softc *sc)
  352 {
  353         Mpi2ConfigReply_t       mpi_reply;
  354         pMpi2RaidVolPage0_t     raid_vol_pg0 = NULL;
  355         Mpi2RaidPhysDiskPage0_t phys_disk_pg0;
  356         pMpi2RaidVol0PhysDisk_t pRVPD;
  357         uint32_t                stripe_size, phys_disk_page_address;
  358         uint16_t                block_size;
  359         uint8_t                 index, stripe_exp = 0, block_exp = 0;
  360 
  361         /*
  362          * Get the WD settings from manufacturing page 10 if using a WD HBA.
  363          * This will be used to determine if phys disks should always be
  364          * hidden, hidden only if part of a WD volume, or never hidden.  Also,
  365          * get the WD RAID Volume info and fail if volume does not exist or if
  366          * volume does not meet the requirements for a WD volume.  No retry
  367          * here.  Just default to HIDE ALWAYS if man Page10 fails, or clear WD
  368          * Valid flag if Volume info fails.
  369          */
  370         sc->WD_valid_config = FALSE;
  371         if (sc->mps_flags & MPS_FLAGS_WD_AVAILABLE) {
  372                 if (mps_config_get_man_pg10(sc, &mpi_reply)) {
  373                         mps_dprint(sc, MPS_FAULT,
  374                             "mps_config_get_man_pg10 failed! Using 0 (Hide "
  375                             "Always) for WarpDrive hide/expose value.\n");
  376                         sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
  377                 }
  378 
  379                 /*
  380                  * Get first RAID Volume Page0 using GET_NEXT_HANDLE.
  381                  */
  382                 raid_vol_pg0 = malloc(sizeof(Mpi2RaidVolPage0_t) +
  383                     (sizeof(Mpi2RaidVol0PhysDisk_t) * MPS_MAX_DISKS_IN_VOL),
  384                     M_MPT2, M_ZERO | M_NOWAIT);
  385                 if (!raid_vol_pg0) {
  386                         printf("%s: page alloc failed\n", __func__);
  387                         goto out;
  388                 }
  389 
  390                 if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, raid_vol_pg0,
  391                     0x0000FFFF)) {
  392                         mps_dprint(sc, MPS_INFO,
  393                             "mps_config_get_raid_volume_pg0 failed! Assuming "
  394                             "WarpDrive IT mode.\n");
  395                         goto out;
  396                 }
  397 
  398                 /*
  399                  * Check for valid WD configuration:
  400                  *   volume type is RAID0
  401                  *   number of phys disks in the volume is no more than 8
  402                  */
  403                 if ((raid_vol_pg0->VolumeType != MPI2_RAID_VOL_TYPE_RAID0) ||
  404                     (raid_vol_pg0->NumPhysDisks > 8)) {
  405                         mps_dprint(sc, MPS_FAULT,
  406                             "Invalid WarpDrive configuration. Direct Drive I/O "
  407                             "will not be used.\n");
  408                         goto out;
  409                 }
  410 
  411                 /*
  412                  * Save the WD RAID data to be used during WD I/O.
  413                  */
  414                 sc->DD_max_lba = le64toh((uint64_t)raid_vol_pg0->MaxLBA.High <<
  415                     32 | (uint64_t)raid_vol_pg0->MaxLBA.Low);
  416                 sc->DD_num_phys_disks = raid_vol_pg0->NumPhysDisks;
  417                 sc->DD_dev_handle = raid_vol_pg0->DevHandle;
  418                 sc->DD_stripe_size = raid_vol_pg0->StripeSize;
  419                 sc->DD_block_size = raid_vol_pg0->BlockSize;
  420 
  421                 /*
  422                  * Find power of 2 of stripe size and set this as the exponent.
  423                  * Fail if stripe size is 0.
  424                  */
  425                 stripe_size = raid_vol_pg0->StripeSize;
  426                 for (index = 0; index < 32; index++) {
  427                         if (stripe_size & 1)
  428                                 break;
  429                         stripe_exp++;
  430                         stripe_size >>= 1;
  431                 }
  432                 if (index == 32) {
  433                         mps_dprint(sc, MPS_FAULT,
  434                             "RAID Volume's stripe size is 0. Direct Drive I/O "
  435                             "will not be used.\n");
  436                         goto out;
  437                 }
  438                 sc->DD_stripe_exponent = stripe_exp;
  439 
  440                 /*
  441                  * Find power of 2 of block size and set this as the exponent.
  442                  * Fail if block size is 0.
  443                  */
  444                 block_size = raid_vol_pg0->BlockSize;
  445                 for (index = 0; index < 16; index++) {
  446                         if (block_size & 1)
  447                                 break;
  448                         block_exp++;
  449                         block_size >>= 1;
  450                 }
  451                 if (index == 16) {
  452                         mps_dprint(sc, MPS_FAULT,
  453                             "RAID Volume's block size is 0. Direct Drive I/O "
  454                             "will not be used.\n");
  455                         goto out;
  456                 }
  457                 sc->DD_block_exponent = block_exp;
  458 
  459                 /*
  460                  * Loop through all of the volume's Phys Disks to map the phys
  461                  * disk number into the columm map.  This is used during Direct
  462                  * Drive I/O to send the request to the correct SSD.
  463                  */
  464                 pRVPD = (pMpi2RaidVol0PhysDisk_t)&raid_vol_pg0->PhysDisk;
  465                 for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
  466                         sc->DD_column_map[pRVPD->PhysDiskMap].phys_disk_num =
  467                             pRVPD->PhysDiskNum;
  468                         pRVPD++;
  469                 }
  470 
  471                 /*
  472                  * Get second RAID Volume Page0 using previous handle.  This
  473                  * page should not exist.  If it does, must not proceed with WD
  474                  * handling.
  475                  */
  476                 if (mps_config_get_raid_volume_pg0(sc, &mpi_reply,
  477                     raid_vol_pg0, (u32)raid_vol_pg0->DevHandle)) {
  478                         if (mpi_reply.IOCStatus !=
  479                             MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
  480                                 mps_dprint(sc, MPS_FAULT,
  481                                     "Multiple RAID Volume Page0! Direct Drive "
  482                                     "I/O will not be used.\n");
  483                                 goto out;
  484                         }
  485                 } else {
  486                         mps_dprint(sc, MPS_FAULT,
  487                             "Multiple volumes! Direct Drive I/O will not be "
  488                             "used.\n");
  489                         goto out;
  490                 }
  491 
  492                 /*
  493                  * Get RAID Volume Phys Disk Page 0 for all SSDs in the volume.
  494                  */
  495                 for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
  496                         phys_disk_page_address =
  497                             MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM +
  498                             sc->DD_column_map[index].phys_disk_num;
  499                         if (mps_config_get_raid_pd_pg0(sc, &mpi_reply,
  500                             &phys_disk_pg0, phys_disk_page_address)) {
  501                                 mps_dprint(sc, MPS_FAULT,
  502                                     "mps_config_get_raid_pd_pg0 failed! Direct "
  503                                     "Drive I/O will not be used.\n");
  504                                 goto out;
  505                         }
  506                         if (phys_disk_pg0.DevHandle == 0xFFFF) {
  507                                 mps_dprint(sc, MPS_FAULT,
  508                                     "Invalid Phys Disk DevHandle! Direct Drive "
  509                                     "I/O will not be used.\n");
  510                                 goto out;
  511                         }
  512                         sc->DD_column_map[index].dev_handle =
  513                             phys_disk_pg0.DevHandle;
  514                 }
  515                 sc->WD_valid_config = TRUE;
  516 out:
  517                 if (raid_vol_pg0)
  518                         free(raid_vol_pg0, M_MPT2);
  519         }
  520 }
  521 
  522 /**
  523  * mps_config_get_dpm_pg0 - obtain driver persistent mapping page0
  524  * @sc: per adapter object
  525  * @mpi_reply: reply mf payload returned from firmware
  526  * @config_page: contents of the config page
  527  * @sz: size of buffer passed in config_page
  528  * Context: sleep.
  529  *
  530  * Returns 0 for success, non-zero for failure.
  531  */
  532 int
  533 mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
  534     Mpi2DriverMappingPage0_t *config_page, u16 sz)
  535 {
  536         MPI2_CONFIG_REQUEST *request;
  537         MPI2_CONFIG_REPLY *reply;
  538         struct mps_command *cm;
  539         Mpi2DriverMappingPage0_t *page = NULL;
  540         int error = 0;
  541         u16 ioc_status;
  542 
  543         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
  544 
  545         memset(config_page, 0, sz);
  546         if ((cm = mps_alloc_command(sc)) == NULL) {
  547                 printf("%s: command alloc failed @ line %d\n", __func__,
  548                     __LINE__);
  549                 error = EBUSY;
  550                 goto out;
  551         }
  552         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
  553         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
  554         request->Function = MPI2_FUNCTION_CONFIG;
  555         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  556         request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  557         request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
  558         request->Header.PageNumber = 0;
  559         request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
  560         request->PageAddress = sc->max_dpm_entries <<
  561             MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
  562         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  563         cm->cm_data = NULL;
  564         error = mps_request_polled(sc, cm);
  565         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  566         if (error || (reply == NULL)) {
  567                 /* FIXME */
  568                 /* If the poll returns error then we need to do diag reset */ 
  569                 printf("%s: poll for header completed with error %d",
  570                     __func__, error);
  571                 error = ENXIO;
  572                 goto out;
  573         }
  574         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  575         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  576         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  577                 /* FIXME */
  578                 /* If the poll returns error then we need to do diag reset */ 
  579                 printf("%s: header read with error; iocstatus = 0x%x\n",
  580                     __func__, ioc_status);
  581                 error = ENXIO;
  582                 goto out;
  583         }
  584         /* We have to do free and alloc for the reply-free and reply-post
  585          * counters to match - Need to review the reply FIFO handling.
  586          */
  587         mps_free_command(sc, cm);
  588 
  589         if ((cm = mps_alloc_command(sc)) == NULL) {
  590                 printf("%s: command alloc failed @ line %d\n", __func__,
  591                     __LINE__);
  592                 error = EBUSY;
  593                 goto out;
  594         }
  595         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
  596         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
  597         request->Function = MPI2_FUNCTION_CONFIG;
  598         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM;
  599         request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  600         request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
  601         request->Header.PageNumber = 0;
  602         request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
  603         request->PageAddress = sc->max_dpm_entries <<
  604             MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
  605         request->ExtPageLength = mpi_reply->ExtPageLength;
  606         cm->cm_length =  le16toh(request->ExtPageLength) * 4;
  607         cm->cm_sge = &request->PageBufferSGE;
  608         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
  609         cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
  610         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  611         page = malloc(cm->cm_length, M_MPT2, M_ZERO|M_NOWAIT);
  612         if (!page) {
  613                 printf("%s: page alloc failed\n", __func__);
  614                 error = ENOMEM;
  615                 goto out;
  616         }
  617         cm->cm_data = page;
  618         error = mps_request_polled(sc, cm);
  619         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  620         if (error || (reply == NULL)) {
  621                 /* FIXME */
  622                 /* If the poll returns error then we need to do diag reset */ 
  623                 printf("%s: poll for page completed with error %d",
  624                     __func__, error);
  625                 error = ENXIO;
  626                 goto out;
  627         }
  628         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  629         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  630         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  631                 /* FIXME */
  632                 /* If the poll returns error then we need to do diag reset */ 
  633                 printf("%s: page read with error; iocstatus = 0x%x\n",
  634                     __func__, ioc_status);
  635                 error = ENXIO;
  636                 goto out;
  637         }
  638         bcopy(page, config_page, MIN(cm->cm_length, sz));
  639 out:
  640         free(page, M_MPT2);
  641         if (cm)
  642                 mps_free_command(sc, cm);
  643         return (error);
  644 }
  645 
  646 /**
  647  * mps_config_set_dpm_pg0 - write an entry in driver persistent mapping page0
  648  * @sc: per adapter object
  649  * @mpi_reply: reply mf payload returned from firmware
  650  * @config_page: contents of the config page
  651  * @entry_idx: entry index in DPM Page0 to be modified
  652  * Context: sleep.
  653  *
  654  * Returns 0 for success, non-zero for failure.
  655  */
  656 
  657 int mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
  658     Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
  659 {
  660         MPI2_CONFIG_REQUEST *request;
  661         MPI2_CONFIG_REPLY *reply;
  662         struct mps_command *cm;
  663         MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL; 
  664         int error = 0;
  665         u16 ioc_status;
  666 
  667         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
  668 
  669         if ((cm = mps_alloc_command(sc)) == NULL) {
  670                 printf("%s: command alloc failed @ line %d\n", __func__,
  671                     __LINE__);
  672                 error = EBUSY;
  673                 goto out;
  674         }
  675         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
  676         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
  677         request->Function = MPI2_FUNCTION_CONFIG;
  678         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  679         request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  680         request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
  681         request->Header.PageNumber = 0;
  682         request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
  683         /* We can remove below two lines ????*/
  684         request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
  685         request->PageAddress |= htole16(entry_idx);
  686         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  687         cm->cm_data = NULL;
  688         error = mps_request_polled(sc, cm);
  689         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  690         if (error || (reply == NULL)) {
  691                 /* FIXME */
  692                 /* If the poll returns error then we need to do diag reset */ 
  693                 printf("%s: poll for header completed with error %d",
  694                     __func__, error);
  695                 error = ENXIO;
  696                 goto out;
  697         }
  698         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  699         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  700         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  701                 /* FIXME */
  702                 /* If the poll returns error then we need to do diag reset */ 
  703                 printf("%s: header read with error; iocstatus = 0x%x\n",
  704                     __func__, ioc_status);
  705                 error = ENXIO;
  706                 goto out;
  707         }
  708         /* We have to do free and alloc for the reply-free and reply-post
  709          * counters to match - Need to review the reply FIFO handling.
  710          */     
  711         mps_free_command(sc, cm);
  712 
  713         if ((cm = mps_alloc_command(sc)) == NULL) {
  714                 printf("%s: command alloc failed @ line %d\n", __func__,
  715                     __LINE__);
  716                 error = EBUSY;
  717                 goto out;
  718         }
  719         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
  720         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
  721         request->Function = MPI2_FUNCTION_CONFIG;
  722         request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
  723         request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  724         request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
  725         request->Header.PageNumber = 0;
  726         request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
  727         request->ExtPageLength = mpi_reply->ExtPageLength;
  728         request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
  729         request->PageAddress |= htole16(entry_idx);
  730         cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
  731         cm->cm_sge = &request->PageBufferSGE;
  732         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
  733         cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAOUT;
  734         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  735         page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
  736         if (!page) {
  737                 printf("%s: page alloc failed\n", __func__);
  738                 error = ENOMEM;
  739                 goto out;
  740         }
  741         bcopy(config_page, page, MIN(cm->cm_length, 
  742             (sizeof(Mpi2DriverMappingPage0_t))));
  743         cm->cm_data = page;
  744         error = mps_request_polled(sc, cm);
  745         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  746         if (error || (reply == NULL)) {
  747                 /* FIXME */
  748                 /* If the poll returns error then we need to do diag reset */ 
  749                 printf("%s: poll for page completed with error %d",
  750                     __func__, error);
  751                 error = ENXIO;
  752                 goto out;
  753         }
  754         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  755         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  756         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  757                 /* FIXME */
  758                 /* If the poll returns error then we need to do diag reset */ 
  759                 printf("%s: page written with error; iocstatus = 0x%x\n",
  760                     __func__, ioc_status);
  761                 error = ENXIO;
  762                 goto out;
  763         }
  764 out:
  765         free(page, M_MPT2);
  766         if (cm)
  767                 mps_free_command(sc, cm);
  768         return (error);
  769 }
  770 
  771 /**
  772  * mps_config_get_sas_device_pg0 - obtain sas device page 0
  773  * @sc: per adapter object
  774  * @mpi_reply: reply mf payload returned from firmware
  775  * @config_page: contents of the config page
  776  * @form: GET_NEXT_HANDLE or HANDLE
  777  * @handle: device handle
  778  * Context: sleep.
  779  *
  780  * Returns 0 for success, non-zero for failure.
  781  */
  782 int
  783 mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
  784     *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
  785 {
  786         MPI2_CONFIG_REQUEST *request;
  787         MPI2_CONFIG_REPLY *reply;
  788         struct mps_command *cm;
  789         Mpi2SasDevicePage0_t *page = NULL;
  790         int error = 0;
  791         u16 ioc_status;
  792 
  793         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
  794 
  795         if ((cm = mps_alloc_command(sc)) == NULL) {
  796                 printf("%s: command alloc failed @ line %d\n", __func__,
  797                     __LINE__);
  798                 error = EBUSY;
  799                 goto out;
  800         }
  801         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
  802         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
  803         request->Function = MPI2_FUNCTION_CONFIG;
  804         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  805         request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  806         request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
  807         request->Header.PageNumber = 0;
  808         request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
  809         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  810         cm->cm_data = NULL;
  811         error = mps_request_polled(sc, cm);
  812         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  813         if (error || (reply == NULL)) {
  814                 /* FIXME */
  815                 /* If the poll returns error then we need to do diag reset */ 
  816                 printf("%s: poll for header completed with error %d",
  817                     __func__, error);
  818                 error = ENXIO;
  819                 goto out;
  820         }
  821         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  822         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  823         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  824                 /* FIXME */
  825                 /* If the poll returns error then we need to do diag reset */ 
  826                 printf("%s: header read with error; iocstatus = 0x%x\n",
  827                     __func__, ioc_status);
  828                 error = ENXIO;
  829                 goto out;
  830         }
  831         /* We have to do free and alloc for the reply-free and reply-post
  832          * counters to match - Need to review the reply FIFO handling.
  833          */
  834         mps_free_command(sc, cm);
  835 
  836         if ((cm = mps_alloc_command(sc)) == NULL) {
  837                 printf("%s: command alloc failed @ line %d\n", __func__,
  838                     __LINE__);
  839                 error = EBUSY;
  840                 goto out;
  841         }
  842         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
  843         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
  844         request->Function = MPI2_FUNCTION_CONFIG;
  845         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  846         request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  847         request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
  848         request->Header.PageNumber = 0;
  849         request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
  850         request->ExtPageLength = mpi_reply->ExtPageLength;
  851         request->PageAddress = htole32(form | handle);
  852         cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
  853         cm->cm_sge = &request->PageBufferSGE;
  854         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
  855         cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
  856         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  857         page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
  858         if (!page) {
  859                 printf("%s: page alloc failed\n", __func__);
  860                 error = ENOMEM;
  861                 goto out;
  862         }
  863         cm->cm_data = page;
  864 
  865         error = mps_request_polled(sc, cm);
  866         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  867         if (error || (reply == NULL)) {
  868                 /* FIXME */
  869                 /* If the poll returns error then we need to do diag reset */ 
  870                 printf("%s: poll for page completed with error %d",
  871                     __func__, error);
  872                 error = ENXIO;
  873                 goto out;
  874         }
  875         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  876         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  877         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  878                 /* FIXME */
  879                 /* If the poll returns error then we need to do diag reset */ 
  880                 printf("%s: page read with error; iocstatus = 0x%x\n",
  881                     __func__, ioc_status);
  882                 error = ENXIO;
  883                 goto out;
  884         }
  885         bcopy(page, config_page, MIN(cm->cm_length, 
  886             sizeof(Mpi2SasDevicePage0_t)));
  887 out:
  888         free(page, M_MPT2);
  889         if (cm)
  890                 mps_free_command(sc, cm);
  891         return (error);
  892 }
  893 
  894 /**
  895  * mps_config_get_bios_pg3 - obtain BIOS page 3
  896  * @sc: per adapter object
  897  * @mpi_reply: reply mf payload returned from firmware
  898  * @config_page: contents of the config page
  899  * Context: sleep.
  900  *
  901  * Returns 0 for success, non-zero for failure.
  902  */
  903 int
  904 mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
  905     Mpi2BiosPage3_t *config_page)
  906 {
  907         MPI2_CONFIG_REQUEST *request;
  908         MPI2_CONFIG_REPLY *reply;
  909         struct mps_command *cm;
  910         Mpi2BiosPage3_t *page = NULL;
  911         int error = 0;
  912         u16 ioc_status;
  913 
  914         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
  915 
  916         if ((cm = mps_alloc_command(sc)) == NULL) {
  917                 printf("%s: command alloc failed @ line %d\n", __func__,
  918                     __LINE__);
  919                 error = EBUSY;
  920                 goto out;
  921         }
  922         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
  923         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
  924         request->Function = MPI2_FUNCTION_CONFIG;
  925         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  926         request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
  927         request->Header.PageNumber = 3;
  928         request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
  929         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  930         cm->cm_data = NULL;
  931         error = mps_request_polled(sc, cm);
  932         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  933         if (error || (reply == NULL)) {
  934                 /* FIXME */
  935                 /* If the poll returns error then we need to do diag reset */ 
  936                 printf("%s: poll for header completed with error %d",
  937                     __func__, error);
  938                 error = ENXIO;
  939                 goto out;
  940         }
  941         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  942         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  943         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  944                 /* FIXME */
  945                 /* If the poll returns error then we need to do diag reset */ 
  946                 printf("%s: header read with error; iocstatus = 0x%x\n",
  947                     __func__, ioc_status);
  948                 error = ENXIO;
  949                 goto out;
  950         }
  951         /* We have to do free and alloc for the reply-free and reply-post
  952          * counters to match - Need to review the reply FIFO handling.
  953          */
  954         mps_free_command(sc, cm);
  955 
  956         if ((cm = mps_alloc_command(sc)) == NULL) {
  957                 printf("%s: command alloc failed @ line %d\n", __func__,
  958                     __LINE__);
  959                 error = EBUSY;
  960                 goto out;
  961         }
  962         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
  963         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
  964         request->Function = MPI2_FUNCTION_CONFIG;
  965         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  966         request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
  967         request->Header.PageNumber = 3;
  968         request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
  969         request->Header.PageLength = mpi_reply->Header.PageLength;
  970         cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
  971         cm->cm_sge = &request->PageBufferSGE;
  972         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
  973         cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
  974         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  975         page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
  976         if (!page) {
  977                 printf("%s: page alloc failed\n", __func__);
  978                 error = ENOMEM;
  979                 goto out;
  980         }
  981         cm->cm_data = page;
  982 
  983         error = mps_request_polled(sc, cm);
  984         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  985         if (error || (reply == NULL)) {
  986                 /* FIXME */
  987                 /* If the poll returns error then we need to do diag reset */ 
  988                 printf("%s: poll for page completed with error %d",
  989                     __func__, error);
  990                 error = ENXIO;
  991                 goto out;
  992         }
  993         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  994         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  995         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  996                 /* FIXME */
  997                 /* If the poll returns error then we need to do diag reset */ 
  998                 printf("%s: page read with error; iocstatus = 0x%x\n",
  999                     __func__, ioc_status);
 1000                 error = ENXIO;
 1001                 goto out;
 1002         }
 1003         bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
 1004 out:
 1005         free(page, M_MPT2);
 1006         if (cm)
 1007                 mps_free_command(sc, cm);
 1008         return (error);
 1009 }
 1010 
 1011 /**
 1012  * mps_config_get_raid_volume_pg0 - obtain raid volume page 0
 1013  * @sc: per adapter object
 1014  * @mpi_reply: reply mf payload returned from firmware
 1015  * @config_page: contents of the config page
 1016  * @page_address: form and handle value used to get page
 1017  * Context: sleep.
 1018  *
 1019  * Returns 0 for success, non-zero for failure.
 1020  */
 1021 int
 1022 mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
 1023     *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
 1024 {
 1025         MPI2_CONFIG_REQUEST *request;
 1026         MPI2_CONFIG_REPLY *reply;
 1027         struct mps_command *cm;
 1028         Mpi2RaidVolPage0_t *page = NULL;
 1029         int error = 0;
 1030         u16 ioc_status;
 1031 
 1032         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
 1033 
 1034         if ((cm = mps_alloc_command(sc)) == NULL) {
 1035                 printf("%s: command alloc failed @ line %d\n", __func__,
 1036                     __LINE__);
 1037                 error = EBUSY;
 1038                 goto out;
 1039         }
 1040         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
 1041         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
 1042         request->Function = MPI2_FUNCTION_CONFIG;
 1043         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 1044         request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
 1045         request->Header.PageNumber = 0;
 1046         request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
 1047         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1048         cm->cm_data = NULL;
 1049         error = mps_request_polled(sc, cm);
 1050         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
 1051         if (error || (reply == NULL)) {
 1052                 /* FIXME */
 1053                 /* If the poll returns error then we need to do diag reset */ 
 1054                 printf("%s: poll for header completed with error %d",
 1055                     __func__, error);
 1056                 error = ENXIO;
 1057                 goto out;
 1058         }
 1059         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
 1060         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
 1061         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
 1062                 /* FIXME */
 1063                 /* If the poll returns error then we need to do diag reset */ 
 1064                 printf("%s: header read with error; iocstatus = 0x%x\n",
 1065                     __func__, ioc_status);
 1066                 error = ENXIO;
 1067                 goto out;
 1068         }
 1069         /* We have to do free and alloc for the reply-free and reply-post
 1070          * counters to match - Need to review the reply FIFO handling.
 1071          */
 1072         mps_free_command(sc, cm);
 1073 
 1074         if ((cm = mps_alloc_command(sc)) == NULL) {
 1075                 printf("%s: command alloc failed @ line %d\n", __func__,
 1076                     __LINE__);
 1077                 error = EBUSY;
 1078                 goto out;
 1079         }
 1080         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
 1081         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
 1082         request->Function = MPI2_FUNCTION_CONFIG;
 1083         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 1084         request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
 1085         request->Header.PageNumber = 0;
 1086         request->Header.PageLength = mpi_reply->Header.PageLength;
 1087         request->Header.PageVersion = mpi_reply->Header.PageVersion;
 1088         request->PageAddress = page_address;
 1089         cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
 1090         cm->cm_sge = &request->PageBufferSGE;
 1091         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
 1092         cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
 1093         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1094         page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
 1095         if (!page) {
 1096                 printf("%s: page alloc failed\n", __func__);
 1097                 error = ENOMEM;
 1098                 goto out;
 1099         }
 1100         cm->cm_data = page;
 1101 
 1102         error = mps_request_polled(sc, cm);
 1103         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
 1104         if (error || (reply == NULL)) {
 1105                 /* FIXME */
 1106                 /* If the poll returns error then we need to do diag reset */ 
 1107                 printf("%s: poll for page completed with error %d",
 1108                     __func__, error);
 1109                 error = ENXIO;
 1110                 goto out;
 1111         }
 1112         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
 1113         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
 1114         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
 1115                 /* FIXME */
 1116                 /* If the poll returns error then we need to do diag reset */ 
 1117                 printf("%s: page read with error; iocstatus = 0x%x\n",
 1118                     __func__, ioc_status);
 1119                 error = ENXIO;
 1120                 goto out;
 1121         }
 1122         bcopy(page, config_page, cm->cm_length);
 1123 out:
 1124         free(page, M_MPT2);
 1125         if (cm)
 1126                 mps_free_command(sc, cm);
 1127         return (error);
 1128 }
 1129 
 1130 /**
 1131  * mps_config_get_raid_volume_pg1 - obtain raid volume page 1
 1132  * @sc: per adapter object
 1133  * @mpi_reply: reply mf payload returned from firmware
 1134  * @config_page: contents of the config page
 1135  * @form: GET_NEXT_HANDLE or HANDLE
 1136  * @handle: volume handle
 1137  * Context: sleep.
 1138  *
 1139  * Returns 0 for success, non-zero for failure.
 1140  */
 1141 int
 1142 mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t
 1143     *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
 1144 {
 1145         MPI2_CONFIG_REQUEST *request;
 1146         MPI2_CONFIG_REPLY *reply;
 1147         struct mps_command *cm;
 1148         Mpi2RaidVolPage1_t *page = NULL;
 1149         int error = 0;
 1150         u16 ioc_status;
 1151 
 1152         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
 1153 
 1154         if ((cm = mps_alloc_command(sc)) == NULL) {
 1155                 printf("%s: command alloc failed @ line %d\n", __func__,
 1156                     __LINE__);
 1157                 error = EBUSY;
 1158                 goto out;
 1159         }
 1160         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
 1161         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
 1162         request->Function = MPI2_FUNCTION_CONFIG;
 1163         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 1164         request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
 1165         request->Header.PageNumber = 1;
 1166         request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
 1167         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1168         cm->cm_data = NULL;
 1169         error = mps_request_polled(sc, cm);
 1170         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
 1171         if (error || (reply == NULL)) {
 1172                 /* FIXME */
 1173                 /* If the poll returns error then we need to do diag reset */ 
 1174                 printf("%s: poll for header completed with error %d",
 1175                     __func__, error);
 1176                 error = ENXIO;
 1177                 goto out;
 1178         }
 1179         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
 1180         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
 1181         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
 1182                 /* FIXME */
 1183                 /* If the poll returns error then we need to do diag reset */ 
 1184                 printf("%s: header read with error; iocstatus = 0x%x\n",
 1185                     __func__, ioc_status);
 1186                 error = ENXIO;
 1187                 goto out;
 1188         }
 1189         /* We have to do free and alloc for the reply-free and reply-post
 1190          * counters to match - Need to review the reply FIFO handling.
 1191          */
 1192         mps_free_command(sc, cm);
 1193 
 1194         if ((cm = mps_alloc_command(sc)) == NULL) {
 1195                 printf("%s: command alloc failed @ line %d\n", __func__,
 1196                     __LINE__);
 1197                 error = EBUSY;
 1198                 goto out;
 1199         }
 1200         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
 1201         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
 1202         request->Function = MPI2_FUNCTION_CONFIG;
 1203         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 1204         request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
 1205         request->Header.PageNumber = 1;
 1206         request->Header.PageLength = mpi_reply->Header.PageLength;
 1207         request->Header.PageVersion = mpi_reply->Header.PageVersion;
 1208         request->PageAddress = htole32(form | handle);
 1209         cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
 1210         cm->cm_sge = &request->PageBufferSGE;
 1211         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
 1212         cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
 1213         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1214         page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
 1215         if (!page) {
 1216                 printf("%s: page alloc failed\n", __func__);
 1217                 error = ENOMEM;
 1218                 goto out;
 1219         }
 1220         cm->cm_data = page;
 1221 
 1222         error = mps_request_polled(sc, cm);
 1223         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
 1224         if (error || (reply == NULL)) {
 1225                 /* FIXME */
 1226                 /* If the poll returns error then we need to do diag reset */ 
 1227                 printf("%s: poll for page completed with error %d",
 1228                     __func__, error);
 1229                 error = ENXIO;
 1230                 goto out;
 1231         }
 1232         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
 1233         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
 1234         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
 1235                 /* FIXME */
 1236                 /* If the poll returns error then we need to do diag reset */ 
 1237                 printf("%s: page read with error; iocstatus = 0x%x\n",
 1238                     __func__, ioc_status);
 1239                 error = ENXIO;
 1240                 goto out;
 1241         }
 1242         bcopy(page, config_page, MIN(cm->cm_length,
 1243             sizeof(Mpi2RaidVolPage1_t)));
 1244 out:
 1245         free(page, M_MPT2);
 1246         if (cm)
 1247                 mps_free_command(sc, cm);
 1248         return (error);
 1249 }
 1250 
 1251 /**
 1252  * mps_config_get_volume_wwid - returns wwid given the volume handle
 1253  * @sc: per adapter object
 1254  * @volume_handle: volume handle
 1255  * @wwid: volume wwid
 1256  * Context: sleep.
 1257  *
 1258  * Returns 0 for success, non-zero for failure.
 1259  */
 1260 int
 1261 mps_config_get_volume_wwid(struct mps_softc *sc, u16 volume_handle, u64 *wwid)
 1262 {
 1263         Mpi2ConfigReply_t mpi_reply;
 1264         Mpi2RaidVolPage1_t raid_vol_pg1;
 1265 
 1266         *wwid = 0;
 1267         if (!(mps_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
 1268             MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
 1269                 *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
 1270                     raid_vol_pg1.WWID.Low);
 1271                 return 0;
 1272         } else
 1273                 return -1;
 1274 }
 1275 
 1276 /**
 1277  * mps_config_get_pd_pg0 - obtain raid phys disk page 0
 1278  * @sc: per adapter object
 1279  * @mpi_reply: reply mf payload returned from firmware
 1280  * @config_page: contents of the config page
 1281  * @page_address: form and handle value used to get page
 1282  * Context: sleep.
 1283  *
 1284  * Returns 0 for success, non-zero for failure.
 1285  */
 1286 int
 1287 mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
 1288     Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
 1289 {
 1290         MPI2_CONFIG_REQUEST *request;
 1291         MPI2_CONFIG_REPLY *reply;
 1292         struct mps_command *cm;
 1293         Mpi2RaidPhysDiskPage0_t *page = NULL;
 1294         int error = 0;
 1295         u16 ioc_status;
 1296 
 1297         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
 1298 
 1299         if ((cm = mps_alloc_command(sc)) == NULL) {
 1300                 printf("%s: command alloc failed @ line %d\n", __func__,
 1301                     __LINE__);
 1302                 error = EBUSY;
 1303                 goto out;
 1304         }
 1305         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
 1306         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
 1307         request->Function = MPI2_FUNCTION_CONFIG;
 1308         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 1309         request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
 1310         request->Header.PageNumber = 0;
 1311         request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
 1312         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1313         cm->cm_data = NULL;
 1314         error = mps_request_polled(sc, cm);
 1315         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
 1316         if (error || (reply == NULL)) {
 1317                 /* FIXME */
 1318                 /* If the poll returns error then we need to do diag reset */ 
 1319                 printf("%s: poll for header completed with error %d",
 1320                     __func__, error);
 1321                 error = ENXIO;
 1322                 goto out;
 1323         }
 1324         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
 1325         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
 1326         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
 1327                 /* FIXME */
 1328                 /* If the poll returns error then we need to do diag reset */ 
 1329                 printf("%s: header read with error; iocstatus = 0x%x\n",
 1330                     __func__, ioc_status);
 1331                 error = ENXIO;
 1332                 goto out;
 1333         }
 1334         /* We have to do free and alloc for the reply-free and reply-post
 1335          * counters to match - Need to review the reply FIFO handling.
 1336          */
 1337         mps_free_command(sc, cm);
 1338 
 1339         if ((cm = mps_alloc_command(sc)) == NULL) {
 1340                 printf("%s: command alloc failed @ line %d\n", __func__,
 1341                     __LINE__);
 1342                 error = EBUSY;
 1343                 goto out;
 1344         }
 1345         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
 1346         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
 1347         request->Function = MPI2_FUNCTION_CONFIG;
 1348         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 1349         request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
 1350         request->Header.PageNumber = 0;
 1351         request->Header.PageLength = mpi_reply->Header.PageLength;
 1352         request->Header.PageVersion = mpi_reply->Header.PageVersion;
 1353         request->PageAddress = page_address;
 1354         cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
 1355         cm->cm_sge = &request->PageBufferSGE;
 1356         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
 1357         cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
 1358         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1359         page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
 1360         if (!page) {
 1361                 printf("%s: page alloc failed\n", __func__);
 1362                 error = ENOMEM;
 1363                 goto out;
 1364         }
 1365         cm->cm_data = page;
 1366 
 1367         error = mps_request_polled(sc, cm);
 1368         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
 1369         if (error || (reply == NULL)) {
 1370                 /* FIXME */
 1371                 /* If the poll returns error then we need to do diag reset */ 
 1372                 printf("%s: poll for page completed with error %d",
 1373                     __func__, error);
 1374                 error = ENXIO;
 1375                 goto out;
 1376         }
 1377         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
 1378         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
 1379         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
 1380                 /* FIXME */
 1381                 /* If the poll returns error then we need to do diag reset */ 
 1382                 printf("%s: page read with error; iocstatus = 0x%x\n",
 1383                     __func__, ioc_status);
 1384                 error = ENXIO;
 1385                 goto out;
 1386         }
 1387         bcopy(page, config_page, MIN(cm->cm_length,
 1388             sizeof(Mpi2RaidPhysDiskPage0_t)));
 1389 out:
 1390         free(page, M_MPT2);
 1391         if (cm)
 1392                 mps_free_command(sc, cm);
 1393         return (error);
 1394 }

Cache object: 400a647f1255db64769486a8ba8adb8c


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