The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/mps/mps_user.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-3-Clause
    3  *
    4  * Copyright (c) 2008 Yahoo!, Inc.
    5  * All rights reserved.
    6  * Written by: John Baldwin <jhb@FreeBSD.org>
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the author nor the names of any co-contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD userland interface
   33  */
   34 /*-
   35  * Copyright (c) 2011-2015 LSI Corp.
   36  * Copyright (c) 2013-2015 Avago Technologies
   37  * All rights reserved.
   38  *
   39  * Redistribution and use in source and binary forms, with or without
   40  * modification, are permitted provided that the following conditions
   41  * are met:
   42  * 1. Redistributions of source code must retain the above copyright
   43  *    notice, this list of conditions and the following disclaimer.
   44  * 2. Redistributions in binary form must reproduce the above copyright
   45  *    notice, this list of conditions and the following disclaimer in the
   46  *    documentation and/or other materials provided with the distribution.
   47  *
   48  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   58  * SUCH DAMAGE.
   59  *
   60  * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
   61  *
   62  * $FreeBSD$
   63  */
   64 
   65 #include <sys/cdefs.h>
   66 __FBSDID("$FreeBSD$");
   67 
   68 /* TODO Move headers to mpsvar */
   69 #include <sys/types.h>
   70 #include <sys/param.h>
   71 #include <sys/systm.h>
   72 #include <sys/kernel.h>
   73 #include <sys/selinfo.h>
   74 #include <sys/module.h>
   75 #include <sys/bus.h>
   76 #include <sys/conf.h>
   77 #include <sys/bio.h>
   78 #include <sys/abi_compat.h>
   79 #include <sys/malloc.h>
   80 #include <sys/uio.h>
   81 #include <sys/sysctl.h>
   82 #include <sys/ioccom.h>
   83 #include <sys/endian.h>
   84 #include <sys/queue.h>
   85 #include <sys/kthread.h>
   86 #include <sys/taskqueue.h>
   87 #include <sys/proc.h>
   88 #include <sys/sysent.h>
   89 
   90 #include <machine/bus.h>
   91 #include <machine/resource.h>
   92 #include <sys/rman.h>
   93 
   94 #include <cam/cam.h>
   95 #include <cam/cam_ccb.h>
   96 #include <cam/scsi/scsi_all.h>
   97 
   98 #include <dev/mps/mpi/mpi2_type.h>
   99 #include <dev/mps/mpi/mpi2.h>
  100 #include <dev/mps/mpi/mpi2_ioc.h>
  101 #include <dev/mps/mpi/mpi2_cnfg.h>
  102 #include <dev/mps/mpi/mpi2_init.h>
  103 #include <dev/mps/mpi/mpi2_tool.h>
  104 #include <dev/mps/mps_ioctl.h>
  105 #include <dev/mps/mpsvar.h>
  106 #include <dev/mps/mps_table.h>
  107 #include <dev/mps/mps_sas.h>
  108 #include <dev/pci/pcivar.h>
  109 #include <dev/pci/pcireg.h>
  110 
  111 static d_open_t         mps_open;
  112 static d_close_t        mps_close;
  113 static d_ioctl_t        mps_ioctl_devsw;
  114 
  115 static struct cdevsw mps_cdevsw = {
  116         .d_version =    D_VERSION,
  117         .d_flags =      0,
  118         .d_open =       mps_open,
  119         .d_close =      mps_close,
  120         .d_ioctl =      mps_ioctl_devsw,
  121         .d_name =       "mps",
  122 };
  123 
  124 typedef int (mps_user_f)(struct mps_command *, struct mps_usr_command *);
  125 static mps_user_f       mpi_pre_ioc_facts;
  126 static mps_user_f       mpi_pre_port_facts;
  127 static mps_user_f       mpi_pre_fw_download;
  128 static mps_user_f       mpi_pre_fw_upload;
  129 static mps_user_f       mpi_pre_sata_passthrough;
  130 static mps_user_f       mpi_pre_smp_passthrough;
  131 static mps_user_f       mpi_pre_config;
  132 static mps_user_f       mpi_pre_sas_io_unit_control;
  133 
  134 static int mps_user_read_cfg_header(struct mps_softc *,
  135                                     struct mps_cfg_page_req *);
  136 static int mps_user_read_cfg_page(struct mps_softc *,
  137                                   struct mps_cfg_page_req *, void *);
  138 static int mps_user_read_extcfg_header(struct mps_softc *,
  139                                      struct mps_ext_cfg_page_req *);
  140 static int mps_user_read_extcfg_page(struct mps_softc *,
  141                                      struct mps_ext_cfg_page_req *, void *);
  142 static int mps_user_write_cfg_page(struct mps_softc *,
  143                                    struct mps_cfg_page_req *, void *);
  144 static int mps_user_setup_request(struct mps_command *,
  145                                   struct mps_usr_command *);
  146 static int mps_user_command(struct mps_softc *, struct mps_usr_command *);
  147 
  148 static int mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data);
  149 static void mps_user_get_adapter_data(struct mps_softc *sc,
  150     mps_adapter_data_t *data);
  151 static void mps_user_read_pci_info(struct mps_softc *sc,
  152     mps_pci_info_t *data);
  153 static uint8_t mps_get_fw_diag_buffer_number(struct mps_softc *sc,
  154     uint32_t unique_id);
  155 static int mps_post_fw_diag_buffer(struct mps_softc *sc,
  156     mps_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code);
  157 static int mps_release_fw_diag_buffer(struct mps_softc *sc,
  158     mps_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
  159     uint32_t diag_type);
  160 static int mps_diag_register(struct mps_softc *sc,
  161     mps_fw_diag_register_t *diag_register, uint32_t *return_code);
  162 static int mps_diag_unregister(struct mps_softc *sc,
  163     mps_fw_diag_unregister_t *diag_unregister, uint32_t *return_code);
  164 static int mps_diag_query(struct mps_softc *sc, mps_fw_diag_query_t *diag_query,
  165     uint32_t *return_code);
  166 static int mps_diag_read_buffer(struct mps_softc *sc,
  167     mps_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
  168     uint32_t *return_code);
  169 static int mps_diag_release(struct mps_softc *sc,
  170     mps_fw_diag_release_t *diag_release, uint32_t *return_code);
  171 static int mps_do_diag_action(struct mps_softc *sc, uint32_t action,
  172     uint8_t *diag_action, uint32_t length, uint32_t *return_code);
  173 static int mps_user_diag_action(struct mps_softc *sc, mps_diag_action_t *data);
  174 static void mps_user_event_query(struct mps_softc *sc, mps_event_query_t *data);
  175 static void mps_user_event_enable(struct mps_softc *sc,
  176     mps_event_enable_t *data);
  177 static int mps_user_event_report(struct mps_softc *sc,
  178     mps_event_report_t *data);
  179 static int mps_user_reg_access(struct mps_softc *sc, mps_reg_access_t *data);
  180 static int mps_user_btdh(struct mps_softc *sc, mps_btdh_mapping_t *data);
  181 
  182 MALLOC_DEFINE(M_MPSUSER, "mps_user", "Buffers for mps(4) ioctls");
  183 
  184 int
  185 mps_attach_user(struct mps_softc *sc)
  186 {
  187         int unit;
  188 
  189         unit = device_get_unit(sc->mps_dev);
  190         sc->mps_cdev = make_dev(&mps_cdevsw, unit, UID_ROOT, GID_OPERATOR, 0640,
  191             "mps%d", unit);
  192         if (sc->mps_cdev == NULL) {
  193                 return (ENOMEM);
  194         }
  195         sc->mps_cdev->si_drv1 = sc;
  196         return (0);
  197 }
  198 
  199 void
  200 mps_detach_user(struct mps_softc *sc)
  201 {
  202 
  203         /* XXX: do a purge of pending requests? */
  204         if (sc->mps_cdev != NULL)
  205                 destroy_dev(sc->mps_cdev);
  206 }
  207 
  208 static int
  209 mps_open(struct cdev *dev, int flags, int fmt, struct thread *td)
  210 {
  211 
  212         return (0);
  213 }
  214 
  215 static int
  216 mps_close(struct cdev *dev, int flags, int fmt, struct thread *td)
  217 {
  218 
  219         return (0);
  220 }
  221 
  222 static int
  223 mps_user_read_cfg_header(struct mps_softc *sc,
  224     struct mps_cfg_page_req *page_req)
  225 {
  226         MPI2_CONFIG_PAGE_HEADER *hdr;
  227         struct mps_config_params params;
  228         int         error;
  229 
  230         hdr = &params.hdr.Struct;
  231         params.action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  232         params.page_address = le32toh(page_req->page_address);
  233         hdr->PageVersion = 0;
  234         hdr->PageLength = 0;
  235         hdr->PageNumber = page_req->header.PageNumber;
  236         hdr->PageType = page_req->header.PageType;
  237         params.buffer = NULL;
  238         params.length = 0;
  239         params.callback = NULL;
  240 
  241         if ((error = mps_read_config_page(sc, &params)) != 0) {
  242                 /*
  243                  * Leave the request. Without resetting the chip, it's
  244                  * still owned by it and we'll just get into trouble
  245                  * freeing it now. Mark it as abandoned so that if it
  246                  * shows up later it can be freed.
  247                  */
  248                 mps_printf(sc, "read_cfg_header timed out\n");
  249                 return (ETIMEDOUT);
  250         }
  251 
  252         page_req->ioc_status = htole16(params.status);
  253         if ((page_req->ioc_status & MPI2_IOCSTATUS_MASK) ==
  254             MPI2_IOCSTATUS_SUCCESS) {
  255                 bcopy(hdr, &page_req->header, sizeof(page_req->header));
  256         }
  257 
  258         return (0);
  259 }
  260 
  261 static int
  262 mps_user_read_cfg_page(struct mps_softc *sc, struct mps_cfg_page_req *page_req,
  263     void *buf)
  264 {
  265         MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr;
  266         struct mps_config_params params;
  267         int           error;
  268 
  269         reqhdr = buf;
  270         hdr = &params.hdr.Struct;
  271         hdr->PageVersion = reqhdr->PageVersion;
  272         hdr->PageLength = reqhdr->PageLength;
  273         hdr->PageNumber = reqhdr->PageNumber;
  274         hdr->PageType = reqhdr->PageType & MPI2_CONFIG_PAGETYPE_MASK;
  275         params.action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  276         params.page_address = le32toh(page_req->page_address);
  277         params.buffer = buf;
  278         params.length = le32toh(page_req->len);
  279         params.callback = NULL;
  280 
  281         if ((error = mps_read_config_page(sc, &params)) != 0) {
  282                 mps_printf(sc, "mps_user_read_cfg_page timed out\n");
  283                 return (ETIMEDOUT);
  284         }
  285 
  286         page_req->ioc_status = htole16(params.status);
  287         return (0);
  288 }
  289 
  290 static int
  291 mps_user_read_extcfg_header(struct mps_softc *sc,
  292     struct mps_ext_cfg_page_req *ext_page_req)
  293 {
  294         MPI2_CONFIG_EXTENDED_PAGE_HEADER *hdr;
  295         struct mps_config_params params;
  296         int         error;
  297 
  298         hdr = &params.hdr.Ext;
  299         params.action = MPI2_CONFIG_ACTION_PAGE_HEADER;
  300         hdr->PageVersion = ext_page_req->header.PageVersion;
  301         hdr->PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  302         hdr->ExtPageLength = 0;
  303         hdr->PageNumber = ext_page_req->header.PageNumber;
  304         hdr->ExtPageType = ext_page_req->header.ExtPageType;
  305         params.page_address = le32toh(ext_page_req->page_address);
  306         params.buffer = NULL;
  307         params.length = 0;
  308         params.callback = NULL;
  309 
  310         if ((error = mps_read_config_page(sc, &params)) != 0) {
  311                 /*
  312                  * Leave the request. Without resetting the chip, it's
  313                  * still owned by it and we'll just get into trouble
  314                  * freeing it now. Mark it as abandoned so that if it
  315                  * shows up later it can be freed.
  316                  */
  317                 mps_printf(sc, "mps_user_read_extcfg_header timed out\n");
  318                 return (ETIMEDOUT);
  319         }
  320 
  321         ext_page_req->ioc_status = htole16(params.status);
  322         if ((ext_page_req->ioc_status & MPI2_IOCSTATUS_MASK) ==
  323             MPI2_IOCSTATUS_SUCCESS) {
  324                 ext_page_req->header.PageVersion = hdr->PageVersion;
  325                 ext_page_req->header.PageNumber = hdr->PageNumber;
  326                 ext_page_req->header.PageType = hdr->PageType;
  327                 ext_page_req->header.ExtPageLength = hdr->ExtPageLength;
  328                 ext_page_req->header.ExtPageType = hdr->ExtPageType;
  329         }
  330 
  331         return (0);
  332 }
  333 
  334 static int
  335 mps_user_read_extcfg_page(struct mps_softc *sc,
  336     struct mps_ext_cfg_page_req *ext_page_req, void *buf)
  337 {
  338         MPI2_CONFIG_EXTENDED_PAGE_HEADER *reqhdr, *hdr;
  339         struct mps_config_params params;
  340         int error;
  341 
  342         reqhdr = buf;
  343         hdr = &params.hdr.Ext;
  344         params.action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
  345         params.page_address = le32toh(ext_page_req->page_address);
  346         hdr->PageVersion = reqhdr->PageVersion;
  347         hdr->PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
  348         hdr->PageNumber = reqhdr->PageNumber;
  349         hdr->ExtPageType = reqhdr->ExtPageType;
  350         hdr->ExtPageLength = reqhdr->ExtPageLength;
  351         params.buffer = buf;
  352         params.length = le32toh(ext_page_req->len);
  353         params.callback = NULL;
  354 
  355         if ((error = mps_read_config_page(sc, &params)) != 0) {
  356                 mps_printf(sc, "mps_user_read_extcfg_page timed out\n");
  357                 return (ETIMEDOUT);
  358         }
  359 
  360         ext_page_req->ioc_status = htole16(params.status);
  361         return (0);
  362 }
  363 
  364 static int
  365 mps_user_write_cfg_page(struct mps_softc *sc,
  366     struct mps_cfg_page_req *page_req, void *buf)
  367 {
  368         MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr;
  369         struct mps_config_params params;
  370         u_int         hdr_attr;
  371         int           error;
  372 
  373         reqhdr = buf;
  374         hdr = &params.hdr.Struct;
  375         hdr_attr = reqhdr->PageType & MPI2_CONFIG_PAGEATTR_MASK;
  376         if (hdr_attr != MPI2_CONFIG_PAGEATTR_CHANGEABLE &&
  377             hdr_attr != MPI2_CONFIG_PAGEATTR_PERSISTENT) {
  378                 mps_printf(sc, "page type 0x%x not changeable\n",
  379                         reqhdr->PageType & MPI2_CONFIG_PAGETYPE_MASK);
  380                 return (EINVAL);
  381         }
  382 
  383         /*
  384          * There isn't any point in restoring stripped out attributes
  385          * if you then mask them going down to issue the request.
  386          */
  387 
  388         hdr->PageVersion = reqhdr->PageVersion;
  389         hdr->PageLength = reqhdr->PageLength;
  390         hdr->PageNumber = reqhdr->PageNumber;
  391         hdr->PageType = reqhdr->PageType;
  392         params.action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
  393         params.page_address = le32toh(page_req->page_address);
  394         params.buffer = buf;
  395         params.length = le32toh(page_req->len);
  396         params.callback = NULL;
  397 
  398         if ((error = mps_write_config_page(sc, &params)) != 0) {
  399                 mps_printf(sc, "mps_write_cfg_page timed out\n");
  400                 return (ETIMEDOUT);
  401         }
  402 
  403         page_req->ioc_status = htole16(params.status);
  404         return (0);
  405 }
  406 
  407 void
  408 mpi_init_sge(struct mps_command *cm, void *req, void *sge)
  409 {
  410         int off, space;
  411 
  412         space = (int)cm->cm_sc->reqframesz;
  413         off = (uintptr_t)sge - (uintptr_t)req;
  414 
  415         KASSERT(off < space, ("bad pointers %p %p, off %d, space %d",
  416             req, sge, off, space));
  417 
  418         cm->cm_sge = sge;
  419         cm->cm_sglsize = space - off;
  420 }
  421 
  422 /*
  423  * Prepare the mps_command for an IOC_FACTS request.
  424  */
  425 static int
  426 mpi_pre_ioc_facts(struct mps_command *cm, struct mps_usr_command *cmd)
  427 {
  428         MPI2_IOC_FACTS_REQUEST *req = (void *)cm->cm_req;
  429         MPI2_IOC_FACTS_REPLY *rpl;
  430 
  431         if (cmd->req_len != sizeof *req)
  432                 return (EINVAL);
  433         if (cmd->rpl_len != sizeof *rpl)
  434                 return (EINVAL);
  435 
  436         cm->cm_sge = NULL;
  437         cm->cm_sglsize = 0;
  438         return (0);
  439 }
  440 
  441 /*
  442  * Prepare the mps_command for a PORT_FACTS request.
  443  */
  444 static int
  445 mpi_pre_port_facts(struct mps_command *cm, struct mps_usr_command *cmd)
  446 {
  447         MPI2_PORT_FACTS_REQUEST *req = (void *)cm->cm_req;
  448         MPI2_PORT_FACTS_REPLY *rpl;
  449 
  450         if (cmd->req_len != sizeof *req)
  451                 return (EINVAL);
  452         if (cmd->rpl_len != sizeof *rpl)
  453                 return (EINVAL);
  454 
  455         cm->cm_sge = NULL;
  456         cm->cm_sglsize = 0;
  457         return (0);
  458 }
  459 
  460 /*
  461  * Prepare the mps_command for a FW_DOWNLOAD request.
  462  */
  463 static int
  464 mpi_pre_fw_download(struct mps_command *cm, struct mps_usr_command *cmd)
  465 {
  466         MPI2_FW_DOWNLOAD_REQUEST *req = (void *)cm->cm_req;
  467         MPI2_FW_DOWNLOAD_REPLY *rpl;
  468         MPI2_FW_DOWNLOAD_TCSGE tc;
  469         int error;
  470 
  471         if (cmd->req_len != sizeof *req)
  472                 return (EINVAL);
  473         if (cmd->rpl_len != sizeof *rpl)
  474                 return (EINVAL);
  475 
  476         if (cmd->len == 0)
  477                 return (EINVAL);
  478 
  479         error = copyin(cmd->buf, cm->cm_data, cmd->len);
  480         if (error != 0)
  481                 return (error);
  482 
  483         mpi_init_sge(cm, req, &req->SGL);
  484         bzero(&tc, sizeof tc);
  485 
  486         /*
  487          * For now, the F/W image must be provided in a single request.
  488          */
  489         if ((req->MsgFlags & MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT) == 0)
  490                 return (EINVAL);
  491         if (req->TotalImageSize != cmd->len)
  492                 return (EINVAL);
  493 
  494         /*
  495          * The value of the first two elements is specified in the
  496          * Fusion-MPT Message Passing Interface document.
  497          */
  498         tc.ContextSize = 0;
  499         tc.DetailsLength = 12;
  500         tc.ImageOffset = 0;
  501         tc.ImageSize = cmd->len;
  502 
  503         cm->cm_flags |= MPS_CM_FLAGS_DATAOUT;
  504 
  505         return (mps_push_sge(cm, &tc, sizeof tc, 0));
  506 }
  507 
  508 /*
  509  * Prepare the mps_command for a FW_UPLOAD request.
  510  */
  511 static int
  512 mpi_pre_fw_upload(struct mps_command *cm, struct mps_usr_command *cmd)
  513 {
  514         MPI2_FW_UPLOAD_REQUEST *req = (void *)cm->cm_req;
  515         MPI2_FW_UPLOAD_REPLY *rpl;
  516         MPI2_FW_UPLOAD_TCSGE tc;
  517 
  518         if (cmd->req_len != sizeof *req)
  519                 return (EINVAL);
  520         if (cmd->rpl_len != sizeof *rpl)
  521                 return (EINVAL);
  522 
  523         mpi_init_sge(cm, req, &req->SGL);
  524         bzero(&tc, sizeof tc);
  525 
  526         /*
  527          * The value of the first two elements is specified in the
  528          * Fusion-MPT Message Passing Interface document.
  529          */
  530         tc.ContextSize = 0;
  531         tc.DetailsLength = 12;
  532         /*
  533          * XXX Is there any reason to fetch a partial image?  I.e. to
  534          * set ImageOffset to something other than 0?
  535          */
  536         tc.ImageOffset = 0;
  537         tc.ImageSize = cmd->len;
  538 
  539         cm->cm_flags |= MPS_CM_FLAGS_DATAIN;
  540 
  541         return (mps_push_sge(cm, &tc, sizeof tc, 0));
  542 }
  543 
  544 /*
  545  * Prepare the mps_command for a SATA_PASSTHROUGH request.
  546  */
  547 static int
  548 mpi_pre_sata_passthrough(struct mps_command *cm, struct mps_usr_command *cmd)
  549 {
  550         MPI2_SATA_PASSTHROUGH_REQUEST *req = (void *)cm->cm_req;
  551         MPI2_SATA_PASSTHROUGH_REPLY *rpl;
  552 
  553         if (cmd->req_len != sizeof *req)
  554                 return (EINVAL);
  555         if (cmd->rpl_len != sizeof *rpl)
  556                 return (EINVAL);
  557 
  558         mpi_init_sge(cm, req, &req->SGL);
  559         return (0);
  560 }
  561 
  562 /*
  563  * Prepare the mps_command for a SMP_PASSTHROUGH request.
  564  */
  565 static int
  566 mpi_pre_smp_passthrough(struct mps_command *cm, struct mps_usr_command *cmd)
  567 {
  568         MPI2_SMP_PASSTHROUGH_REQUEST *req = (void *)cm->cm_req;
  569         MPI2_SMP_PASSTHROUGH_REPLY *rpl;
  570 
  571         if (cmd->req_len != sizeof *req)
  572                 return (EINVAL);
  573         if (cmd->rpl_len != sizeof *rpl)
  574                 return (EINVAL);
  575 
  576         mpi_init_sge(cm, req, &req->SGL);
  577         return (0);
  578 }
  579 
  580 /*
  581  * Prepare the mps_command for a CONFIG request.
  582  */
  583 static int
  584 mpi_pre_config(struct mps_command *cm, struct mps_usr_command *cmd)
  585 {
  586         MPI2_CONFIG_REQUEST *req = (void *)cm->cm_req;
  587         MPI2_CONFIG_REPLY *rpl;
  588 
  589         if (cmd->req_len != sizeof *req)
  590                 return (EINVAL);
  591         if (cmd->rpl_len != sizeof *rpl)
  592                 return (EINVAL);
  593 
  594         mpi_init_sge(cm, req, &req->PageBufferSGE);
  595         return (0);
  596 }
  597 
  598 /*
  599  * Prepare the mps_command for a SAS_IO_UNIT_CONTROL request.
  600  */
  601 static int
  602 mpi_pre_sas_io_unit_control(struct mps_command *cm,
  603                              struct mps_usr_command *cmd)
  604 {
  605 
  606         cm->cm_sge = NULL;
  607         cm->cm_sglsize = 0;
  608         return (0);
  609 }
  610 
  611 /*
  612  * A set of functions to prepare an mps_command for the various
  613  * supported requests.
  614  */
  615 struct mps_user_func {
  616         U8              Function;
  617         mps_user_f      *f_pre;
  618 } mps_user_func_list[] = {
  619         { MPI2_FUNCTION_IOC_FACTS,              mpi_pre_ioc_facts },
  620         { MPI2_FUNCTION_PORT_FACTS,             mpi_pre_port_facts },
  621         { MPI2_FUNCTION_FW_DOWNLOAD,            mpi_pre_fw_download },
  622         { MPI2_FUNCTION_FW_UPLOAD,              mpi_pre_fw_upload },
  623         { MPI2_FUNCTION_SATA_PASSTHROUGH,       mpi_pre_sata_passthrough },
  624         { MPI2_FUNCTION_SMP_PASSTHROUGH,        mpi_pre_smp_passthrough},
  625         { MPI2_FUNCTION_CONFIG,                 mpi_pre_config},
  626         { MPI2_FUNCTION_SAS_IO_UNIT_CONTROL,    mpi_pre_sas_io_unit_control },
  627         { 0xFF,                                 NULL } /* list end */
  628 };
  629 
  630 static int
  631 mps_user_setup_request(struct mps_command *cm, struct mps_usr_command *cmd)
  632 {
  633         MPI2_REQUEST_HEADER *hdr = (MPI2_REQUEST_HEADER *)cm->cm_req;   
  634         struct mps_user_func *f;
  635 
  636         for (f = mps_user_func_list; f->f_pre != NULL; f++) {
  637                 if (hdr->Function == f->Function)
  638                         return (f->f_pre(cm, cmd));
  639         }
  640         return (EINVAL);
  641 }       
  642 
  643 static int
  644 mps_user_command(struct mps_softc *sc, struct mps_usr_command *cmd)
  645 {
  646         MPI2_REQUEST_HEADER *hdr;       
  647         MPI2_DEFAULT_REPLY *rpl;
  648         void *buf = NULL;
  649         struct mps_command *cm = NULL;
  650         int err = 0;
  651         int sz;
  652 
  653         mps_lock(sc);
  654         cm = mps_alloc_command(sc);
  655 
  656         if (cm == NULL) {
  657                 mps_printf(sc, "%s: no mps requests\n", __func__);
  658                 err = ENOMEM;
  659                 goto RetFree;
  660         }
  661         mps_unlock(sc);
  662 
  663         hdr = (MPI2_REQUEST_HEADER *)cm->cm_req;
  664 
  665         mps_dprint(sc, MPS_USER, "%s: req %p %d  rpl %p %d\n", __func__,
  666             cmd->req, cmd->req_len, cmd->rpl, cmd->rpl_len);
  667 
  668         if (cmd->req_len > sc->reqframesz) {
  669                 err = EINVAL;
  670                 goto RetFreeUnlocked;
  671         }
  672         err = copyin(cmd->req, hdr, cmd->req_len);
  673         if (err != 0)
  674                 goto RetFreeUnlocked;
  675 
  676         mps_dprint(sc, MPS_USER, "%s: Function %02X MsgFlags %02X\n", __func__,
  677             hdr->Function, hdr->MsgFlags);
  678 
  679         if (cmd->len > 0) {
  680                 buf = malloc(cmd->len, M_MPSUSER, M_WAITOK|M_ZERO);
  681                 cm->cm_data = buf;
  682                 cm->cm_length = cmd->len;
  683         } else {
  684                 cm->cm_data = NULL;
  685                 cm->cm_length = 0;
  686         }
  687 
  688         cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE;
  689         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  690 
  691         err = mps_user_setup_request(cm, cmd);
  692         if (err == EINVAL) {
  693                 mps_printf(sc, "%s: unsupported parameter or unsupported "
  694                     "function in request (function = 0x%X)\n", __func__,
  695                     hdr->Function);
  696         }
  697         if (err != 0)
  698                 goto RetFreeUnlocked;
  699 
  700         mps_lock(sc);
  701         err = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
  702 
  703         if (err || (cm == NULL)) {
  704                 mps_printf(sc, "%s: invalid request: error %d\n",
  705                     __func__, err);
  706                 goto RetFree;
  707         }
  708 
  709         rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply;
  710         if (rpl != NULL)
  711                 sz = rpl->MsgLength * 4;
  712         else
  713                 sz = 0;
  714 
  715         if (sz > cmd->rpl_len) {
  716                 mps_printf(sc, "%s: user reply buffer (%d) smaller than "
  717                     "returned buffer (%d)\n", __func__, cmd->rpl_len, sz);
  718                 sz = cmd->rpl_len;
  719         }       
  720 
  721         mps_unlock(sc);
  722         copyout(rpl, cmd->rpl, sz);
  723         if (buf != NULL)
  724                 copyout(buf, cmd->buf, cmd->len);
  725         mps_dprint(sc, MPS_USER, "%s: reply size %d\n", __func__, sz);
  726 
  727 RetFreeUnlocked:
  728         mps_lock(sc);
  729 RetFree:
  730         if (cm != NULL)
  731                 mps_free_command(sc, cm);
  732         mps_unlock(sc);
  733         if (buf != NULL)
  734                 free(buf, M_MPSUSER);
  735         return (err);
  736 }
  737 
  738 static int
  739 mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data)
  740 {
  741         MPI2_REQUEST_HEADER     *hdr, *tmphdr;
  742         MPI2_DEFAULT_REPLY      *rpl = NULL;
  743         struct mps_command      *cm = NULL;
  744         void                    *req = NULL;
  745         int                     err = 0, dir = 0, sz;
  746         uint8_t                 function = 0;
  747         u_int                   sense_len;
  748         struct mpssas_target    *targ = NULL;
  749 
  750         /*
  751          * Only allow one passthru command at a time.  Use the MPS_FLAGS_BUSY
  752          * bit to denote that a passthru is being processed.
  753          */
  754         mps_lock(sc);
  755         if (sc->mps_flags & MPS_FLAGS_BUSY) {
  756                 mps_dprint(sc, MPS_USER, "%s: Only one passthru command "
  757                     "allowed at a single time.", __func__);
  758                 mps_unlock(sc);
  759                 return (EBUSY);
  760         }
  761         sc->mps_flags |= MPS_FLAGS_BUSY;
  762         mps_unlock(sc);
  763 
  764         /*
  765          * Do some validation on data direction.  Valid cases are:
  766          *    1) DataSize is 0 and direction is NONE
  767          *    2) DataSize is non-zero and one of:
  768          *        a) direction is READ or
  769          *        b) direction is WRITE or
  770          *        c) direction is BOTH and DataOutSize is non-zero
  771          * If valid and the direction is BOTH, change the direction to READ.
  772          * if valid and the direction is not BOTH, make sure DataOutSize is 0.
  773          */
  774         if (((data->DataSize == 0) &&
  775             (data->DataDirection == MPS_PASS_THRU_DIRECTION_NONE)) ||
  776             ((data->DataSize != 0) &&
  777             ((data->DataDirection == MPS_PASS_THRU_DIRECTION_READ) ||
  778             (data->DataDirection == MPS_PASS_THRU_DIRECTION_WRITE) ||
  779             ((data->DataDirection == MPS_PASS_THRU_DIRECTION_BOTH) &&
  780             (data->DataOutSize != 0))))) {
  781                 if (data->DataDirection == MPS_PASS_THRU_DIRECTION_BOTH)
  782                         data->DataDirection = MPS_PASS_THRU_DIRECTION_READ;
  783                 else
  784                         data->DataOutSize = 0;
  785         } else {
  786                 err = EINVAL;
  787                 goto RetFreeUnlocked;
  788         }
  789 
  790         mps_dprint(sc, MPS_USER, "%s: req 0x%jx %d  rpl 0x%jx %d "
  791             "data in 0x%jx %d data out 0x%jx %d data dir %d\n", __func__,
  792             data->PtrRequest, data->RequestSize, data->PtrReply,
  793             data->ReplySize, data->PtrData, data->DataSize,
  794             data->PtrDataOut, data->DataOutSize, data->DataDirection);
  795 
  796         if (data->RequestSize > sc->reqframesz) {
  797                 err = EINVAL;
  798                 goto RetFreeUnlocked;
  799         }
  800 
  801         req = malloc(data->RequestSize, M_MPSUSER, M_WAITOK | M_ZERO);
  802         tmphdr = (MPI2_REQUEST_HEADER *)req;
  803 
  804         err = copyin(PTRIN(data->PtrRequest), req, data->RequestSize);
  805         if (err != 0)
  806                 goto RetFreeUnlocked;
  807 
  808         function = tmphdr->Function;
  809         mps_dprint(sc, MPS_USER, "%s: Function %02X MsgFlags %02X\n", __func__,
  810             function, tmphdr->MsgFlags);
  811 
  812         /*
  813          * Handle a passthru TM request.
  814          */
  815         if (function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
  816                 MPI2_SCSI_TASK_MANAGE_REQUEST   *task;
  817 
  818                 mps_lock(sc);
  819                 cm = mpssas_alloc_tm(sc);
  820                 if (cm == NULL) {
  821                         err = EINVAL;
  822                         goto Ret;
  823                 }
  824 
  825                 /* Copy the header in.  Only a small fixup is needed. */
  826                 task = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req;
  827                 memcpy(task, req, data->RequestSize);
  828                 task->TaskMID = cm->cm_desc.Default.SMID;
  829 
  830                 cm->cm_data = NULL;
  831                 cm->cm_complete = NULL;
  832                 cm->cm_complete_data = NULL;
  833 
  834                 targ = mpssas_find_target_by_handle(sc->sassc, 0,
  835                     task->DevHandle);
  836                 if (targ == NULL) {
  837                         mps_dprint(sc, MPS_INFO,
  838                            "%s %d : invalid handle for requested TM 0x%x \n",
  839                            __func__, __LINE__, task->DevHandle);
  840                         err = 1;
  841                 } else {
  842                         mpssas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD);
  843                         err = mps_wait_command(sc, &cm, 30, CAN_SLEEP);
  844                 }
  845 
  846                 if (err != 0) {
  847                         err = EIO;
  848                         mps_dprint(sc, MPS_FAULT, "%s: task management failed",
  849                             __func__);
  850                 }
  851                 /*
  852                  * Copy the reply data and sense data to user space.
  853                  */
  854                 if ((cm != NULL) && (cm->cm_reply != NULL)) {
  855                         rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply;
  856                         sz = rpl->MsgLength * 4;
  857 
  858                         if (sz > data->ReplySize) {
  859                                 mps_printf(sc, "%s: user reply buffer (%d) "
  860                                     "smaller than returned buffer (%d)\n",
  861                                     __func__, data->ReplySize, sz);
  862                         }
  863                         mps_unlock(sc);
  864                         copyout(cm->cm_reply, PTRIN(data->PtrReply),
  865                             data->ReplySize);
  866                         mps_lock(sc);
  867                 }
  868                 mpssas_free_tm(sc, cm);
  869                 goto Ret;
  870         }
  871 
  872         mps_lock(sc);
  873         cm = mps_alloc_command(sc);
  874         if (cm == NULL) {
  875                 mps_printf(sc, "%s: no mps requests\n", __func__);
  876                 err = ENOMEM;
  877                 goto Ret;
  878         }
  879         mps_unlock(sc);
  880 
  881         hdr = (MPI2_REQUEST_HEADER *)cm->cm_req;
  882         memcpy(hdr, req, data->RequestSize);
  883 
  884         /*
  885          * Do some checking to make sure the IOCTL request contains a valid
  886          * request.  Then set the SGL info.
  887          */
  888         mpi_init_sge(cm, hdr, (void *)((uint8_t *)hdr + data->RequestSize));
  889 
  890         /*
  891          * Set up for read, write or both.  From check above, DataOutSize will
  892          * be 0 if direction is READ or WRITE, but it will have some non-zero
  893          * value if the direction is BOTH.  So, just use the biggest size to get
  894          * the cm_data buffer size.  If direction is BOTH, 2 SGLs need to be set
  895          * up; the first is for the request and the second will contain the
  896          * response data. cm_out_len needs to be set here and this will be used
  897          * when the SGLs are set up.
  898          */
  899         cm->cm_data = NULL;
  900         cm->cm_length = MAX(data->DataSize, data->DataOutSize);
  901         cm->cm_out_len = data->DataOutSize;
  902         cm->cm_flags = 0;
  903         if (cm->cm_length != 0) {
  904                 cm->cm_data = malloc(cm->cm_length, M_MPSUSER, M_WAITOK |
  905                     M_ZERO);
  906                 cm->cm_flags = MPS_CM_FLAGS_DATAIN;
  907                 if (data->DataOutSize) {
  908                         cm->cm_flags |= MPS_CM_FLAGS_DATAOUT;
  909                         err = copyin(PTRIN(data->PtrDataOut),
  910                             cm->cm_data, data->DataOutSize);
  911                 } else if (data->DataDirection ==
  912                     MPS_PASS_THRU_DIRECTION_WRITE) {
  913                         cm->cm_flags = MPS_CM_FLAGS_DATAOUT;
  914                         err = copyin(PTRIN(data->PtrData),
  915                             cm->cm_data, data->DataSize);
  916                 }
  917                 if (err != 0)
  918                         mps_dprint(sc, MPS_FAULT, "%s: failed to copy "
  919                             "IOCTL data from user space\n", __func__);
  920         }
  921         cm->cm_flags |= MPS_CM_FLAGS_SGE_SIMPLE;
  922         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
  923 
  924         /*
  925          * Set up Sense buffer and SGL offset for IO passthru.  SCSI IO request
  926          * uses SCSI IO descriptor.
  927          */
  928         if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
  929             (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
  930                 MPI2_SCSI_IO_REQUEST    *scsi_io_req;
  931 
  932                 scsi_io_req = (MPI2_SCSI_IO_REQUEST *)hdr;
  933                 /*
  934                  * Put SGE for data and data_out buffer at the end of
  935                  * scsi_io_request message header (64 bytes in total).
  936                  * Following above SGEs, the residual space will be used by
  937                  * sense data.
  938                  */
  939                 scsi_io_req->SenseBufferLength = (uint8_t)(data->RequestSize -
  940                     64);
  941                 scsi_io_req->SenseBufferLowAddress = htole32(cm->cm_sense_busaddr);
  942 
  943                 /*
  944                  * Set SGLOffset0 value.  This is the number of dwords that SGL
  945                  * is offset from the beginning of MPI2_SCSI_IO_REQUEST struct.
  946                  */
  947                 scsi_io_req->SGLOffset0 = 24;
  948 
  949                 /*
  950                  * Setup descriptor info.  RAID passthrough must use the
  951                  * default request descriptor which is already set, so if this
  952                  * is a SCSI IO request, change the descriptor to SCSI IO.
  953                  * Also, if this is a SCSI IO request, handle the reply in the
  954                  * mpssas_scsio_complete function.
  955                  */
  956                 if (function == MPI2_FUNCTION_SCSI_IO_REQUEST) {
  957                         cm->cm_desc.SCSIIO.RequestFlags =
  958                             MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
  959                         cm->cm_desc.SCSIIO.DevHandle = scsi_io_req->DevHandle;
  960 
  961                         /*
  962                          * Make sure the DevHandle is not 0 because this is a
  963                          * likely error.
  964                          */
  965                         if (scsi_io_req->DevHandle == 0) {
  966                                 err = EINVAL;
  967                                 goto RetFreeUnlocked;
  968                         }
  969                 }
  970         }
  971 
  972         mps_lock(sc);
  973 
  974         err = mps_wait_command(sc, &cm, 30, CAN_SLEEP);
  975 
  976         if (err || (cm == NULL)) {
  977                 mps_printf(sc, "%s: invalid request: error %d\n", __func__,
  978                     err);
  979                 mps_unlock(sc);
  980                 goto RetFreeUnlocked;
  981         }
  982 
  983         /*
  984          * Sync the DMA data, if any.  Then copy the data to user space.
  985          */
  986         if (cm->cm_data != NULL) {
  987                 if (cm->cm_flags & MPS_CM_FLAGS_DATAIN)
  988                         dir = BUS_DMASYNC_POSTREAD;
  989                 else if (cm->cm_flags & MPS_CM_FLAGS_DATAOUT)
  990                         dir = BUS_DMASYNC_POSTWRITE;
  991                 bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, dir);
  992                 bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap);
  993 
  994                 if (cm->cm_flags & MPS_CM_FLAGS_DATAIN) {
  995                         mps_unlock(sc);
  996                         err = copyout(cm->cm_data,
  997                             PTRIN(data->PtrData), data->DataSize);
  998                         mps_lock(sc);
  999                         if (err != 0)
 1000                                 mps_dprint(sc, MPS_FAULT, "%s: failed to copy "
 1001                                     "IOCTL data to user space\n", __func__);
 1002                 }
 1003         }
 1004 
 1005         /*
 1006          * Copy the reply data and sense data to user space.
 1007          */
 1008         if (cm->cm_reply != NULL) {
 1009                 rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply;
 1010                 sz = rpl->MsgLength * 4;
 1011 
 1012                 if (sz > data->ReplySize) {
 1013                         mps_printf(sc, "%s: user reply buffer (%d) smaller "
 1014                             "than returned buffer (%d)\n", __func__,
 1015                             data->ReplySize, sz);
 1016                 }
 1017                 mps_unlock(sc);
 1018                 copyout(cm->cm_reply, PTRIN(data->PtrReply), data->ReplySize);
 1019                 mps_lock(sc);
 1020 
 1021                 if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
 1022                     (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
 1023                         if (((MPI2_SCSI_IO_REPLY *)rpl)->SCSIState &
 1024                             MPI2_SCSI_STATE_AUTOSENSE_VALID) {
 1025                                 sense_len =
 1026                                     MIN((le32toh(((MPI2_SCSI_IO_REPLY *)rpl)->
 1027                                     SenseCount)), sizeof(struct
 1028                                     scsi_sense_data));
 1029                                 mps_unlock(sc);
 1030                                 copyout(cm->cm_sense, (PTRIN(data->PtrReply +
 1031                                     sizeof(MPI2_SCSI_IO_REPLY))), sense_len);
 1032                                 mps_lock(sc);
 1033                         }
 1034                 }
 1035         }
 1036         mps_unlock(sc);
 1037 
 1038 RetFreeUnlocked:
 1039         mps_lock(sc);
 1040 
 1041         if (cm != NULL) {
 1042                 if (cm->cm_data)
 1043                         free(cm->cm_data, M_MPSUSER);
 1044                 mps_free_command(sc, cm);
 1045         }
 1046 Ret:
 1047         sc->mps_flags &= ~MPS_FLAGS_BUSY;
 1048         mps_unlock(sc);
 1049         free(req, M_MPSUSER);
 1050 
 1051         return (err);
 1052 }
 1053 
 1054 static void
 1055 mps_user_get_adapter_data(struct mps_softc *sc, mps_adapter_data_t *data)
 1056 {
 1057         Mpi2ConfigReply_t       mpi_reply;
 1058         Mpi2BiosPage3_t         config_page;
 1059 
 1060         /*
 1061          * Use the PCI interface functions to get the Bus, Device, and Function
 1062          * information.
 1063          */
 1064         data->PciInformation.u.bits.BusNumber = pci_get_bus(sc->mps_dev);
 1065         data->PciInformation.u.bits.DeviceNumber = pci_get_slot(sc->mps_dev);
 1066         data->PciInformation.u.bits.FunctionNumber =
 1067             pci_get_function(sc->mps_dev);
 1068 
 1069         /*
 1070          * Get the FW version that should already be saved in IOC Facts.
 1071          */
 1072         data->MpiFirmwareVersion = sc->facts->FWVersion.Word;
 1073 
 1074         /*
 1075          * General device info.
 1076          */
 1077         data->AdapterType = MPSIOCTL_ADAPTER_TYPE_SAS2;
 1078         if (sc->mps_flags & MPS_FLAGS_WD_AVAILABLE)
 1079                 data->AdapterType = MPSIOCTL_ADAPTER_TYPE_SAS2_SSS6200;
 1080         data->PCIDeviceHwId = pci_get_device(sc->mps_dev);
 1081         data->PCIDeviceHwRev = pci_read_config(sc->mps_dev, PCIR_REVID, 1);
 1082         data->SubSystemId = pci_get_subdevice(sc->mps_dev);
 1083         data->SubsystemVendorId = pci_get_subvendor(sc->mps_dev);
 1084 
 1085         /*
 1086          * Get the driver version.
 1087          */
 1088         strcpy((char *)&data->DriverVersion[0], MPS_DRIVER_VERSION);
 1089 
 1090         /*
 1091          * Need to get BIOS Config Page 3 for the BIOS Version.
 1092          */
 1093         data->BiosVersion = 0;
 1094         mps_lock(sc);
 1095         if (mps_config_get_bios_pg3(sc, &mpi_reply, &config_page))
 1096                 printf("%s: Error while retrieving BIOS Version\n", __func__);
 1097         else
 1098                 data->BiosVersion = config_page.BiosVersion;
 1099         mps_unlock(sc);
 1100 }
 1101 
 1102 static void
 1103 mps_user_read_pci_info(struct mps_softc *sc, mps_pci_info_t *data)
 1104 {
 1105         int     i;
 1106 
 1107         /*
 1108          * Use the PCI interface functions to get the Bus, Device, and Function
 1109          * information.
 1110          */
 1111         data->BusNumber = pci_get_bus(sc->mps_dev);
 1112         data->DeviceNumber = pci_get_slot(sc->mps_dev);
 1113         data->FunctionNumber = pci_get_function(sc->mps_dev);
 1114 
 1115         /*
 1116          * Now get the interrupt vector and the pci header.  The vector can
 1117          * only be 0 right now.  The header is the first 256 bytes of config
 1118          * space.
 1119          */
 1120         data->InterruptVector = 0;
 1121         for (i = 0; i < sizeof (data->PciHeader); i++) {
 1122                 data->PciHeader[i] = pci_read_config(sc->mps_dev, i, 1);
 1123         }
 1124 }
 1125 
 1126 static uint8_t
 1127 mps_get_fw_diag_buffer_number(struct mps_softc *sc, uint32_t unique_id)
 1128 {
 1129         uint8_t index;
 1130 
 1131         for (index = 0; index < MPI2_DIAG_BUF_TYPE_COUNT; index++) {
 1132                 if (sc->fw_diag_buffer_list[index].unique_id == unique_id) {
 1133                         return (index);
 1134                 }
 1135         }
 1136 
 1137         return (MPS_FW_DIAGNOSTIC_UID_NOT_FOUND);
 1138 }
 1139 
 1140 static int
 1141 mps_post_fw_diag_buffer(struct mps_softc *sc,
 1142     mps_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code)
 1143 {
 1144         MPI2_DIAG_BUFFER_POST_REQUEST   *req;
 1145         MPI2_DIAG_BUFFER_POST_REPLY     *reply = NULL;
 1146         struct mps_command              *cm = NULL;
 1147         int                             i, status;
 1148 
 1149         /*
 1150          * If buffer is not enabled, just leave.
 1151          */
 1152         *return_code = MPS_FW_DIAG_ERROR_POST_FAILED;
 1153         if (!pBuffer->enabled) {
 1154                 return (MPS_DIAG_FAILURE);
 1155         }
 1156 
 1157         /*
 1158          * Clear some flags initially.
 1159          */
 1160         pBuffer->force_release = FALSE;
 1161         pBuffer->valid_data = FALSE;
 1162         pBuffer->owned_by_firmware = FALSE;
 1163 
 1164         /*
 1165          * Get a command.
 1166          */
 1167         cm = mps_alloc_command(sc);
 1168         if (cm == NULL) {
 1169                 mps_printf(sc, "%s: no mps requests\n", __func__);
 1170                 return (MPS_DIAG_FAILURE);
 1171         }
 1172 
 1173         /*
 1174          * Build the request for releasing the FW Diag Buffer and send it.
 1175          */
 1176         req = (MPI2_DIAG_BUFFER_POST_REQUEST *)cm->cm_req;
 1177         req->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
 1178         req->BufferType = pBuffer->buffer_type;
 1179         req->ExtendedType = pBuffer->extended_type;
 1180         req->BufferLength = pBuffer->size;
 1181         for (i = 0; i < (sizeof(req->ProductSpecific) / 4); i++)
 1182                 req->ProductSpecific[i] = pBuffer->product_specific[i];
 1183         mps_from_u64(sc->fw_diag_busaddr, &req->BufferAddress);
 1184         cm->cm_data = NULL;
 1185         cm->cm_length = 0;
 1186         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1187         cm->cm_complete_data = NULL;
 1188 
 1189         /*
 1190          * Send command synchronously.
 1191          */
 1192         status = mps_wait_command(sc, &cm, 30, CAN_SLEEP);
 1193         if (status || (cm == NULL)) {
 1194                 mps_printf(sc, "%s: invalid request: error %d\n", __func__,
 1195                     status);
 1196                 status = MPS_DIAG_FAILURE;
 1197                 goto done;
 1198         }
 1199 
 1200         /*
 1201          * Process POST reply.
 1202          */
 1203         reply = (MPI2_DIAG_BUFFER_POST_REPLY *)cm->cm_reply;
 1204         if (reply == NULL) {
 1205                 mps_printf(sc, "%s: reply is NULL, probably due to "
 1206                     "reinitialization\n", __func__);
 1207                 status = MPS_DIAG_FAILURE;
 1208                 goto done;
 1209         }
 1210         if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
 1211             MPI2_IOCSTATUS_SUCCESS) {
 1212                 status = MPS_DIAG_FAILURE;
 1213                 mps_dprint(sc, MPS_FAULT, "%s: post of FW  Diag Buffer failed "
 1214                     "with IOCStatus = 0x%x, IOCLogInfo = 0x%x and "
 1215                     "TransferLength = 0x%x\n", __func__,
 1216                     le16toh(reply->IOCStatus), le32toh(reply->IOCLogInfo),
 1217                     le32toh(reply->TransferLength));
 1218                 goto done;
 1219         }
 1220 
 1221         /*
 1222          * Post was successful.
 1223          */
 1224         pBuffer->valid_data = TRUE;
 1225         pBuffer->owned_by_firmware = TRUE;
 1226         *return_code = MPS_FW_DIAG_ERROR_SUCCESS;
 1227         status = MPS_DIAG_SUCCESS;
 1228 
 1229 done:
 1230         if (cm != NULL)
 1231                 mps_free_command(sc, cm);
 1232         return (status);
 1233 }
 1234 
 1235 static int
 1236 mps_release_fw_diag_buffer(struct mps_softc *sc,
 1237     mps_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
 1238     uint32_t diag_type)
 1239 {
 1240         MPI2_DIAG_RELEASE_REQUEST       *req;
 1241         MPI2_DIAG_RELEASE_REPLY         *reply = NULL;
 1242         struct mps_command              *cm = NULL;
 1243         int                             status;
 1244 
 1245         /*
 1246          * If buffer is not enabled, just leave.
 1247          */
 1248         *return_code = MPS_FW_DIAG_ERROR_RELEASE_FAILED;
 1249         if (!pBuffer->enabled) {
 1250                 mps_dprint(sc, MPS_USER, "%s: This buffer type is not "
 1251                     "supported by the IOC", __func__);
 1252                 return (MPS_DIAG_FAILURE);
 1253         }
 1254 
 1255         /*
 1256          * Clear some flags initially.
 1257          */
 1258         pBuffer->force_release = FALSE;
 1259         pBuffer->valid_data = FALSE;
 1260         pBuffer->owned_by_firmware = FALSE;
 1261 
 1262         /*
 1263          * Get a command.
 1264          */
 1265         cm = mps_alloc_command(sc);
 1266         if (cm == NULL) {
 1267                 mps_printf(sc, "%s: no mps requests\n", __func__);
 1268                 return (MPS_DIAG_FAILURE);
 1269         }
 1270 
 1271         /*
 1272          * Build the request for releasing the FW Diag Buffer and send it.
 1273          */
 1274         req = (MPI2_DIAG_RELEASE_REQUEST *)cm->cm_req;
 1275         req->Function = MPI2_FUNCTION_DIAG_RELEASE;
 1276         req->BufferType = pBuffer->buffer_type;
 1277         cm->cm_data = NULL;
 1278         cm->cm_length = 0;
 1279         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
 1280         cm->cm_complete_data = NULL;
 1281 
 1282         /*
 1283          * Send command synchronously.
 1284          */
 1285         status = mps_wait_command(sc, &cm, 30, CAN_SLEEP);
 1286         if (status || (cm == NULL)) {
 1287                 mps_printf(sc, "%s: invalid request: error %d\n", __func__,
 1288                     status);
 1289                 status = MPS_DIAG_FAILURE;
 1290                 goto done;
 1291         }
 1292 
 1293         /*
 1294          * Process RELEASE reply.
 1295          */
 1296         reply = (MPI2_DIAG_RELEASE_REPLY *)cm->cm_reply;
 1297         if (reply == NULL) {
 1298                 mps_printf(sc, "%s: reply is NULL, probably due to "
 1299                     "reinitialization\n", __func__);
 1300                 status = MPS_DIAG_FAILURE;
 1301                 goto done;
 1302         }
 1303         if (((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
 1304             MPI2_IOCSTATUS_SUCCESS) || pBuffer->owned_by_firmware) {
 1305                 status = MPS_DIAG_FAILURE;
 1306                 mps_dprint(sc, MPS_FAULT, "%s: release of FW Diag Buffer "
 1307                     "failed with IOCStatus = 0x%x and IOCLogInfo = 0x%x\n",
 1308                     __func__, le16toh(reply->IOCStatus),
 1309                     le32toh(reply->IOCLogInfo));
 1310                 goto done;
 1311         }
 1312 
 1313         /*
 1314          * Release was successful.
 1315          */
 1316         *return_code = MPS_FW_DIAG_ERROR_SUCCESS;
 1317         status = MPS_DIAG_SUCCESS;
 1318 
 1319         /*
 1320          * If this was for an UNREGISTER diag type command, clear the unique ID.
 1321          */
 1322         if (diag_type == MPS_FW_DIAG_TYPE_UNREGISTER) {
 1323                 pBuffer->unique_id = MPS_FW_DIAG_INVALID_UID;
 1324         }
 1325 
 1326 done:
 1327         if (cm != NULL)
 1328                 mps_free_command(sc, cm);
 1329 
 1330         return (status);
 1331 }
 1332 
 1333 static int
 1334 mps_diag_register(struct mps_softc *sc, mps_fw_diag_register_t *diag_register,
 1335     uint32_t *return_code)
 1336 {
 1337         bus_dma_template_t              t;
 1338         mps_fw_diagnostic_buffer_t      *pBuffer;
 1339         struct mps_busdma_context       *ctx;
 1340         uint8_t                         extended_type, buffer_type, i;
 1341         uint32_t                        buffer_size;
 1342         uint32_t                        unique_id;
 1343         int                             status;
 1344         int                             error;
 1345 
 1346         extended_type = diag_register->ExtendedType;
 1347         buffer_type = diag_register->BufferType;
 1348         buffer_size = diag_register->RequestedBufferSize;
 1349         unique_id = diag_register->UniqueId;
 1350         ctx = NULL;
 1351         error = 0;
 1352 
 1353         /*
 1354          * Check for valid buffer type
 1355          */
 1356         if (buffer_type >= MPI2_DIAG_BUF_TYPE_COUNT) {
 1357                 *return_code = MPS_FW_DIAG_ERROR_INVALID_PARAMETER;
 1358                 return (MPS_DIAG_FAILURE);
 1359         }
 1360 
 1361         /*
 1362          * Get the current buffer and look up the unique ID.  The unique ID
 1363          * should not be found.  If it is, the ID is already in use.
 1364          */
 1365         i = mps_get_fw_diag_buffer_number(sc, unique_id);
 1366         pBuffer = &sc->fw_diag_buffer_list[buffer_type];
 1367         if (i != MPS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
 1368                 *return_code = MPS_FW_DIAG_ERROR_INVALID_UID;
 1369                 return (MPS_DIAG_FAILURE);
 1370         }
 1371 
 1372         /*
 1373          * The buffer's unique ID should not be registered yet, and the given
 1374          * unique ID cannot be 0.
 1375          */
 1376         if ((pBuffer->unique_id != MPS_FW_DIAG_INVALID_UID) ||
 1377             (unique_id == MPS_FW_DIAG_INVALID_UID)) {
 1378                 *return_code = MPS_FW_DIAG_ERROR_INVALID_UID;
 1379                 return (MPS_DIAG_FAILURE);
 1380         }
 1381 
 1382         /*
 1383          * If this buffer is already posted as immediate, just change owner.
 1384          */
 1385         if (pBuffer->immediate && pBuffer->owned_by_firmware &&
 1386             (pBuffer->unique_id == MPS_FW_DIAG_INVALID_UID)) {
 1387                 pBuffer->immediate = FALSE;
 1388                 pBuffer->unique_id = unique_id;
 1389                 return (MPS_DIAG_SUCCESS);
 1390         }
 1391 
 1392         /*
 1393          * Post a new buffer after checking if it's enabled.  The DMA buffer
 1394          * that is allocated will be contiguous (nsegments = 1).
 1395          */
 1396         if (!pBuffer->enabled) {
 1397                 *return_code = MPS_FW_DIAG_ERROR_NO_BUFFER;
 1398                 return (MPS_DIAG_FAILURE);
 1399         }
 1400         bus_dma_template_init(&t, sc->mps_parent_dmat);
 1401         BUS_DMA_TEMPLATE_FILL(&t, BD_NSEGMENTS(1), BD_MAXSIZE(buffer_size),
 1402             BD_MAXSEGSIZE(buffer_size), BD_LOWADDR(BUS_SPACE_MAXADDR_32BIT));
 1403         if (bus_dma_template_tag(&t, &sc->fw_diag_dmat)) {
 1404                 mps_dprint(sc, MPS_ERROR,
 1405                     "Cannot allocate FW diag buffer DMA tag\n");
 1406                 *return_code = MPS_FW_DIAG_ERROR_NO_BUFFER;
 1407                 status = MPS_DIAG_FAILURE;
 1408                 goto bailout;
 1409         }
 1410         if (bus_dmamem_alloc(sc->fw_diag_dmat, (void **)&sc->fw_diag_buffer,
 1411             BUS_DMA_NOWAIT, &sc->fw_diag_map)) {
 1412                 mps_dprint(sc, MPS_ERROR,
 1413                     "Cannot allocate FW diag buffer memory\n");
 1414                 *return_code = MPS_FW_DIAG_ERROR_NO_BUFFER;
 1415                 status = MPS_DIAG_FAILURE;
 1416                 goto bailout;
 1417         }
 1418         bzero(sc->fw_diag_buffer, buffer_size);
 1419 
 1420         ctx = malloc(sizeof(*ctx), M_MPSUSER, M_WAITOK | M_ZERO);
 1421         ctx->addr = &sc->fw_diag_busaddr;
 1422         ctx->buffer_dmat = sc->fw_diag_dmat;
 1423         ctx->buffer_dmamap = sc->fw_diag_map;
 1424         ctx->softc = sc;
 1425         error = bus_dmamap_load(sc->fw_diag_dmat, sc->fw_diag_map,
 1426             sc->fw_diag_buffer, buffer_size, mps_memaddr_wait_cb,
 1427             ctx, 0);
 1428 
 1429         if (error == EINPROGRESS) {
 1430                 /* XXX KDM */
 1431                 device_printf(sc->mps_dev, "%s: Deferred bus_dmamap_load\n",
 1432                     __func__);
 1433                 /*
 1434                  * Wait for the load to complete.  If we're interrupted,
 1435                  * bail out.
 1436                  */
 1437                 mps_lock(sc);
 1438                 if (ctx->completed == 0) {
 1439                         error = msleep(ctx, &sc->mps_mtx, PCATCH, "mpswait", 0);
 1440                         if (error != 0) {
 1441                                 /*
 1442                                  * We got an error from msleep(9).  This is
 1443                                  * most likely due to a signal.  Tell
 1444                                  * mpr_memaddr_wait_cb() that we've abandoned
 1445                                  * the context, so it needs to clean up when
 1446                                  * it is called.
 1447                                  */
 1448                                 ctx->abandoned = 1;
 1449 
 1450                                 /* The callback will free this memory */
 1451                                 ctx = NULL;
 1452                                 mps_unlock(sc);
 1453 
 1454                                 device_printf(sc->mps_dev, "Cannot "
 1455                                     "bus_dmamap_load FW diag buffer, error = "
 1456                                     "%d returned from msleep\n", error);
 1457                                 *return_code = MPS_FW_DIAG_ERROR_NO_BUFFER;
 1458                                 status = MPS_DIAG_FAILURE;
 1459                                 goto bailout;
 1460                         }
 1461                 }
 1462                 mps_unlock(sc);
 1463         } 
 1464 
 1465         if ((error != 0) || (ctx->error != 0)) {
 1466                 device_printf(sc->mps_dev, "Cannot bus_dmamap_load FW diag "
 1467                     "buffer, %serror = %d\n", error ? "" : "callback ",
 1468                     error ? error : ctx->error);
 1469                 *return_code = MPS_FW_DIAG_ERROR_NO_BUFFER;
 1470                 status = MPS_DIAG_FAILURE;
 1471                 goto bailout;
 1472         }
 1473 
 1474         bus_dmamap_sync(sc->fw_diag_dmat, sc->fw_diag_map, BUS_DMASYNC_PREREAD);
 1475 
 1476         pBuffer->size = buffer_size;
 1477 
 1478         /*
 1479          * Copy the given info to the diag buffer and post the buffer.
 1480          */
 1481         pBuffer->buffer_type = buffer_type;
 1482         pBuffer->immediate = FALSE;
 1483         if (buffer_type == MPI2_DIAG_BUF_TYPE_TRACE) {
 1484                 for (i = 0; i < (sizeof (pBuffer->product_specific) / 4);
 1485                     i++) {
 1486                         pBuffer->product_specific[i] =
 1487                             diag_register->ProductSpecific[i];
 1488                 }
 1489         }
 1490         pBuffer->extended_type = extended_type;
 1491         pBuffer->unique_id = unique_id;
 1492         status = mps_post_fw_diag_buffer(sc, pBuffer, return_code);
 1493 
 1494 bailout:
 1495         /*
 1496          * In case there was a failure, free the DMA buffer.
 1497          */
 1498         if (status == MPS_DIAG_FAILURE) {
 1499                 if (sc->fw_diag_busaddr != 0) {
 1500                         bus_dmamap_unload(sc->fw_diag_dmat, sc->fw_diag_map);
 1501                         sc->fw_diag_busaddr = 0;
 1502                 }
 1503                 if (sc->fw_diag_buffer != NULL) {
 1504                         bus_dmamem_free(sc->fw_diag_dmat, sc->fw_diag_buffer,
 1505                             sc->fw_diag_map);
 1506                         sc->fw_diag_buffer = NULL;
 1507                 }
 1508                 if (sc->fw_diag_dmat != NULL) {
 1509                         bus_dma_tag_destroy(sc->fw_diag_dmat);
 1510                         sc->fw_diag_dmat = NULL;
 1511                 }
 1512         }
 1513 
 1514         if (ctx != NULL)
 1515                 free(ctx, M_MPSUSER);
 1516 
 1517         return (status);
 1518 }
 1519 
 1520 static int
 1521 mps_diag_unregister(struct mps_softc *sc,
 1522     mps_fw_diag_unregister_t *diag_unregister, uint32_t *return_code)
 1523 {
 1524         mps_fw_diagnostic_buffer_t      *pBuffer;
 1525         uint8_t                         i;
 1526         uint32_t                        unique_id;
 1527         int                             status;
 1528 
 1529         unique_id = diag_unregister->UniqueId;
 1530 
 1531         /*
 1532          * Get the current buffer and look up the unique ID.  The unique ID
 1533          * should be there.
 1534          */
 1535         i = mps_get_fw_diag_buffer_number(sc, unique_id);
 1536         if (i == MPS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
 1537                 *return_code = MPS_FW_DIAG_ERROR_INVALID_UID;
 1538                 return (MPS_DIAG_FAILURE);
 1539         }
 1540 
 1541         pBuffer = &sc->fw_diag_buffer_list[i];
 1542 
 1543         /*
 1544          * Try to release the buffer from FW before freeing it.  If release
 1545          * fails, don't free the DMA buffer in case FW tries to access it
 1546          * later.  If buffer is not owned by firmware, can't release it.
 1547          */
 1548         if (!pBuffer->owned_by_firmware) {
 1549                 status = MPS_DIAG_SUCCESS;
 1550         } else {
 1551                 status = mps_release_fw_diag_buffer(sc, pBuffer, return_code,
 1552                     MPS_FW_DIAG_TYPE_UNREGISTER);
 1553         }
 1554 
 1555         /*
 1556          * At this point, return the current status no matter what happens with
 1557          * the DMA buffer.
 1558          */
 1559         pBuffer->unique_id = MPS_FW_DIAG_INVALID_UID;
 1560         if (status == MPS_DIAG_SUCCESS) {
 1561                 if (sc->fw_diag_busaddr != 0) {
 1562                         bus_dmamap_unload(sc->fw_diag_dmat, sc->fw_diag_map);
 1563                         sc->fw_diag_busaddr = 0;
 1564                 }
 1565                 if (sc->fw_diag_buffer != NULL) {
 1566                         bus_dmamem_free(sc->fw_diag_dmat, sc->fw_diag_buffer,
 1567                             sc->fw_diag_map);
 1568                         sc->fw_diag_buffer = NULL;
 1569                 }
 1570                 if (sc->fw_diag_dmat != NULL) {
 1571                         bus_dma_tag_destroy(sc->fw_diag_dmat);
 1572                         sc->fw_diag_dmat = NULL;
 1573                 }
 1574         }
 1575 
 1576         return (status);
 1577 }
 1578 
 1579 static int
 1580 mps_diag_query(struct mps_softc *sc, mps_fw_diag_query_t *diag_query,
 1581     uint32_t *return_code)
 1582 {
 1583         mps_fw_diagnostic_buffer_t      *pBuffer;
 1584         uint8_t                         i;
 1585         uint32_t                        unique_id;
 1586 
 1587         unique_id = diag_query->UniqueId;
 1588 
 1589         /*
 1590          * If ID is valid, query on ID.
 1591          * If ID is invalid, query on buffer type.
 1592          */
 1593         if (unique_id == MPS_FW_DIAG_INVALID_UID) {
 1594                 i = diag_query->BufferType;
 1595                 if (i >= MPI2_DIAG_BUF_TYPE_COUNT) {
 1596                         *return_code = MPS_FW_DIAG_ERROR_INVALID_UID;
 1597                         return (MPS_DIAG_FAILURE);
 1598                 }
 1599         } else {
 1600                 i = mps_get_fw_diag_buffer_number(sc, unique_id);
 1601                 if (i == MPS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
 1602                         *return_code = MPS_FW_DIAG_ERROR_INVALID_UID;
 1603                         return (MPS_DIAG_FAILURE);
 1604                 }
 1605         }
 1606 
 1607         /*
 1608          * Fill query structure with the diag buffer info.
 1609          */
 1610         pBuffer = &sc->fw_diag_buffer_list[i];
 1611         diag_query->BufferType = pBuffer->buffer_type;
 1612         diag_query->ExtendedType = pBuffer->extended_type;
 1613         if (diag_query->BufferType == MPI2_DIAG_BUF_TYPE_TRACE) {
 1614                 for (i = 0; i < (sizeof(diag_query->ProductSpecific) / 4);
 1615                     i++) {
 1616                         diag_query->ProductSpecific[i] =
 1617                             pBuffer->product_specific[i];
 1618                 }
 1619         }
 1620         diag_query->TotalBufferSize = pBuffer->size;
 1621         diag_query->DriverAddedBufferSize = 0;
 1622         diag_query->UniqueId = pBuffer->unique_id;
 1623         diag_query->ApplicationFlags = 0;
 1624         diag_query->DiagnosticFlags = 0;
 1625 
 1626         /*
 1627          * Set/Clear application flags
 1628          */
 1629         if (pBuffer->immediate) {
 1630                 diag_query->ApplicationFlags &= ~MPS_FW_DIAG_FLAG_APP_OWNED;
 1631         } else {
 1632                 diag_query->ApplicationFlags |= MPS_FW_DIAG_FLAG_APP_OWNED;
 1633         }
 1634         if (pBuffer->valid_data || pBuffer->owned_by_firmware) {
 1635                 diag_query->ApplicationFlags |= MPS_FW_DIAG_FLAG_BUFFER_VALID;
 1636         } else {
 1637                 diag_query->ApplicationFlags &= ~MPS_FW_DIAG_FLAG_BUFFER_VALID;
 1638         }
 1639         if (pBuffer->owned_by_firmware) {
 1640                 diag_query->ApplicationFlags |=
 1641                     MPS_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
 1642         } else {
 1643                 diag_query->ApplicationFlags &=
 1644                     ~MPS_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
 1645         }
 1646 
 1647         return (MPS_DIAG_SUCCESS);
 1648 }
 1649 
 1650 static int
 1651 mps_diag_read_buffer(struct mps_softc *sc,
 1652     mps_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
 1653     uint32_t *return_code)
 1654 {
 1655         mps_fw_diagnostic_buffer_t      *pBuffer;
 1656         uint8_t                         i, *pData;
 1657         uint32_t                        unique_id;
 1658         int                             status;
 1659 
 1660         unique_id = diag_read_buffer->UniqueId;
 1661 
 1662         /*
 1663          * Get the current buffer and look up the unique ID.  The unique ID
 1664          * should be there.
 1665          */
 1666         i = mps_get_fw_diag_buffer_number(sc, unique_id);
 1667         if (i == MPS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
 1668                 *return_code = MPS_FW_DIAG_ERROR_INVALID_UID;
 1669                 return (MPS_DIAG_FAILURE);
 1670         }
 1671 
 1672         pBuffer = &sc->fw_diag_buffer_list[i];
 1673 
 1674         /*
 1675          * Make sure requested read is within limits
 1676          */
 1677         if (diag_read_buffer->StartingOffset + diag_read_buffer->BytesToRead >
 1678             pBuffer->size) {
 1679                 *return_code = MPS_FW_DIAG_ERROR_INVALID_PARAMETER;
 1680                 return (MPS_DIAG_FAILURE);
 1681         }
 1682 
 1683         /* Sync the DMA map before we copy to userland. */
 1684         bus_dmamap_sync(sc->fw_diag_dmat, sc->fw_diag_map,
 1685             BUS_DMASYNC_POSTREAD);
 1686 
 1687         /*
 1688          * Copy the requested data from DMA to the diag_read_buffer.  The DMA
 1689          * buffer that was allocated is one contiguous buffer.
 1690          */
 1691         pData = (uint8_t *)(sc->fw_diag_buffer +
 1692             diag_read_buffer->StartingOffset);
 1693         if (copyout(pData, ioctl_buf, diag_read_buffer->BytesToRead) != 0)
 1694                 return (MPS_DIAG_FAILURE);
 1695         diag_read_buffer->Status = 0;
 1696 
 1697         /*
 1698          * Set or clear the Force Release flag.
 1699          */
 1700         if (pBuffer->force_release) {
 1701                 diag_read_buffer->Flags |= MPS_FW_DIAG_FLAG_FORCE_RELEASE;
 1702         } else {
 1703                 diag_read_buffer->Flags &= ~MPS_FW_DIAG_FLAG_FORCE_RELEASE;
 1704         }
 1705 
 1706         /*
 1707          * If buffer is to be reregistered, make sure it's not already owned by
 1708          * firmware first.
 1709          */
 1710         status = MPS_DIAG_SUCCESS;
 1711         if (!pBuffer->owned_by_firmware) {
 1712                 if (diag_read_buffer->Flags & MPS_FW_DIAG_FLAG_REREGISTER) {
 1713                         status = mps_post_fw_diag_buffer(sc, pBuffer,
 1714                             return_code);
 1715                 }
 1716         }
 1717 
 1718         return (status);
 1719 }
 1720 
 1721 static int
 1722 mps_diag_release(struct mps_softc *sc, mps_fw_diag_release_t *diag_release,
 1723     uint32_t *return_code)
 1724 {
 1725         mps_fw_diagnostic_buffer_t      *pBuffer;
 1726         uint8_t                         i;
 1727         uint32_t                        unique_id;
 1728         int                             status;
 1729 
 1730         unique_id = diag_release->UniqueId;
 1731 
 1732         /*
 1733          * Get the current buffer and look up the unique ID.  The unique ID
 1734          * should be there.
 1735          */
 1736         i = mps_get_fw_diag_buffer_number(sc, unique_id);
 1737         if (i == MPS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
 1738                 *return_code = MPS_FW_DIAG_ERROR_INVALID_UID;
 1739                 return (MPS_DIAG_FAILURE);
 1740         }
 1741 
 1742         pBuffer = &sc->fw_diag_buffer_list[i];
 1743 
 1744         /*
 1745          * If buffer is not owned by firmware, it's already been released.
 1746          */
 1747         if (!pBuffer->owned_by_firmware) {
 1748                 *return_code = MPS_FW_DIAG_ERROR_ALREADY_RELEASED;
 1749                 return (MPS_DIAG_FAILURE);
 1750         }
 1751 
 1752         /*
 1753          * Release the buffer.
 1754          */
 1755         status = mps_release_fw_diag_buffer(sc, pBuffer, return_code,
 1756             MPS_FW_DIAG_TYPE_RELEASE);
 1757         return (status);
 1758 }
 1759 
 1760 static int
 1761 mps_do_diag_action(struct mps_softc *sc, uint32_t action, uint8_t *diag_action,
 1762     uint32_t length, uint32_t *return_code)
 1763 {
 1764         mps_fw_diag_register_t          diag_register;
 1765         mps_fw_diag_unregister_t        diag_unregister;
 1766         mps_fw_diag_query_t             diag_query;
 1767         mps_diag_read_buffer_t          diag_read_buffer;
 1768         mps_fw_diag_release_t           diag_release;
 1769         int                             status = MPS_DIAG_SUCCESS;
 1770         uint32_t                        original_return_code;
 1771 
 1772         original_return_code = *return_code;
 1773         *return_code = MPS_FW_DIAG_ERROR_SUCCESS;
 1774 
 1775         switch (action) {
 1776                 case MPS_FW_DIAG_TYPE_REGISTER:
 1777                         if (!length) {
 1778                                 *return_code =
 1779                                     MPS_FW_DIAG_ERROR_INVALID_PARAMETER;
 1780                                 status = MPS_DIAG_FAILURE;
 1781                                 break;
 1782                         }
 1783                         if (copyin(diag_action, &diag_register,
 1784                             sizeof(diag_register)) != 0)
 1785                                 return (MPS_DIAG_FAILURE);
 1786                         status = mps_diag_register(sc, &diag_register,
 1787                             return_code);
 1788                         break;
 1789 
 1790                 case MPS_FW_DIAG_TYPE_UNREGISTER:
 1791                         if (length < sizeof(diag_unregister)) {
 1792                                 *return_code =
 1793                                     MPS_FW_DIAG_ERROR_INVALID_PARAMETER;
 1794                                 status = MPS_DIAG_FAILURE;
 1795                                 break;
 1796                         }
 1797                         if (copyin(diag_action, &diag_unregister,
 1798                             sizeof(diag_unregister)) != 0)
 1799                                 return (MPS_DIAG_FAILURE);
 1800                         status = mps_diag_unregister(sc, &diag_unregister,
 1801                             return_code);
 1802                         break;
 1803 
 1804                 case MPS_FW_DIAG_TYPE_QUERY:
 1805                         if (length < sizeof (diag_query)) {
 1806                                 *return_code =
 1807                                     MPS_FW_DIAG_ERROR_INVALID_PARAMETER;
 1808                                 status = MPS_DIAG_FAILURE;
 1809                                 break;
 1810                         }
 1811                         if (copyin(diag_action, &diag_query, sizeof(diag_query))
 1812                             != 0)
 1813                                 return (MPS_DIAG_FAILURE);
 1814                         status = mps_diag_query(sc, &diag_query, return_code);
 1815                         if (status == MPS_DIAG_SUCCESS)
 1816                                 if (copyout(&diag_query, diag_action,
 1817                                     sizeof (diag_query)) != 0)
 1818                                         return (MPS_DIAG_FAILURE);
 1819                         break;
 1820 
 1821                 case MPS_FW_DIAG_TYPE_READ_BUFFER:
 1822                         if (copyin(diag_action, &diag_read_buffer,
 1823                             sizeof(diag_read_buffer)) != 0)
 1824                                 return (MPS_DIAG_FAILURE);
 1825                         if (length < diag_read_buffer.BytesToRead) {
 1826                                 *return_code =
 1827                                     MPS_FW_DIAG_ERROR_INVALID_PARAMETER;
 1828                                 status = MPS_DIAG_FAILURE;
 1829                                 break;
 1830                         }
 1831                         status = mps_diag_read_buffer(sc, &diag_read_buffer,
 1832                             PTRIN(diag_read_buffer.PtrDataBuffer),
 1833                             return_code);
 1834                         if (status == MPS_DIAG_SUCCESS) {
 1835                                 if (copyout(&diag_read_buffer, diag_action,
 1836                                     sizeof(diag_read_buffer) -
 1837                                     sizeof(diag_read_buffer.PtrDataBuffer)) !=
 1838                                     0)
 1839                                         return (MPS_DIAG_FAILURE);
 1840                         }
 1841                         break;
 1842 
 1843                 case MPS_FW_DIAG_TYPE_RELEASE:
 1844                         if (length < sizeof(diag_release)) {
 1845                                 *return_code =
 1846                                     MPS_FW_DIAG_ERROR_INVALID_PARAMETER;
 1847                                 status = MPS_DIAG_FAILURE;
 1848                                 break;
 1849                         }
 1850                         if (copyin(diag_action, &diag_release,
 1851                             sizeof(diag_release)) != 0)
 1852                                 return (MPS_DIAG_FAILURE);
 1853                         status = mps_diag_release(sc, &diag_release,
 1854                             return_code);
 1855                         break;
 1856 
 1857                 default:
 1858                         *return_code = MPS_FW_DIAG_ERROR_INVALID_PARAMETER;
 1859                         status = MPS_DIAG_FAILURE;
 1860                         break;
 1861         }
 1862 
 1863         if ((status == MPS_DIAG_FAILURE) &&
 1864             (original_return_code == MPS_FW_DIAG_NEW) &&
 1865             (*return_code != MPS_FW_DIAG_ERROR_SUCCESS))
 1866                 status = MPS_DIAG_SUCCESS;
 1867 
 1868         return (status);
 1869 }
 1870 
 1871 static int
 1872 mps_user_diag_action(struct mps_softc *sc, mps_diag_action_t *data)
 1873 {
 1874         int                     status;
 1875 
 1876         /*
 1877          * Only allow one diag action at one time.
 1878          */
 1879         if (sc->mps_flags & MPS_FLAGS_BUSY) {
 1880                 mps_dprint(sc, MPS_USER, "%s: Only one FW diag command "
 1881                     "allowed at a single time.", __func__);
 1882                 return (EBUSY);
 1883         }
 1884         sc->mps_flags |= MPS_FLAGS_BUSY;
 1885 
 1886         /*
 1887          * Send diag action request
 1888          */
 1889         if (data->Action == MPS_FW_DIAG_TYPE_REGISTER ||
 1890             data->Action == MPS_FW_DIAG_TYPE_UNREGISTER ||
 1891             data->Action == MPS_FW_DIAG_TYPE_QUERY ||
 1892             data->Action == MPS_FW_DIAG_TYPE_READ_BUFFER ||
 1893             data->Action == MPS_FW_DIAG_TYPE_RELEASE) {
 1894                 status = mps_do_diag_action(sc, data->Action,
 1895                     PTRIN(data->PtrDiagAction), data->Length,
 1896                     &data->ReturnCode);
 1897         } else
 1898                 status = EINVAL;
 1899 
 1900         sc->mps_flags &= ~MPS_FLAGS_BUSY;
 1901         return (status);
 1902 }
 1903 
 1904 /*
 1905  * Copy the event recording mask and the event queue size out.  For
 1906  * clarification, the event recording mask (events_to_record) is not the same
 1907  * thing as the event mask (event_mask).  events_to_record has a bit set for
 1908  * every event type that is to be recorded by the driver, and event_mask has a
 1909  * bit cleared for every event that is allowed into the driver from the IOC.
 1910  * They really have nothing to do with each other.
 1911  */
 1912 static void
 1913 mps_user_event_query(struct mps_softc *sc, mps_event_query_t *data)
 1914 {
 1915         uint8_t i;
 1916 
 1917         mps_lock(sc);
 1918         data->Entries = MPS_EVENT_QUEUE_SIZE;
 1919 
 1920         for (i = 0; i < 4; i++) {
 1921                 data->Types[i] = sc->events_to_record[i];
 1922         }
 1923         mps_unlock(sc);
 1924 }
 1925 
 1926 /*
 1927  * Set the driver's event mask according to what's been given.  See
 1928  * mps_user_event_query for explanation of the event recording mask and the IOC
 1929  * event mask.  It's the app's responsibility to enable event logging by setting
 1930  * the bits in events_to_record.  Initially, no events will be logged.
 1931  */
 1932 static void
 1933 mps_user_event_enable(struct mps_softc *sc, mps_event_enable_t *data)
 1934 {
 1935         uint8_t i;
 1936 
 1937         mps_lock(sc);
 1938         for (i = 0; i < 4; i++) {
 1939                 sc->events_to_record[i] = data->Types[i];
 1940         }
 1941         mps_unlock(sc);
 1942 }
 1943 
 1944 /*
 1945  * Copy out the events that have been recorded, up to the max events allowed.
 1946  */
 1947 static int
 1948 mps_user_event_report(struct mps_softc *sc, mps_event_report_t *data)
 1949 {
 1950         int             status = 0;
 1951         uint32_t        size;
 1952 
 1953         mps_lock(sc);
 1954         size = data->Size;
 1955         if ((size >= sizeof(sc->recorded_events)) && (status == 0)) {
 1956                 mps_unlock(sc);
 1957                 if (copyout((void *)sc->recorded_events,
 1958                     PTRIN(data->PtrEvents), size) != 0)
 1959                         status = EFAULT;
 1960                 mps_lock(sc);
 1961         } else {
 1962                 /*
 1963                  * data->Size value is not large enough to copy event data.
 1964                  */
 1965                 status = EFAULT;
 1966         }
 1967 
 1968         /*
 1969          * Change size value to match the number of bytes that were copied.
 1970          */
 1971         if (status == 0)
 1972                 data->Size = sizeof(sc->recorded_events);
 1973         mps_unlock(sc);
 1974 
 1975         return (status);
 1976 }
 1977 
 1978 /*
 1979  * Record events into the driver from the IOC if they are not masked.
 1980  */
 1981 void
 1982 mpssas_record_event(struct mps_softc *sc,
 1983     MPI2_EVENT_NOTIFICATION_REPLY *event_reply)
 1984 {
 1985         uint32_t        event;
 1986         int             i, j;
 1987         uint16_t        event_data_len;
 1988         boolean_t       sendAEN = FALSE;
 1989 
 1990         event = event_reply->Event;
 1991 
 1992         /*
 1993          * Generate a system event to let anyone who cares know that a
 1994          * LOG_ENTRY_ADDED event has occurred.  This is sent no matter what the
 1995          * event mask is set to.
 1996          */
 1997         if (event == MPI2_EVENT_LOG_ENTRY_ADDED) {
 1998                 sendAEN = TRUE;
 1999         }
 2000 
 2001         /*
 2002          * Record the event only if its corresponding bit is set in
 2003          * events_to_record.  event_index is the index into recorded_events and
 2004          * event_number is the overall number of an event being recorded since
 2005          * start-of-day.  event_index will roll over; event_number will never
 2006          * roll over.
 2007          */
 2008         i = (uint8_t)(event / 32);
 2009         j = (uint8_t)(event % 32);
 2010         if ((i < 4) && ((1 << j) & sc->events_to_record[i])) {
 2011                 i = sc->event_index;
 2012                 sc->recorded_events[i].Type = event;
 2013                 sc->recorded_events[i].Number = ++sc->event_number;
 2014                 bzero(sc->recorded_events[i].Data, MPS_MAX_EVENT_DATA_LENGTH *
 2015                     4);
 2016                 event_data_len = event_reply->EventDataLength;
 2017 
 2018                 if (event_data_len > 0) {
 2019                         /*
 2020                          * Limit data to size in m_event entry
 2021                          */
 2022                         if (event_data_len > MPS_MAX_EVENT_DATA_LENGTH) {
 2023                                 event_data_len = MPS_MAX_EVENT_DATA_LENGTH;
 2024                         }
 2025                         for (j = 0; j < event_data_len; j++) {
 2026                                 sc->recorded_events[i].Data[j] =
 2027                                     event_reply->EventData[j];
 2028                         }
 2029 
 2030                         /*
 2031                          * check for index wrap-around
 2032                          */
 2033                         if (++i == MPS_EVENT_QUEUE_SIZE) {
 2034                                 i = 0;
 2035                         }
 2036                         sc->event_index = (uint8_t)i;
 2037 
 2038                         /*
 2039                          * Set flag to send the event.
 2040                          */
 2041                         sendAEN = TRUE;
 2042                 }
 2043         }
 2044 
 2045         /*
 2046          * Generate a system event if flag is set to let anyone who cares know
 2047          * that an event has occurred.
 2048          */
 2049         if (sendAEN) {
 2050 //SLM-how to send a system event (see kqueue, kevent)
 2051 //              (void) ddi_log_sysevent(mpt->m_dip, DDI_VENDOR_LSI, "MPT_SAS",
 2052 //                  "SAS", NULL, NULL, DDI_NOSLEEP);
 2053         }
 2054 }
 2055 
 2056 static int
 2057 mps_user_reg_access(struct mps_softc *sc, mps_reg_access_t *data)
 2058 {
 2059         int     status = 0;
 2060 
 2061         switch (data->Command) {
 2062                 /*
 2063                  * IO access is not supported.
 2064                  */
 2065                 case REG_IO_READ:
 2066                 case REG_IO_WRITE:
 2067                         mps_dprint(sc, MPS_USER, "IO access is not supported. "
 2068                             "Use memory access.");
 2069                         status = EINVAL;
 2070                         break;
 2071 
 2072                 case REG_MEM_READ:
 2073                         data->RegData = mps_regread(sc, data->RegOffset);
 2074                         break;
 2075 
 2076                 case REG_MEM_WRITE:
 2077                         mps_regwrite(sc, data->RegOffset, data->RegData);
 2078                         break;
 2079 
 2080                 default:
 2081                         status = EINVAL;
 2082                         break;
 2083         }
 2084 
 2085         return (status);
 2086 }
 2087 
 2088 static int
 2089 mps_user_btdh(struct mps_softc *sc, mps_btdh_mapping_t *data)
 2090 {
 2091         uint8_t         bt2dh = FALSE;
 2092         uint8_t         dh2bt = FALSE;
 2093         uint16_t        dev_handle, bus, target;
 2094 
 2095         bus = data->Bus;
 2096         target = data->TargetID;
 2097         dev_handle = data->DevHandle;
 2098 
 2099         /*
 2100          * When DevHandle is 0xFFFF and Bus/Target are not 0xFFFF, use Bus/
 2101          * Target to get DevHandle.  When Bus/Target are 0xFFFF and DevHandle is
 2102          * not 0xFFFF, use DevHandle to get Bus/Target.  Anything else is
 2103          * invalid.
 2104          */
 2105         if ((bus == 0xFFFF) && (target == 0xFFFF) && (dev_handle != 0xFFFF))
 2106                 dh2bt = TRUE;
 2107         if ((dev_handle == 0xFFFF) && (bus != 0xFFFF) && (target != 0xFFFF))
 2108                 bt2dh = TRUE;
 2109         if (!dh2bt && !bt2dh)
 2110                 return (EINVAL);
 2111 
 2112         /*
 2113          * Only handle bus of 0.  Make sure target is within range.
 2114          */
 2115         if (bt2dh) {
 2116                 if (bus != 0)
 2117                         return (EINVAL);
 2118 
 2119                 if (target >= sc->max_devices) {
 2120                         mps_dprint(sc, MPS_FAULT, "Target ID is out of range "
 2121                            "for Bus/Target to DevHandle mapping.");
 2122                         return (EINVAL);
 2123                 }
 2124                 dev_handle = sc->mapping_table[target].dev_handle;
 2125                 if (dev_handle)
 2126                         data->DevHandle = dev_handle;
 2127         } else {
 2128                 bus = 0;
 2129                 target = mps_mapping_get_tid_from_handle(sc, dev_handle);
 2130                 data->Bus = bus;
 2131                 data->TargetID = target;
 2132         }
 2133 
 2134         return (0);
 2135 }
 2136 
 2137 static int
 2138 mps_ioctl(struct cdev *dev, u_long cmd, void *arg, int flag,
 2139     struct thread *td)
 2140 {
 2141         struct mps_softc *sc;
 2142         struct mps_cfg_page_req *page_req;
 2143         struct mps_ext_cfg_page_req *ext_page_req;
 2144         void *mps_page;
 2145         int error, msleep_ret;
 2146 
 2147         mps_page = NULL;
 2148         sc = dev->si_drv1;
 2149         page_req = (void *)arg;
 2150         ext_page_req = (void *)arg;
 2151 
 2152         switch (cmd) {
 2153         case MPSIO_READ_CFG_HEADER:
 2154                 mps_lock(sc);
 2155                 error = mps_user_read_cfg_header(sc, page_req);
 2156                 mps_unlock(sc);
 2157                 break;
 2158         case MPSIO_READ_CFG_PAGE:
 2159                 if (page_req->len < (int)sizeof(MPI2_CONFIG_PAGE_HEADER)) {
 2160                         error = EINVAL;
 2161                         break;
 2162                 }
 2163                 mps_page = malloc(page_req->len, M_MPSUSER, M_WAITOK | M_ZERO);
 2164                 error = copyin(page_req->buf, mps_page,
 2165                     sizeof(MPI2_CONFIG_PAGE_HEADER));
 2166                 if (error)
 2167                         break;
 2168                 mps_lock(sc);
 2169                 error = mps_user_read_cfg_page(sc, page_req, mps_page);
 2170                 mps_unlock(sc);
 2171                 if (error)
 2172                         break;
 2173                 error = copyout(mps_page, page_req->buf, page_req->len);
 2174                 break;
 2175         case MPSIO_READ_EXT_CFG_HEADER:
 2176                 mps_lock(sc);
 2177                 error = mps_user_read_extcfg_header(sc, ext_page_req);
 2178                 mps_unlock(sc);
 2179                 break;
 2180         case MPSIO_READ_EXT_CFG_PAGE:
 2181                 if (ext_page_req->len <
 2182                     (int)sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER)) {
 2183                         error = EINVAL;
 2184                         break;
 2185                 }
 2186                 mps_page = malloc(ext_page_req->len, M_MPSUSER, M_WAITOK|M_ZERO);
 2187                 error = copyin(ext_page_req->buf, mps_page,
 2188                     sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
 2189                 if (error)
 2190                         break;
 2191                 mps_lock(sc);
 2192                 error = mps_user_read_extcfg_page(sc, ext_page_req, mps_page);
 2193                 mps_unlock(sc);
 2194                 if (error)
 2195                         break;
 2196                 error = copyout(mps_page, ext_page_req->buf, ext_page_req->len);
 2197                 break;
 2198         case MPSIO_WRITE_CFG_PAGE:
 2199                 if (page_req->len < (int)sizeof(MPI2_CONFIG_PAGE_HEADER)) {
 2200                         error = EINVAL;
 2201                         break;
 2202                 }
 2203                 mps_page = malloc(page_req->len, M_MPSUSER, M_WAITOK|M_ZERO);
 2204                 error = copyin(page_req->buf, mps_page, page_req->len);
 2205                 if (error)
 2206                         break;
 2207                 mps_lock(sc);
 2208                 error = mps_user_write_cfg_page(sc, page_req, mps_page);
 2209                 mps_unlock(sc);
 2210                 break;
 2211         case MPSIO_MPS_COMMAND:
 2212                 error = mps_user_command(sc, (struct mps_usr_command *)arg);
 2213                 break;
 2214         case MPTIOCTL_PASS_THRU:
 2215                 /*
 2216                  * The user has requested to pass through a command to be
 2217                  * executed by the MPT firmware.  Call our routine which does
 2218                  * this.  Only allow one passthru IOCTL at one time.
 2219                  */
 2220                 error = mps_user_pass_thru(sc, (mps_pass_thru_t *)arg);
 2221                 break;
 2222         case MPTIOCTL_GET_ADAPTER_DATA:
 2223                 /*
 2224                  * The user has requested to read adapter data.  Call our
 2225                  * routine which does this.
 2226                  */
 2227                 error = 0;
 2228                 mps_user_get_adapter_data(sc, (mps_adapter_data_t *)arg);
 2229                 break;
 2230         case MPTIOCTL_GET_PCI_INFO:
 2231                 /*
 2232                  * The user has requested to read pci info.  Call
 2233                  * our routine which does this.
 2234                  */
 2235                 mps_lock(sc);
 2236                 error = 0;
 2237                 mps_user_read_pci_info(sc, (mps_pci_info_t *)arg);
 2238                 mps_unlock(sc);
 2239                 break;
 2240         case MPTIOCTL_RESET_ADAPTER:
 2241                 mps_lock(sc);
 2242                 sc->port_enable_complete = 0;
 2243                 uint32_t reinit_start = time_uptime;
 2244                 error = mps_reinit(sc);
 2245                 /* Sleep for 300 second. */
 2246                 msleep_ret = msleep(&sc->port_enable_complete, &sc->mps_mtx, PRIBIO,
 2247                        "mps_porten", 300 * hz);
 2248                 mps_unlock(sc);
 2249                 if (msleep_ret)
 2250                         printf("Port Enable did not complete after Diag "
 2251                             "Reset msleep error %d.\n", msleep_ret);
 2252                 else
 2253                         mps_dprint(sc, MPS_USER,
 2254                                 "Hard Reset with Port Enable completed in %d seconds.\n",
 2255                                  (uint32_t) (time_uptime - reinit_start));
 2256                 break;
 2257         case MPTIOCTL_DIAG_ACTION:
 2258                 /*
 2259                  * The user has done a diag buffer action.  Call our routine
 2260                  * which does this.  Only allow one diag action at one time.
 2261                  */
 2262                 mps_lock(sc);
 2263                 error = mps_user_diag_action(sc, (mps_diag_action_t *)arg);
 2264                 mps_unlock(sc);
 2265                 break;
 2266         case MPTIOCTL_EVENT_QUERY:
 2267                 /*
 2268                  * The user has done an event query. Call our routine which does
 2269                  * this.
 2270                  */
 2271                 error = 0;
 2272                 mps_user_event_query(sc, (mps_event_query_t *)arg);
 2273                 break;
 2274         case MPTIOCTL_EVENT_ENABLE:
 2275                 /*
 2276                  * The user has done an event enable. Call our routine which
 2277                  * does this.
 2278                  */
 2279                 error = 0;
 2280                 mps_user_event_enable(sc, (mps_event_enable_t *)arg);
 2281                 break;
 2282         case MPTIOCTL_EVENT_REPORT:
 2283                 /*
 2284                  * The user has done an event report. Call our routine which
 2285                  * does this.
 2286                  */
 2287                 error = mps_user_event_report(sc, (mps_event_report_t *)arg);
 2288                 break;
 2289         case MPTIOCTL_REG_ACCESS:
 2290                 /*
 2291                  * The user has requested register access.  Call our routine
 2292                  * which does this.
 2293                  */
 2294                 mps_lock(sc);
 2295                 error = mps_user_reg_access(sc, (mps_reg_access_t *)arg);
 2296                 mps_unlock(sc);
 2297                 break;
 2298         case MPTIOCTL_BTDH_MAPPING:
 2299                 /*
 2300                  * The user has requested to translate a bus/target to a
 2301                  * DevHandle or a DevHandle to a bus/target.  Call our routine
 2302                  * which does this.
 2303                  */
 2304                 error = mps_user_btdh(sc, (mps_btdh_mapping_t *)arg);
 2305                 break;
 2306         default:
 2307                 error = ENOIOCTL;
 2308                 break;
 2309         }
 2310 
 2311         if (mps_page != NULL)
 2312                 free(mps_page, M_MPSUSER);
 2313 
 2314         return (error);
 2315 }
 2316 
 2317 #ifdef COMPAT_FREEBSD32
 2318 
 2319 struct mps_cfg_page_req32 {
 2320         MPI2_CONFIG_PAGE_HEADER header;
 2321         uint32_t page_address;
 2322         uint32_t buf;
 2323         int     len;    
 2324         uint16_t ioc_status;
 2325 };
 2326 
 2327 struct mps_ext_cfg_page_req32 {
 2328         MPI2_CONFIG_EXTENDED_PAGE_HEADER header;
 2329         uint32_t page_address;
 2330         uint32_t buf;
 2331         int     len;
 2332         uint16_t ioc_status;
 2333 };
 2334 
 2335 struct mps_raid_action32 {
 2336         uint8_t action;
 2337         uint8_t volume_bus;
 2338         uint8_t volume_id;
 2339         uint8_t phys_disk_num;
 2340         uint32_t action_data_word;
 2341         uint32_t buf;
 2342         int len;
 2343         uint32_t volume_status;
 2344         uint32_t action_data[4];
 2345         uint16_t action_status;
 2346         uint16_t ioc_status;
 2347         uint8_t write;
 2348 };
 2349 
 2350 struct mps_usr_command32 {
 2351         uint32_t req;
 2352         uint32_t req_len;
 2353         uint32_t rpl;
 2354         uint32_t rpl_len;
 2355         uint32_t buf;
 2356         int len;
 2357         uint32_t flags;
 2358 };
 2359 
 2360 #define MPSIO_READ_CFG_HEADER32 _IOWR('M', 200, struct mps_cfg_page_req32)
 2361 #define MPSIO_READ_CFG_PAGE32   _IOWR('M', 201, struct mps_cfg_page_req32)
 2362 #define MPSIO_READ_EXT_CFG_HEADER32 _IOWR('M', 202, struct mps_ext_cfg_page_req32)
 2363 #define MPSIO_READ_EXT_CFG_PAGE32 _IOWR('M', 203, struct mps_ext_cfg_page_req32)
 2364 #define MPSIO_WRITE_CFG_PAGE32  _IOWR('M', 204, struct mps_cfg_page_req32)
 2365 #define MPSIO_RAID_ACTION32     _IOWR('M', 205, struct mps_raid_action32)
 2366 #define MPSIO_MPS_COMMAND32     _IOWR('M', 210, struct mps_usr_command32)
 2367 
 2368 static int
 2369 mps_ioctl32(struct cdev *dev, u_long cmd32, void *_arg, int flag,
 2370     struct thread *td)
 2371 {
 2372         struct mps_cfg_page_req32 *page32 = _arg;
 2373         struct mps_ext_cfg_page_req32 *ext32 = _arg;
 2374         struct mps_raid_action32 *raid32 = _arg;
 2375         struct mps_usr_command32 *user32 = _arg;
 2376         union {
 2377                 struct mps_cfg_page_req page;
 2378                 struct mps_ext_cfg_page_req ext;
 2379                 struct mps_raid_action raid;
 2380                 struct mps_usr_command user;
 2381         } arg;
 2382         u_long cmd;
 2383         int error;
 2384 
 2385         switch (cmd32) {
 2386         case MPSIO_READ_CFG_HEADER32:
 2387         case MPSIO_READ_CFG_PAGE32:
 2388         case MPSIO_WRITE_CFG_PAGE32:
 2389                 if (cmd32 == MPSIO_READ_CFG_HEADER32)
 2390                         cmd = MPSIO_READ_CFG_HEADER;
 2391                 else if (cmd32 == MPSIO_READ_CFG_PAGE32)
 2392                         cmd = MPSIO_READ_CFG_PAGE;
 2393                 else
 2394                         cmd = MPSIO_WRITE_CFG_PAGE;
 2395                 CP(*page32, arg.page, header);
 2396                 CP(*page32, arg.page, page_address);
 2397                 PTRIN_CP(*page32, arg.page, buf);
 2398                 CP(*page32, arg.page, len);
 2399                 CP(*page32, arg.page, ioc_status);
 2400                 break;
 2401 
 2402         case MPSIO_READ_EXT_CFG_HEADER32:
 2403         case MPSIO_READ_EXT_CFG_PAGE32:
 2404                 if (cmd32 == MPSIO_READ_EXT_CFG_HEADER32)
 2405                         cmd = MPSIO_READ_EXT_CFG_HEADER;
 2406                 else
 2407                         cmd = MPSIO_READ_EXT_CFG_PAGE;
 2408                 CP(*ext32, arg.ext, header);
 2409                 CP(*ext32, arg.ext, page_address);
 2410                 PTRIN_CP(*ext32, arg.ext, buf);
 2411                 CP(*ext32, arg.ext, len);
 2412                 CP(*ext32, arg.ext, ioc_status);
 2413                 break;
 2414 
 2415         case MPSIO_RAID_ACTION32:
 2416                 cmd = MPSIO_RAID_ACTION;
 2417                 CP(*raid32, arg.raid, action);
 2418                 CP(*raid32, arg.raid, volume_bus);
 2419                 CP(*raid32, arg.raid, volume_id);
 2420                 CP(*raid32, arg.raid, phys_disk_num);
 2421                 CP(*raid32, arg.raid, action_data_word);
 2422                 PTRIN_CP(*raid32, arg.raid, buf);
 2423                 CP(*raid32, arg.raid, len);
 2424                 CP(*raid32, arg.raid, volume_status);
 2425                 bcopy(raid32->action_data, arg.raid.action_data,
 2426                     sizeof arg.raid.action_data);
 2427                 CP(*raid32, arg.raid, ioc_status);
 2428                 CP(*raid32, arg.raid, write);
 2429                 break;
 2430 
 2431         case MPSIO_MPS_COMMAND32:
 2432                 cmd = MPSIO_MPS_COMMAND;
 2433                 PTRIN_CP(*user32, arg.user, req);
 2434                 CP(*user32, arg.user, req_len);
 2435                 PTRIN_CP(*user32, arg.user, rpl);
 2436                 CP(*user32, arg.user, rpl_len);
 2437                 PTRIN_CP(*user32, arg.user, buf);
 2438                 CP(*user32, arg.user, len);
 2439                 CP(*user32, arg.user, flags);
 2440                 break;
 2441         default:
 2442                 return (ENOIOCTL);
 2443         }
 2444 
 2445         error = mps_ioctl(dev, cmd, &arg, flag, td);
 2446         if (error == 0 && (cmd32 & IOC_OUT) != 0) {
 2447                 switch (cmd32) {
 2448                 case MPSIO_READ_CFG_HEADER32:
 2449                 case MPSIO_READ_CFG_PAGE32:
 2450                 case MPSIO_WRITE_CFG_PAGE32:
 2451                         CP(arg.page, *page32, header);
 2452                         CP(arg.page, *page32, page_address);
 2453                         PTROUT_CP(arg.page, *page32, buf);
 2454                         CP(arg.page, *page32, len);
 2455                         CP(arg.page, *page32, ioc_status);
 2456                         break;
 2457 
 2458                 case MPSIO_READ_EXT_CFG_HEADER32:
 2459                 case MPSIO_READ_EXT_CFG_PAGE32:
 2460                         CP(arg.ext, *ext32, header);
 2461                         CP(arg.ext, *ext32, page_address);
 2462                         PTROUT_CP(arg.ext, *ext32, buf);
 2463                         CP(arg.ext, *ext32, len);
 2464                         CP(arg.ext, *ext32, ioc_status);
 2465                         break;
 2466 
 2467                 case MPSIO_RAID_ACTION32:
 2468                         CP(arg.raid, *raid32, action);
 2469                         CP(arg.raid, *raid32, volume_bus);
 2470                         CP(arg.raid, *raid32, volume_id);
 2471                         CP(arg.raid, *raid32, phys_disk_num);
 2472                         CP(arg.raid, *raid32, action_data_word);
 2473                         PTROUT_CP(arg.raid, *raid32, buf);
 2474                         CP(arg.raid, *raid32, len);
 2475                         CP(arg.raid, *raid32, volume_status);
 2476                         bcopy(arg.raid.action_data, raid32->action_data,
 2477                             sizeof arg.raid.action_data);
 2478                         CP(arg.raid, *raid32, ioc_status);
 2479                         CP(arg.raid, *raid32, write);
 2480                         break;
 2481 
 2482                 case MPSIO_MPS_COMMAND32:
 2483                         PTROUT_CP(arg.user, *user32, req);
 2484                         CP(arg.user, *user32, req_len);
 2485                         PTROUT_CP(arg.user, *user32, rpl);
 2486                         CP(arg.user, *user32, rpl_len);
 2487                         PTROUT_CP(arg.user, *user32, buf);
 2488                         CP(arg.user, *user32, len);
 2489                         CP(arg.user, *user32, flags);
 2490                         break;
 2491                 }
 2492         }
 2493 
 2494         return (error);
 2495 }
 2496 #endif /* COMPAT_FREEBSD32 */
 2497 
 2498 static int
 2499 mps_ioctl_devsw(struct cdev *dev, u_long com, caddr_t arg, int flag,
 2500     struct thread *td)
 2501 {
 2502 #ifdef COMPAT_FREEBSD32
 2503         if (SV_CURPROC_FLAG(SV_ILP32))
 2504                 return (mps_ioctl32(dev, com, arg, flag, td));
 2505 #endif
 2506         return (mps_ioctl(dev, com, arg, flag, td));
 2507 }

Cache object: 198d35ed0dc173d0354b063868bf4520


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