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

Cache object: 01b5e6910abd515ac82b96b144fc333d


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