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

Cache object: c9d2cb7747d8045e956b1d5de1c38481


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