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/mpr/mpr_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-2015 LSI Corp.
    3  * Copyright (c) 2013-2016 Avago Technologies
    4  * Copyright 2000-2020 Broadcom Inc.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  *
   28  * Broadcom Inc. (LSI) MPT-Fusion Host Adapter FreeBSD
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD$");
   33 
   34 /* TODO Move headers to mprvar */
   35 #include <sys/types.h>
   36 #include <sys/param.h>
   37 #include <sys/lock.h>
   38 #include <sys/mutex.h>
   39 #include <sys/systm.h>
   40 #include <sys/kernel.h>
   41 #include <sys/malloc.h>
   42 #include <sys/kthread.h>
   43 #include <sys/taskqueue.h>
   44 #include <sys/bus.h>
   45 #include <sys/endian.h>
   46 #include <sys/sysctl.h>
   47 #include <sys/eventhandler.h>
   48 #include <sys/uio.h>
   49 #include <machine/bus.h>
   50 #include <machine/resource.h>
   51 #include <dev/mpr/mpi/mpi2_type.h>
   52 #include <dev/mpr/mpi/mpi2.h>
   53 #include <dev/mpr/mpi/mpi2_ioc.h>
   54 #include <dev/mpr/mpi/mpi2_sas.h>
   55 #include <dev/mpr/mpi/mpi2_pci.h>
   56 #include <dev/mpr/mpi/mpi2_cnfg.h>
   57 #include <dev/mpr/mpi/mpi2_init.h>
   58 #include <dev/mpr/mpi/mpi2_tool.h>
   59 #include <dev/mpr/mpr_ioctl.h>
   60 #include <dev/mpr/mprvar.h>
   61 
   62 /**
   63  * mpr_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 mpr_config_get_ioc_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
   73     Mpi2IOCPage8_t *config_page)
   74 {
   75         MPI2_CONFIG_REQUEST *request;
   76         MPI2_CONFIG_REPLY *reply;
   77         struct mpr_command *cm;
   78         MPI2_CONFIG_PAGE_IOC_8 *page = NULL;
   79         int error = 0;
   80         u16 ioc_status;
   81 
   82         mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
   83 
   84         if ((cm = mpr_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.PageLength = request->Header.PageVersion = 0;
   97         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
   98         cm->cm_data = NULL;
   99         error = mpr_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",
  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         mpr_free_command(sc, cm);
  130 
  131         if ((cm = mpr_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 = mpi_reply->Header.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 = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
  149         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  150         page = malloc((cm->cm_length), M_MPR, 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 = mpr_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",
  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_MPR);
  189         if (cm)
  190                 mpr_free_command(sc, cm);
  191         return (error);
  192 }
  193 
  194 /**
  195  * mpr_config_get_iounit_pg8 - obtain iounit page 8
  196  * @sc: per adapter object
  197  * @mpi_reply: reply mf payload returned from firmware
  198  * @config_page: contents of the config page
  199  * Context: sleep.
  200  *
  201  * Returns 0 for success, non-zero for failure.
  202  */
  203 int
  204 mpr_config_get_iounit_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
  205     Mpi2IOUnitPage8_t *config_page)
  206 {
  207         MPI2_CONFIG_REQUEST *request;
  208         MPI2_CONFIG_REPLY *reply;
  209         struct mpr_command *cm;
  210         MPI2_CONFIG_PAGE_IO_UNIT_8 *page = NULL;
  211         int error = 0;
  212         u16 ioc_status;
  213 
  214         mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
  215 
  216         if ((cm = mpr_alloc_command(sc)) == NULL) {
  217                 printf("%s: command alloc failed @ line %d\n", __func__,
  218                     __LINE__);
  219                 error = EBUSY;
  220                 goto out;
  221         }
  222         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
  223         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
  224         request->Function = MPI2_FUNCTION_CONFIG;
  225         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  226         request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
  227         request->Header.PageNumber = 8;
  228         request->Header.PageLength = request->Header.PageVersion = 0;
  229         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  230         cm->cm_data = NULL;
  231         error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
  232         if (cm != NULL)
  233                 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  234         if (error || (reply == NULL)) {
  235                 /* FIXME */
  236                 /*
  237                  * If the request returns an error then we need to do a diag
  238                  * reset
  239                  */ 
  240                 printf("%s: request for header completed with error %d",
  241                     __func__, error);
  242                 error = ENXIO;
  243                 goto out;
  244         }
  245         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  246         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  247         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  248                 /* FIXME */
  249                 /*
  250                  * If the request returns an error then we need to do a diag
  251                  * reset
  252                  */ 
  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         mpr_free_command(sc, cm);
  262 
  263         if ((cm = mpr_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_IO_UNIT;
  274         request->Header.PageNumber = 8;
  275         request->Header.PageVersion = mpi_reply->Header.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 = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
  281         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  282         page = malloc((cm->cm_length), M_MPR, 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         error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
  291         if (cm != NULL)
  292                 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  293         if (error || (reply == NULL)) {
  294                 /* FIXME */
  295                 /*
  296                  * If the request returns an error then we need to do a diag
  297                  * reset
  298                  */ 
  299                 printf("%s: request for page completed with error %d",
  300                     __func__, error);
  301                 error = ENXIO;
  302                 goto out;
  303         }
  304         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  305         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  306         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  307                 /* FIXME */
  308                 /*
  309                  * If the request returns an error then we need to do a diag
  310                  * reset
  311                  */ 
  312                 printf("%s: page read with error; iocstatus = 0x%x\n",
  313                     __func__, ioc_status);
  314                 error = ENXIO;
  315                 goto out;
  316         }
  317         bcopy(page, config_page, MIN(cm->cm_length,
  318             (sizeof(Mpi2IOUnitPage8_t))));
  319 
  320 out:
  321         free(page, M_MPR);
  322         if (cm)
  323                 mpr_free_command(sc, cm);
  324         return (error);
  325 }
  326 
  327 /**
  328  * mpr_config_get_man_pg11 - obtain manufacturing page 11
  329  * @sc: per adapter object
  330  * @mpi_reply: reply mf payload returned from firmware
  331  * @config_page: contents of the config page
  332  * Context: sleep.
  333  *
  334  * Returns 0 for success, non-zero for failure.
  335  */
  336 int
  337 mpr_config_get_man_pg11(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
  338     Mpi2ManufacturingPage11_t *config_page)
  339 {
  340         MPI2_CONFIG_REQUEST *request;
  341         MPI2_CONFIG_REPLY *reply;
  342         struct mpr_command *cm;
  343         MPI2_CONFIG_PAGE_MAN_11 *page = NULL;
  344         int error = 0;
  345         u16 ioc_status;
  346 
  347         mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
  348 
  349         if ((cm = mpr_alloc_command(sc)) == NULL) {
  350                 printf("%s: command alloc failed @ line %d\n", __func__,
  351                     __LINE__);
  352                 error = EBUSY;
  353                 goto out;
  354         }
  355         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
  356         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
  357         request->Function = MPI2_FUNCTION_CONFIG;
  358         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  359         request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
  360         request->Header.PageNumber = 11;
  361         request->Header.PageLength = request->Header.PageVersion = 0;
  362         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  363         cm->cm_data = NULL;
  364         error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
  365         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  366         if (error || (reply == NULL)) {
  367                 /* FIXME */
  368                 /*
  369                  * If the request returns an error then we need to do a diag
  370                  * reset
  371                  */ 
  372                 printf("%s: request for header completed with error %d",
  373                     __func__, error);
  374                 error = ENXIO;
  375                 goto out;
  376         }
  377         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  378         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  379         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  380                 /* FIXME */
  381                 /*
  382                  * If the request returns an error then we need to do a diag
  383                  * reset
  384                  */ 
  385                 printf("%s: header read with error; iocstatus = 0x%x\n",
  386                     __func__, ioc_status);
  387                 error = ENXIO;
  388                 goto out;
  389         }
  390         /* We have to do free and alloc for the reply-free and reply-post
  391          * counters to match - Need to review the reply FIFO handling.
  392          */
  393         mpr_free_command(sc, cm);
  394 
  395         if ((cm = mpr_alloc_command(sc)) == NULL) {
  396                 printf("%s: command alloc failed @ line %d\n", __func__,
  397                     __LINE__);
  398                 error = EBUSY;
  399                 goto out;
  400         }
  401         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
  402         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
  403         request->Function = MPI2_FUNCTION_CONFIG;
  404         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  405         request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
  406         request->Header.PageNumber = 11;
  407         request->Header.PageVersion = mpi_reply->Header.PageVersion;
  408         request->Header.PageLength = mpi_reply->Header.PageLength;
  409         cm->cm_length =  le16toh(mpi_reply->Header.PageLength) * 4;
  410         cm->cm_sge = &request->PageBufferSGE;
  411         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
  412         cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
  413         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  414         page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
  415         if (!page) {
  416                 printf("%s: page alloc failed\n", __func__);
  417                 error = ENOMEM;
  418                 goto out;
  419         }
  420         cm->cm_data = page;
  421 
  422         error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
  423         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  424         if (error || (reply == NULL)) {
  425                 /* FIXME */
  426                 /*
  427                  * If the request returns an error then we need to do a diag
  428                  * reset
  429                  */ 
  430                 printf("%s: request for page completed with error %d",
  431                     __func__, error);
  432                 error = ENXIO;
  433                 goto out;
  434         }
  435         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  436         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  437         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  438                 /* FIXME */
  439                 /*
  440                  * If the request returns an error then we need to do a diag
  441                  * reset
  442                  */ 
  443                 printf("%s: page read with error; iocstatus = 0x%x\n",
  444                     __func__, ioc_status);
  445                 error = ENXIO;
  446                 goto out;
  447         }
  448         bcopy(page, config_page, MIN(cm->cm_length,
  449             (sizeof(Mpi2ManufacturingPage11_t))));
  450 
  451 out:
  452         free(page, M_MPR);
  453         if (cm)
  454                 mpr_free_command(sc, cm);
  455         return (error);
  456 }
  457 
  458 /**
  459  * mpr_base_static_config_pages - static start of day config pages.
  460  * @sc: per adapter object
  461  *
  462  * Return nothing.
  463  */
  464 void
  465 mpr_base_static_config_pages(struct mpr_softc *sc)
  466 {
  467         Mpi2ConfigReply_t               mpi_reply;
  468         Mpi2ManufacturingPage11_t       man_pg11;
  469         int                             retry, rc;
  470 
  471         retry = 0;
  472         while (mpr_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
  473                 retry++;
  474                 if (retry > 5) {
  475                         /* We need to Handle this situation */
  476                         /*FIXME*/
  477                         break;
  478                 }
  479         }
  480         retry = 0;
  481         while (mpr_config_get_iounit_pg8(sc, &mpi_reply, &sc->iounit_pg8)) {
  482                 retry++;
  483                 if (retry > 5) {
  484                         /* We need to Handle this situation */
  485                         /*FIXME*/
  486                         break;
  487                 }
  488         }
  489         retry = 0;
  490         while ((rc = mpr_config_get_man_pg11(sc, &mpi_reply, &man_pg11))) {
  491                 retry++;
  492                 if (retry > 5) {
  493                         /* We need to Handle this situation */
  494                         /*FIXME*/
  495                         break;
  496                 }
  497         }
  498 
  499         if (!rc) {
  500                 sc->custom_nvme_tm_handling = (le16toh(man_pg11.AddlFlags2) &
  501                     MPI2_MAN_PG11_ADDLFLAGS2_CUSTOM_TM_HANDLING_MASK);
  502                 sc->nvme_abort_timeout = man_pg11.NVMeAbortTO;
  503 
  504                 /* Minimum NVMe Abort timeout value should be 6 seconds &
  505                  * maximum value should be 60 seconds.
  506                  */
  507                 if (sc->nvme_abort_timeout < 6)
  508                         sc->nvme_abort_timeout = 6;
  509                 if (sc->nvme_abort_timeout > 60)
  510                         sc->nvme_abort_timeout = 60;
  511         }
  512 }
  513 
  514 /**
  515  * mpr_config_get_dpm_pg0 - obtain driver persistent mapping page0
  516  * @sc: per adapter object
  517  * @mpi_reply: reply mf payload returned from firmware
  518  * @config_page: contents of the config page
  519  * @sz: size of buffer passed in config_page
  520  * Context: sleep.
  521  *
  522  * Returns 0 for success, non-zero for failure.
  523  */
  524 int
  525 mpr_config_get_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
  526     Mpi2DriverMappingPage0_t *config_page, u16 sz)
  527 {
  528         MPI2_CONFIG_REQUEST *request;
  529         MPI2_CONFIG_REPLY *reply;
  530         struct mpr_command *cm;
  531         Mpi2DriverMappingPage0_t *page = NULL;
  532         int error = 0;
  533         u16 ioc_status;
  534 
  535         mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
  536 
  537         memset(config_page, 0, sz);
  538         if ((cm = mpr_alloc_command(sc)) == NULL) {
  539                 printf("%s: command alloc failed @ line %d\n", __func__,
  540                     __LINE__);
  541                 error = EBUSY;
  542                 goto out;
  543         }
  544         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
  545         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
  546         request->Function = MPI2_FUNCTION_CONFIG;
  547         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  548         request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  549         request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
  550         request->Header.PageNumber = 0;
  551         request->ExtPageLength = request->Header.PageVersion = 0;
  552         request->PageAddress = sc->max_dpm_entries <<
  553             MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
  554         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  555         cm->cm_data = NULL;
  556         error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
  557         if (cm != NULL)
  558                 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  559         if (error || (reply == NULL)) {
  560                 /* FIXME */
  561                 /*
  562                  * If the request returns an error then we need to do a diag
  563                  * reset
  564                  */ 
  565                 printf("%s: request for header completed with error %d",
  566                     __func__, error);
  567                 error = ENXIO;
  568                 goto out;
  569         }
  570         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  571         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  572         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  573                 /* FIXME */
  574                 /*
  575                  * If the request returns an error then we need to do a diag
  576                  * reset
  577                  */ 
  578                 printf("%s: header read with error; iocstatus = 0x%x\n",
  579                     __func__, ioc_status);
  580                 error = ENXIO;
  581                 goto out;
  582         }
  583         /* We have to do free and alloc for the reply-free and reply-post
  584          * counters to match - Need to review the reply FIFO handling.
  585          */
  586         mpr_free_command(sc, cm);
  587 
  588         if ((cm = mpr_alloc_command(sc)) == NULL) {
  589                 printf("%s: command alloc failed @ line %d\n", __func__,
  590                     __LINE__);
  591                 error = EBUSY;
  592                 goto out;
  593         }
  594         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
  595         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
  596         request->Function = MPI2_FUNCTION_CONFIG;
  597         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM;
  598         request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  599         request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
  600         request->Header.PageNumber = 0;
  601         request->Header.PageVersion = mpi_reply->Header.PageVersion;
  602         request->PageAddress = sc->max_dpm_entries <<
  603             MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
  604         request->ExtPageLength = mpi_reply->ExtPageLength;
  605         cm->cm_length =  le16toh(request->ExtPageLength) * 4;
  606         cm->cm_sge = &request->PageBufferSGE;
  607         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
  608         cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
  609         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  610         page = malloc(cm->cm_length, M_MPR, M_ZERO|M_NOWAIT);
  611         if (!page) {
  612                 printf("%s: page alloc failed\n", __func__);
  613                 error = ENOMEM;
  614                 goto out;
  615         }
  616         cm->cm_data = page;
  617         error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
  618         if (cm != NULL)
  619                 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  620         if (error || (reply == NULL)) {
  621                 /* FIXME */
  622                 /*
  623                  * If the request returns an error then we need to do a diag
  624                  * reset
  625                  */ 
  626                 printf("%s: request for page completed with error %d",
  627                     __func__, error);
  628                 error = ENXIO;
  629                 goto out;
  630         }
  631         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  632         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  633         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  634                 /* FIXME */
  635                 /*
  636                  * If the request returns an error then we need to do a diag
  637                  * reset
  638                  */ 
  639                 printf("%s: page read with error; iocstatus = 0x%x\n",
  640                     __func__, ioc_status);
  641                 error = ENXIO;
  642                 goto out;
  643         }
  644         bcopy(page, config_page, MIN(cm->cm_length, sz));
  645 out:
  646         free(page, M_MPR);
  647         if (cm)
  648                 mpr_free_command(sc, cm);
  649         return (error);
  650 }
  651 
  652 /**
  653  * mpr_config_set_dpm_pg0 - write an entry in driver persistent mapping page0
  654  * @sc: per adapter object
  655  * @mpi_reply: reply mf payload returned from firmware
  656  * @config_page: contents of the config page
  657  * @entry_idx: entry index in DPM Page0 to be modified
  658  * Context: sleep.
  659  *
  660  * Returns 0 for success, non-zero for failure.
  661  */
  662 
  663 int mpr_config_set_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
  664     Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
  665 {
  666         MPI2_CONFIG_REQUEST *request;
  667         MPI2_CONFIG_REPLY *reply;
  668         struct mpr_command *cm;
  669         MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL; 
  670         int error = 0;
  671         u16 ioc_status;
  672 
  673         mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
  674 
  675         if ((cm = mpr_alloc_command(sc)) == NULL) {
  676                 printf("%s: command alloc failed @ line %d\n", __func__,
  677                     __LINE__);
  678                 error = EBUSY;
  679                 goto out;
  680         }
  681         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
  682         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
  683         request->Function = MPI2_FUNCTION_CONFIG;
  684         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  685         request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  686         request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
  687         request->Header.PageNumber = 0;
  688         request->ExtPageLength = request->Header.PageVersion = 0;
  689         /* We can remove below two lines ????*/
  690         request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
  691         request->PageAddress |= htole16(entry_idx);
  692         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  693         cm->cm_data = NULL;
  694         error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
  695         if (cm != NULL)
  696                 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  697         if (error || (reply == NULL)) {
  698                 /* FIXME */
  699                 /*
  700                  * If the request returns an error then we need to do a diag
  701                  * reset
  702                  */ 
  703                 printf("%s: request for header completed with error %d",
  704                     __func__, error);
  705                 error = ENXIO;
  706                 goto out;
  707         }
  708         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  709         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  710         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  711                 /* FIXME */
  712                 /*
  713                  * If the request returns an error then we need to do a diag
  714                  * reset
  715                  */ 
  716                 printf("%s: header read with error; iocstatus = 0x%x\n",
  717                     __func__, ioc_status);
  718                 error = ENXIO;
  719                 goto out;
  720         }
  721         /* We have to do free and alloc for the reply-free and reply-post
  722          * counters to match - Need to review the reply FIFO handling.
  723          */     
  724         mpr_free_command(sc, cm);
  725 
  726         if ((cm = mpr_alloc_command(sc)) == NULL) {
  727                 printf("%s: command alloc failed @ line %d\n", __func__,
  728                     __LINE__);
  729                 error = EBUSY;
  730                 goto out;
  731         }
  732         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
  733         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
  734         request->Function = MPI2_FUNCTION_CONFIG;
  735         request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
  736         request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  737         request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
  738         request->Header.PageNumber = 0;
  739         request->Header.PageVersion = mpi_reply->Header.PageVersion;
  740         request->ExtPageLength = mpi_reply->ExtPageLength;
  741         request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
  742         request->PageAddress |= htole16(entry_idx);
  743         cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
  744         cm->cm_sge = &request->PageBufferSGE;
  745         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
  746         cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAOUT;
  747         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  748         page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
  749         if (!page) {
  750                 printf("%s: page alloc failed\n", __func__);
  751                 error = ENOMEM;
  752                 goto out;
  753         }
  754         bcopy(config_page, page, MIN(cm->cm_length, 
  755             (sizeof(Mpi2DriverMappingPage0_t))));
  756         cm->cm_data = page;
  757         error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
  758         if (cm != NULL)
  759                 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  760         if (error || (reply == NULL)) {
  761                 /* FIXME */
  762                 /*
  763                  * If the request returns an error then we need to do a diag
  764                  * reset
  765                  */ 
  766                 printf("%s: request to write page completed with error %d",
  767                     __func__, error);
  768                 error = ENXIO;
  769                 goto out;
  770         }
  771         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  772         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  773         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  774                 /* FIXME */
  775                 /*
  776                  * If the request returns an error then we need to do a diag
  777                  * reset
  778                  */ 
  779                 printf("%s: page written with error; iocstatus = 0x%x\n",
  780                     __func__, ioc_status);
  781                 error = ENXIO;
  782                 goto out;
  783         }
  784 out:
  785         free(page, M_MPR);
  786         if (cm)
  787                 mpr_free_command(sc, cm);
  788         return (error);
  789 }
  790 
  791 /**
  792  * mpr_config_get_sas_device_pg0 - obtain sas device page 0
  793  * @sc: per adapter object
  794  * @mpi_reply: reply mf payload returned from firmware
  795  * @config_page: contents of the config page
  796  * @form: GET_NEXT_HANDLE or HANDLE
  797  * @handle: device handle
  798  * Context: sleep.
  799  *
  800  * Returns 0 for success, non-zero for failure.
  801  */
  802 int
  803 mpr_config_get_sas_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
  804     *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
  805 {
  806         MPI2_CONFIG_REQUEST *request;
  807         MPI2_CONFIG_REPLY *reply;
  808         struct mpr_command *cm;
  809         Mpi2SasDevicePage0_t *page = NULL;
  810         int error = 0;
  811         u16 ioc_status;
  812 
  813         mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
  814 
  815         if ((cm = mpr_alloc_command(sc)) == NULL) {
  816                 printf("%s: command alloc failed @ line %d\n", __func__,
  817                     __LINE__);
  818                 error = EBUSY;
  819                 goto out;
  820         }
  821         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
  822         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
  823         request->Function = MPI2_FUNCTION_CONFIG;
  824         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  825         request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  826         request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
  827         request->Header.PageNumber = 0;
  828         request->ExtPageLength = request->Header.PageVersion = 0;
  829         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  830         cm->cm_data = NULL;
  831         error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
  832         if (cm != NULL)
  833                 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  834         if (error || (reply == NULL)) {
  835                 /* FIXME */
  836                 /*
  837                  * If the request returns an error then we need to do a diag
  838                  * reset
  839                  */ 
  840                 printf("%s: request for header completed with error %d",
  841                     __func__, error);
  842                 error = ENXIO;
  843                 goto out;
  844         }
  845         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  846         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  847         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  848                 /* FIXME */
  849                 /*
  850                  * If the request returns an error then we need to do a diag
  851                  * reset
  852                  */ 
  853                 printf("%s: header read with error; iocstatus = 0x%x\n",
  854                     __func__, ioc_status);
  855                 error = ENXIO;
  856                 goto out;
  857         }
  858         /* We have to do free and alloc for the reply-free and reply-post
  859          * counters to match - Need to review the reply FIFO handling.
  860          */
  861         mpr_free_command(sc, cm);
  862 
  863         if ((cm = mpr_alloc_command(sc)) == NULL) {
  864                 printf("%s: command alloc failed @ line %d\n", __func__,
  865                     __LINE__);
  866                 error = EBUSY;
  867                 goto out;
  868         }
  869         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
  870         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
  871         request->Function = MPI2_FUNCTION_CONFIG;
  872         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  873         request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  874         request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
  875         request->Header.PageNumber = 0;
  876         request->Header.PageVersion = mpi_reply->Header.PageVersion;
  877         request->ExtPageLength = mpi_reply->ExtPageLength;
  878         request->PageAddress = htole32(form | handle);
  879         cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
  880         cm->cm_sge = &request->PageBufferSGE;
  881         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
  882         cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
  883         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  884         page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
  885         if (!page) {
  886                 printf("%s: page alloc failed\n", __func__);
  887                 error = ENOMEM;
  888                 goto out;
  889         }
  890         cm->cm_data = page;
  891 
  892         error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
  893         if (cm != NULL)
  894                 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  895         if (error || (reply == NULL)) {
  896                 /* FIXME */
  897                 /*
  898                  * If the request returns an error then we need to do a diag
  899                  * reset
  900                  */ 
  901                 printf("%s: request for page completed with error %d",
  902                     __func__, error);
  903                 error = ENXIO;
  904                 goto out;
  905         }
  906         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  907         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  908         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  909                 /* FIXME */
  910                 /*
  911                  * If the request returns an error then we need to do a diag
  912                  * reset
  913                  */ 
  914                 printf("%s: page read with error; iocstatus = 0x%x\n",
  915                     __func__, ioc_status);
  916                 error = ENXIO;
  917                 goto out;
  918         }
  919         bcopy(page, config_page, MIN(cm->cm_length, 
  920             sizeof(Mpi2SasDevicePage0_t)));
  921 out:
  922         free(page, M_MPR);
  923         if (cm)
  924                 mpr_free_command(sc, cm);
  925         return (error);
  926 }
  927 
  928 /**
  929  * mpr_config_get_pcie_device_pg0 - obtain PCIe device page 0
  930  * @sc: per adapter object
  931  * @mpi_reply: reply mf payload returned from firmware
  932  * @config_page: contents of the config page
  933  * @form: GET_NEXT_HANDLE or HANDLE
  934  * @handle: device handle
  935  * Context: sleep.
  936  *
  937  * Returns 0 for success, non-zero for failure.
  938  */
  939 int
  940 mpr_config_get_pcie_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
  941     *mpi_reply, Mpi26PCIeDevicePage0_t *config_page, u32 form, u16 handle)
  942 {
  943         MPI2_CONFIG_REQUEST *request;
  944         MPI2_CONFIG_REPLY *reply;
  945         struct mpr_command *cm;
  946         Mpi26PCIeDevicePage0_t *page = NULL;
  947         int error = 0;
  948         u16 ioc_status;
  949 
  950         mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
  951 
  952         if ((cm = mpr_alloc_command(sc)) == NULL) {
  953                 printf("%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_HEADER;
  962         request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  963         request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
  964         request->Header.PageNumber = 0;
  965         request->ExtPageLength = request->Header.PageVersion = 0;
  966         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  967         cm->cm_data = NULL;
  968         error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
  969         if (cm != NULL)
  970                 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
  971         if (error || (reply == NULL)) {
  972                 /* FIXME */
  973                 /*
  974                  * If the request returns an error then we need to do a diag
  975                  * reset
  976                  */ 
  977                 printf("%s: request for header completed with error %d",
  978                     __func__, error);
  979                 error = ENXIO;
  980                 goto out;
  981         }
  982         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
  983         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
  984         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
  985                 /* FIXME */
  986                 /*
  987                  * If the request returns an error then we need to do a diag
  988                  * reset
  989                  */ 
  990                 printf("%s: header read with error; iocstatus = 0x%x\n",
  991                     __func__, ioc_status);
  992                 error = ENXIO;
  993                 goto out;
  994         }
  995         /* We have to do free and alloc for the reply-free and reply-post
  996          * counters to match - Need to review the reply FIFO handling.
  997          */
  998         mpr_free_command(sc, cm);
  999 
 1000         if ((cm = mpr_alloc_command(sc)) == NULL) {
 1001                 printf("%s: command alloc failed @ line %d\n", __func__,
 1002                     __LINE__);
 1003                 error = EBUSY;
 1004                 goto out;
 1005         }
 1006         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
 1007         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
 1008         request->Function = MPI2_FUNCTION_CONFIG;
 1009         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 1010         request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
 1011         request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
 1012         request->Header.PageNumber = 0;
 1013         request->Header.PageVersion = mpi_reply->Header.PageVersion;
 1014         request->ExtPageLength = mpi_reply->ExtPageLength;
 1015         request->PageAddress = htole32(form | handle);
 1016         cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
 1017         cm->cm_sge = &request->PageBufferSGE;
 1018         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
 1019         cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
 1020         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1021         page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
 1022         if (!page) {
 1023                 printf("%s: page alloc failed\n", __func__);
 1024                 error = ENOMEM;
 1025                 goto out;
 1026         }
 1027         cm->cm_data = page;
 1028 
 1029         error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
 1030         if (cm != NULL)
 1031                 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
 1032         if (error || (reply == NULL)) {
 1033                 /* FIXME */
 1034                 /*
 1035                  * If the request returns an error then we need to do a diag
 1036                  * reset
 1037                  */ 
 1038                 printf("%s: request for page completed with error %d",
 1039                     __func__, error);
 1040                 error = ENXIO;
 1041                 goto out;
 1042         }
 1043         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
 1044         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
 1045         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
 1046                 /* FIXME */
 1047                 /*
 1048                  * If the request returns an error then we need to do a diag
 1049                  * reset
 1050                  */ 
 1051                 printf("%s: page read with error; iocstatus = 0x%x\n",
 1052                     __func__, ioc_status);
 1053                 error = ENXIO;
 1054                 goto out;
 1055         }
 1056         bcopy(page, config_page, MIN(cm->cm_length, 
 1057             sizeof(Mpi26PCIeDevicePage0_t)));
 1058 out:
 1059         free(page, M_MPR);
 1060         if (cm)
 1061                 mpr_free_command(sc, cm);
 1062         return (error);
 1063 }
 1064 
 1065 /**
 1066  * mpr_config_get_pcie_device_pg2 - obtain PCIe device page 2
 1067  * @sc: per adapter object
 1068  * @mpi_reply: reply mf payload returned from firmware
 1069  * @config_page: contents of the config page
 1070  * @form: GET_NEXT_HANDLE or HANDLE
 1071  * @handle: device handle
 1072  * Context: sleep.
 1073  *
 1074  * Returns 0 for success, non-zero for failure.
 1075  */
 1076 int
 1077 mpr_config_get_pcie_device_pg2(struct mpr_softc *sc, Mpi2ConfigReply_t
 1078     *mpi_reply, Mpi26PCIeDevicePage2_t *config_page, u32 form, u16 handle)
 1079 {
 1080         MPI2_CONFIG_REQUEST *request;
 1081         MPI2_CONFIG_REPLY *reply;
 1082         struct mpr_command *cm;
 1083         Mpi26PCIeDevicePage2_t *page = NULL;
 1084         int error = 0;
 1085         u16 ioc_status;
 1086 
 1087         mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
 1088 
 1089         if ((cm = mpr_alloc_command(sc)) == NULL) {
 1090                 printf("%s: command alloc failed @ line %d\n", __func__,
 1091                     __LINE__);
 1092                 error = EBUSY;
 1093                 goto out;
 1094         }
 1095         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
 1096         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
 1097         request->Function = MPI2_FUNCTION_CONFIG;
 1098         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 1099         request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
 1100         request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
 1101         request->Header.PageNumber = 2;
 1102         request->ExtPageLength = request->Header.PageVersion = 0;
 1103         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1104         cm->cm_data = NULL;
 1105         error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
 1106         if (cm != NULL)
 1107                 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
 1108         if (error || (reply == NULL)) {
 1109                 /* FIXME */
 1110                 /*
 1111                  * If the request returns an error then we need to do a diag
 1112                  * reset
 1113                  */ 
 1114                 printf("%s: request for header completed with error %d",
 1115                     __func__, error);
 1116                 error = ENXIO;
 1117                 goto out;
 1118         }
 1119         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
 1120         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
 1121         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
 1122                 /* FIXME */
 1123                 /*
 1124                  * If the request returns an error then we need to do a diag
 1125                  * reset
 1126                  */ 
 1127                 printf("%s: header read with error; iocstatus = 0x%x\n",
 1128                     __func__, ioc_status);
 1129                 error = ENXIO;
 1130                 goto out;
 1131         }
 1132         /* We have to do free and alloc for the reply-free and reply-post
 1133          * counters to match - Need to review the reply FIFO handling.
 1134          */
 1135         mpr_free_command(sc, cm);
 1136 
 1137         if ((cm = mpr_alloc_command(sc)) == NULL) {
 1138                 printf("%s: command alloc failed @ line %d\n", __func__,
 1139                     __LINE__);
 1140                 error = EBUSY;
 1141                 goto out;
 1142         }
 1143         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
 1144         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
 1145         request->Function = MPI2_FUNCTION_CONFIG;
 1146         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 1147         request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
 1148         request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
 1149         request->Header.PageNumber = 2;
 1150         request->Header.PageVersion = mpi_reply->Header.PageVersion;
 1151         request->ExtPageLength = mpi_reply->ExtPageLength;
 1152         request->PageAddress = htole32(form | handle);
 1153         cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
 1154         cm->cm_sge = &request->PageBufferSGE;
 1155         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
 1156         cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
 1157         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1158         page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
 1159         if (!page) {
 1160                 printf("%s: page alloc failed\n", __func__);
 1161                 error = ENOMEM;
 1162                 goto out;
 1163         }
 1164         cm->cm_data = page;
 1165 
 1166         error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
 1167         if (cm != NULL)
 1168                 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
 1169         if (error || (reply == NULL)) {
 1170                 /* FIXME */
 1171                 /*
 1172                  * If the request returns an error then we need to do a diag
 1173                  * reset
 1174                  */ 
 1175                 printf("%s: request for page completed with error %d",
 1176                     __func__, error);
 1177                 error = ENXIO;
 1178                 goto out;
 1179         }
 1180         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
 1181         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
 1182         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
 1183                 /* FIXME */
 1184                 /*
 1185                  * If the request returns an error then we need to do a diag
 1186                  * reset
 1187                  */ 
 1188                 printf("%s: page read with error; iocstatus = 0x%x\n",
 1189                     __func__, ioc_status);
 1190                 error = ENXIO;
 1191                 goto out;
 1192         }
 1193         bcopy(page, config_page, MIN(cm->cm_length, 
 1194             sizeof(Mpi26PCIeDevicePage2_t)));
 1195 out:
 1196         free(page, M_MPR);
 1197         if (cm)
 1198                 mpr_free_command(sc, cm);
 1199         return (error);
 1200 }
 1201 
 1202 /**
 1203  * mpr_config_get_bios_pg3 - obtain BIOS page 3
 1204  * @sc: per adapter object
 1205  * @mpi_reply: reply mf payload returned from firmware
 1206  * @config_page: contents of the config page
 1207  * Context: sleep.
 1208  *
 1209  * Returns 0 for success, non-zero for failure.
 1210  */
 1211 int
 1212 mpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
 1213     Mpi2BiosPage3_t *config_page)
 1214 {
 1215         MPI2_CONFIG_REQUEST *request;
 1216         MPI2_CONFIG_REPLY *reply;
 1217         struct mpr_command *cm;
 1218         Mpi2BiosPage3_t *page = NULL;
 1219         int error = 0;
 1220         u16 ioc_status;
 1221 
 1222         mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
 1223 
 1224         if ((cm = mpr_alloc_command(sc)) == NULL) {
 1225                 printf("%s: command alloc failed @ line %d\n", __func__,
 1226                     __LINE__);
 1227                 error = EBUSY;
 1228                 goto out;
 1229         }
 1230         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
 1231         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
 1232         request->Function = MPI2_FUNCTION_CONFIG;
 1233         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 1234         request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
 1235         request->Header.PageNumber = 3;
 1236         request->Header.PageLength = request->Header.PageVersion = 0;
 1237         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1238         cm->cm_data = NULL;
 1239         error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
 1240         if (cm != NULL)
 1241                 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
 1242         if (error || (reply == NULL)) {
 1243                 /* FIXME */
 1244                 /*
 1245                  * If the request returns an error then we need to do a diag
 1246                  * reset
 1247                  */ 
 1248                 printf("%s: request for header completed with error %d",
 1249                     __func__, error);
 1250                 error = ENXIO;
 1251                 goto out;
 1252         }
 1253         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
 1254         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
 1255         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
 1256                 /* FIXME */
 1257                 /*
 1258                  * If the request returns an error then we need to do a diag
 1259                  * reset
 1260                  */ 
 1261                 printf("%s: header read with error; iocstatus = 0x%x\n",
 1262                     __func__, ioc_status);
 1263                 error = ENXIO;
 1264                 goto out;
 1265         }
 1266         /* We have to do free and alloc for the reply-free and reply-post
 1267          * counters to match - Need to review the reply FIFO handling.
 1268          */
 1269         mpr_free_command(sc, cm);
 1270 
 1271         if ((cm = mpr_alloc_command(sc)) == NULL) {
 1272                 printf("%s: command alloc failed @ line %d\n", __func__,
 1273                     __LINE__);
 1274                 error = EBUSY;
 1275                 goto out;
 1276         }
 1277         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
 1278         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
 1279         request->Function = MPI2_FUNCTION_CONFIG;
 1280         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 1281         request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
 1282         request->Header.PageNumber = 3;
 1283         request->Header.PageVersion = mpi_reply->Header.PageVersion;
 1284         request->Header.PageLength = mpi_reply->Header.PageLength;
 1285         cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
 1286         cm->cm_sge = &request->PageBufferSGE;
 1287         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
 1288         cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
 1289         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1290         page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
 1291         if (!page) {
 1292                 printf("%s: page alloc failed\n", __func__);
 1293                 error = ENOMEM;
 1294                 goto out;
 1295         }
 1296         cm->cm_data = page;
 1297 
 1298         error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
 1299         if (cm != NULL)
 1300                 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
 1301         if (error || (reply == NULL)) {
 1302                 /* FIXME */
 1303                 /*
 1304                  * If the request returns an error then we need to do a diag
 1305                  * reset
 1306                  */ 
 1307                 printf("%s: request for page completed with error %d",
 1308                     __func__, error);
 1309                 error = ENXIO;
 1310                 goto out;
 1311         }
 1312         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
 1313         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
 1314         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
 1315                 /* FIXME */
 1316                 /*
 1317                  * If the request returns an error then we need to do a diag
 1318                  * reset
 1319                  */ 
 1320                 printf("%s: page read with error; iocstatus = 0x%x\n",
 1321                     __func__, ioc_status);
 1322                 error = ENXIO;
 1323                 goto out;
 1324         }
 1325         bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
 1326 out:
 1327         free(page, M_MPR);
 1328         if (cm)
 1329                 mpr_free_command(sc, cm);
 1330         return (error);
 1331 }
 1332 
 1333 /**
 1334  * mpr_config_get_raid_volume_pg0 - obtain raid volume page 0
 1335  * @sc: per adapter object
 1336  * @mpi_reply: reply mf payload returned from firmware
 1337  * @config_page: contents of the config page
 1338  * @page_address: form and handle value used to get page
 1339  * Context: sleep.
 1340  *
 1341  * Returns 0 for success, non-zero for failure.
 1342  */
 1343 int
 1344 mpr_config_get_raid_volume_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
 1345     *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
 1346 {
 1347         MPI2_CONFIG_REQUEST *request;
 1348         MPI2_CONFIG_REPLY *reply = NULL;
 1349         struct mpr_command *cm;
 1350         Mpi2RaidVolPage0_t *page = NULL;
 1351         int error = 0;
 1352         u16 ioc_status;
 1353 
 1354         mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
 1355 
 1356         if ((cm = mpr_alloc_command(sc)) == NULL) {
 1357                 printf("%s: command alloc failed @ line %d\n", __func__,
 1358                     __LINE__);
 1359                 error = EBUSY;
 1360                 goto out;
 1361         }
 1362         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
 1363         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
 1364         request->Function = MPI2_FUNCTION_CONFIG;
 1365         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 1366         request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
 1367         request->Header.PageNumber = 0;
 1368         request->Header.PageLength = request->Header.PageVersion = 0;
 1369         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1370         cm->cm_data = NULL;
 1371 
 1372         /*
 1373          * This page must be polled because the IOC isn't ready yet when this
 1374          * page is needed.
 1375          */
 1376         error = mpr_request_polled(sc, &cm);
 1377         if (cm != NULL)
 1378                 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
 1379         if (error || (reply == NULL)) {
 1380                 /* FIXME */
 1381                 /* If the poll returns error then we need to do diag reset */ 
 1382                 printf("%s: poll for header completed with error %d",
 1383                     __func__, error);
 1384                 error = ENXIO;
 1385                 goto out;
 1386         }
 1387         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
 1388         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
 1389         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
 1390                 /* FIXME */
 1391                 /* If the poll returns error then we need to do diag reset */ 
 1392                 printf("%s: header read with error; iocstatus = 0x%x\n",
 1393                     __func__, ioc_status);
 1394                 error = ENXIO;
 1395                 goto out;
 1396         }
 1397         /* We have to do free and alloc for the reply-free and reply-post
 1398          * counters to match - Need to review the reply FIFO handling.
 1399          */
 1400         mpr_free_command(sc, cm);
 1401 
 1402         if ((cm = mpr_alloc_command(sc)) == NULL) {
 1403                 printf("%s: command alloc failed @ line %d\n", __func__,
 1404                     __LINE__);
 1405                 error = EBUSY;
 1406                 goto out;
 1407         }
 1408         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
 1409         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
 1410         request->Function = MPI2_FUNCTION_CONFIG;
 1411         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 1412         request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
 1413         request->Header.PageNumber = 0;
 1414         request->Header.PageLength = mpi_reply->Header.PageLength;
 1415         request->Header.PageVersion = mpi_reply->Header.PageVersion;
 1416         request->PageAddress = page_address;
 1417         cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
 1418         cm->cm_sge = &request->PageBufferSGE;
 1419         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
 1420         cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
 1421         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1422         page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
 1423         if (!page) {
 1424                 printf("%s: page alloc failed\n", __func__);
 1425                 error = ENOMEM;
 1426                 goto out;
 1427         }
 1428         cm->cm_data = page;
 1429 
 1430         /*
 1431          * This page must be polled because the IOC isn't ready yet when this
 1432          * page is needed.
 1433          */
 1434         error = mpr_request_polled(sc, &cm);
 1435         if (cm != NULL)
 1436                 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
 1437         if (error || (reply == NULL)) {
 1438                 /* FIXME */
 1439                 /* If the poll returns error then we need to do diag reset */ 
 1440                 printf("%s: poll for page completed with error %d",
 1441                     __func__, error);
 1442                 error = ENXIO;
 1443                 goto out;
 1444         }
 1445         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
 1446         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
 1447         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
 1448                 /* FIXME */
 1449                 /* If the poll returns error then we need to do diag reset */ 
 1450                 printf("%s: page read with error; iocstatus = 0x%x\n",
 1451                     __func__, ioc_status);
 1452                 error = ENXIO;
 1453                 goto out;
 1454         }
 1455         bcopy(page, config_page, cm->cm_length);
 1456 out:
 1457         free(page, M_MPR);
 1458         if (cm)
 1459                 mpr_free_command(sc, cm);
 1460         return (error);
 1461 }
 1462 
 1463 /**
 1464  * mpr_config_get_raid_volume_pg1 - obtain raid volume page 1
 1465  * @sc: per adapter object
 1466  * @mpi_reply: reply mf payload returned from firmware
 1467  * @config_page: contents of the config page
 1468  * @form: GET_NEXT_HANDLE or HANDLE
 1469  * @handle: volume handle
 1470  * Context: sleep.
 1471  *
 1472  * Returns 0 for success, non-zero for failure.
 1473  */
 1474 int
 1475 mpr_config_get_raid_volume_pg1(struct mpr_softc *sc, Mpi2ConfigReply_t
 1476     *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
 1477 {
 1478         MPI2_CONFIG_REQUEST *request;
 1479         MPI2_CONFIG_REPLY *reply;
 1480         struct mpr_command *cm;
 1481         Mpi2RaidVolPage1_t *page = NULL;
 1482         int error = 0;
 1483         u16 ioc_status;
 1484 
 1485         mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
 1486 
 1487         if ((cm = mpr_alloc_command(sc)) == NULL) {
 1488                 printf("%s: command alloc failed @ line %d\n", __func__,
 1489                     __LINE__);
 1490                 error = EBUSY;
 1491                 goto out;
 1492         }
 1493         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
 1494         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
 1495         request->Function = MPI2_FUNCTION_CONFIG;
 1496         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 1497         request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
 1498         request->Header.PageNumber = 1;
 1499         request->Header.PageLength = request->Header.PageVersion = 0;
 1500         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1501         cm->cm_data = NULL;
 1502         error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
 1503         if (cm != NULL)
 1504                 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
 1505         if (error || (reply == NULL)) {
 1506                 /* FIXME */
 1507                 /*
 1508                  * If the request returns an error then we need to do a diag
 1509                  * reset
 1510                  */ 
 1511                 printf("%s: request for header completed with error %d",
 1512                     __func__, error);
 1513                 error = ENXIO;
 1514                 goto out;
 1515         }
 1516         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
 1517         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
 1518         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
 1519                 /* FIXME */
 1520                 /*
 1521                  * If the request returns an error then we need to do a diag
 1522                  * reset
 1523                  */ 
 1524                 printf("%s: header read with error; iocstatus = 0x%x\n",
 1525                     __func__, ioc_status);
 1526                 error = ENXIO;
 1527                 goto out;
 1528         }
 1529         /* We have to do free and alloc for the reply-free and reply-post
 1530          * counters to match - Need to review the reply FIFO handling.
 1531          */
 1532         mpr_free_command(sc, cm);
 1533 
 1534         if ((cm = mpr_alloc_command(sc)) == NULL) {
 1535                 printf("%s: command alloc failed @ line %d\n", __func__,
 1536                     __LINE__);
 1537                 error = EBUSY;
 1538                 goto out;
 1539         }
 1540         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
 1541         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
 1542         request->Function = MPI2_FUNCTION_CONFIG;
 1543         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 1544         request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
 1545         request->Header.PageNumber = 1;
 1546         request->Header.PageLength = mpi_reply->Header.PageLength;
 1547         request->Header.PageVersion = mpi_reply->Header.PageVersion;
 1548         request->PageAddress = htole32(form | handle);
 1549         cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
 1550         cm->cm_sge = &request->PageBufferSGE;
 1551         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
 1552         cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
 1553         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1554         page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
 1555         if (!page) {
 1556                 printf("%s: page alloc failed\n", __func__);
 1557                 error = ENOMEM;
 1558                 goto out;
 1559         }
 1560         cm->cm_data = page;
 1561 
 1562         error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
 1563         if (cm != NULL)
 1564                 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
 1565         if (error || (reply == NULL)) {
 1566                 /* FIXME */
 1567                 /*
 1568                  * If the request returns an error then we need to do a diag
 1569                  * reset
 1570                  */ 
 1571                 printf("%s: request for page completed with error %d",
 1572                     __func__, error);
 1573                 error = ENXIO;
 1574                 goto out;
 1575         }
 1576         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
 1577         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
 1578         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
 1579                 /* FIXME */
 1580                 /*
 1581                  * If the request returns an error then we need to do a diag
 1582                  * reset
 1583                  */ 
 1584                 printf("%s: page read with error; iocstatus = 0x%x\n",
 1585                     __func__, ioc_status);
 1586                 error = ENXIO;
 1587                 goto out;
 1588         }
 1589         bcopy(page, config_page, MIN(cm->cm_length,
 1590             sizeof(Mpi2RaidVolPage1_t)));
 1591 out:
 1592         free(page, M_MPR);
 1593         if (cm)
 1594                 mpr_free_command(sc, cm);
 1595         return (error);
 1596 }
 1597 
 1598 /**
 1599  * mpr_config_get_volume_wwid - returns wwid given the volume handle
 1600  * @sc: per adapter object
 1601  * @volume_handle: volume handle
 1602  * @wwid: volume wwid
 1603  * Context: sleep.
 1604  *
 1605  * Returns 0 for success, non-zero for failure.
 1606  */
 1607 int
 1608 mpr_config_get_volume_wwid(struct mpr_softc *sc, u16 volume_handle, u64 *wwid)
 1609 {
 1610         Mpi2ConfigReply_t mpi_reply;
 1611         Mpi2RaidVolPage1_t raid_vol_pg1;
 1612 
 1613         *wwid = 0;
 1614         if (!(mpr_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
 1615             MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
 1616                 *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
 1617                     raid_vol_pg1.WWID.Low);
 1618                 return 0;
 1619         } else
 1620                 return -1;
 1621 }
 1622 
 1623 /**
 1624  * mpr_config_get_pd_pg0 - obtain raid phys disk page 0
 1625  * @sc: per adapter object
 1626  * @mpi_reply: reply mf payload returned from firmware
 1627  * @config_page: contents of the config page
 1628  * @page_address: form and handle value used to get page
 1629  * Context: sleep.
 1630  *
 1631  * Returns 0 for success, non-zero for failure.
 1632  */
 1633 int
 1634 mpr_config_get_raid_pd_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
 1635     Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
 1636 {
 1637         MPI2_CONFIG_REQUEST *request;
 1638         MPI2_CONFIG_REPLY *reply = NULL;
 1639         struct mpr_command *cm;
 1640         Mpi2RaidPhysDiskPage0_t *page = NULL;
 1641         int error = 0;
 1642         u16 ioc_status;
 1643 
 1644         mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
 1645 
 1646         if ((cm = mpr_alloc_command(sc)) == NULL) {
 1647                 printf("%s: command alloc failed @ line %d\n", __func__,
 1648                     __LINE__);
 1649                 error = EBUSY;
 1650                 goto out;
 1651         }
 1652         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
 1653         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
 1654         request->Function = MPI2_FUNCTION_CONFIG;
 1655         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 1656         request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
 1657         request->Header.PageNumber = 0;
 1658         request->Header.PageLength = request->Header.PageVersion = 0;
 1659         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1660         cm->cm_data = NULL;
 1661 
 1662         /*
 1663          * This page must be polled because the IOC isn't ready yet when this
 1664          * page is needed.
 1665          */
 1666         error = mpr_request_polled(sc, &cm);
 1667         if (cm != NULL)
 1668                 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
 1669         if (error || (reply == NULL)) {
 1670                 /* FIXME */
 1671                 /* If the poll returns error then we need to do diag reset */ 
 1672                 printf("%s: poll for header completed with error %d",
 1673                     __func__, error);
 1674                 error = ENXIO;
 1675                 goto out;
 1676         }
 1677         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
 1678         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
 1679         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
 1680                 /* FIXME */
 1681                 /* If the poll returns error then we need to do diag reset */ 
 1682                 printf("%s: header read with error; iocstatus = 0x%x\n",
 1683                     __func__, ioc_status);
 1684                 error = ENXIO;
 1685                 goto out;
 1686         }
 1687         /* We have to do free and alloc for the reply-free and reply-post
 1688          * counters to match - Need to review the reply FIFO handling.
 1689          */
 1690         mpr_free_command(sc, cm);
 1691 
 1692         if ((cm = mpr_alloc_command(sc)) == NULL) {
 1693                 printf("%s: command alloc failed @ line %d\n", __func__,
 1694                     __LINE__);
 1695                 error = EBUSY;
 1696                 goto out;
 1697         }
 1698         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
 1699         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
 1700         request->Function = MPI2_FUNCTION_CONFIG;
 1701         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 1702         request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
 1703         request->Header.PageNumber = 0;
 1704         request->Header.PageLength = mpi_reply->Header.PageLength;
 1705         request->Header.PageVersion = mpi_reply->Header.PageVersion;
 1706         request->PageAddress = page_address;
 1707         cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
 1708         cm->cm_sge = &request->PageBufferSGE;
 1709         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
 1710         cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
 1711         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1712         page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
 1713         if (!page) {
 1714                 printf("%s: page alloc failed\n", __func__);
 1715                 error = ENOMEM;
 1716                 goto out;
 1717         }
 1718         cm->cm_data = page;
 1719 
 1720         /*
 1721          * This page must be polled because the IOC isn't ready yet when this
 1722          * page is needed.
 1723          */
 1724         error = mpr_request_polled(sc, &cm);
 1725         if (cm != NULL)
 1726                 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
 1727         if (error || (reply == NULL)) {
 1728                 /* FIXME */
 1729                 /* If the poll returns error then we need to do diag reset */ 
 1730                 printf("%s: poll for page completed with error %d",
 1731                     __func__, error);
 1732                 error = ENXIO;
 1733                 goto out;
 1734         }
 1735         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
 1736         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
 1737         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
 1738                 /* FIXME */
 1739                 /* If the poll returns error then we need to do diag reset */ 
 1740                 printf("%s: page read with error; iocstatus = 0x%x\n",
 1741                     __func__, ioc_status);
 1742                 error = ENXIO;
 1743                 goto out;
 1744         }
 1745         bcopy(page, config_page, MIN(cm->cm_length,
 1746             sizeof(Mpi2RaidPhysDiskPage0_t)));
 1747 out:
 1748         free(page, M_MPR);
 1749         if (cm)
 1750                 mpr_free_command(sc, cm);
 1751         return (error);
 1752 }

Cache object: 22d76aa6251af71268c407f40ee12e48


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