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/mpt/mpt_cam.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  * FreeBSD/CAM specific routines for LSI '909 FC  adapters.
    3  * FreeBSD Version.
    4  *
    5  * Copyright (c)  2000, 2001 by Greg Ansley
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice immediately at the beginning of the file, without modification,
   12  *    this list of conditions, and the following disclaimer.
   13  * 2. The name of the author may not be used to endorse or promote products
   14  *    derived from this software without specific prior written permission.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 /*-
   29  * Copyright (c) 2002, 2006 by Matthew Jacob
   30  * All rights reserved.
   31  * 
   32  * Redistribution and use in source and binary forms, with or without
   33  * modification, are permitted provided that the following conditions are
   34  * met:
   35  * 1. Redistributions of source code must retain the above copyright
   36  *    notice, this list of conditions and the following disclaimer.
   37  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   38  *    substantially similar to the "NO WARRANTY" disclaimer below
   39  *    ("Disclaimer") and any redistribution must be conditioned upon including
   40  *    a substantially similar Disclaimer requirement for further binary
   41  *    redistribution.
   42  * 3. Neither the names of the above listed copyright holders nor the names
   43  *    of any contributors may be used to endorse or promote products derived
   44  *    from this software without specific prior written permission.
   45  * 
   46  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   47  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   48  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   49  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   50  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   51  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   52  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   53  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   54  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   55  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT
   56  * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   57  *
   58  * Support from Chris Ellsworth in order to make SAS adapters work
   59  * is gratefully acknowledged.
   60  *
   61  * Support from LSI-Logic has also gone a great deal toward making this a
   62  * workable subsystem and is gratefully acknowledged.
   63  */
   64 /*-
   65  * Copyright (c) 2004, Avid Technology, Inc. and its contributors.
   66  * Copyright (c) 2005, WHEEL Sp. z o.o.
   67  * Copyright (c) 2004, 2005 Justin T. Gibbs
   68  * All rights reserved.
   69  * 
   70  * Redistribution and use in source and binary forms, with or without
   71  * modification, are permitted provided that the following conditions are
   72  * met:
   73  * 1. Redistributions of source code must retain the above copyright
   74  *    notice, this list of conditions and the following disclaimer.
   75  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   76  *    substantially similar to the "NO WARRANTY" disclaimer below
   77  *    ("Disclaimer") and any redistribution must be conditioned upon including
   78  *    a substantially similar Disclaimer requirement for further binary
   79  *    redistribution.
   80  * 3. Neither the names of the above listed copyright holders nor the names
   81  *    of any contributors may be used to endorse or promote products derived
   82  *    from this software without specific prior written permission.
   83  * 
   84  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   85  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   86  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   87  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   88  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   89  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   90  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   91  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   92  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   93  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT
   94  * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   95  */
   96 #include <sys/cdefs.h>
   97 __FBSDID("$FreeBSD: releng/8.4/sys/dev/mpt/mpt_cam.c 245987 2013-01-27 17:15:58Z marius $");
   98 
   99 #include <dev/mpt/mpt.h>
  100 #include <dev/mpt/mpt_cam.h>
  101 #include <dev/mpt/mpt_raid.h>
  102 
  103 #include "dev/mpt/mpilib/mpi_ioc.h" /* XXX Fix Event Handling!!! */
  104 #include "dev/mpt/mpilib/mpi_init.h"
  105 #include "dev/mpt/mpilib/mpi_targ.h"
  106 #include "dev/mpt/mpilib/mpi_fc.h"
  107 #include "dev/mpt/mpilib/mpi_sas.h"
  108 
  109 #include <sys/callout.h>
  110 #include <sys/kthread.h>
  111 #include <sys/sysctl.h>
  112 
  113 #if __FreeBSD_version >= 700025
  114 #ifndef CAM_NEW_TRAN_CODE
  115 #define CAM_NEW_TRAN_CODE       1
  116 #endif
  117 #endif
  118 
  119 static void mpt_poll(struct cam_sim *);
  120 static timeout_t mpt_timeout;
  121 static void mpt_action(struct cam_sim *, union ccb *);
  122 static int
  123 mpt_get_spi_settings(struct mpt_softc *, struct ccb_trans_settings *);
  124 static void mpt_setwidth(struct mpt_softc *, int, int);
  125 static void mpt_setsync(struct mpt_softc *, int, int, int);
  126 static int mpt_update_spi_config(struct mpt_softc *, int);
  127 
  128 static mpt_reply_handler_t mpt_scsi_reply_handler;
  129 static mpt_reply_handler_t mpt_scsi_tmf_reply_handler;
  130 static mpt_reply_handler_t mpt_fc_els_reply_handler;
  131 static int mpt_scsi_reply_frame_handler(struct mpt_softc *, request_t *,
  132                                         MSG_DEFAULT_REPLY *);
  133 static int mpt_bus_reset(struct mpt_softc *, target_id_t, lun_id_t, int);
  134 static int mpt_fc_reset_link(struct mpt_softc *, int);
  135 
  136 static int mpt_spawn_recovery_thread(struct mpt_softc *mpt);
  137 static void mpt_terminate_recovery_thread(struct mpt_softc *mpt);
  138 static void mpt_recovery_thread(void *arg);
  139 static void mpt_recover_commands(struct mpt_softc *mpt);
  140 
  141 static int mpt_scsi_send_tmf(struct mpt_softc *, u_int, u_int, u_int,
  142     u_int, u_int, u_int, int);
  143 
  144 static void mpt_fc_post_els(struct mpt_softc *mpt, request_t *, int);
  145 static void mpt_post_target_command(struct mpt_softc *, request_t *, int);
  146 static int mpt_add_els_buffers(struct mpt_softc *mpt);
  147 static int mpt_add_target_commands(struct mpt_softc *mpt);
  148 static int mpt_enable_lun(struct mpt_softc *, target_id_t, lun_id_t);
  149 static int mpt_disable_lun(struct mpt_softc *, target_id_t, lun_id_t);
  150 static void mpt_target_start_io(struct mpt_softc *, union ccb *);
  151 static cam_status mpt_abort_target_ccb(struct mpt_softc *, union ccb *);
  152 static int mpt_abort_target_cmd(struct mpt_softc *, request_t *);
  153 static void mpt_scsi_tgt_status(struct mpt_softc *, union ccb *, request_t *,
  154     uint8_t, uint8_t const *);
  155 static void
  156 mpt_scsi_tgt_tsk_mgmt(struct mpt_softc *, request_t *, mpt_task_mgmt_t,
  157     tgt_resource_t *, int);
  158 static void mpt_tgt_dump_tgt_state(struct mpt_softc *, request_t *);
  159 static void mpt_tgt_dump_req_state(struct mpt_softc *, request_t *);
  160 static mpt_reply_handler_t mpt_scsi_tgt_reply_handler;
  161 static mpt_reply_handler_t mpt_sata_pass_reply_handler;
  162 
  163 static uint32_t scsi_io_handler_id = MPT_HANDLER_ID_NONE;
  164 static uint32_t scsi_tmf_handler_id = MPT_HANDLER_ID_NONE;
  165 static uint32_t fc_els_handler_id = MPT_HANDLER_ID_NONE;
  166 static uint32_t sata_pass_handler_id = MPT_HANDLER_ID_NONE;
  167 
  168 static mpt_probe_handler_t      mpt_cam_probe;
  169 static mpt_attach_handler_t     mpt_cam_attach;
  170 static mpt_enable_handler_t     mpt_cam_enable;
  171 static mpt_ready_handler_t      mpt_cam_ready;
  172 static mpt_event_handler_t      mpt_cam_event;
  173 static mpt_reset_handler_t      mpt_cam_ioc_reset;
  174 static mpt_detach_handler_t     mpt_cam_detach;
  175 
  176 static struct mpt_personality mpt_cam_personality =
  177 {
  178         .name           = "mpt_cam",
  179         .probe          = mpt_cam_probe,
  180         .attach         = mpt_cam_attach,
  181         .enable         = mpt_cam_enable,
  182         .ready          = mpt_cam_ready,
  183         .event          = mpt_cam_event,
  184         .reset          = mpt_cam_ioc_reset,
  185         .detach         = mpt_cam_detach,
  186 };
  187 
  188 DECLARE_MPT_PERSONALITY(mpt_cam, SI_ORDER_SECOND);
  189 MODULE_DEPEND(mpt_cam, cam, 1, 1, 1);
  190 
  191 int mpt_enable_sata_wc = -1;
  192 TUNABLE_INT("hw.mpt.enable_sata_wc", &mpt_enable_sata_wc);
  193 
  194 static int
  195 mpt_cam_probe(struct mpt_softc *mpt)
  196 {
  197         int role;
  198 
  199         /*
  200          * Only attach to nodes that support the initiator or target role
  201          * (or want to) or have RAID physical devices that need CAM pass-thru
  202          * support.
  203          */
  204         if (mpt->do_cfg_role) {
  205                 role = mpt->cfg_role;
  206         } else {
  207                 role = mpt->role;
  208         }
  209         if ((role & (MPT_ROLE_TARGET|MPT_ROLE_INITIATOR)) != 0 ||
  210             (mpt->ioc_page2 != NULL && mpt->ioc_page2->MaxPhysDisks != 0)) {
  211                 return (0);
  212         }
  213         return (ENODEV);
  214 }
  215 
  216 static int
  217 mpt_cam_attach(struct mpt_softc *mpt)
  218 {
  219         struct cam_devq *devq;
  220         mpt_handler_t    handler;
  221         int              maxq;
  222         int              error;
  223 
  224         MPT_LOCK(mpt);
  225         TAILQ_INIT(&mpt->request_timeout_list);
  226         maxq = (mpt->ioc_facts.GlobalCredits < MPT_MAX_REQUESTS(mpt))?
  227             mpt->ioc_facts.GlobalCredits : MPT_MAX_REQUESTS(mpt);
  228 
  229         handler.reply_handler = mpt_scsi_reply_handler;
  230         error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler,
  231                                      &scsi_io_handler_id);
  232         if (error != 0) {
  233                 MPT_UNLOCK(mpt);
  234                 goto cleanup;
  235         }
  236 
  237         handler.reply_handler = mpt_scsi_tmf_reply_handler;
  238         error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler,
  239                                      &scsi_tmf_handler_id);
  240         if (error != 0) {
  241                 MPT_UNLOCK(mpt);
  242                 goto cleanup;
  243         }
  244 
  245         /*
  246          * If we're fibre channel and could support target mode, we register
  247          * an ELS reply handler and give it resources.
  248          */
  249         if (mpt->is_fc && (mpt->role & MPT_ROLE_TARGET) != 0) {
  250                 handler.reply_handler = mpt_fc_els_reply_handler;
  251                 error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler,
  252                     &fc_els_handler_id);
  253                 if (error != 0) {
  254                         MPT_UNLOCK(mpt);
  255                         goto cleanup;
  256                 }
  257                 if (mpt_add_els_buffers(mpt) == FALSE) {
  258                         error = ENOMEM;
  259                         MPT_UNLOCK(mpt);
  260                         goto cleanup;
  261                 }
  262                 maxq -= mpt->els_cmds_allocated;
  263         }
  264 
  265         /*
  266          * If we support target mode, we register a reply handler for it,
  267          * but don't add command resources until we actually enable target
  268          * mode.
  269          */
  270         if (mpt->is_fc && (mpt->role & MPT_ROLE_TARGET) != 0) {
  271                 handler.reply_handler = mpt_scsi_tgt_reply_handler;
  272                 error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler,
  273                     &mpt->scsi_tgt_handler_id);
  274                 if (error != 0) {
  275                         MPT_UNLOCK(mpt);
  276                         goto cleanup;
  277                 }
  278         }
  279 
  280         if (mpt->is_sas) {
  281                 handler.reply_handler = mpt_sata_pass_reply_handler;
  282                 error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler,
  283                     &sata_pass_handler_id);
  284                 if (error != 0) {
  285                         MPT_UNLOCK(mpt);
  286                         goto cleanup;
  287                 }
  288         }
  289 
  290         /*
  291          * We keep one request reserved for timeout TMF requests.
  292          */
  293         mpt->tmf_req = mpt_get_request(mpt, FALSE);
  294         if (mpt->tmf_req == NULL) {
  295                 mpt_prt(mpt, "Unable to allocate dedicated TMF request!\n");
  296                 error = ENOMEM;
  297                 MPT_UNLOCK(mpt);
  298                 goto cleanup;
  299         }
  300 
  301         /*
  302          * Mark the request as free even though not on the free list.
  303          * There is only one TMF request allowed to be outstanding at
  304          * a time and the TMF routines perform their own allocation
  305          * tracking using the standard state flags.
  306          */
  307         mpt->tmf_req->state = REQ_STATE_FREE;
  308         maxq--;
  309 
  310         /*
  311          * The rest of this is CAM foo, for which we need to drop our lock
  312          */
  313         MPT_UNLOCK(mpt);
  314 
  315         if (mpt_spawn_recovery_thread(mpt) != 0) {
  316                 mpt_prt(mpt, "Unable to spawn recovery thread!\n");
  317                 error = ENOMEM;
  318                 goto cleanup;
  319         }
  320 
  321         /*
  322          * Create the device queue for our SIM(s).
  323          */
  324         devq = cam_simq_alloc(maxq);
  325         if (devq == NULL) {
  326                 mpt_prt(mpt, "Unable to allocate CAM SIMQ!\n");
  327                 error = ENOMEM;
  328                 goto cleanup;
  329         }
  330 
  331         /*
  332          * Construct our SIM entry.
  333          */
  334         mpt->sim =
  335             mpt_sim_alloc(mpt_action, mpt_poll, "mpt", mpt, 1, maxq, devq);
  336         if (mpt->sim == NULL) {
  337                 mpt_prt(mpt, "Unable to allocate CAM SIM!\n");
  338                 cam_simq_free(devq);
  339                 error = ENOMEM;
  340                 goto cleanup;
  341         }
  342 
  343         /*
  344          * Register exactly this bus.
  345          */
  346         MPT_LOCK(mpt);
  347         if (mpt_xpt_bus_register(mpt->sim, mpt->dev, 0) != CAM_SUCCESS) {
  348                 mpt_prt(mpt, "Bus registration Failed!\n");
  349                 error = ENOMEM;
  350                 MPT_UNLOCK(mpt);
  351                 goto cleanup;
  352         }
  353 
  354         if (xpt_create_path(&mpt->path, NULL, cam_sim_path(mpt->sim),
  355             CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
  356                 mpt_prt(mpt, "Unable to allocate Path!\n");
  357                 error = ENOMEM;
  358                 MPT_UNLOCK(mpt);
  359                 goto cleanup;
  360         }
  361         MPT_UNLOCK(mpt);
  362 
  363         /*
  364          * Only register a second bus for RAID physical
  365          * devices if the controller supports RAID.
  366          */
  367         if (mpt->ioc_page2 == NULL || mpt->ioc_page2->MaxPhysDisks == 0) {
  368                 return (0);
  369         }
  370 
  371         /*
  372          * Create a "bus" to export all hidden disks to CAM.
  373          */
  374         mpt->phydisk_sim =
  375             mpt_sim_alloc(mpt_action, mpt_poll, "mpt", mpt, 1, maxq, devq);
  376         if (mpt->phydisk_sim == NULL) {
  377                 mpt_prt(mpt, "Unable to allocate Physical Disk CAM SIM!\n");
  378                 error = ENOMEM;
  379                 goto cleanup;
  380         }
  381 
  382         /*
  383          * Register this bus.
  384          */
  385         MPT_LOCK(mpt);
  386         if (mpt_xpt_bus_register(mpt->phydisk_sim, mpt->dev, 1) !=
  387             CAM_SUCCESS) {
  388                 mpt_prt(mpt, "Physical Disk Bus registration Failed!\n");
  389                 error = ENOMEM;
  390                 MPT_UNLOCK(mpt);
  391                 goto cleanup;
  392         }
  393 
  394         if (xpt_create_path(&mpt->phydisk_path, NULL,
  395             cam_sim_path(mpt->phydisk_sim),
  396             CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
  397                 mpt_prt(mpt, "Unable to allocate Physical Disk Path!\n");
  398                 error = ENOMEM;
  399                 MPT_UNLOCK(mpt);
  400                 goto cleanup;
  401         }
  402         MPT_UNLOCK(mpt);
  403         mpt_lprt(mpt, MPT_PRT_DEBUG, "attached cam\n");
  404         return (0);
  405 
  406 cleanup:
  407         mpt_cam_detach(mpt);
  408         return (error);
  409 }
  410 
  411 /*
  412  * Read FC configuration information
  413  */
  414 static int
  415 mpt_read_config_info_fc(struct mpt_softc *mpt)
  416 {
  417         struct sysctl_ctx_list *ctx;
  418         struct sysctl_oid *tree;
  419         char *topology = NULL;
  420         int rv;
  421 
  422         rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_FC_PORT, 0,
  423             0, &mpt->mpt_fcport_page0.Header, FALSE, 5000);
  424         if (rv) {
  425                 return (-1);
  426         }
  427         mpt_lprt(mpt, MPT_PRT_DEBUG, "FC Port Page 0 Header: %x %x %x %x\n",
  428                  mpt->mpt_fcport_page0.Header.PageVersion,
  429                  mpt->mpt_fcport_page0.Header.PageLength,
  430                  mpt->mpt_fcport_page0.Header.PageNumber,
  431                  mpt->mpt_fcport_page0.Header.PageType);
  432 
  433 
  434         rv = mpt_read_cur_cfg_page(mpt, 0, &mpt->mpt_fcport_page0.Header,
  435             sizeof(mpt->mpt_fcport_page0), FALSE, 5000);
  436         if (rv) {
  437                 mpt_prt(mpt, "failed to read FC Port Page 0\n");
  438                 return (-1);
  439         }
  440         mpt2host_config_page_fc_port_0(&mpt->mpt_fcport_page0);
  441 
  442         mpt->mpt_fcport_speed = mpt->mpt_fcport_page0.CurrentSpeed;
  443 
  444         switch (mpt->mpt_fcport_page0.Flags &
  445             MPI_FCPORTPAGE0_FLAGS_ATTACH_TYPE_MASK) {
  446         case MPI_FCPORTPAGE0_FLAGS_ATTACH_NO_INIT:
  447                 mpt->mpt_fcport_speed = 0;
  448                 topology = "<NO LOOP>";
  449                 break;
  450         case MPI_FCPORTPAGE0_FLAGS_ATTACH_POINT_TO_POINT:
  451                 topology = "N-Port";
  452                 break;
  453         case MPI_FCPORTPAGE0_FLAGS_ATTACH_PRIVATE_LOOP:
  454                 topology = "NL-Port";
  455                 break;
  456         case MPI_FCPORTPAGE0_FLAGS_ATTACH_FABRIC_DIRECT:
  457                 topology = "F-Port";
  458                 break;
  459         case MPI_FCPORTPAGE0_FLAGS_ATTACH_PUBLIC_LOOP:
  460                 topology = "FL-Port";
  461                 break;
  462         default:
  463                 mpt->mpt_fcport_speed = 0;
  464                 topology = "?";
  465                 break;
  466         }
  467 
  468         mpt_lprt(mpt, MPT_PRT_INFO,
  469             "FC Port Page 0: Topology <%s> WWNN 0x%08x%08x WWPN 0x%08x%08x "
  470             "Speed %u-Gbit\n", topology,
  471             mpt->mpt_fcport_page0.WWNN.High,
  472             mpt->mpt_fcport_page0.WWNN.Low,
  473             mpt->mpt_fcport_page0.WWPN.High,
  474             mpt->mpt_fcport_page0.WWPN.Low,
  475             mpt->mpt_fcport_speed);
  476         MPT_UNLOCK(mpt);
  477         ctx = device_get_sysctl_ctx(mpt->dev);
  478         tree = device_get_sysctl_tree(mpt->dev);
  479 
  480         snprintf(mpt->scinfo.fc.wwnn, sizeof (mpt->scinfo.fc.wwnn),
  481             "0x%08x%08x", mpt->mpt_fcport_page0.WWNN.High,
  482             mpt->mpt_fcport_page0.WWNN.Low);
  483 
  484         snprintf(mpt->scinfo.fc.wwpn, sizeof (mpt->scinfo.fc.wwpn),
  485             "0x%08x%08x", mpt->mpt_fcport_page0.WWPN.High,
  486             mpt->mpt_fcport_page0.WWPN.Low);
  487 
  488         SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
  489             "wwnn", CTLFLAG_RD, mpt->scinfo.fc.wwnn, 0,
  490             "World Wide Node Name");
  491 
  492         SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
  493              "wwpn", CTLFLAG_RD, mpt->scinfo.fc.wwpn, 0,
  494              "World Wide Port Name");
  495 
  496         MPT_LOCK(mpt);
  497         return (0);
  498 }
  499 
  500 /*
  501  * Set FC configuration information.
  502  */
  503 static int
  504 mpt_set_initial_config_fc(struct mpt_softc *mpt)
  505 {
  506         CONFIG_PAGE_FC_PORT_1 fc;
  507         U32 fl;
  508         int r, doit = 0;
  509         int role;
  510 
  511         r = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0,
  512             &fc.Header, FALSE, 5000);
  513         if (r) {
  514                 mpt_prt(mpt, "failed to read FC page 1 header\n");
  515                 return (mpt_fc_reset_link(mpt, 1));
  516         }
  517 
  518         r = mpt_read_cfg_page(mpt, MPI_CONFIG_ACTION_PAGE_READ_NVRAM, 0,
  519             &fc.Header, sizeof (fc), FALSE, 5000);
  520         if (r) {
  521                 mpt_prt(mpt, "failed to read FC page 1\n");
  522                 return (mpt_fc_reset_link(mpt, 1));
  523         }
  524         mpt2host_config_page_fc_port_1(&fc);
  525 
  526         /*
  527          * Check our flags to make sure we support the role we want.
  528          */
  529         doit = 0;
  530         role = 0;
  531         fl = fc.Flags;
  532 
  533         if (fl & MPI_FCPORTPAGE1_FLAGS_PROT_FCP_INIT) {
  534                 role |= MPT_ROLE_INITIATOR;
  535         }
  536         if (fl & MPI_FCPORTPAGE1_FLAGS_PROT_FCP_TARG) {
  537                 role |= MPT_ROLE_TARGET;
  538         }
  539 
  540         fl &= ~MPI_FCPORTPAGE1_FLAGS_PROT_MASK;
  541 
  542         if (mpt->do_cfg_role == 0) {
  543                 role = mpt->cfg_role;
  544         } else {
  545                 mpt->do_cfg_role = 0;
  546         }
  547 
  548         if (role != mpt->cfg_role) {
  549                 if (mpt->cfg_role & MPT_ROLE_INITIATOR) {
  550                         if ((role & MPT_ROLE_INITIATOR) == 0) {
  551                                 mpt_prt(mpt, "adding initiator role\n");
  552                                 fl |= MPI_FCPORTPAGE1_FLAGS_PROT_FCP_INIT;
  553                                 doit++;
  554                         } else {
  555                                 mpt_prt(mpt, "keeping initiator role\n");
  556                         }
  557                 } else if (role & MPT_ROLE_INITIATOR) {
  558                         mpt_prt(mpt, "removing initiator role\n");
  559                         doit++;
  560                 }
  561                 if (mpt->cfg_role & MPT_ROLE_TARGET) {
  562                         if ((role & MPT_ROLE_TARGET) == 0) {
  563                                 mpt_prt(mpt, "adding target role\n");
  564                                 fl |= MPI_FCPORTPAGE1_FLAGS_PROT_FCP_TARG;
  565                                 doit++;
  566                         } else {
  567                                 mpt_prt(mpt, "keeping target role\n");
  568                         }
  569                 } else if (role & MPT_ROLE_TARGET) {
  570                         mpt_prt(mpt, "removing target role\n");
  571                         doit++;
  572                 }
  573                 mpt->role = mpt->cfg_role;
  574         }
  575 
  576         if (fl & MPI_FCPORTPAGE1_FLAGS_PROT_FCP_TARG) {
  577                 if ((fl & MPI_FCPORTPAGE1_FLAGS_TARGET_MODE_OXID) == 0) {
  578                         mpt_prt(mpt, "adding OXID option\n");
  579                         fl |= MPI_FCPORTPAGE1_FLAGS_TARGET_MODE_OXID;
  580                         doit++;
  581                 }
  582         }
  583 
  584         if (doit) {
  585                 fc.Flags = fl;
  586                 host2mpt_config_page_fc_port_1(&fc);
  587                 r = mpt_write_cfg_page(mpt,
  588                     MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM, 0, &fc.Header,
  589                     sizeof(fc), FALSE, 5000);
  590                 if (r != 0) {
  591                         mpt_prt(mpt, "failed to update NVRAM with changes\n");
  592                         return (0);
  593                 }
  594                 mpt_prt(mpt, "NOTE: NVRAM changes will not take "
  595                     "effect until next reboot or IOC reset\n");
  596         }
  597         return (0);
  598 }
  599 
  600 static int
  601 mptsas_sas_io_unit_pg0(struct mpt_softc *mpt, struct mptsas_portinfo *portinfo)
  602 {
  603         ConfigExtendedPageHeader_t hdr;
  604         struct mptsas_phyinfo *phyinfo;
  605         SasIOUnitPage0_t *buffer;
  606         int error, len, i;
  607 
  608         error = mpt_read_extcfg_header(mpt, MPI_SASIOUNITPAGE0_PAGEVERSION,
  609                                        0, 0, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT,
  610                                        &hdr, 0, 10000);
  611         if (error)
  612                 goto out;
  613         if (hdr.ExtPageLength == 0) {
  614                 error = ENXIO;
  615                 goto out;
  616         }
  617 
  618         len = hdr.ExtPageLength * 4;
  619         buffer = malloc(len, M_DEVBUF, M_NOWAIT|M_ZERO);
  620         if (buffer == NULL) {
  621                 error = ENOMEM;
  622                 goto out;
  623         }
  624 
  625         error = mpt_read_extcfg_page(mpt, MPI_CONFIG_ACTION_PAGE_READ_CURRENT,
  626                                      0, &hdr, buffer, len, 0, 10000);
  627         if (error) {
  628                 free(buffer, M_DEVBUF);
  629                 goto out;
  630         }
  631 
  632         portinfo->num_phys = buffer->NumPhys;
  633         portinfo->phy_info = malloc(sizeof(*portinfo->phy_info) *
  634             portinfo->num_phys, M_DEVBUF, M_NOWAIT|M_ZERO);
  635         if (portinfo->phy_info == NULL) {
  636                 free(buffer, M_DEVBUF);
  637                 error = ENOMEM;
  638                 goto out;
  639         }
  640 
  641         for (i = 0; i < portinfo->num_phys; i++) {
  642                 phyinfo = &portinfo->phy_info[i];
  643                 phyinfo->phy_num = i;
  644                 phyinfo->port_id = buffer->PhyData[i].Port;
  645                 phyinfo->negotiated_link_rate =
  646                     buffer->PhyData[i].NegotiatedLinkRate;
  647                 phyinfo->handle =
  648                     le16toh(buffer->PhyData[i].ControllerDevHandle);
  649         }
  650 
  651         free(buffer, M_DEVBUF);
  652 out:
  653         return (error);
  654 }
  655 
  656 static int
  657 mptsas_sas_phy_pg0(struct mpt_softc *mpt, struct mptsas_phyinfo *phy_info,
  658         uint32_t form, uint32_t form_specific)
  659 {
  660         ConfigExtendedPageHeader_t hdr;
  661         SasPhyPage0_t *buffer;
  662         int error;
  663 
  664         error = mpt_read_extcfg_header(mpt, MPI_SASPHY0_PAGEVERSION, 0, 0,
  665                                        MPI_CONFIG_EXTPAGETYPE_SAS_PHY, &hdr,
  666                                        0, 10000);
  667         if (error)
  668                 goto out;
  669         if (hdr.ExtPageLength == 0) {
  670                 error = ENXIO;
  671                 goto out;
  672         }
  673 
  674         buffer = malloc(sizeof(SasPhyPage0_t), M_DEVBUF, M_NOWAIT|M_ZERO);
  675         if (buffer == NULL) {
  676                 error = ENOMEM;
  677                 goto out;
  678         }
  679 
  680         error = mpt_read_extcfg_page(mpt, MPI_CONFIG_ACTION_PAGE_READ_CURRENT,
  681                                      form + form_specific, &hdr, buffer,
  682                                      sizeof(SasPhyPage0_t), 0, 10000);
  683         if (error) {
  684                 free(buffer, M_DEVBUF);
  685                 goto out;
  686         }
  687 
  688         phy_info->hw_link_rate = buffer->HwLinkRate;
  689         phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
  690         phy_info->identify.dev_handle = le16toh(buffer->OwnerDevHandle);
  691         phy_info->attached.dev_handle = le16toh(buffer->AttachedDevHandle);
  692 
  693         free(buffer, M_DEVBUF);
  694 out:
  695         return (error);
  696 }
  697 
  698 static int
  699 mptsas_sas_device_pg0(struct mpt_softc *mpt, struct mptsas_devinfo *device_info,
  700         uint32_t form, uint32_t form_specific)
  701 {
  702         ConfigExtendedPageHeader_t hdr;
  703         SasDevicePage0_t *buffer;
  704         uint64_t sas_address;
  705         int error = 0;
  706 
  707         bzero(device_info, sizeof(*device_info));
  708         error = mpt_read_extcfg_header(mpt, MPI_SASDEVICE0_PAGEVERSION, 0, 0,
  709                                        MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE,
  710                                        &hdr, 0, 10000);
  711         if (error)
  712                 goto out;
  713         if (hdr.ExtPageLength == 0) {
  714                 error = ENXIO;
  715                 goto out;
  716         }
  717 
  718         buffer = malloc(sizeof(SasDevicePage0_t), M_DEVBUF, M_NOWAIT|M_ZERO);
  719         if (buffer == NULL) {
  720                 error = ENOMEM;
  721                 goto out;
  722         }
  723 
  724         error = mpt_read_extcfg_page(mpt, MPI_CONFIG_ACTION_PAGE_READ_CURRENT,
  725                                      form + form_specific, &hdr, buffer,
  726                                      sizeof(SasDevicePage0_t), 0, 10000);
  727         if (error) {
  728                 free(buffer, M_DEVBUF);
  729                 goto out;
  730         }
  731 
  732         device_info->dev_handle = le16toh(buffer->DevHandle);
  733         device_info->parent_dev_handle = le16toh(buffer->ParentDevHandle);
  734         device_info->enclosure_handle = le16toh(buffer->EnclosureHandle);
  735         device_info->slot = le16toh(buffer->Slot);
  736         device_info->phy_num = buffer->PhyNum;
  737         device_info->physical_port = buffer->PhysicalPort;
  738         device_info->target_id = buffer->TargetID;
  739         device_info->bus = buffer->Bus;
  740         bcopy(&buffer->SASAddress, &sas_address, sizeof(uint64_t));
  741         device_info->sas_address = le64toh(sas_address);
  742         device_info->device_info = le32toh(buffer->DeviceInfo);
  743 
  744         free(buffer, M_DEVBUF);
  745 out:
  746         return (error);
  747 }
  748 
  749 /*
  750  * Read SAS configuration information. Nothing to do yet.
  751  */
  752 static int
  753 mpt_read_config_info_sas(struct mpt_softc *mpt)
  754 {
  755         struct mptsas_portinfo *portinfo;
  756         struct mptsas_phyinfo *phyinfo;
  757         int error, i;
  758 
  759         portinfo = malloc(sizeof(*portinfo), M_DEVBUF, M_NOWAIT|M_ZERO);
  760         if (portinfo == NULL)
  761                 return (ENOMEM);
  762 
  763         error = mptsas_sas_io_unit_pg0(mpt, portinfo);
  764         if (error) {
  765                 free(portinfo, M_DEVBUF);
  766                 return (0);
  767         }
  768 
  769         for (i = 0; i < portinfo->num_phys; i++) {
  770                 phyinfo = &portinfo->phy_info[i];
  771                 error = mptsas_sas_phy_pg0(mpt, phyinfo,
  772                     (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
  773                     MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
  774                 if (error)
  775                         break;
  776                 error = mptsas_sas_device_pg0(mpt, &phyinfo->identify,
  777                     (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
  778                     MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
  779                     phyinfo->handle);
  780                 if (error)
  781                         break;
  782                 phyinfo->identify.phy_num = phyinfo->phy_num = i;
  783                 if (phyinfo->attached.dev_handle)
  784                         error = mptsas_sas_device_pg0(mpt,
  785                             &phyinfo->attached,
  786                             (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
  787                             MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
  788                             phyinfo->attached.dev_handle);
  789                 if (error)
  790                         break;
  791         }
  792         mpt->sas_portinfo = portinfo;
  793         return (0);
  794 }
  795 
  796 static void
  797 mptsas_set_sata_wc(struct mpt_softc *mpt, struct mptsas_devinfo *devinfo,
  798         int enabled)
  799 {
  800         SataPassthroughRequest_t        *pass;
  801         request_t *req;
  802         int error, status;
  803 
  804         req = mpt_get_request(mpt, 0);
  805         if (req == NULL)
  806                 return;
  807 
  808         pass = req->req_vbuf;
  809         bzero(pass, sizeof(SataPassthroughRequest_t));
  810         pass->Function = MPI_FUNCTION_SATA_PASSTHROUGH;
  811         pass->TargetID = devinfo->target_id;
  812         pass->Bus = devinfo->bus;
  813         pass->PassthroughFlags = 0;
  814         pass->ConnectionRate = MPI_SATA_PT_REQ_CONNECT_RATE_NEGOTIATED;
  815         pass->DataLength = 0;
  816         pass->MsgContext = htole32(req->index | sata_pass_handler_id);
  817         pass->CommandFIS[0] = 0x27;
  818         pass->CommandFIS[1] = 0x80;
  819         pass->CommandFIS[2] = 0xef;
  820         pass->CommandFIS[3] = (enabled) ? 0x02 : 0x82;
  821         pass->CommandFIS[7] = 0x40;
  822         pass->CommandFIS[15] = 0x08;
  823 
  824         mpt_check_doorbell(mpt);
  825         mpt_send_cmd(mpt, req);
  826         error = mpt_wait_req(mpt, req, REQ_STATE_DONE, REQ_STATE_DONE, 0,
  827                              10 * 1000);
  828         if (error) {
  829                 mpt_free_request(mpt, req);
  830                 printf("error %d sending passthrough\n", error);
  831                 return;
  832         }
  833 
  834         status = le16toh(req->IOCStatus);
  835         if (status != MPI_IOCSTATUS_SUCCESS) {
  836                 mpt_free_request(mpt, req);
  837                 printf("IOCSTATUS %d\n", status);
  838                 return;
  839         }
  840 
  841         mpt_free_request(mpt, req);
  842 }
  843 
  844 /*
  845  * Set SAS configuration information. Nothing to do yet.
  846  */
  847 static int
  848 mpt_set_initial_config_sas(struct mpt_softc *mpt)
  849 {
  850         struct mptsas_phyinfo *phyinfo;
  851         int i;
  852 
  853         if ((mpt_enable_sata_wc != -1) && (mpt->sas_portinfo != NULL)) {
  854                 for (i = 0; i < mpt->sas_portinfo->num_phys; i++) {
  855                         phyinfo = &mpt->sas_portinfo->phy_info[i];
  856                         if (phyinfo->attached.dev_handle == 0)
  857                                 continue;
  858                         if ((phyinfo->attached.device_info &
  859                             MPI_SAS_DEVICE_INFO_SATA_DEVICE) == 0)
  860                                 continue;
  861                         if (bootverbose)
  862                                 device_printf(mpt->dev,
  863                                     "%sabling SATA WC on phy %d\n",
  864                                     (mpt_enable_sata_wc) ? "En" : "Dis", i);
  865                         mptsas_set_sata_wc(mpt, &phyinfo->attached,
  866                                            mpt_enable_sata_wc);
  867                 }
  868         }
  869 
  870         return (0);
  871 }
  872 
  873 static int
  874 mpt_sata_pass_reply_handler(struct mpt_softc *mpt, request_t *req,
  875  uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame)
  876 {
  877 
  878         if (req != NULL) {
  879                 if (reply_frame != NULL) {
  880                         req->IOCStatus = le16toh(reply_frame->IOCStatus);
  881                 }
  882                 req->state &= ~REQ_STATE_QUEUED;
  883                 req->state |= REQ_STATE_DONE;
  884                 TAILQ_REMOVE(&mpt->request_pending_list, req, links);
  885                 if ((req->state & REQ_STATE_NEED_WAKEUP) != 0) {
  886                         wakeup(req);
  887                 } else if ((req->state & REQ_STATE_TIMEDOUT) != 0) {
  888                         /*
  889                          * Whew- we can free this request (late completion)
  890                          */
  891                         mpt_free_request(mpt, req);
  892                 }
  893         }
  894 
  895         return (TRUE);
  896 }
  897 
  898 /*
  899  * Read SCSI configuration information
  900  */
  901 static int
  902 mpt_read_config_info_spi(struct mpt_softc *mpt)
  903 {
  904         int rv, i;
  905 
  906         rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 0, 0,
  907             &mpt->mpt_port_page0.Header, FALSE, 5000);
  908         if (rv) {
  909                 return (-1);
  910         }
  911         mpt_lprt(mpt, MPT_PRT_DEBUG, "SPI Port Page 0 Header: %x %x %x %x\n",
  912             mpt->mpt_port_page0.Header.PageVersion,
  913             mpt->mpt_port_page0.Header.PageLength,
  914             mpt->mpt_port_page0.Header.PageNumber,
  915             mpt->mpt_port_page0.Header.PageType);
  916 
  917         rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 1, 0,
  918             &mpt->mpt_port_page1.Header, FALSE, 5000);
  919         if (rv) {
  920                 return (-1);
  921         }
  922         mpt_lprt(mpt, MPT_PRT_DEBUG, "SPI Port Page 1 Header: %x %x %x %x\n",
  923             mpt->mpt_port_page1.Header.PageVersion,
  924             mpt->mpt_port_page1.Header.PageLength,
  925             mpt->mpt_port_page1.Header.PageNumber,
  926             mpt->mpt_port_page1.Header.PageType);
  927 
  928         rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2, 0,
  929             &mpt->mpt_port_page2.Header, FALSE, 5000);
  930         if (rv) {
  931                 return (-1);
  932         }
  933         mpt_lprt(mpt, MPT_PRT_DEBUG, "SPI Port Page 2 Header: %x %x %x %x\n",
  934             mpt->mpt_port_page2.Header.PageVersion,
  935             mpt->mpt_port_page2.Header.PageLength,
  936             mpt->mpt_port_page2.Header.PageNumber,
  937             mpt->mpt_port_page2.Header.PageType);
  938 
  939         for (i = 0; i < 16; i++) {
  940                 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
  941                     0, i, &mpt->mpt_dev_page0[i].Header, FALSE, 5000);
  942                 if (rv) {
  943                         return (-1);
  944                 }
  945                 mpt_lprt(mpt, MPT_PRT_DEBUG,
  946                     "SPI Target %d Device Page 0 Header: %x %x %x %x\n", i,
  947                     mpt->mpt_dev_page0[i].Header.PageVersion,
  948                     mpt->mpt_dev_page0[i].Header.PageLength,
  949                     mpt->mpt_dev_page0[i].Header.PageNumber,
  950                     mpt->mpt_dev_page0[i].Header.PageType);
  951                 
  952                 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
  953                     1, i, &mpt->mpt_dev_page1[i].Header, FALSE, 5000);
  954                 if (rv) {
  955                         return (-1);
  956                 }
  957                 mpt_lprt(mpt, MPT_PRT_DEBUG,
  958                     "SPI Target %d Device Page 1 Header: %x %x %x %x\n", i,
  959                     mpt->mpt_dev_page1[i].Header.PageVersion,
  960                     mpt->mpt_dev_page1[i].Header.PageLength,
  961                     mpt->mpt_dev_page1[i].Header.PageNumber,
  962                     mpt->mpt_dev_page1[i].Header.PageType);
  963         }
  964 
  965         /*
  966          * At this point, we don't *have* to fail. As long as we have
  967          * valid config header information, we can (barely) lurch
  968          * along.
  969          */
  970 
  971         rv = mpt_read_cur_cfg_page(mpt, 0, &mpt->mpt_port_page0.Header,
  972             sizeof(mpt->mpt_port_page0), FALSE, 5000);
  973         if (rv) {
  974                 mpt_prt(mpt, "failed to read SPI Port Page 0\n");
  975         } else {
  976                 mpt2host_config_page_scsi_port_0(&mpt->mpt_port_page0);
  977                 mpt_lprt(mpt, MPT_PRT_NEGOTIATION,
  978                     "SPI Port Page 0: Capabilities %x PhysicalInterface %x\n",
  979                     mpt->mpt_port_page0.Capabilities,
  980                     mpt->mpt_port_page0.PhysicalInterface);
  981         }
  982 
  983         rv = mpt_read_cur_cfg_page(mpt, 0, &mpt->mpt_port_page1.Header,
  984             sizeof(mpt->mpt_port_page1), FALSE, 5000);
  985         if (rv) {
  986                 mpt_prt(mpt, "failed to read SPI Port Page 1\n");
  987         } else {
  988                 mpt2host_config_page_scsi_port_1(&mpt->mpt_port_page1);
  989                 mpt_lprt(mpt, MPT_PRT_DEBUG,
  990                     "SPI Port Page 1: Configuration %x OnBusTimerValue %x\n",
  991                     mpt->mpt_port_page1.Configuration,
  992                     mpt->mpt_port_page1.OnBusTimerValue);
  993         }
  994 
  995         rv = mpt_read_cur_cfg_page(mpt, 0, &mpt->mpt_port_page2.Header,
  996             sizeof(mpt->mpt_port_page2), FALSE, 5000);
  997         if (rv) {
  998                 mpt_prt(mpt, "failed to read SPI Port Page 2\n");
  999         } else {
 1000                 mpt_lprt(mpt, MPT_PRT_NEGOTIATION,
 1001                     "Port Page 2: Flags %x Settings %x\n",
 1002                     mpt->mpt_port_page2.PortFlags,
 1003                     mpt->mpt_port_page2.PortSettings);
 1004                 mpt2host_config_page_scsi_port_2(&mpt->mpt_port_page2);
 1005                 for (i = 0; i < 16; i++) {
 1006                         mpt_lprt(mpt, MPT_PRT_NEGOTIATION,
 1007                             " Port Page 2 Tgt %d: timo %x SF %x Flags %x\n",
 1008                             i, mpt->mpt_port_page2.DeviceSettings[i].Timeout,
 1009                             mpt->mpt_port_page2.DeviceSettings[i].SyncFactor,
 1010                             mpt->mpt_port_page2.DeviceSettings[i].DeviceFlags);
 1011                 }
 1012         }
 1013 
 1014         for (i = 0; i < 16; i++) {
 1015                 rv = mpt_read_cur_cfg_page(mpt, i,
 1016                     &mpt->mpt_dev_page0[i].Header, sizeof(*mpt->mpt_dev_page0),
 1017                     FALSE, 5000);
 1018                 if (rv) {
 1019                         mpt_prt(mpt,
 1020                             "cannot read SPI Target %d Device Page 0\n", i);
 1021                         continue;
 1022                 }
 1023                 mpt2host_config_page_scsi_device_0(&mpt->mpt_dev_page0[i]);
 1024                 mpt_lprt(mpt, MPT_PRT_NEGOTIATION,
 1025                     "target %d page 0: Negotiated Params %x Information %x\n",
 1026                     i, mpt->mpt_dev_page0[i].NegotiatedParameters,
 1027                     mpt->mpt_dev_page0[i].Information);
 1028 
 1029                 rv = mpt_read_cur_cfg_page(mpt, i,
 1030                     &mpt->mpt_dev_page1[i].Header, sizeof(*mpt->mpt_dev_page1),
 1031                     FALSE, 5000);
 1032                 if (rv) {
 1033                         mpt_prt(mpt,
 1034                             "cannot read SPI Target %d Device Page 1\n", i);
 1035                         continue;
 1036                 }
 1037                 mpt2host_config_page_scsi_device_1(&mpt->mpt_dev_page1[i]);
 1038                 mpt_lprt(mpt, MPT_PRT_NEGOTIATION,
 1039                     "target %d page 1: Requested Params %x Configuration %x\n",
 1040                     i, mpt->mpt_dev_page1[i].RequestedParameters,
 1041                     mpt->mpt_dev_page1[i].Configuration);
 1042         }
 1043         return (0);
 1044 }
 1045 
 1046 /*
 1047  * Validate SPI configuration information.
 1048  *
 1049  * In particular, validate SPI Port Page 1.
 1050  */
 1051 static int
 1052 mpt_set_initial_config_spi(struct mpt_softc *mpt)
 1053 {
 1054         int error, i, pp1val;
 1055 
 1056         mpt->mpt_disc_enable = 0xff;
 1057         mpt->mpt_tag_enable = 0;
 1058 
 1059         pp1val = ((1 << mpt->mpt_ini_id) <<
 1060             MPI_SCSIPORTPAGE1_CFG_SHIFT_PORT_RESPONSE_ID) | mpt->mpt_ini_id;
 1061         if (mpt->mpt_port_page1.Configuration != pp1val) {
 1062                 CONFIG_PAGE_SCSI_PORT_1 tmp;
 1063 
 1064                 mpt_prt(mpt, "SPI Port Page 1 Config value bad (%x)- should "
 1065                     "be %x\n", mpt->mpt_port_page1.Configuration, pp1val);
 1066                 tmp = mpt->mpt_port_page1;
 1067                 tmp.Configuration = pp1val;
 1068                 host2mpt_config_page_scsi_port_1(&tmp);
 1069                 error = mpt_write_cur_cfg_page(mpt, 0,
 1070                     &tmp.Header, sizeof(tmp), FALSE, 5000);
 1071                 if (error) {
 1072                         return (-1);
 1073                 }
 1074                 error = mpt_read_cur_cfg_page(mpt, 0,
 1075                     &tmp.Header, sizeof(tmp), FALSE, 5000);
 1076                 if (error) {
 1077                         return (-1);
 1078                 }
 1079                 mpt2host_config_page_scsi_port_1(&tmp);
 1080                 if (tmp.Configuration != pp1val) {
 1081                         mpt_prt(mpt,
 1082                             "failed to reset SPI Port Page 1 Config value\n");
 1083                         return (-1);
 1084                 }
 1085                 mpt->mpt_port_page1 = tmp;
 1086         }
 1087 
 1088         /*
 1089          * The purpose of this exercise is to get
 1090          * all targets back to async/narrow.
 1091          *
 1092          * We skip this step if the BIOS has already negotiated
 1093          * speeds with the targets.
 1094          */
 1095         i = mpt->mpt_port_page2.PortSettings &
 1096             MPI_SCSIPORTPAGE2_PORT_MASK_NEGO_MASTER_SETTINGS;
 1097         if (i == MPI_SCSIPORTPAGE2_PORT_ALL_MASTER_SETTINGS) {
 1098                 mpt_lprt(mpt, MPT_PRT_NEGOTIATION,
 1099                     "honoring BIOS transfer negotiations\n");
 1100         } else {
 1101                 for (i = 0; i < 16; i++) {
 1102                         mpt->mpt_dev_page1[i].RequestedParameters = 0;
 1103                         mpt->mpt_dev_page1[i].Configuration = 0;
 1104                         (void) mpt_update_spi_config(mpt, i);
 1105                 }
 1106         }
 1107         return (0);
 1108 }
 1109 
 1110 static int
 1111 mpt_cam_enable(struct mpt_softc *mpt)
 1112 {
 1113         int error;
 1114 
 1115         MPT_LOCK(mpt);
 1116 
 1117         error = EIO;
 1118         if (mpt->is_fc) {
 1119                 if (mpt_read_config_info_fc(mpt)) {
 1120                         goto out;
 1121                 }
 1122                 if (mpt_set_initial_config_fc(mpt)) {
 1123                         goto out;
 1124                 }
 1125         } else if (mpt->is_sas) {
 1126                 if (mpt_read_config_info_sas(mpt)) {
 1127                         goto out;
 1128                 }
 1129                 if (mpt_set_initial_config_sas(mpt)) {
 1130                         goto out;
 1131                 }
 1132         } else if (mpt->is_spi) {
 1133                 if (mpt_read_config_info_spi(mpt)) {
 1134                         goto out;
 1135                 }
 1136                 if (mpt_set_initial_config_spi(mpt)) {
 1137                         goto out;
 1138                 }
 1139         }
 1140         error = 0;
 1141 
 1142 out:
 1143         MPT_UNLOCK(mpt);
 1144         return (error);
 1145 }
 1146 
 1147 static void
 1148 mpt_cam_ready(struct mpt_softc *mpt)
 1149 {
 1150 
 1151         /*
 1152          * If we're in target mode, hang out resources now
 1153          * so we don't cause the world to hang talking to us.
 1154          */
 1155         if (mpt->is_fc && (mpt->role & MPT_ROLE_TARGET)) {
 1156                 /*
 1157                  * Try to add some target command resources
 1158                  */
 1159                 MPT_LOCK(mpt);
 1160                 if (mpt_add_target_commands(mpt) == FALSE) {
 1161                         mpt_prt(mpt, "failed to add target commands\n");
 1162                 }
 1163                 MPT_UNLOCK(mpt);
 1164         }
 1165         mpt->ready = 1;
 1166 }
 1167 
 1168 static void
 1169 mpt_cam_detach(struct mpt_softc *mpt)
 1170 {
 1171         mpt_handler_t handler;
 1172 
 1173         MPT_LOCK(mpt);
 1174         mpt->ready = 0;
 1175         mpt_terminate_recovery_thread(mpt); 
 1176 
 1177         handler.reply_handler = mpt_scsi_reply_handler;
 1178         mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler,
 1179                                scsi_io_handler_id);
 1180         handler.reply_handler = mpt_scsi_tmf_reply_handler;
 1181         mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler,
 1182                                scsi_tmf_handler_id);
 1183         handler.reply_handler = mpt_fc_els_reply_handler;
 1184         mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler,
 1185                                fc_els_handler_id);
 1186         handler.reply_handler = mpt_scsi_tgt_reply_handler;
 1187         mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler,
 1188                                mpt->scsi_tgt_handler_id);
 1189         handler.reply_handler = mpt_sata_pass_reply_handler;
 1190         mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler,
 1191                                sata_pass_handler_id);
 1192 
 1193         if (mpt->tmf_req != NULL) {
 1194                 mpt->tmf_req->state = REQ_STATE_ALLOCATED;
 1195                 mpt_free_request(mpt, mpt->tmf_req);
 1196                 mpt->tmf_req = NULL;
 1197         }
 1198         if (mpt->sas_portinfo != NULL) {
 1199                 free(mpt->sas_portinfo, M_DEVBUF);
 1200                 mpt->sas_portinfo = NULL;
 1201         }
 1202 
 1203         if (mpt->sim != NULL) {
 1204                 xpt_free_path(mpt->path);
 1205                 xpt_bus_deregister(cam_sim_path(mpt->sim));
 1206                 cam_sim_free(mpt->sim, TRUE);
 1207                 mpt->sim = NULL;
 1208         }
 1209 
 1210         if (mpt->phydisk_sim != NULL) {
 1211                 xpt_free_path(mpt->phydisk_path);
 1212                 xpt_bus_deregister(cam_sim_path(mpt->phydisk_sim));
 1213                 cam_sim_free(mpt->phydisk_sim, TRUE);
 1214                 mpt->phydisk_sim = NULL;
 1215         }
 1216         MPT_UNLOCK(mpt);
 1217 }
 1218 
 1219 /* This routine is used after a system crash to dump core onto the swap device.
 1220  */
 1221 static void
 1222 mpt_poll(struct cam_sim *sim)
 1223 {
 1224         struct mpt_softc *mpt;
 1225 
 1226         mpt = (struct mpt_softc *)cam_sim_softc(sim);
 1227         mpt_intr(mpt);
 1228 }
 1229 
 1230 /*
 1231  * Watchdog timeout routine for SCSI requests.
 1232  */
 1233 static void
 1234 mpt_timeout(void *arg)
 1235 {
 1236         union ccb        *ccb;
 1237         struct mpt_softc *mpt;
 1238         request_t        *req;
 1239 
 1240         ccb = (union ccb *)arg;
 1241         mpt = ccb->ccb_h.ccb_mpt_ptr;
 1242 
 1243         MPT_LOCK_ASSERT(mpt);
 1244         req = ccb->ccb_h.ccb_req_ptr;
 1245         mpt_prt(mpt, "request %p:%u timed out for ccb %p (req->ccb %p)\n", req,
 1246             req->serno, ccb, req->ccb);
 1247 /* XXX: WHAT ARE WE TRYING TO DO HERE? */
 1248         if ((req->state & REQ_STATE_QUEUED) == REQ_STATE_QUEUED) {
 1249                 TAILQ_REMOVE(&mpt->request_pending_list, req, links);
 1250                 TAILQ_INSERT_TAIL(&mpt->request_timeout_list, req, links);
 1251                 req->state |= REQ_STATE_TIMEDOUT;
 1252                 mpt_wakeup_recovery_thread(mpt);
 1253         }
 1254 }
 1255 
 1256 /*
 1257  * Callback routine from "bus_dmamap_load" or, in simple cases, called directly.
 1258  *
 1259  * Takes a list of physical segments and builds the SGL for SCSI IO command
 1260  * and forwards the commard to the IOC after one last check that CAM has not
 1261  * aborted the transaction.
 1262  */
 1263 static void
 1264 mpt_execute_req_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
 1265 {
 1266         request_t *req, *trq;
 1267         char *mpt_off;
 1268         union ccb *ccb;
 1269         struct mpt_softc *mpt;
 1270         bus_addr_t chain_list_addr;
 1271         int first_lim, seg, this_seg_lim;
 1272         uint32_t addr, cur_off, flags, nxt_off, tf;
 1273         void *sglp = NULL;
 1274         MSG_REQUEST_HEADER *hdrp;
 1275         SGE_SIMPLE64 *se;
 1276         SGE_CHAIN64 *ce;
 1277         int istgt = 0;
 1278 
 1279         req = (request_t *)arg;
 1280         ccb = req->ccb;
 1281 
 1282         mpt = ccb->ccb_h.ccb_mpt_ptr;
 1283         req = ccb->ccb_h.ccb_req_ptr;
 1284 
 1285         hdrp = req->req_vbuf;
 1286         mpt_off = req->req_vbuf;
 1287 
 1288         if (error == 0 && ((uint32_t)nseg) >= mpt->max_seg_cnt) {
 1289                 error = EFBIG;
 1290         }
 1291 
 1292         if (error == 0) {
 1293                 switch (hdrp->Function) {
 1294                 case MPI_FUNCTION_SCSI_IO_REQUEST:
 1295                 case MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
 1296                         istgt = 0;
 1297                         sglp = &((PTR_MSG_SCSI_IO_REQUEST)hdrp)->SGL;
 1298                         break;
 1299                 case MPI_FUNCTION_TARGET_ASSIST:
 1300                         istgt = 1;
 1301                         sglp = &((PTR_MSG_TARGET_ASSIST_REQUEST)hdrp)->SGL;
 1302                         break;
 1303                 default:
 1304                         mpt_prt(mpt, "bad fct 0x%x in mpt_execute_req_a64\n",
 1305                             hdrp->Function);
 1306                         error = EINVAL;
 1307                         break;
 1308                 }
 1309         }
 1310 
 1311         if (error == 0 && ((uint32_t)nseg) >= mpt->max_seg_cnt) {
 1312                 error = EFBIG;
 1313                 mpt_prt(mpt, "segment count %d too large (max %u)\n",
 1314                     nseg, mpt->max_seg_cnt);
 1315         }
 1316 
 1317 bad:
 1318         if (error != 0) {
 1319                 if (error != EFBIG && error != ENOMEM) {
 1320                         mpt_prt(mpt, "mpt_execute_req_a64: err %d\n", error);
 1321                 }
 1322                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
 1323                         cam_status status;
 1324                         mpt_freeze_ccb(ccb);
 1325                         if (error == EFBIG) {
 1326                                 status = CAM_REQ_TOO_BIG;
 1327                         } else if (error == ENOMEM) {
 1328                                 if (mpt->outofbeer == 0) {
 1329                                         mpt->outofbeer = 1;
 1330                                         xpt_freeze_simq(mpt->sim, 1);
 1331                                         mpt_lprt(mpt, MPT_PRT_DEBUG,
 1332                                             "FREEZEQ\n");
 1333                                 }
 1334                                 status = CAM_REQUEUE_REQ;
 1335                         } else {
 1336                                 status = CAM_REQ_CMP_ERR;
 1337                         }
 1338                         mpt_set_ccb_status(ccb, status);
 1339                 }
 1340                 if (hdrp->Function == MPI_FUNCTION_TARGET_ASSIST) {
 1341                         request_t *cmd_req =
 1342                                 MPT_TAG_2_REQ(mpt, ccb->csio.tag_id);
 1343                         MPT_TGT_STATE(mpt, cmd_req)->state = TGT_STATE_IN_CAM;
 1344                         MPT_TGT_STATE(mpt, cmd_req)->ccb = NULL;
 1345                         MPT_TGT_STATE(mpt, cmd_req)->req = NULL;
 1346                 }
 1347                 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 1348                 KASSERT(ccb->ccb_h.status, ("zero ccb sts at %d", __LINE__));
 1349                 xpt_done(ccb);
 1350                 mpt_free_request(mpt, req);
 1351                 return;
 1352         }
 1353 
 1354         /*
 1355          * No data to transfer?
 1356          * Just make a single simple SGL with zero length.
 1357          */
 1358 
 1359         if (mpt->verbose >= MPT_PRT_DEBUG) {
 1360                 int tidx = ((char *)sglp) - mpt_off;
 1361                 memset(&mpt_off[tidx], 0xff, MPT_REQUEST_AREA - tidx);
 1362         }
 1363 
 1364         if (nseg == 0) {
 1365                 SGE_SIMPLE32 *se1 = (SGE_SIMPLE32 *) sglp;
 1366                 MPI_pSGE_SET_FLAGS(se1,
 1367                     (MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
 1368                     MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_LIST));
 1369                 se1->FlagsLength = htole32(se1->FlagsLength);
 1370                 goto out;
 1371         }
 1372 
 1373 
 1374         flags = MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_64_BIT_ADDRESSING;
 1375         if (istgt == 0) {
 1376                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
 1377                         flags |= MPI_SGE_FLAGS_HOST_TO_IOC;
 1378                 }
 1379         } else {
 1380                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
 1381                         flags |= MPI_SGE_FLAGS_HOST_TO_IOC;
 1382                 }
 1383         }
 1384 
 1385         if (!(ccb->ccb_h.flags & (CAM_SG_LIST_PHYS|CAM_DATA_PHYS))) {
 1386                 bus_dmasync_op_t op;
 1387                 if (istgt == 0) {
 1388                         if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
 1389                                 op = BUS_DMASYNC_PREREAD;
 1390                         } else {
 1391                                 op = BUS_DMASYNC_PREWRITE;
 1392                         }
 1393                 } else {
 1394                         if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
 1395                                 op = BUS_DMASYNC_PREWRITE;
 1396                         } else {
 1397                                 op = BUS_DMASYNC_PREREAD;
 1398                         }
 1399                 }
 1400                 bus_dmamap_sync(mpt->buffer_dmat, req->dmap, op);
 1401         }
 1402 
 1403         /*
 1404          * Okay, fill in what we can at the end of the command frame.
 1405          * If we have up to MPT_NSGL_FIRST, we can fit them all into
 1406          * the command frame.
 1407          *
 1408          * Otherwise, we fill up through MPT_NSGL_FIRST less one
 1409          * SIMPLE64 pointers and start doing CHAIN64 entries after
 1410          * that.
 1411          */
 1412 
 1413         if (nseg < MPT_NSGL_FIRST(mpt)) {
 1414                 first_lim = nseg;
 1415         } else {
 1416                 /*
 1417                  * Leave room for CHAIN element
 1418                  */
 1419                 first_lim = MPT_NSGL_FIRST(mpt) - 1;
 1420         }
 1421 
 1422         se = (SGE_SIMPLE64 *) sglp;
 1423         for (seg = 0; seg < first_lim; seg++, se++, dm_segs++) {
 1424                 tf = flags;
 1425                 memset(se, 0, sizeof (*se));
 1426                 MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
 1427                 se->Address.Low = htole32(dm_segs->ds_addr & 0xffffffff);
 1428                 if (sizeof(bus_addr_t) > 4) {
 1429                         addr = ((uint64_t)dm_segs->ds_addr) >> 32;
 1430                         /* SAS1078 36GB limitation WAR */
 1431                         if (mpt->is_1078 && (((uint64_t)dm_segs->ds_addr +
 1432                             MPI_SGE_LENGTH(se->FlagsLength)) >> 32) == 9) {
 1433                                 addr |= (1 << 31);
 1434                                 tf |= MPI_SGE_FLAGS_LOCAL_ADDRESS;
 1435                         }
 1436                         se->Address.High = htole32(addr);
 1437                 }
 1438                 if (seg == first_lim - 1) {
 1439                         tf |= MPI_SGE_FLAGS_LAST_ELEMENT;
 1440                 }
 1441                 if (seg == nseg - 1) {
 1442                         tf |=   MPI_SGE_FLAGS_END_OF_LIST |
 1443                                 MPI_SGE_FLAGS_END_OF_BUFFER;
 1444                 }
 1445                 MPI_pSGE_SET_FLAGS(se, tf);
 1446                 se->FlagsLength = htole32(se->FlagsLength);
 1447         }
 1448 
 1449         if (seg == nseg) {
 1450                 goto out;
 1451         }
 1452 
 1453         /*
 1454          * Tell the IOC where to find the first chain element.
 1455          */
 1456         hdrp->ChainOffset = ((char *)se - (char *)hdrp) >> 2;
 1457         nxt_off = MPT_RQSL(mpt);
 1458         trq = req;
 1459 
 1460         /*
 1461          * Make up the rest of the data segments out of a chain element
 1462          * (contained in the current request frame) which points to
 1463          * SIMPLE64 elements in the next request frame, possibly ending
 1464          * with *another* chain element (if there's more).
 1465          */
 1466         while (seg < nseg) {
 1467                 /*
 1468                  * Point to the chain descriptor. Note that the chain
 1469                  * descriptor is at the end of the *previous* list (whether
 1470                  * chain or simple).
 1471                  */
 1472                 ce = (SGE_CHAIN64 *) se;
 1473 
 1474                 /*
 1475                  * Before we change our current pointer, make  sure we won't
 1476                  * overflow the request area with this frame. Note that we
 1477                  * test against 'greater than' here as it's okay in this case
 1478                  * to have next offset be just outside the request area.
 1479                  */
 1480                 if ((nxt_off + MPT_RQSL(mpt)) > MPT_REQUEST_AREA) {
 1481                         nxt_off = MPT_REQUEST_AREA;
 1482                         goto next_chain;
 1483                 }
 1484 
 1485                 /*
 1486                  * Set our SGE element pointer to the beginning of the chain
 1487                  * list and update our next chain list offset.
 1488                  */
 1489                 se = (SGE_SIMPLE64 *) &mpt_off[nxt_off];
 1490                 cur_off = nxt_off;
 1491                 nxt_off += MPT_RQSL(mpt);
 1492 
 1493                 /*
 1494                  * Now initialize the chain descriptor.
 1495                  */
 1496                 memset(ce, 0, sizeof (*ce));
 1497 
 1498                 /*
 1499                  * Get the physical address of the chain list.
 1500                  */
 1501                 chain_list_addr = trq->req_pbuf;
 1502                 chain_list_addr += cur_off;
 1503                 if (sizeof (bus_addr_t) > 4) {
 1504                         ce->Address.High =
 1505                             htole32(((uint64_t)chain_list_addr) >> 32);
 1506                 }
 1507                 ce->Address.Low = htole32(chain_list_addr & 0xffffffff);
 1508                 ce->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT |
 1509                             MPI_SGE_FLAGS_64_BIT_ADDRESSING;
 1510 
 1511                 /*
 1512                  * If we have more than a frame's worth of segments left,
 1513                  * set up the chain list to have the last element be another
 1514                  * chain descriptor.
 1515                  */
 1516                 if ((nseg - seg) > MPT_NSGL(mpt)) {
 1517                         this_seg_lim = seg + MPT_NSGL(mpt) - 1;
 1518                         /*
 1519                          * The length of the chain is the length in bytes of the
 1520                          * number of segments plus the next chain element.
 1521                          *
 1522                          * The next chain descriptor offset is the length,
 1523                          * in words, of the number of segments.
 1524                          */
 1525                         ce->Length = (this_seg_lim - seg) *
 1526                             sizeof (SGE_SIMPLE64);
 1527                         ce->NextChainOffset = ce->Length >> 2;
 1528                         ce->Length += sizeof (SGE_CHAIN64);
 1529                 } else {
 1530                         this_seg_lim = nseg;
 1531                         ce->Length = (this_seg_lim - seg) *
 1532                             sizeof (SGE_SIMPLE64);
 1533                 }
 1534                 ce->Length = htole16(ce->Length);
 1535 
 1536                 /*
 1537                  * Fill in the chain list SGE elements with our segment data.
 1538                  *
 1539                  * If we're the last element in this chain list, set the last
 1540                  * element flag. If we're the completely last element period,
 1541                  * set the end of list and end of buffer flags.
 1542                  */
 1543                 while (seg < this_seg_lim) {
 1544                         tf = flags;
 1545                         memset(se, 0, sizeof (*se));
 1546                         MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
 1547                         se->Address.Low = htole32(dm_segs->ds_addr &
 1548                             0xffffffff);
 1549                         if (sizeof (bus_addr_t) > 4) {
 1550                                 addr = ((uint64_t)dm_segs->ds_addr) >> 32;
 1551                                 /* SAS1078 36GB limitation WAR */
 1552                                 if (mpt->is_1078 &&
 1553                                     (((uint64_t)dm_segs->ds_addr +
 1554                                     MPI_SGE_LENGTH(se->FlagsLength)) >>
 1555                                     32) == 9) {
 1556                                         addr |= (1 << 31);
 1557                                         tf |= MPI_SGE_FLAGS_LOCAL_ADDRESS;
 1558                                 }
 1559                                 se->Address.High = htole32(addr);
 1560                         }
 1561                         if (seg == this_seg_lim - 1) {
 1562                                 tf |=   MPI_SGE_FLAGS_LAST_ELEMENT;
 1563                         }
 1564                         if (seg == nseg - 1) {
 1565                                 tf |=   MPI_SGE_FLAGS_END_OF_LIST |
 1566                                         MPI_SGE_FLAGS_END_OF_BUFFER;
 1567                         }
 1568                         MPI_pSGE_SET_FLAGS(se, tf);
 1569                         se->FlagsLength = htole32(se->FlagsLength);
 1570                         se++;
 1571                         seg++;
 1572                         dm_segs++;
 1573                 }
 1574 
 1575     next_chain:
 1576                 /*
 1577                  * If we have more segments to do and we've used up all of
 1578                  * the space in a request area, go allocate another one
 1579                  * and chain to that.
 1580                  */
 1581                 if (seg < nseg && nxt_off >= MPT_REQUEST_AREA) {
 1582                         request_t *nrq;
 1583 
 1584                         nrq = mpt_get_request(mpt, FALSE);
 1585 
 1586                         if (nrq == NULL) {
 1587                                 error = ENOMEM;
 1588                                 goto bad;
 1589                         }
 1590 
 1591                         /*
 1592                          * Append the new request area on the tail of our list.
 1593                          */
 1594                         if ((trq = req->chain) == NULL) {
 1595                                 req->chain = nrq;
 1596                         } else {
 1597                                 while (trq->chain != NULL) {
 1598                                         trq = trq->chain;
 1599                                 }
 1600                                 trq->chain = nrq;
 1601                         }
 1602                         trq = nrq;
 1603                         mpt_off = trq->req_vbuf;
 1604                         if (mpt->verbose >= MPT_PRT_DEBUG) {
 1605                                 memset(mpt_off, 0xff, MPT_REQUEST_AREA);
 1606                         }
 1607                         nxt_off = 0;
 1608                 }
 1609         }
 1610 out:
 1611 
 1612         /*
 1613          * Last time we need to check if this CCB needs to be aborted.
 1614          */
 1615         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
 1616                 if (hdrp->Function == MPI_FUNCTION_TARGET_ASSIST) {
 1617                         request_t *cmd_req =
 1618                                 MPT_TAG_2_REQ(mpt, ccb->csio.tag_id);
 1619                         MPT_TGT_STATE(mpt, cmd_req)->state = TGT_STATE_IN_CAM;
 1620                         MPT_TGT_STATE(mpt, cmd_req)->ccb = NULL;
 1621                         MPT_TGT_STATE(mpt, cmd_req)->req = NULL;
 1622                 }
 1623                 mpt_prt(mpt,
 1624                     "mpt_execute_req_a64: I/O cancelled (status 0x%x)\n",
 1625                     ccb->ccb_h.status & CAM_STATUS_MASK);
 1626                 if (nseg && (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) {
 1627                         bus_dmamap_unload(mpt->buffer_dmat, req->dmap);
 1628                 }
 1629                 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 1630                 KASSERT(ccb->ccb_h.status, ("zero ccb sts at %d", __LINE__));
 1631                 xpt_done(ccb);
 1632                 mpt_free_request(mpt, req);
 1633                 return;
 1634         }
 1635 
 1636         ccb->ccb_h.status |= CAM_SIM_QUEUED;
 1637         if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
 1638                 mpt_req_timeout(req, (ccb->ccb_h.timeout * hz) / 1000,
 1639                     mpt_timeout, ccb);
 1640         }
 1641         if (mpt->verbose > MPT_PRT_DEBUG) {
 1642                 int nc = 0;
 1643                 mpt_print_request(req->req_vbuf);
 1644                 for (trq = req->chain; trq; trq = trq->chain) {
 1645                         printf("  Additional Chain Area %d\n", nc++);
 1646                         mpt_dump_sgl(trq->req_vbuf, 0);
 1647                 }
 1648         }
 1649 
 1650         if (hdrp->Function == MPI_FUNCTION_TARGET_ASSIST) {
 1651                 request_t *cmd_req = MPT_TAG_2_REQ(mpt, ccb->csio.tag_id);
 1652                 mpt_tgt_state_t *tgt = MPT_TGT_STATE(mpt, cmd_req);
 1653 #ifdef  WE_TRUST_AUTO_GOOD_STATUS
 1654                 if ((ccb->ccb_h.flags & CAM_SEND_STATUS) &&
 1655                     csio->scsi_status == SCSI_STATUS_OK && tgt->resid == 0) {
 1656                         tgt->state = TGT_STATE_MOVING_DATA_AND_STATUS;
 1657                 } else {
 1658                         tgt->state = TGT_STATE_MOVING_DATA;
 1659                 }
 1660 #else
 1661                 tgt->state = TGT_STATE_MOVING_DATA;
 1662 #endif
 1663         }
 1664         mpt_send_cmd(mpt, req);
 1665 }
 1666 
 1667 static void
 1668 mpt_execute_req(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
 1669 {
 1670         request_t *req, *trq;
 1671         char *mpt_off;
 1672         union ccb *ccb;
 1673         struct mpt_softc *mpt;
 1674         int seg, first_lim;
 1675         uint32_t flags, nxt_off;
 1676         void *sglp = NULL;
 1677         MSG_REQUEST_HEADER *hdrp;
 1678         SGE_SIMPLE32 *se;
 1679         SGE_CHAIN32 *ce;
 1680         int istgt = 0;
 1681 
 1682         req = (request_t *)arg;
 1683         ccb = req->ccb;
 1684 
 1685         mpt = ccb->ccb_h.ccb_mpt_ptr;
 1686         req = ccb->ccb_h.ccb_req_ptr;
 1687 
 1688         hdrp = req->req_vbuf;
 1689         mpt_off = req->req_vbuf;
 1690 
 1691 
 1692         if (error == 0 && ((uint32_t)nseg) >= mpt->max_seg_cnt) {
 1693                 error = EFBIG;
 1694         }
 1695 
 1696         if (error == 0) {
 1697                 switch (hdrp->Function) {
 1698                 case MPI_FUNCTION_SCSI_IO_REQUEST:
 1699                 case MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
 1700                         sglp = &((PTR_MSG_SCSI_IO_REQUEST)hdrp)->SGL;
 1701                         break;
 1702                 case MPI_FUNCTION_TARGET_ASSIST:
 1703                         istgt = 1;
 1704                         sglp = &((PTR_MSG_TARGET_ASSIST_REQUEST)hdrp)->SGL;
 1705                         break;
 1706                 default:
 1707                         mpt_prt(mpt, "bad fct 0x%x in mpt_execute_req\n",
 1708                             hdrp->Function);
 1709                         error = EINVAL;
 1710                         break;
 1711                 }
 1712         }
 1713 
 1714         if (error == 0 && ((uint32_t)nseg) >= mpt->max_seg_cnt) {
 1715                 error = EFBIG;
 1716                 mpt_prt(mpt, "segment count %d too large (max %u)\n",
 1717                     nseg, mpt->max_seg_cnt);
 1718         }
 1719 
 1720 bad:
 1721         if (error != 0) {
 1722                 if (error != EFBIG && error != ENOMEM) {
 1723                         mpt_prt(mpt, "mpt_execute_req: err %d\n", error);
 1724                 }
 1725                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
 1726                         cam_status status;
 1727                         mpt_freeze_ccb(ccb);
 1728                         if (error == EFBIG) {
 1729                                 status = CAM_REQ_TOO_BIG;
 1730                         } else if (error == ENOMEM) {
 1731                                 if (mpt->outofbeer == 0) {
 1732                                         mpt->outofbeer = 1;
 1733                                         xpt_freeze_simq(mpt->sim, 1);
 1734                                         mpt_lprt(mpt, MPT_PRT_DEBUG,
 1735                                             "FREEZEQ\n");
 1736                                 }
 1737                                 status = CAM_REQUEUE_REQ;
 1738                         } else {
 1739                                 status = CAM_REQ_CMP_ERR;
 1740                         }
 1741                         mpt_set_ccb_status(ccb, status);
 1742                 }
 1743                 if (hdrp->Function == MPI_FUNCTION_TARGET_ASSIST) {
 1744                         request_t *cmd_req =
 1745                                 MPT_TAG_2_REQ(mpt, ccb->csio.tag_id);
 1746                         MPT_TGT_STATE(mpt, cmd_req)->state = TGT_STATE_IN_CAM;
 1747                         MPT_TGT_STATE(mpt, cmd_req)->ccb = NULL;
 1748                         MPT_TGT_STATE(mpt, cmd_req)->req = NULL;
 1749                 }
 1750                 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 1751                 KASSERT(ccb->ccb_h.status, ("zero ccb sts at %d", __LINE__));
 1752                 xpt_done(ccb);
 1753                 mpt_free_request(mpt, req);
 1754                 return;
 1755         }
 1756 
 1757         /*
 1758          * No data to transfer?
 1759          * Just make a single simple SGL with zero length.
 1760          */
 1761 
 1762         if (mpt->verbose >= MPT_PRT_DEBUG) {
 1763                 int tidx = ((char *)sglp) - mpt_off;
 1764                 memset(&mpt_off[tidx], 0xff, MPT_REQUEST_AREA - tidx);
 1765         }
 1766 
 1767         if (nseg == 0) {
 1768                 SGE_SIMPLE32 *se1 = (SGE_SIMPLE32 *) sglp;
 1769                 MPI_pSGE_SET_FLAGS(se1,
 1770                     (MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
 1771                     MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_LIST));
 1772                 se1->FlagsLength = htole32(se1->FlagsLength);
 1773                 goto out;
 1774         }
 1775 
 1776 
 1777         flags = MPI_SGE_FLAGS_SIMPLE_ELEMENT;
 1778         if (istgt == 0) {
 1779                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
 1780                         flags |= MPI_SGE_FLAGS_HOST_TO_IOC;
 1781                 }
 1782         } else {
 1783                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
 1784                         flags |= MPI_SGE_FLAGS_HOST_TO_IOC;
 1785                 }
 1786         }
 1787 
 1788         if (!(ccb->ccb_h.flags & (CAM_SG_LIST_PHYS|CAM_DATA_PHYS))) {
 1789                 bus_dmasync_op_t op;
 1790                 if (istgt) {
 1791                         if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
 1792                                 op = BUS_DMASYNC_PREREAD;
 1793                         } else {
 1794                                 op = BUS_DMASYNC_PREWRITE;
 1795                         }
 1796                 } else {
 1797                         if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
 1798                                 op = BUS_DMASYNC_PREWRITE;
 1799                         } else {
 1800                                 op = BUS_DMASYNC_PREREAD;
 1801                         }
 1802                 }
 1803                 bus_dmamap_sync(mpt->buffer_dmat, req->dmap, op);
 1804         }
 1805 
 1806         /*
 1807          * Okay, fill in what we can at the end of the command frame.
 1808          * If we have up to MPT_NSGL_FIRST, we can fit them all into
 1809          * the command frame.
 1810          *
 1811          * Otherwise, we fill up through MPT_NSGL_FIRST less one
 1812          * SIMPLE32 pointers and start doing CHAIN32 entries after
 1813          * that.
 1814          */
 1815 
 1816         if (nseg < MPT_NSGL_FIRST(mpt)) {
 1817                 first_lim = nseg;
 1818         } else {
 1819                 /*
 1820                  * Leave room for CHAIN element
 1821                  */
 1822                 first_lim = MPT_NSGL_FIRST(mpt) - 1;
 1823         }
 1824 
 1825         se = (SGE_SIMPLE32 *) sglp;
 1826         for (seg = 0; seg < first_lim; seg++, se++, dm_segs++) {
 1827                 uint32_t tf;
 1828 
 1829                 memset(se, 0,sizeof (*se));
 1830                 se->Address = htole32(dm_segs->ds_addr);
 1831 
 1832                 MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
 1833                 tf = flags;
 1834                 if (seg == first_lim - 1) {
 1835                         tf |= MPI_SGE_FLAGS_LAST_ELEMENT;
 1836                 }
 1837                 if (seg == nseg - 1) {
 1838                         tf |=   MPI_SGE_FLAGS_END_OF_LIST |
 1839                                 MPI_SGE_FLAGS_END_OF_BUFFER;
 1840                 }
 1841                 MPI_pSGE_SET_FLAGS(se, tf);
 1842                 se->FlagsLength = htole32(se->FlagsLength);
 1843         }
 1844 
 1845         if (seg == nseg) {
 1846                 goto out;
 1847         }
 1848 
 1849         /*
 1850          * Tell the IOC where to find the first chain element.
 1851          */
 1852         hdrp->ChainOffset = ((char *)se - (char *)hdrp) >> 2;
 1853         nxt_off = MPT_RQSL(mpt);
 1854         trq = req;
 1855 
 1856         /*
 1857          * Make up the rest of the data segments out of a chain element
 1858          * (contained in the current request frame) which points to
 1859          * SIMPLE32 elements in the next request frame, possibly ending
 1860          * with *another* chain element (if there's more).
 1861          */
 1862         while (seg < nseg) {
 1863                 int this_seg_lim;
 1864                 uint32_t tf, cur_off;
 1865                 bus_addr_t chain_list_addr;
 1866 
 1867                 /*
 1868                  * Point to the chain descriptor. Note that the chain
 1869                  * descriptor is at the end of the *previous* list (whether
 1870                  * chain or simple).
 1871                  */
 1872                 ce = (SGE_CHAIN32 *) se;
 1873 
 1874                 /*
 1875                  * Before we change our current pointer, make  sure we won't
 1876                  * overflow the request area with this frame. Note that we
 1877                  * test against 'greater than' here as it's okay in this case
 1878                  * to have next offset be just outside the request area.
 1879                  */
 1880                 if ((nxt_off + MPT_RQSL(mpt)) > MPT_REQUEST_AREA) {
 1881                         nxt_off = MPT_REQUEST_AREA;
 1882                         goto next_chain;
 1883                 }
 1884 
 1885                 /*
 1886                  * Set our SGE element pointer to the beginning of the chain
 1887                  * list and update our next chain list offset.
 1888                  */
 1889                 se = (SGE_SIMPLE32 *) &mpt_off[nxt_off];
 1890                 cur_off = nxt_off;
 1891                 nxt_off += MPT_RQSL(mpt);
 1892 
 1893                 /*
 1894                  * Now initialize the chain descriptor.
 1895                  */
 1896                 memset(ce, 0, sizeof (*ce));
 1897 
 1898                 /*
 1899                  * Get the physical address of the chain list.
 1900                  */
 1901                 chain_list_addr = trq->req_pbuf;
 1902                 chain_list_addr += cur_off;
 1903 
 1904 
 1905 
 1906                 ce->Address = htole32(chain_list_addr);
 1907                 ce->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT;
 1908 
 1909 
 1910                 /*
 1911                  * If we have more than a frame's worth of segments left,
 1912                  * set up the chain list to have the last element be another
 1913                  * chain descriptor.
 1914                  */
 1915                 if ((nseg - seg) > MPT_NSGL(mpt)) {
 1916                         this_seg_lim = seg + MPT_NSGL(mpt) - 1;
 1917                         /*
 1918                          * The length of the chain is the length in bytes of the
 1919                          * number of segments plus the next chain element.
 1920                          *
 1921                          * The next chain descriptor offset is the length,
 1922                          * in words, of the number of segments.
 1923                          */
 1924                         ce->Length = (this_seg_lim - seg) *
 1925                             sizeof (SGE_SIMPLE32);
 1926                         ce->NextChainOffset = ce->Length >> 2;
 1927                         ce->Length += sizeof (SGE_CHAIN32);
 1928                 } else {
 1929                         this_seg_lim = nseg;
 1930                         ce->Length = (this_seg_lim - seg) *
 1931                             sizeof (SGE_SIMPLE32);
 1932                 }
 1933                 ce->Length = htole16(ce->Length);
 1934 
 1935                 /*
 1936                  * Fill in the chain list SGE elements with our segment data.
 1937                  *
 1938                  * If we're the last element in this chain list, set the last
 1939                  * element flag. If we're the completely last element period,
 1940                  * set the end of list and end of buffer flags.
 1941                  */
 1942                 while (seg < this_seg_lim) {
 1943                         memset(se, 0, sizeof (*se));
 1944                         se->Address = htole32(dm_segs->ds_addr);
 1945 
 1946                         MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
 1947                         tf = flags;
 1948                         if (seg == this_seg_lim - 1) {
 1949                                 tf |=   MPI_SGE_FLAGS_LAST_ELEMENT;
 1950                         }
 1951                         if (seg == nseg - 1) {
 1952                                 tf |=   MPI_SGE_FLAGS_END_OF_LIST |
 1953                                         MPI_SGE_FLAGS_END_OF_BUFFER;
 1954                         }
 1955                         MPI_pSGE_SET_FLAGS(se, tf);
 1956                         se->FlagsLength = htole32(se->FlagsLength);
 1957                         se++;
 1958                         seg++;
 1959                         dm_segs++;
 1960                 }
 1961 
 1962     next_chain:
 1963                 /*
 1964                  * If we have more segments to do and we've used up all of
 1965                  * the space in a request area, go allocate another one
 1966                  * and chain to that.
 1967                  */
 1968                 if (seg < nseg && nxt_off >= MPT_REQUEST_AREA) {
 1969                         request_t *nrq;
 1970 
 1971                         nrq = mpt_get_request(mpt, FALSE);
 1972 
 1973                         if (nrq == NULL) {
 1974                                 error = ENOMEM;
 1975                                 goto bad;
 1976                         }
 1977 
 1978                         /*
 1979                          * Append the new request area on the tail of our list.
 1980                          */
 1981                         if ((trq = req->chain) == NULL) {
 1982                                 req->chain = nrq;
 1983                         } else {
 1984                                 while (trq->chain != NULL) {
 1985                                         trq = trq->chain;
 1986                                 }
 1987                                 trq->chain = nrq;
 1988                         }
 1989                         trq = nrq;
 1990                         mpt_off = trq->req_vbuf;
 1991                         if (mpt->verbose >= MPT_PRT_DEBUG) {
 1992                                 memset(mpt_off, 0xff, MPT_REQUEST_AREA);
 1993                         }
 1994                         nxt_off = 0;
 1995                 }
 1996         }
 1997 out:
 1998 
 1999         /*
 2000          * Last time we need to check if this CCB needs to be aborted.
 2001          */
 2002         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
 2003                 if (hdrp->Function == MPI_FUNCTION_TARGET_ASSIST) {
 2004                         request_t *cmd_req =
 2005                                 MPT_TAG_2_REQ(mpt, ccb->csio.tag_id);
 2006                         MPT_TGT_STATE(mpt, cmd_req)->state = TGT_STATE_IN_CAM;
 2007                         MPT_TGT_STATE(mpt, cmd_req)->ccb = NULL;
 2008                         MPT_TGT_STATE(mpt, cmd_req)->req = NULL;
 2009                 }
 2010                 mpt_prt(mpt,
 2011                     "mpt_execute_req: I/O cancelled (status 0x%x)\n",
 2012                     ccb->ccb_h.status & CAM_STATUS_MASK);
 2013                 if (nseg && (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) {
 2014                         bus_dmamap_unload(mpt->buffer_dmat, req->dmap);
 2015                 }
 2016                 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 2017                 KASSERT(ccb->ccb_h.status, ("zero ccb sts at %d", __LINE__));
 2018                 xpt_done(ccb);
 2019                 mpt_free_request(mpt, req);
 2020                 return;
 2021         }
 2022 
 2023         ccb->ccb_h.status |= CAM_SIM_QUEUED;
 2024         if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
 2025                 mpt_req_timeout(req, (ccb->ccb_h.timeout * hz) / 1000,
 2026                     mpt_timeout, ccb);
 2027         }
 2028         if (mpt->verbose > MPT_PRT_DEBUG) {
 2029                 int nc = 0;
 2030                 mpt_print_request(req->req_vbuf);
 2031                 for (trq = req->chain; trq; trq = trq->chain) {
 2032                         printf("  Additional Chain Area %d\n", nc++);
 2033                         mpt_dump_sgl(trq->req_vbuf, 0);
 2034                 }
 2035         }
 2036 
 2037         if (hdrp->Function == MPI_FUNCTION_TARGET_ASSIST) {
 2038                 request_t *cmd_req = MPT_TAG_2_REQ(mpt, ccb->csio.tag_id);
 2039                 mpt_tgt_state_t *tgt = MPT_TGT_STATE(mpt, cmd_req);
 2040 #ifdef  WE_TRUST_AUTO_GOOD_STATUS
 2041                 if ((ccb->ccb_h.flags & CAM_SEND_STATUS) &&
 2042                     csio->scsi_status == SCSI_STATUS_OK && tgt->resid == 0) {
 2043                         tgt->state = TGT_STATE_MOVING_DATA_AND_STATUS;
 2044                 } else {
 2045                         tgt->state = TGT_STATE_MOVING_DATA;
 2046                 }
 2047 #else
 2048                 tgt->state = TGT_STATE_MOVING_DATA;
 2049 #endif
 2050         }
 2051         mpt_send_cmd(mpt, req);
 2052 }
 2053 
 2054 static void
 2055 mpt_start(struct cam_sim *sim, union ccb *ccb)
 2056 {
 2057         request_t *req;
 2058         struct mpt_softc *mpt;
 2059         MSG_SCSI_IO_REQUEST *mpt_req;
 2060         struct ccb_scsiio *csio = &ccb->csio;
 2061         struct ccb_hdr *ccbh = &ccb->ccb_h;
 2062         bus_dmamap_callback_t *cb;
 2063         target_id_t tgt;
 2064         int raid_passthru;
 2065 
 2066         /* Get the pointer for the physical addapter */
 2067         mpt = ccb->ccb_h.ccb_mpt_ptr;
 2068         raid_passthru = (sim == mpt->phydisk_sim);
 2069 
 2070         if ((req = mpt_get_request(mpt, FALSE)) == NULL) {
 2071                 if (mpt->outofbeer == 0) {
 2072                         mpt->outofbeer = 1;
 2073                         xpt_freeze_simq(mpt->sim, 1);
 2074                         mpt_lprt(mpt, MPT_PRT_DEBUG, "FREEZEQ\n");
 2075                 }
 2076                 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 2077                 mpt_set_ccb_status(ccb, CAM_REQUEUE_REQ);
 2078                 xpt_done(ccb);
 2079                 return;
 2080         }
 2081 #ifdef  INVARIANTS
 2082         mpt_req_not_spcl(mpt, req, "mpt_start", __LINE__);
 2083 #endif
 2084 
 2085         if (sizeof (bus_addr_t) > 4) {
 2086                 cb = mpt_execute_req_a64;
 2087         } else {
 2088                 cb = mpt_execute_req;
 2089         }
 2090 
 2091         /*
 2092          * Link the ccb and the request structure so we can find
 2093          * the other knowing either the request or the ccb
 2094          */
 2095         req->ccb = ccb;
 2096         ccb->ccb_h.ccb_req_ptr = req;
 2097 
 2098         /* Now we build the command for the IOC */
 2099         mpt_req = req->req_vbuf;
 2100         memset(mpt_req, 0, sizeof (MSG_SCSI_IO_REQUEST));
 2101 
 2102         mpt_req->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
 2103         if (raid_passthru) {
 2104                 mpt_req->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
 2105                 if (mpt_map_physdisk(mpt, ccb, &tgt) != 0) {
 2106                         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 2107                         mpt_set_ccb_status(ccb, CAM_DEV_NOT_THERE);
 2108                         xpt_done(ccb);
 2109                         return;
 2110                 }
 2111                 mpt_req->Bus = 0;       /* we never set bus here */
 2112         } else {
 2113                 tgt = ccb->ccb_h.target_id;
 2114                 mpt_req->Bus = 0;       /* XXX */
 2115                 
 2116         }
 2117         mpt_req->SenseBufferLength =
 2118                 (csio->sense_len < MPT_SENSE_SIZE) ?
 2119                  csio->sense_len : MPT_SENSE_SIZE;
 2120 
 2121         /*
 2122          * We use the message context to find the request structure when we
 2123          * Get the command completion interrupt from the IOC.
 2124          */
 2125         mpt_req->MsgContext = htole32(req->index | scsi_io_handler_id);
 2126 
 2127         /* Which physical device to do the I/O on */
 2128         mpt_req->TargetID = tgt;
 2129 
 2130         /* We assume a single level LUN type */
 2131         if (ccb->ccb_h.target_lun >= MPT_MAX_LUNS) {
 2132                 mpt_req->LUN[0] = 0x40 | ((ccb->ccb_h.target_lun >> 8) & 0x3f);
 2133                 mpt_req->LUN[1] = ccb->ccb_h.target_lun & 0xff;
 2134         } else {
 2135                 mpt_req->LUN[1] = ccb->ccb_h.target_lun;
 2136         }
 2137 
 2138         /* Set the direction of the transfer */
 2139         if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
 2140                 mpt_req->Control = MPI_SCSIIO_CONTROL_READ;
 2141         } else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
 2142                 mpt_req->Control = MPI_SCSIIO_CONTROL_WRITE;
 2143         } else {
 2144                 mpt_req->Control = MPI_SCSIIO_CONTROL_NODATATRANSFER;
 2145         }
 2146 
 2147         if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0) {
 2148                 switch(ccb->csio.tag_action) {
 2149                 case MSG_HEAD_OF_Q_TAG:
 2150                         mpt_req->Control |= MPI_SCSIIO_CONTROL_HEADOFQ;
 2151                         break;
 2152                 case MSG_ACA_TASK:
 2153                         mpt_req->Control |= MPI_SCSIIO_CONTROL_ACAQ;
 2154                         break;
 2155                 case MSG_ORDERED_Q_TAG:
 2156                         mpt_req->Control |= MPI_SCSIIO_CONTROL_ORDEREDQ;
 2157                         break;
 2158                 case MSG_SIMPLE_Q_TAG:
 2159                 default:
 2160                         mpt_req->Control |= MPI_SCSIIO_CONTROL_SIMPLEQ;
 2161                         break;
 2162                 }
 2163         } else {
 2164                 if (mpt->is_fc || mpt->is_sas) {
 2165                         mpt_req->Control |= MPI_SCSIIO_CONTROL_SIMPLEQ;
 2166                 } else {
 2167                         /* XXX No such thing for a target doing packetized. */
 2168                         mpt_req->Control |= MPI_SCSIIO_CONTROL_UNTAGGED;
 2169                 }
 2170         }
 2171 
 2172         if (mpt->is_spi) {
 2173                 if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) {
 2174                         mpt_req->Control |= MPI_SCSIIO_CONTROL_NO_DISCONNECT;
 2175                 }
 2176         }
 2177         mpt_req->Control = htole32(mpt_req->Control);
 2178 
 2179         /* Copy the scsi command block into place */
 2180         if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
 2181                 bcopy(csio->cdb_io.cdb_ptr, mpt_req->CDB, csio->cdb_len);
 2182         } else {
 2183                 bcopy(csio->cdb_io.cdb_bytes, mpt_req->CDB, csio->cdb_len);
 2184         }
 2185 
 2186         mpt_req->CDBLength = csio->cdb_len;
 2187         mpt_req->DataLength = htole32(csio->dxfer_len);
 2188         mpt_req->SenseBufferLowAddr = htole32(req->sense_pbuf);
 2189 
 2190         /*
 2191          * Do a *short* print here if we're set to MPT_PRT_DEBUG
 2192          */
 2193         if (mpt->verbose == MPT_PRT_DEBUG) {
 2194                 U32 df;
 2195                 mpt_prt(mpt, "mpt_start: %s op 0x%x ",
 2196                     (mpt_req->Function == MPI_FUNCTION_SCSI_IO_REQUEST)?
 2197                     "SCSI_IO_REQUEST" : "SCSI_IO_PASSTHRU", mpt_req->CDB[0]);
 2198                 df = mpt_req->Control & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
 2199                 if (df != MPI_SCSIIO_CONTROL_NODATATRANSFER) {
 2200                         mpt_prtc(mpt, "(%s %u byte%s ",
 2201                             (df == MPI_SCSIIO_CONTROL_READ)?
 2202                             "read" : "write",  csio->dxfer_len,
 2203                             (csio->dxfer_len == 1)? ")" : "s)");
 2204                 }
 2205                 mpt_prtc(mpt, "tgt %u lun %u req %p:%u\n", tgt,
 2206                     ccb->ccb_h.target_lun, req, req->serno);
 2207         }
 2208 
 2209         /*
 2210          * If we have any data to send with this command map it into bus space.
 2211          */
 2212         if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
 2213                 if ((ccbh->flags & CAM_SCATTER_VALID) == 0) {
 2214                         /*
 2215                          * We've been given a pointer to a single buffer.
 2216                          */
 2217                         if ((ccbh->flags & CAM_DATA_PHYS) == 0) {
 2218                                 /*
 2219                                  * Virtual address that needs to translated into
 2220                                  * one or more physical address ranges.
 2221                                  */
 2222                                 int error;
 2223                                 int s = splsoftvm();
 2224                                 error = bus_dmamap_load(mpt->buffer_dmat,
 2225                                     req->dmap, csio->data_ptr, csio->dxfer_len,
 2226                                     cb, req, 0);
 2227                                 splx(s);
 2228                                 if (error == EINPROGRESS) {
 2229                                         /*
 2230                                          * So as to maintain ordering,
 2231                                          * freeze the controller queue
 2232                                          * until our mapping is
 2233                                          * returned.
 2234                                          */
 2235                                         xpt_freeze_simq(mpt->sim, 1);
 2236                                         ccbh->status |= CAM_RELEASE_SIMQ;
 2237                                 }
 2238                         } else {
 2239                                 /*
 2240                                  * We have been given a pointer to single
 2241                                  * physical buffer.
 2242                                  */
 2243                                 struct bus_dma_segment seg;
 2244                                 seg.ds_addr = 
 2245                                     (bus_addr_t)(vm_offset_t)csio->data_ptr;
 2246                                 seg.ds_len = csio->dxfer_len;
 2247                                 (*cb)(req, &seg, 1, 0);
 2248                         }
 2249                 } else {
 2250                         /*
 2251                          * We have been given a list of addresses.
 2252                          * This case could be easily supported but they are not
 2253                          * currently generated by the CAM subsystem so there
 2254                          * is no point in wasting the time right now.
 2255                          */
 2256                         struct bus_dma_segment *segs;
 2257                         if ((ccbh->flags & CAM_SG_LIST_PHYS) == 0) {
 2258                                 (*cb)(req, NULL, 0, EFAULT);
 2259                         } else {
 2260                                 /* Just use the segments provided */
 2261                                 segs = (struct bus_dma_segment *)csio->data_ptr;
 2262                                 (*cb)(req, segs, csio->sglist_cnt, 0);
 2263                         }
 2264                 }
 2265         } else {
 2266                 (*cb)(req, NULL, 0, 0);
 2267         }
 2268 }
 2269 
 2270 static int
 2271 mpt_bus_reset(struct mpt_softc *mpt, target_id_t tgt, lun_id_t lun,
 2272     int sleep_ok)
 2273 {
 2274         int   error;
 2275         uint16_t status;
 2276         uint8_t response;
 2277 
 2278         error = mpt_scsi_send_tmf(mpt,
 2279             (tgt != CAM_TARGET_WILDCARD || lun != CAM_LUN_WILDCARD) ?
 2280             MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET :
 2281             MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
 2282             mpt->is_fc ? MPI_SCSITASKMGMT_MSGFLAGS_LIP_RESET_OPTION : 0,
 2283             0,  /* XXX How do I get the channel ID? */
 2284             tgt != CAM_TARGET_WILDCARD ? tgt : 0,
 2285             lun != CAM_LUN_WILDCARD ? lun : 0,
 2286             0, sleep_ok);
 2287 
 2288         if (error != 0) {
 2289                 /*
 2290                  * mpt_scsi_send_tmf hard resets on failure, so no
 2291                  * need to do so here.
 2292                  */
 2293                 mpt_prt(mpt,
 2294                     "mpt_bus_reset: mpt_scsi_send_tmf returned %d\n", error);
 2295                 return (EIO);
 2296         }
 2297 
 2298         /* Wait for bus reset to be processed by the IOC. */
 2299         error = mpt_wait_req(mpt, mpt->tmf_req, REQ_STATE_DONE,
 2300             REQ_STATE_DONE, sleep_ok, 5000);
 2301 
 2302         status = le16toh(mpt->tmf_req->IOCStatus);
 2303         response = mpt->tmf_req->ResponseCode;
 2304         mpt->tmf_req->state = REQ_STATE_FREE;
 2305 
 2306         if (error) {
 2307                 mpt_prt(mpt, "mpt_bus_reset: Reset timed-out. "
 2308                     "Resetting controller.\n");
 2309                 mpt_reset(mpt, TRUE);
 2310                 return (ETIMEDOUT);
 2311         }
 2312 
 2313         if ((status & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
 2314                 mpt_prt(mpt, "mpt_bus_reset: TMF IOC Status 0x%x. "
 2315                     "Resetting controller.\n", status);
 2316                 mpt_reset(mpt, TRUE);
 2317                 return (EIO);
 2318         }
 2319 
 2320         if (response != MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED &&
 2321             response != MPI_SCSITASKMGMT_RSP_TM_COMPLETE) {
 2322                 mpt_prt(mpt, "mpt_bus_reset: TMF Response 0x%x. "
 2323                     "Resetting controller.\n", response);
 2324                 mpt_reset(mpt, TRUE);
 2325                 return (EIO);
 2326         }
 2327         return (0);
 2328 }
 2329 
 2330 static int
 2331 mpt_fc_reset_link(struct mpt_softc *mpt, int dowait)
 2332 {
 2333         int r = 0;
 2334         request_t *req;
 2335         PTR_MSG_FC_PRIMITIVE_SEND_REQUEST fc;
 2336 
 2337         req = mpt_get_request(mpt, FALSE);
 2338         if (req == NULL) {
 2339                 return (ENOMEM);
 2340         }
 2341         fc = req->req_vbuf;
 2342         memset(fc, 0, sizeof(*fc));
 2343         fc->SendFlags = MPI_FC_PRIM_SEND_FLAGS_RESET_LINK;
 2344         fc->Function = MPI_FUNCTION_FC_PRIMITIVE_SEND;
 2345         fc->MsgContext = htole32(req->index | fc_els_handler_id);
 2346         mpt_send_cmd(mpt, req);
 2347         if (dowait) {
 2348                 r = mpt_wait_req(mpt, req, REQ_STATE_DONE,
 2349                     REQ_STATE_DONE, FALSE, 60 * 1000);
 2350                 if (r == 0) {
 2351                         mpt_free_request(mpt, req);
 2352                 }
 2353         }
 2354         return (r);
 2355 }
 2356 
 2357 static int
 2358 mpt_cam_event(struct mpt_softc *mpt, request_t *req,
 2359               MSG_EVENT_NOTIFY_REPLY *msg)
 2360 {
 2361         uint32_t data0, data1;
 2362 
 2363         data0 = le32toh(msg->Data[0]);
 2364         data1 = le32toh(msg->Data[1]);
 2365         switch(msg->Event & 0xFF) {
 2366         case MPI_EVENT_UNIT_ATTENTION:
 2367                 mpt_prt(mpt, "UNIT ATTENTION: Bus: 0x%02x TargetID: 0x%02x\n",
 2368                     (data0 >> 8) & 0xff, data0 & 0xff);
 2369                 break;
 2370 
 2371         case MPI_EVENT_IOC_BUS_RESET:
 2372                 /* We generated a bus reset */
 2373                 mpt_prt(mpt, "IOC Generated Bus Reset Port: %d\n",
 2374                     (data0 >> 8) & 0xff);
 2375                 xpt_async(AC_BUS_RESET, mpt->path, NULL);
 2376                 break;
 2377 
 2378         case MPI_EVENT_EXT_BUS_RESET:
 2379                 /* Someone else generated a bus reset */
 2380                 mpt_prt(mpt, "External Bus Reset Detected\n");
 2381                 /*
 2382                  * These replies don't return EventData like the MPI
 2383                  * spec says they do
 2384                  */     
 2385                 xpt_async(AC_BUS_RESET, mpt->path, NULL);
 2386                 break;
 2387 
 2388         case MPI_EVENT_RESCAN:
 2389 #if __FreeBSD_version >= 600000
 2390         {
 2391                 union ccb *ccb;
 2392                 uint32_t pathid;
 2393                 /*
 2394                  * In general this means a device has been added to the loop.
 2395                  */
 2396                 mpt_prt(mpt, "Rescan Port: %d\n", (data0 >> 8) & 0xff);
 2397                 if (mpt->ready == 0) {
 2398                         break;
 2399                 }
 2400                 if (mpt->phydisk_sim) {
 2401                         pathid = cam_sim_path(mpt->phydisk_sim);
 2402                 } else {
 2403                         pathid = cam_sim_path(mpt->sim);
 2404                 }
 2405                 /*
 2406                  * Allocate a CCB, create a wildcard path for this bus,
 2407                  * and schedule a rescan.
 2408                  */
 2409                 ccb = xpt_alloc_ccb_nowait();
 2410                 if (ccb == NULL) {
 2411                         mpt_prt(mpt, "unable to alloc CCB for rescan\n");
 2412                         break;
 2413                 }
 2414 
 2415                 if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, pathid,
 2416                     CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
 2417                         mpt_prt(mpt, "unable to create path for rescan\n");
 2418                         xpt_free_ccb(ccb);
 2419                         break;
 2420                 }
 2421                 xpt_rescan(ccb);
 2422                 break;
 2423         }
 2424 #else
 2425                 mpt_prt(mpt, "Rescan Port: %d\n", (data0 >> 8) & 0xff);
 2426                 break;
 2427 #endif
 2428         case MPI_EVENT_LINK_STATUS_CHANGE:
 2429                 mpt_prt(mpt, "Port %d: LinkState: %s\n",
 2430                     (data1 >> 8) & 0xff,
 2431                     ((data0 & 0xff) == 0)?  "Failed" : "Active");
 2432                 break;
 2433 
 2434         case MPI_EVENT_LOOP_STATE_CHANGE:
 2435                 switch ((data0 >> 16) & 0xff) {
 2436                 case 0x01:
 2437                         mpt_prt(mpt,
 2438                             "Port 0x%x: FC LinkEvent: LIP(%02x,%02x) "
 2439                             "(Loop Initialization)\n",
 2440                             (data1 >> 8) & 0xff,
 2441                             (data0 >> 8) & 0xff,
 2442                             (data0     ) & 0xff);
 2443                         switch ((data0 >> 8) & 0xff) {
 2444                         case 0xF7:
 2445                                 if ((data0 & 0xff) == 0xF7) {
 2446                                         mpt_prt(mpt, "Device needs AL_PA\n");
 2447                                 } else {
 2448                                         mpt_prt(mpt, "Device %02x doesn't like "
 2449                                             "FC performance\n",
 2450                                             data0 & 0xFF);
 2451                                 }
 2452                                 break;
 2453                         case 0xF8:
 2454                                 if ((data0 & 0xff) == 0xF7) {
 2455                                         mpt_prt(mpt, "Device had loop failure "
 2456                                             "at its receiver prior to acquiring"
 2457                                             " AL_PA\n");
 2458                                 } else {
 2459                                         mpt_prt(mpt, "Device %02x detected loop"
 2460                                             " failure at its receiver\n", 
 2461                                             data0 & 0xFF);
 2462                                 }
 2463                                 break;
 2464                         default:
 2465                                 mpt_prt(mpt, "Device %02x requests that device "
 2466                                     "%02x reset itself\n", 
 2467                                     data0 & 0xFF,
 2468                                     (data0 >> 8) & 0xFF);
 2469                                 break;
 2470                         }
 2471                         break;
 2472                 case 0x02:
 2473                         mpt_prt(mpt, "Port 0x%x: FC LinkEvent: "
 2474                             "LPE(%02x,%02x) (Loop Port Enable)\n",
 2475                             (data1 >> 8) & 0xff, /* Port */
 2476                             (data0 >>  8) & 0xff, /* Character 3 */
 2477                             (data0      ) & 0xff  /* Character 4 */);
 2478                         break;
 2479                 case 0x03:
 2480                         mpt_prt(mpt, "Port 0x%x: FC LinkEvent: "
 2481                             "LPB(%02x,%02x) (Loop Port Bypass)\n",
 2482                             (data1 >> 8) & 0xff, /* Port */
 2483                             (data0 >> 8) & 0xff, /* Character 3 */
 2484                             (data0     ) & 0xff  /* Character 4 */);
 2485                         break;
 2486                 default:
 2487                         mpt_prt(mpt, "Port 0x%x: FC LinkEvent: Unknown "
 2488                             "FC event (%02x %02x %02x)\n",
 2489                             (data1 >> 8) & 0xff, /* Port */
 2490                             (data0 >> 16) & 0xff, /* Event */
 2491                             (data0 >>  8) & 0xff, /* Character 3 */
 2492                             (data0      ) & 0xff  /* Character 4 */);
 2493                 }
 2494                 break;
 2495 
 2496         case MPI_EVENT_LOGOUT:
 2497                 mpt_prt(mpt, "FC Logout Port: %d N_PortID: %02x\n",
 2498                     (data1 >> 8) & 0xff, data0);
 2499                 break;
 2500         case MPI_EVENT_QUEUE_FULL:
 2501         {
 2502                 struct cam_sim *sim;
 2503                 struct cam_path *tmppath;
 2504                 struct ccb_relsim crs;
 2505                 PTR_EVENT_DATA_QUEUE_FULL pqf;
 2506                 lun_id_t lun_id;
 2507 
 2508                 pqf = (PTR_EVENT_DATA_QUEUE_FULL)msg->Data;
 2509                 pqf->CurrentDepth = le16toh(pqf->CurrentDepth);
 2510                 mpt_prt(mpt, "QUEUE FULL EVENT: Bus 0x%02x Target 0x%02x Depth "
 2511                     "%d\n", pqf->Bus, pqf->TargetID, pqf->CurrentDepth);
 2512                 if (mpt->phydisk_sim && mpt_is_raid_member(mpt,
 2513                     pqf->TargetID) != 0) {
 2514                         sim = mpt->phydisk_sim;
 2515                 } else {
 2516                         sim = mpt->sim;
 2517                 }
 2518                 for (lun_id = 0; lun_id < MPT_MAX_LUNS; lun_id++) {
 2519                         if (xpt_create_path(&tmppath, NULL, cam_sim_path(sim),
 2520                             pqf->TargetID, lun_id) != CAM_REQ_CMP) {
 2521                                 mpt_prt(mpt, "unable to create a path to send "
 2522                                     "XPT_REL_SIMQ");
 2523                                 break;
 2524                         }
 2525                         xpt_setup_ccb(&crs.ccb_h, tmppath, 5);
 2526                         crs.ccb_h.func_code = XPT_REL_SIMQ;
 2527                         crs.ccb_h.flags = CAM_DEV_QFREEZE;
 2528                         crs.release_flags = RELSIM_ADJUST_OPENINGS;
 2529                         crs.openings = pqf->CurrentDepth - 1;
 2530                         xpt_action((union ccb *)&crs);
 2531                         if (crs.ccb_h.status != CAM_REQ_CMP) {
 2532                                 mpt_prt(mpt, "XPT_REL_SIMQ failed\n");
 2533                         }
 2534                         xpt_free_path(tmppath);
 2535                 }
 2536                 break;
 2537         }
 2538         case MPI_EVENT_IR_RESYNC_UPDATE:
 2539                 mpt_prt(mpt, "IR resync update %d completed\n",
 2540                     (data0 >> 16) & 0xff);
 2541                 break;
 2542         case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
 2543         {
 2544                 union ccb *ccb;
 2545                 struct cam_sim *sim;
 2546                 struct cam_path *tmppath;
 2547                 PTR_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE psdsc;
 2548 
 2549                 psdsc = (PTR_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE)msg->Data;
 2550                 if (mpt->phydisk_sim && mpt_is_raid_member(mpt,
 2551                     psdsc->TargetID) != 0)
 2552                         sim = mpt->phydisk_sim;
 2553                 else
 2554                         sim = mpt->sim;
 2555                 switch(psdsc->ReasonCode) {
 2556                 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
 2557                         ccb = xpt_alloc_ccb_nowait();
 2558                         if (ccb == NULL) {
 2559                                 mpt_prt(mpt,
 2560                                     "unable to alloc CCB for rescan\n");
 2561                                 break;
 2562                         }
 2563                         if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
 2564                             cam_sim_path(sim), psdsc->TargetID,
 2565                             CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
 2566                                 mpt_prt(mpt,
 2567                                     "unable to create path for rescan\n");
 2568                                 xpt_free_ccb(ccb);
 2569                                 break;
 2570                         }
 2571                         xpt_rescan(ccb);
 2572                         break;
 2573                 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
 2574                         if (xpt_create_path(&tmppath, NULL, cam_sim_path(sim),
 2575                             psdsc->TargetID, CAM_LUN_WILDCARD) !=
 2576                             CAM_REQ_CMP) {
 2577                                 mpt_prt(mpt,
 2578                                     "unable to create path for async event");
 2579                                 break;
 2580                         }
 2581                         xpt_async(AC_LOST_DEVICE, tmppath, NULL);
 2582                         xpt_free_path(tmppath);
 2583                         break;
 2584                 case MPI_EVENT_SAS_DEV_STAT_RC_CMPL_INTERNAL_DEV_RESET:
 2585                 case MPI_EVENT_SAS_DEV_STAT_RC_CMPL_TASK_ABORT_INTERNAL:
 2586                 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
 2587                         break;
 2588                 default:
 2589                         mpt_lprt(mpt, MPT_PRT_WARN,
 2590                             "SAS device status change: Bus: 0x%02x TargetID: "
 2591                             "0x%02x ReasonCode: 0x%02x\n", psdsc->Bus,
 2592                             psdsc->TargetID, psdsc->ReasonCode);
 2593                         break;
 2594                 }
 2595                 break;
 2596         }
 2597         case MPI_EVENT_SAS_DISCOVERY_ERROR:
 2598         {
 2599                 PTR_EVENT_DATA_DISCOVERY_ERROR pde;
 2600 
 2601                 pde = (PTR_EVENT_DATA_DISCOVERY_ERROR)msg->Data;
 2602                 pde->DiscoveryStatus = le32toh(pde->DiscoveryStatus);
 2603                 mpt_lprt(mpt, MPT_PRT_WARN,
 2604                     "SAS discovery error: Port: 0x%02x Status: 0x%08x\n",
 2605                     pde->Port, pde->DiscoveryStatus);
 2606                 break;
 2607         }
 2608         case MPI_EVENT_EVENT_CHANGE:
 2609         case MPI_EVENT_INTEGRATED_RAID:
 2610         case MPI_EVENT_IR2:
 2611         case MPI_EVENT_LOG_ENTRY_ADDED:
 2612         case MPI_EVENT_SAS_DISCOVERY:
 2613         case MPI_EVENT_SAS_PHY_LINK_STATUS:
 2614         case MPI_EVENT_SAS_SES:
 2615                 break;
 2616         default:
 2617                 mpt_lprt(mpt, MPT_PRT_WARN, "mpt_cam_event: 0x%x\n",
 2618                     msg->Event & 0xFF);
 2619                 return (0);
 2620         }
 2621         return (1);
 2622 }
 2623 
 2624 /*
 2625  * Reply path for all SCSI I/O requests, called from our
 2626  * interrupt handler by extracting our handler index from
 2627  * the MsgContext field of the reply from the IOC.
 2628  *
 2629  * This routine is optimized for the common case of a
 2630  * completion without error.  All exception handling is
 2631  * offloaded to non-inlined helper routines to minimize
 2632  * cache footprint.
 2633  */
 2634 static int
 2635 mpt_scsi_reply_handler(struct mpt_softc *mpt, request_t *req,
 2636     uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame)
 2637 {
 2638         MSG_SCSI_IO_REQUEST *scsi_req;
 2639         union ccb *ccb;
 2640 
 2641         if (req->state == REQ_STATE_FREE) {
 2642                 mpt_prt(mpt, "mpt_scsi_reply_handler: req already free\n");
 2643                 return (TRUE);
 2644         }
 2645 
 2646         scsi_req = (MSG_SCSI_IO_REQUEST *)req->req_vbuf;
 2647         ccb = req->ccb;
 2648         if (ccb == NULL) {
 2649                 mpt_prt(mpt, "mpt_scsi_reply_handler: req %p:%u with no ccb\n",
 2650                     req, req->serno);
 2651                 return (TRUE);
 2652         }
 2653 
 2654         mpt_req_untimeout(req, mpt_timeout, ccb);
 2655         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 2656 
 2657         if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
 2658                 bus_dmasync_op_t op;
 2659 
 2660                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
 2661                         op = BUS_DMASYNC_POSTREAD;
 2662                 else
 2663                         op = BUS_DMASYNC_POSTWRITE;
 2664                 bus_dmamap_sync(mpt->buffer_dmat, req->dmap, op);
 2665                 bus_dmamap_unload(mpt->buffer_dmat, req->dmap);
 2666         }
 2667 
 2668         if (reply_frame == NULL) {
 2669                 /*
 2670                  * Context only reply, completion without error status.
 2671                  */
 2672                 ccb->csio.resid = 0;
 2673                 mpt_set_ccb_status(ccb, CAM_REQ_CMP);
 2674                 ccb->csio.scsi_status = SCSI_STATUS_OK;
 2675         } else {
 2676                 mpt_scsi_reply_frame_handler(mpt, req, reply_frame);
 2677         }
 2678 
 2679         if (mpt->outofbeer) {
 2680                 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
 2681                 mpt->outofbeer = 0;
 2682                 mpt_lprt(mpt, MPT_PRT_DEBUG, "THAWQ\n");
 2683         }
 2684         if (scsi_req->CDB[0] == INQUIRY && (scsi_req->CDB[1] & SI_EVPD) == 0) {
 2685                 struct scsi_inquiry_data *iq = 
 2686                     (struct scsi_inquiry_data *)ccb->csio.data_ptr;
 2687                 if (scsi_req->Function ==
 2688                     MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
 2689                         /*
 2690                          * Fake out the device type so that only the
 2691                          * pass-thru device will attach.
 2692                          */
 2693                         iq->device &= ~0x1F;
 2694                         iq->device |= T_NODEVICE;
 2695                 }
 2696         }
 2697         if (mpt->verbose == MPT_PRT_DEBUG) {
 2698                 mpt_prt(mpt, "mpt_scsi_reply_handler: %p:%u complete\n",
 2699                     req, req->serno);
 2700         }
 2701         KASSERT(ccb->ccb_h.status, ("zero ccb sts at %d", __LINE__));
 2702         xpt_done(ccb);
 2703         if ((req->state & REQ_STATE_TIMEDOUT) == 0) {
 2704                 TAILQ_REMOVE(&mpt->request_pending_list, req, links);
 2705         } else {
 2706                 mpt_prt(mpt, "completing timedout/aborted req %p:%u\n",
 2707                     req, req->serno);
 2708                 TAILQ_REMOVE(&mpt->request_timeout_list, req, links);
 2709         }
 2710         KASSERT((req->state & REQ_STATE_NEED_WAKEUP) == 0,
 2711             ("CCB req needed wakeup"));
 2712 #ifdef  INVARIANTS
 2713         mpt_req_not_spcl(mpt, req, "mpt_scsi_reply_handler", __LINE__);
 2714 #endif
 2715         mpt_free_request(mpt, req);
 2716         return (TRUE);
 2717 }
 2718 
 2719 static int
 2720 mpt_scsi_tmf_reply_handler(struct mpt_softc *mpt, request_t *req,
 2721     uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame)
 2722 {
 2723         MSG_SCSI_TASK_MGMT_REPLY *tmf_reply;
 2724 
 2725         KASSERT(req == mpt->tmf_req, ("TMF Reply not using mpt->tmf_req"));
 2726 #ifdef  INVARIANTS
 2727         mpt_req_not_spcl(mpt, req, "mpt_scsi_tmf_reply_handler", __LINE__);
 2728 #endif
 2729         tmf_reply = (MSG_SCSI_TASK_MGMT_REPLY *)reply_frame;
 2730         /* Record IOC Status and Response Code of TMF for any waiters. */
 2731         req->IOCStatus = le16toh(tmf_reply->IOCStatus);
 2732         req->ResponseCode = tmf_reply->ResponseCode;
 2733 
 2734         mpt_lprt(mpt, MPT_PRT_DEBUG, "TMF complete: req %p:%u status 0x%x\n",
 2735             req, req->serno, le16toh(tmf_reply->IOCStatus));
 2736         TAILQ_REMOVE(&mpt->request_pending_list, req, links);
 2737         if ((req->state & REQ_STATE_NEED_WAKEUP) != 0) {
 2738                 req->state |= REQ_STATE_DONE;
 2739                 wakeup(req);
 2740         } else {
 2741                 mpt->tmf_req->state = REQ_STATE_FREE;
 2742         }
 2743         return (TRUE);
 2744 }
 2745 
 2746 /*
 2747  * XXX: Move to definitions file
 2748  */
 2749 #define ELS     0x22
 2750 #define FC4LS   0x32
 2751 #define ABTS    0x81
 2752 #define BA_ACC  0x84
 2753 
 2754 #define LS_RJT  0x01 
 2755 #define LS_ACC  0x02
 2756 #define PLOGI   0x03
 2757 #define LOGO    0x05
 2758 #define SRR     0x14
 2759 #define PRLI    0x20
 2760 #define PRLO    0x21
 2761 #define ADISC   0x52
 2762 #define RSCN    0x61
 2763 
 2764 static void
 2765 mpt_fc_els_send_response(struct mpt_softc *mpt, request_t *req,
 2766     PTR_MSG_LINK_SERVICE_BUFFER_POST_REPLY rp, U8 length)
 2767 {
 2768         uint32_t fl;
 2769         MSG_LINK_SERVICE_RSP_REQUEST tmp;
 2770         PTR_MSG_LINK_SERVICE_RSP_REQUEST rsp;
 2771 
 2772         /*
 2773          * We are going to reuse the ELS request to send this response back.
 2774          */
 2775         rsp = &tmp;
 2776         memset(rsp, 0, sizeof(*rsp));
 2777 
 2778 #ifdef  USE_IMMEDIATE_LINK_DATA
 2779         /*
 2780          * Apparently the IMMEDIATE stuff doesn't seem to work.
 2781          */
 2782         rsp->RspFlags = LINK_SERVICE_RSP_FLAGS_IMMEDIATE;
 2783 #endif
 2784         rsp->RspLength = length;
 2785         rsp->Function = MPI_FUNCTION_FC_LINK_SRVC_RSP;
 2786         rsp->MsgContext = htole32(req->index | fc_els_handler_id);
 2787 
 2788         /*
 2789          * Copy over information from the original reply frame to
 2790          * it's correct place in the response.
 2791          */
 2792         memcpy((U8 *)rsp + 0x0c, (U8 *)rp + 0x1c, 24);
 2793 
 2794         /*
 2795          * And now copy back the temporary area to the original frame.
 2796          */
 2797         memcpy(req->req_vbuf, rsp, sizeof (MSG_LINK_SERVICE_RSP_REQUEST));
 2798         rsp = req->req_vbuf;
 2799 
 2800 #ifdef  USE_IMMEDIATE_LINK_DATA
 2801         memcpy((U8 *)&rsp->SGL, &((U8 *)req->req_vbuf)[MPT_RQSL(mpt)], length);
 2802 #else
 2803 {
 2804         PTR_SGE_SIMPLE32 se = (PTR_SGE_SIMPLE32) &rsp->SGL;
 2805         bus_addr_t paddr = req->req_pbuf;
 2806         paddr += MPT_RQSL(mpt);
 2807 
 2808         fl =
 2809                 MPI_SGE_FLAGS_HOST_TO_IOC       |
 2810                 MPI_SGE_FLAGS_SIMPLE_ELEMENT    |
 2811                 MPI_SGE_FLAGS_LAST_ELEMENT      |
 2812                 MPI_SGE_FLAGS_END_OF_LIST       |
 2813                 MPI_SGE_FLAGS_END_OF_BUFFER;
 2814         fl <<= MPI_SGE_FLAGS_SHIFT;
 2815         fl |= (length);
 2816         se->FlagsLength = htole32(fl);
 2817         se->Address = htole32((uint32_t) paddr);
 2818 }
 2819 #endif
 2820 
 2821         /*
 2822          * Send it on...
 2823          */
 2824         mpt_send_cmd(mpt, req);
 2825 }
 2826 
 2827 static int
 2828 mpt_fc_els_reply_handler(struct mpt_softc *mpt, request_t *req,
 2829     uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame)
 2830 {
 2831         PTR_MSG_LINK_SERVICE_BUFFER_POST_REPLY rp =
 2832             (PTR_MSG_LINK_SERVICE_BUFFER_POST_REPLY) reply_frame;
 2833         U8 rctl;
 2834         U8 type;
 2835         U8 cmd;
 2836         U16 status = le16toh(reply_frame->IOCStatus);
 2837         U32 *elsbuf;
 2838         int ioindex;
 2839         int do_refresh = TRUE;
 2840 
 2841 #ifdef  INVARIANTS
 2842         KASSERT(mpt_req_on_free_list(mpt, req) == 0,
 2843             ("fc_els_reply_handler: req %p:%u for function %x on freelist!",
 2844             req, req->serno, rp->Function));
 2845         if (rp->Function != MPI_FUNCTION_FC_PRIMITIVE_SEND) {
 2846                 mpt_req_spcl(mpt, req, "fc_els_reply_handler", __LINE__);
 2847         } else {
 2848                 mpt_req_not_spcl(mpt, req, "fc_els_reply_handler", __LINE__);
 2849         }
 2850 #endif
 2851         mpt_lprt(mpt, MPT_PRT_DEBUG,
 2852             "FC_ELS Complete: req %p:%u, reply %p function %x\n",
 2853             req, req->serno, reply_frame, reply_frame->Function);
 2854 
 2855         if  (status != MPI_IOCSTATUS_SUCCESS) {
 2856                 mpt_prt(mpt, "ELS REPLY STATUS 0x%x for Function %x\n",
 2857                     status, reply_frame->Function);
 2858                 if (status == MPI_IOCSTATUS_INVALID_STATE) {
 2859                         /*
 2860                          * XXX: to get around shutdown issue
 2861                          */
 2862                         mpt->disabled = 1;
 2863                         return (TRUE);
 2864                 }
 2865                 return (TRUE);
 2866         }
 2867 
 2868         /*
 2869          * If the function of a link service response, we recycle the
 2870          * response to be a refresh for a new link service request.
 2871          *
 2872          * The request pointer is bogus in this case and we have to fetch
 2873          * it based upon the TransactionContext.
 2874          */
 2875         if (rp->Function == MPI_FUNCTION_FC_LINK_SRVC_RSP) {
 2876                 /* Freddie Uncle Charlie Katie */
 2877                 /* We don't get the IOINDEX as part of the Link Svc Rsp */
 2878                 for (ioindex = 0; ioindex < mpt->els_cmds_allocated; ioindex++)
 2879                         if (mpt->els_cmd_ptrs[ioindex] == req) {
 2880                                 break;
 2881                         }
 2882 
 2883                 KASSERT(ioindex < mpt->els_cmds_allocated,
 2884                     ("can't find my mommie!"));
 2885 
 2886                 /* remove from active list as we're going to re-post it */
 2887                 TAILQ_REMOVE(&mpt->request_pending_list, req, links);
 2888                 req->state &= ~REQ_STATE_QUEUED;
 2889                 req->state |= REQ_STATE_DONE;
 2890                 mpt_fc_post_els(mpt, req, ioindex);
 2891                 return (TRUE);
 2892         }
 2893 
 2894         if (rp->Function == MPI_FUNCTION_FC_PRIMITIVE_SEND) {
 2895                 /* remove from active list as we're done */
 2896                 TAILQ_REMOVE(&mpt->request_pending_list, req, links);
 2897                 req->state &= ~REQ_STATE_QUEUED;
 2898                 req->state |= REQ_STATE_DONE;
 2899                 if (req->state & REQ_STATE_TIMEDOUT) {
 2900                         mpt_lprt(mpt, MPT_PRT_DEBUG,
 2901                             "Sync Primitive Send Completed After Timeout\n");
 2902                         mpt_free_request(mpt, req);
 2903                 } else if ((req->state & REQ_STATE_NEED_WAKEUP) == 0) {
 2904                         mpt_lprt(mpt, MPT_PRT_DEBUG,
 2905                             "Async Primitive Send Complete\n");
 2906                         mpt_free_request(mpt, req);
 2907                 } else {
 2908                         mpt_lprt(mpt, MPT_PRT_DEBUG,
 2909                             "Sync Primitive Send Complete- Waking Waiter\n");
 2910                         wakeup(req);
 2911                 }
 2912                 return (TRUE);
 2913         }
 2914 
 2915         if (rp->Function != MPI_FUNCTION_FC_LINK_SRVC_BUF_POST) {
 2916                 mpt_prt(mpt, "unexpected ELS_REPLY: Function 0x%x Flags %x "
 2917                     "Length %d Message Flags %x\n", rp->Function, rp->Flags,
 2918                     rp->MsgLength, rp->MsgFlags);
 2919                 return (TRUE);
 2920         }
 2921 
 2922         if (rp->MsgLength <= 5) {
 2923                 /*
 2924                  * This is just a ack of an original ELS buffer post
 2925                  */
 2926                 mpt_lprt(mpt, MPT_PRT_DEBUG,
 2927                     "RECV'd ACK of FC_ELS buf post %p:%u\n", req, req->serno);
 2928                 return (TRUE);
 2929         }
 2930 
 2931 
 2932         rctl = (le32toh(rp->Rctl_Did) & MPI_FC_RCTL_MASK) >> MPI_FC_RCTL_SHIFT;
 2933         type = (le32toh(rp->Type_Fctl) & MPI_FC_TYPE_MASK) >> MPI_FC_TYPE_SHIFT;
 2934 
 2935         elsbuf = &((U32 *)req->req_vbuf)[MPT_RQSL(mpt)/sizeof (U32)];
 2936         cmd = be32toh(elsbuf[0]) >> 24;
 2937 
 2938         if (rp->Flags & MPI_LS_BUF_POST_REPLY_FLAG_NO_RSP_NEEDED) {
 2939                 mpt_lprt(mpt, MPT_PRT_ALWAYS, "ELS_REPLY: response unneeded\n");
 2940                 return (TRUE);
 2941         }
 2942 
 2943         ioindex = le32toh(rp->TransactionContext);
 2944         req = mpt->els_cmd_ptrs[ioindex];
 2945 
 2946         if (rctl == ELS && type == 1) {
 2947                 switch (cmd) {
 2948                 case PRLI:
 2949                         /*
 2950                          * Send back a PRLI ACC
 2951                          */
 2952                         mpt_prt(mpt, "PRLI from 0x%08x%08x\n",
 2953                             le32toh(rp->Wwn.PortNameHigh),
 2954                             le32toh(rp->Wwn.PortNameLow));
 2955                         elsbuf[0] = htobe32(0x02100014);
 2956                         elsbuf[1] |= htobe32(0x00000100);
 2957                         elsbuf[4] = htobe32(0x00000002);
 2958                         if (mpt->role & MPT_ROLE_TARGET)
 2959                                 elsbuf[4] |= htobe32(0x00000010);
 2960                         if (mpt->role & MPT_ROLE_INITIATOR)
 2961                                 elsbuf[4] |= htobe32(0x00000020);
 2962                         /* remove from active list as we're done */
 2963                         TAILQ_REMOVE(&mpt->request_pending_list, req, links);
 2964                         req->state &= ~REQ_STATE_QUEUED;
 2965                         req->state |= REQ_STATE_DONE;
 2966                         mpt_fc_els_send_response(mpt, req, rp, 20);
 2967                         do_refresh = FALSE;
 2968                         break;
 2969                 case PRLO:
 2970                         memset(elsbuf, 0, 5 * (sizeof (U32)));
 2971                         elsbuf[0] = htobe32(0x02100014);
 2972                         elsbuf[1] = htobe32(0x08000100);
 2973                         mpt_prt(mpt, "PRLO from 0x%08x%08x\n",
 2974                             le32toh(rp->Wwn.PortNameHigh),
 2975                             le32toh(rp->Wwn.PortNameLow));
 2976                         /* remove from active list as we're done */
 2977                         TAILQ_REMOVE(&mpt->request_pending_list, req, links);
 2978                         req->state &= ~REQ_STATE_QUEUED;
 2979                         req->state |= REQ_STATE_DONE;
 2980                         mpt_fc_els_send_response(mpt, req, rp, 20);
 2981                         do_refresh = FALSE;
 2982                         break;
 2983                 default:
 2984                         mpt_prt(mpt, "ELS TYPE 1 COMMAND: %x\n", cmd);
 2985                         break;
 2986                 }
 2987         } else if (rctl == ABTS && type == 0) {
 2988                 uint16_t rx_id = le16toh(rp->Rxid);
 2989                 uint16_t ox_id = le16toh(rp->Oxid);
 2990                 request_t *tgt_req = NULL;
 2991 
 2992                 mpt_prt(mpt,
 2993                     "ELS: ABTS OX_ID 0x%x RX_ID 0x%x from 0x%08x%08x\n",
 2994                     ox_id, rx_id, le32toh(rp->Wwn.PortNameHigh),
 2995                     le32toh(rp->Wwn.PortNameLow));
 2996                 if (rx_id >= mpt->mpt_max_tgtcmds) {
 2997                         mpt_prt(mpt, "Bad RX_ID 0x%x\n", rx_id);
 2998                 } else if (mpt->tgt_cmd_ptrs == NULL) {
 2999                         mpt_prt(mpt, "No TGT CMD PTRS\n");
 3000                 } else {
 3001                         tgt_req = mpt->tgt_cmd_ptrs[rx_id];
 3002                 }
 3003                 if (tgt_req) {
 3004                         mpt_tgt_state_t *tgt = MPT_TGT_STATE(mpt, tgt_req);
 3005                         union ccb *ccb;
 3006                         uint32_t ct_id;
 3007 
 3008                         /*
 3009                          * Check to make sure we have the correct command
 3010                          * The reply descriptor in the target state should
 3011                          * should contain an IoIndex that should match the
 3012                          * RX_ID.
 3013                          *
 3014                          * It'd be nice to have OX_ID to crosscheck with
 3015                          * as well.
 3016                          */
 3017                         ct_id = GET_IO_INDEX(tgt->reply_desc);
 3018 
 3019                         if (ct_id != rx_id) {
 3020                                 mpt_lprt(mpt, MPT_PRT_ERROR, "ABORT Mismatch: "
 3021                                     "RX_ID received=0x%x; RX_ID in cmd=0x%x\n",
 3022                                     rx_id, ct_id);
 3023                                 goto skip;
 3024                         }
 3025 
 3026                         ccb = tgt->ccb;
 3027                         if (ccb) {
 3028                                 mpt_prt(mpt,
 3029                                     "CCB (%p): lun %u flags %x status %x\n",
 3030                                     ccb, ccb->ccb_h.target_lun,
 3031                                     ccb->ccb_h.flags, ccb->ccb_h.status);
 3032                         }
 3033                         mpt_prt(mpt, "target state 0x%x resid %u xfrd %u rpwrd "
 3034                             "%x nxfers %x\n", tgt->state,
 3035                             tgt->resid, tgt->bytes_xfered, tgt->reply_desc,
 3036                             tgt->nxfers);
 3037   skip:
 3038                         if (mpt_abort_target_cmd(mpt, tgt_req)) {
 3039                                 mpt_prt(mpt, "unable to start TargetAbort\n");
 3040                         }
 3041                 } else {
 3042                         mpt_prt(mpt, "no back pointer for RX_ID 0x%x\n", rx_id);
 3043                 }
 3044                 memset(elsbuf, 0, 5 * (sizeof (U32)));
 3045                 elsbuf[0] = htobe32(0);
 3046                 elsbuf[1] = htobe32((ox_id << 16) | rx_id);
 3047                 elsbuf[2] = htobe32(0x000ffff);
 3048                 /*
 3049                  * Dork with the reply frame so that the response to it
 3050                  * will be correct.
 3051                  */
 3052                 rp->Rctl_Did += ((BA_ACC - ABTS) << MPI_FC_RCTL_SHIFT);
 3053                 /* remove from active list as we're done */
 3054                 TAILQ_REMOVE(&mpt->request_pending_list, req, links);
 3055                 req->state &= ~REQ_STATE_QUEUED;
 3056                 req->state |= REQ_STATE_DONE;
 3057                 mpt_fc_els_send_response(mpt, req, rp, 12);
 3058                 do_refresh = FALSE;
 3059         } else {
 3060                 mpt_prt(mpt, "ELS: RCTL %x TYPE %x CMD %x\n", rctl, type, cmd);
 3061         }
 3062         if (do_refresh == TRUE) {
 3063                 /* remove from active list as we're done */
 3064                 TAILQ_REMOVE(&mpt->request_pending_list, req, links);
 3065                 req->state &= ~REQ_STATE_QUEUED;
 3066                 req->state |= REQ_STATE_DONE;
 3067                 mpt_fc_post_els(mpt, req, ioindex);
 3068         }
 3069         return (TRUE);
 3070 }
 3071 
 3072 /*
 3073  * Clean up all SCSI Initiator personality state in response
 3074  * to a controller reset.
 3075  */
 3076 static void
 3077 mpt_cam_ioc_reset(struct mpt_softc *mpt, int type)
 3078 {
 3079 
 3080         /*
 3081          * The pending list is already run down by
 3082          * the generic handler.  Perform the same
 3083          * operation on the timed out request list.
 3084          */
 3085         mpt_complete_request_chain(mpt, &mpt->request_timeout_list,
 3086                                    MPI_IOCSTATUS_INVALID_STATE);
 3087 
 3088         /*
 3089          * XXX: We need to repost ELS and Target Command Buffers?
 3090          */
 3091 
 3092         /*
 3093          * Inform the XPT that a bus reset has occurred.
 3094          */
 3095         xpt_async(AC_BUS_RESET, mpt->path, NULL);
 3096 }
 3097 
 3098 /*
 3099  * Parse additional completion information in the reply
 3100  * frame for SCSI I/O requests.
 3101  */
 3102 static int
 3103 mpt_scsi_reply_frame_handler(struct mpt_softc *mpt, request_t *req,
 3104                              MSG_DEFAULT_REPLY *reply_frame)
 3105 {
 3106         union ccb *ccb;
 3107         MSG_SCSI_IO_REPLY *scsi_io_reply;
 3108         u_int ioc_status;
 3109         u_int sstate;
 3110 
 3111         MPT_DUMP_REPLY_FRAME(mpt, reply_frame);
 3112         KASSERT(reply_frame->Function == MPI_FUNCTION_SCSI_IO_REQUEST
 3113              || reply_frame->Function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH,
 3114                 ("MPT SCSI I/O Handler called with incorrect reply type"));
 3115         KASSERT((reply_frame->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) == 0,
 3116                 ("MPT SCSI I/O Handler called with continuation reply"));
 3117 
 3118         scsi_io_reply = (MSG_SCSI_IO_REPLY *)reply_frame;
 3119         ioc_status = le16toh(scsi_io_reply->IOCStatus);
 3120         ioc_status &= MPI_IOCSTATUS_MASK;
 3121         sstate = scsi_io_reply->SCSIState;
 3122 
 3123         ccb = req->ccb;
 3124         ccb->csio.resid =
 3125             ccb->csio.dxfer_len - le32toh(scsi_io_reply->TransferCount);
 3126 
 3127         if ((sstate & MPI_SCSI_STATE_AUTOSENSE_VALID) != 0
 3128          && (ccb->ccb_h.flags & (CAM_SENSE_PHYS | CAM_SENSE_PTR)) == 0) {
 3129                 ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
 3130                 ccb->csio.sense_resid =
 3131                     ccb->csio.sense_len - le32toh(scsi_io_reply->SenseCount);
 3132                 bzero(&ccb->csio.sense_data, sizeof(ccb->csio.sense_data));
 3133                 bcopy(req->sense_vbuf, &ccb->csio.sense_data,
 3134                     min(ccb->csio.sense_len,
 3135                     le32toh(scsi_io_reply->SenseCount)));
 3136         }
 3137 
 3138         if ((sstate & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) != 0) {
 3139                 /*
 3140                  * Tag messages rejected, but non-tagged retry
 3141                  * was successful.
 3142 XXXX
 3143                 mpt_set_tags(mpt, devinfo, MPT_QUEUE_NONE);
 3144                  */
 3145         }
 3146 
 3147         switch(ioc_status) {
 3148         case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
 3149                 /*
 3150                  * XXX
 3151                  * Linux driver indicates that a zero
 3152                  * transfer length with this error code
 3153                  * indicates a CRC error.
 3154                  *
 3155                  * No need to swap the bytes for checking
 3156                  * against zero.
 3157                  */
 3158                 if (scsi_io_reply->TransferCount == 0) {
 3159                         mpt_set_ccb_status(ccb, CAM_UNCOR_PARITY);
 3160                         break;
 3161                 }
 3162                 /* FALLTHROUGH */
 3163         case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:
 3164         case MPI_IOCSTATUS_SUCCESS:
 3165         case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:
 3166                 if ((sstate & MPI_SCSI_STATE_NO_SCSI_STATUS) != 0) {
 3167                         /*
 3168                          * Status was never returned for this transaction.
 3169                          */
 3170                         mpt_set_ccb_status(ccb, CAM_UNEXP_BUSFREE);
 3171                 } else if (scsi_io_reply->SCSIStatus != SCSI_STATUS_OK) {
 3172                         ccb->csio.scsi_status = scsi_io_reply->SCSIStatus;
 3173                         mpt_set_ccb_status(ccb, CAM_SCSI_STATUS_ERROR);
 3174                         if ((sstate & MPI_SCSI_STATE_AUTOSENSE_FAILED) != 0)
 3175                                 mpt_set_ccb_status(ccb, CAM_AUTOSENSE_FAIL);
 3176                 } else if ((sstate & MPI_SCSI_STATE_RESPONSE_INFO_VALID) != 0) {
 3177 
 3178                         /* XXX Handle SPI-Packet and FCP-2 response info. */
 3179                         mpt_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
 3180                 } else
 3181                         mpt_set_ccb_status(ccb, CAM_REQ_CMP);
 3182                 break;
 3183         case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:
 3184                 mpt_set_ccb_status(ccb, CAM_DATA_RUN_ERR);
 3185                 break;
 3186         case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:
 3187                 mpt_set_ccb_status(ccb, CAM_UNCOR_PARITY);
 3188                 break;
 3189         case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
 3190                 /*
 3191                  * Since selection timeouts and "device really not
 3192                  * there" are grouped into this error code, report
 3193                  * selection timeout.  Selection timeouts are
 3194                  * typically retried before giving up on the device
 3195                  * whereas "device not there" errors are considered
 3196                  * unretryable.
 3197                  */
 3198                 mpt_set_ccb_status(ccb, CAM_SEL_TIMEOUT);
 3199                 break;
 3200         case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:
 3201                 mpt_set_ccb_status(ccb, CAM_SEQUENCE_FAIL);
 3202                 break;
 3203         case MPI_IOCSTATUS_SCSI_INVALID_BUS:
 3204                 mpt_set_ccb_status(ccb, CAM_PATH_INVALID);
 3205                 break;
 3206         case MPI_IOCSTATUS_SCSI_INVALID_TARGETID:
 3207                 mpt_set_ccb_status(ccb, CAM_TID_INVALID);
 3208                 break;
 3209         case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
 3210                 ccb->ccb_h.status = CAM_UA_TERMIO;
 3211                 break;
 3212         case MPI_IOCSTATUS_INVALID_STATE:
 3213                 /*
 3214                  * The IOC has been reset.  Emulate a bus reset.
 3215                  */
 3216                 /* FALLTHROUGH */
 3217         case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:
 3218                 ccb->ccb_h.status = CAM_SCSI_BUS_RESET; 
 3219                 break;
 3220         case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:
 3221         case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:
 3222                 /*
 3223                  * Don't clobber any timeout status that has
 3224                  * already been set for this transaction.  We
 3225                  * want the SCSI layer to be able to differentiate
 3226                  * between the command we aborted due to timeout
 3227                  * and any innocent bystanders.
 3228                  */
 3229                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG)
 3230                         break;
 3231                 mpt_set_ccb_status(ccb, CAM_REQ_TERMIO);
 3232                 break;
 3233 
 3234         case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:
 3235                 mpt_set_ccb_status(ccb, CAM_RESRC_UNAVAIL);
 3236                 break;
 3237         case MPI_IOCSTATUS_BUSY:
 3238                 mpt_set_ccb_status(ccb, CAM_BUSY);
 3239                 break;
 3240         case MPI_IOCSTATUS_INVALID_FUNCTION:
 3241         case MPI_IOCSTATUS_INVALID_SGL:
 3242         case MPI_IOCSTATUS_INTERNAL_ERROR:
 3243         case MPI_IOCSTATUS_INVALID_FIELD:
 3244         default:
 3245                 /* XXX
 3246                  * Some of the above may need to kick
 3247                  * of a recovery action!!!!
 3248                  */
 3249                 ccb->ccb_h.status = CAM_UNREC_HBA_ERROR;
 3250                 break;
 3251         }
 3252 
 3253         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 3254                 mpt_freeze_ccb(ccb);
 3255         }
 3256 
 3257         return (TRUE);
 3258 }
 3259 
 3260 static void
 3261 mpt_action(struct cam_sim *sim, union ccb *ccb)
 3262 {
 3263         struct mpt_softc *mpt;
 3264         struct ccb_trans_settings *cts;
 3265         target_id_t tgt;
 3266         lun_id_t lun;
 3267         int raid_passthru;
 3268 
 3269         CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("mpt_action\n"));
 3270 
 3271         mpt = (struct mpt_softc *)cam_sim_softc(sim);
 3272         raid_passthru = (sim == mpt->phydisk_sim);
 3273         MPT_LOCK_ASSERT(mpt);
 3274 
 3275         tgt = ccb->ccb_h.target_id;
 3276         lun = ccb->ccb_h.target_lun;
 3277         if (raid_passthru &&
 3278             ccb->ccb_h.func_code != XPT_PATH_INQ &&
 3279             ccb->ccb_h.func_code != XPT_RESET_BUS &&
 3280             ccb->ccb_h.func_code != XPT_RESET_DEV) {
 3281                 if (mpt_map_physdisk(mpt, ccb, &tgt) != 0) {
 3282                         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 3283                         mpt_set_ccb_status(ccb, CAM_DEV_NOT_THERE);
 3284                         xpt_done(ccb);
 3285                         return;
 3286                 }
 3287         }
 3288         ccb->ccb_h.ccb_mpt_ptr = mpt;
 3289 
 3290         switch (ccb->ccb_h.func_code) {
 3291         case XPT_SCSI_IO:       /* Execute the requested I/O operation */
 3292                 /*
 3293                  * Do a couple of preliminary checks...
 3294                  */
 3295                 if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
 3296                         if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) {
 3297                                 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 3298                                 mpt_set_ccb_status(ccb, CAM_REQ_INVALID);
 3299                                 break;
 3300                         }
 3301                 }
 3302                 /* Max supported CDB length is 16 bytes */
 3303                 /* XXX Unless we implement the new 32byte message type */
 3304                 if (ccb->csio.cdb_len >
 3305                     sizeof (((PTR_MSG_SCSI_IO_REQUEST)0)->CDB)) {
 3306                         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 3307                         mpt_set_ccb_status(ccb, CAM_REQ_INVALID);
 3308                         break;
 3309                 }
 3310 #ifdef  MPT_TEST_MULTIPATH
 3311                 if (mpt->failure_id == ccb->ccb_h.target_id) {
 3312                         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 3313                         mpt_set_ccb_status(ccb, CAM_SEL_TIMEOUT);
 3314                         break;
 3315                 }
 3316 #endif
 3317                 ccb->csio.scsi_status = SCSI_STATUS_OK;
 3318                 mpt_start(sim, ccb);
 3319                 return;
 3320 
 3321         case XPT_RESET_BUS:
 3322                 if (raid_passthru) {
 3323                         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 3324                         mpt_set_ccb_status(ccb, CAM_REQ_CMP);
 3325                         break;
 3326                 }
 3327         case XPT_RESET_DEV:
 3328                 if (ccb->ccb_h.func_code == XPT_RESET_BUS) {
 3329                         if (bootverbose) {
 3330                                 xpt_print(ccb->ccb_h.path, "reset bus\n");
 3331                         }
 3332                 } else {
 3333                         xpt_print(ccb->ccb_h.path, "reset device\n");
 3334                 }
 3335                 (void) mpt_bus_reset(mpt, tgt, lun, FALSE);
 3336 
 3337                 /*
 3338                  * mpt_bus_reset is always successful in that it
 3339                  * will fall back to a hard reset should a bus
 3340                  * reset attempt fail.
 3341                  */
 3342                 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 3343                 mpt_set_ccb_status(ccb, CAM_REQ_CMP);
 3344                 break;
 3345                 
 3346         case XPT_ABORT:
 3347         {
 3348                 union ccb *accb = ccb->cab.abort_ccb;
 3349                 switch (accb->ccb_h.func_code) {
 3350                 case XPT_ACCEPT_TARGET_IO:
 3351                 case XPT_IMMED_NOTIFY:
 3352                         ccb->ccb_h.status = mpt_abort_target_ccb(mpt, ccb);
 3353                         break;
 3354                 case XPT_CONT_TARGET_IO:
 3355                         mpt_prt(mpt, "cannot abort active CTIOs yet\n");
 3356                         ccb->ccb_h.status = CAM_UA_ABORT;
 3357                         break;
 3358                 case XPT_SCSI_IO:
 3359                         ccb->ccb_h.status = CAM_UA_ABORT;
 3360                         break;
 3361                 default:
 3362                         ccb->ccb_h.status = CAM_REQ_INVALID;
 3363                         break;
 3364                 }
 3365                 break;
 3366         }
 3367 
 3368 #ifdef  CAM_NEW_TRAN_CODE
 3369 #define IS_CURRENT_SETTINGS(c)  ((c)->type == CTS_TYPE_CURRENT_SETTINGS)
 3370 #else
 3371 #define IS_CURRENT_SETTINGS(c)  ((c)->flags & CCB_TRANS_CURRENT_SETTINGS)
 3372 #endif
 3373 #define DP_DISC_ENABLE  0x1
 3374 #define DP_DISC_DISABL  0x2
 3375 #define DP_DISC         (DP_DISC_ENABLE|DP_DISC_DISABL)
 3376 
 3377 #define DP_TQING_ENABLE 0x4
 3378 #define DP_TQING_DISABL 0x8
 3379 #define DP_TQING        (DP_TQING_ENABLE|DP_TQING_DISABL)
 3380 
 3381 #define DP_WIDE         0x10
 3382 #define DP_NARROW       0x20
 3383 #define DP_WIDTH        (DP_WIDE|DP_NARROW)
 3384 
 3385 #define DP_SYNC         0x40
 3386 
 3387         case XPT_SET_TRAN_SETTINGS:     /* Nexus Settings */
 3388         {
 3389 #ifdef  CAM_NEW_TRAN_CODE
 3390                 struct ccb_trans_settings_scsi *scsi;
 3391                 struct ccb_trans_settings_spi *spi;
 3392 #endif
 3393                 uint8_t dval;
 3394                 u_int period;
 3395                 u_int offset;
 3396                 int i, j;
 3397 
 3398                 cts = &ccb->cts;
 3399 
 3400                 if (mpt->is_fc || mpt->is_sas) {
 3401                         mpt_set_ccb_status(ccb, CAM_REQ_CMP);
 3402                         break;
 3403                 }
 3404 
 3405 #ifdef  CAM_NEW_TRAN_CODE
 3406                 scsi = &cts->proto_specific.scsi;
 3407                 spi = &cts->xport_specific.spi;
 3408 
 3409                 /*
 3410                  * We can be called just to valid transport and proto versions
 3411                  */
 3412                 if (scsi->valid == 0 && spi->valid == 0) {
 3413                         mpt_set_ccb_status(ccb, CAM_REQ_CMP);
 3414                         break;
 3415                 }
 3416 #endif
 3417 
 3418                 /*
 3419                  * Skip attempting settings on RAID volume disks.
 3420                  * Other devices on the bus get the normal treatment.
 3421                  */
 3422                 if (mpt->phydisk_sim && raid_passthru == 0 &&
 3423                     mpt_is_raid_volume(mpt, tgt) != 0) {
 3424                         mpt_lprt(mpt, MPT_PRT_NEGOTIATION,
 3425                             "no transfer settings for RAID vols\n");
 3426                         mpt_set_ccb_status(ccb, CAM_REQ_CMP);
 3427                         break;
 3428                 }
 3429 
 3430                 i = mpt->mpt_port_page2.PortSettings &
 3431                     MPI_SCSIPORTPAGE2_PORT_MASK_NEGO_MASTER_SETTINGS;
 3432                 j = mpt->mpt_port_page2.PortFlags &
 3433                     MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
 3434                 if (i == MPI_SCSIPORTPAGE2_PORT_ALL_MASTER_SETTINGS &&
 3435                     j == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) {
 3436                         mpt_lprt(mpt, MPT_PRT_ALWAYS,
 3437                             "honoring BIOS transfer negotiations\n");
 3438                         mpt_set_ccb_status(ccb, CAM_REQ_CMP);
 3439                         break;
 3440                 }
 3441 
 3442                 dval = 0;
 3443                 period = 0;
 3444                 offset = 0;
 3445 
 3446 #ifndef CAM_NEW_TRAN_CODE
 3447                 if ((cts->valid & CCB_TRANS_DISC_VALID) != 0) {
 3448                         dval |= (cts->flags & CCB_TRANS_DISC_ENB) ?
 3449                             DP_DISC_ENABLE : DP_DISC_DISABL;
 3450                 }
 3451 
 3452                 if ((cts->valid & CCB_TRANS_TQ_VALID) != 0) {
 3453                         dval |= (cts->flags & CCB_TRANS_TAG_ENB) ?
 3454                             DP_TQING_ENABLE : DP_TQING_DISABL;
 3455                 }
 3456 
 3457                 if ((cts->valid & CCB_TRANS_BUS_WIDTH_VALID) != 0) {
 3458                         dval |= cts->bus_width ? DP_WIDE : DP_NARROW;
 3459                 }
 3460 
 3461                 if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) &&
 3462                     (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID)) {
 3463                         dval |= DP_SYNC;
 3464                         period = cts->sync_period;
 3465                         offset = cts->sync_offset;
 3466                 }
 3467 #else
 3468                 if ((spi->valid & CTS_SPI_VALID_DISC) != 0) {
 3469                         dval |= ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) ?
 3470                             DP_DISC_ENABLE : DP_DISC_DISABL;
 3471                 }
 3472 
 3473                 if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
 3474                         dval |= ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) ?
 3475                             DP_TQING_ENABLE : DP_TQING_DISABL;
 3476                 }
 3477 
 3478                 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
 3479                         dval |= (spi->bus_width == MSG_EXT_WDTR_BUS_16_BIT) ?
 3480                             DP_WIDE : DP_NARROW;
 3481                 }
 3482 
 3483                 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
 3484                         dval |= DP_SYNC;
 3485                         offset = spi->sync_offset;
 3486                 } else {
 3487                         PTR_CONFIG_PAGE_SCSI_DEVICE_1 ptr =
 3488                             &mpt->mpt_dev_page1[tgt];
 3489                         offset = ptr->RequestedParameters;
 3490                         offset &= MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK;
 3491                         offset >>= MPI_SCSIDEVPAGE1_RP_SHIFT_MAX_SYNC_OFFSET;
 3492                 }
 3493                 if (spi->valid & CTS_SPI_VALID_SYNC_RATE) {
 3494                         dval |= DP_SYNC;
 3495                         period = spi->sync_period;
 3496                 } else {
 3497                         PTR_CONFIG_PAGE_SCSI_DEVICE_1 ptr =
 3498                             &mpt->mpt_dev_page1[tgt];
 3499                         period = ptr->RequestedParameters;
 3500                         period &= MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK;
 3501                         period >>= MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD;
 3502                 }
 3503 #endif
 3504                 if (dval & DP_DISC_ENABLE) {
 3505                         mpt->mpt_disc_enable |= (1 << tgt);
 3506                 } else if (dval & DP_DISC_DISABL) {
 3507                         mpt->mpt_disc_enable &= ~(1 << tgt);
 3508                 }
 3509                 if (dval & DP_TQING_ENABLE) {
 3510                         mpt->mpt_tag_enable |= (1 << tgt);
 3511                 } else if (dval & DP_TQING_DISABL) {
 3512                         mpt->mpt_tag_enable &= ~(1 << tgt);
 3513                 }
 3514                 if (dval & DP_WIDTH) {
 3515                         mpt_setwidth(mpt, tgt, 1);
 3516                 }
 3517                 if (dval & DP_SYNC) {
 3518                         mpt_setsync(mpt, tgt, period, offset);
 3519                 }
 3520                 if (dval == 0) {
 3521                         mpt_set_ccb_status(ccb, CAM_REQ_CMP);
 3522                         break;
 3523                 }
 3524                 mpt_lprt(mpt, MPT_PRT_NEGOTIATION,
 3525                     "set [%d]: 0x%x period 0x%x offset %d\n",
 3526                     tgt, dval, period, offset);
 3527                 if (mpt_update_spi_config(mpt, tgt)) {
 3528                         mpt_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
 3529                 } else {
 3530                         mpt_set_ccb_status(ccb, CAM_REQ_CMP);
 3531                 }
 3532                 break;
 3533         }
 3534         case XPT_GET_TRAN_SETTINGS:
 3535         {
 3536 #ifdef  CAM_NEW_TRAN_CODE
 3537                 struct ccb_trans_settings_scsi *scsi;
 3538                 cts = &ccb->cts;
 3539                 cts->protocol = PROTO_SCSI;
 3540                 if (mpt->is_fc) {
 3541                         struct ccb_trans_settings_fc *fc =
 3542                             &cts->xport_specific.fc;
 3543                         cts->protocol_version = SCSI_REV_SPC;
 3544                         cts->transport = XPORT_FC;
 3545                         cts->transport_version = 0;
 3546                         fc->valid = CTS_FC_VALID_SPEED;
 3547                         fc->bitrate = 100000;
 3548                 } else if (mpt->is_sas) {
 3549                         struct ccb_trans_settings_sas *sas =
 3550                             &cts->xport_specific.sas;
 3551                         cts->protocol_version = SCSI_REV_SPC2;
 3552                         cts->transport = XPORT_SAS;
 3553                         cts->transport_version = 0;
 3554                         sas->valid = CTS_SAS_VALID_SPEED;
 3555                         sas->bitrate = 300000;
 3556                 } else {
 3557                         cts->protocol_version = SCSI_REV_2;
 3558                         cts->transport = XPORT_SPI;
 3559                         cts->transport_version = 2;
 3560                         if (mpt_get_spi_settings(mpt, cts) != 0) {
 3561                                 mpt_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
 3562                                 break;
 3563                         }
 3564                 }
 3565                 scsi = &cts->proto_specific.scsi;
 3566                 scsi->valid = CTS_SCSI_VALID_TQ;
 3567                 scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
 3568 #else
 3569                 cts = &ccb->cts;
 3570                 if (mpt->is_fc) {
 3571                         cts->flags = CCB_TRANS_TAG_ENB | CCB_TRANS_DISC_ENB;
 3572                         cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
 3573                         cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
 3574                 } else if (mpt->is_sas) {
 3575                         cts->flags = CCB_TRANS_TAG_ENB | CCB_TRANS_DISC_ENB;
 3576                         cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
 3577                         cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
 3578                 } else if (mpt_get_spi_settings(mpt, cts) != 0) {
 3579                         mpt_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
 3580                         break;
 3581                 }
 3582 #endif
 3583                 mpt_set_ccb_status(ccb, CAM_REQ_CMP);
 3584                 break;
 3585         }
 3586         case XPT_CALC_GEOMETRY:
 3587         {
 3588                 struct ccb_calc_geometry *ccg;
 3589 
 3590                 ccg = &ccb->ccg;
 3591                 if (ccg->block_size == 0) {
 3592                         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 3593                         mpt_set_ccb_status(ccb, CAM_REQ_INVALID);
 3594                         break;
 3595                 }
 3596                 cam_calc_geometry(ccg, /* extended */ 1);
 3597                 KASSERT(ccb->ccb_h.status, ("zero ccb sts at %d", __LINE__));
 3598                 break;
 3599         }
 3600         case XPT_PATH_INQ:              /* Path routing inquiry */
 3601         {
 3602                 struct ccb_pathinq *cpi = &ccb->cpi;
 3603 
 3604                 cpi->version_num = 1;
 3605                 cpi->target_sprt = 0;
 3606                 cpi->hba_eng_cnt = 0;
 3607                 cpi->max_target = mpt->port_facts[0].MaxDevices - 1;
 3608                 cpi->maxio = (mpt->max_cam_seg_cnt - 1) * PAGE_SIZE;
 3609                 /*
 3610                  * FC cards report MAX_DEVICES of 512, but
 3611                  * the MSG_SCSI_IO_REQUEST target id field
 3612                  * is only 8 bits. Until we fix the driver
 3613                  * to support 'channels' for bus overflow,
 3614                  * just limit it.
 3615                  */
 3616                 if (cpi->max_target > 255) {
 3617                         cpi->max_target = 255;
 3618                 }
 3619 
 3620                 /*
 3621                  * VMware ESX reports > 16 devices and then dies when we probe.
 3622                  */
 3623                 if (mpt->is_spi && cpi->max_target > 15) {
 3624                         cpi->max_target = 15;
 3625                 }
 3626                 if (mpt->is_spi)
 3627                         cpi->max_lun = 7;
 3628                 else
 3629                         cpi->max_lun = MPT_MAX_LUNS;
 3630                 cpi->initiator_id = mpt->mpt_ini_id;
 3631                 cpi->bus_id = cam_sim_bus(sim);
 3632 
 3633                 /*
 3634                  * The base speed is the speed of the underlying connection.
 3635                  */
 3636 #ifdef  CAM_NEW_TRAN_CODE
 3637                 cpi->protocol = PROTO_SCSI;
 3638                 if (mpt->is_fc) {
 3639                         cpi->hba_misc = PIM_NOBUSRESET;
 3640                         cpi->base_transfer_speed = 100000;
 3641                         cpi->hba_inquiry = PI_TAG_ABLE;
 3642                         cpi->transport = XPORT_FC;
 3643                         cpi->transport_version = 0;
 3644                         cpi->protocol_version = SCSI_REV_SPC;
 3645                 } else if (mpt->is_sas) {
 3646                         cpi->hba_misc = PIM_NOBUSRESET;
 3647                         cpi->base_transfer_speed = 300000;
 3648                         cpi->hba_inquiry = PI_TAG_ABLE;
 3649                         cpi->transport = XPORT_SAS;
 3650                         cpi->transport_version = 0;
 3651                         cpi->protocol_version = SCSI_REV_SPC2;
 3652                 } else {
 3653                         cpi->hba_misc = PIM_SEQSCAN;
 3654                         cpi->base_transfer_speed = 3300;
 3655                         cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
 3656                         cpi->transport = XPORT_SPI;
 3657                         cpi->transport_version = 2;
 3658                         cpi->protocol_version = SCSI_REV_2;
 3659                 }
 3660 #else
 3661                 if (mpt->is_fc) {
 3662                         cpi->hba_misc = PIM_NOBUSRESET;
 3663                         cpi->base_transfer_speed = 100000;
 3664                         cpi->hba_inquiry = PI_TAG_ABLE;
 3665                 } else if (mpt->is_sas) {
 3666                         cpi->hba_misc = PIM_NOBUSRESET;
 3667                         cpi->base_transfer_speed = 300000;
 3668                         cpi->hba_inquiry = PI_TAG_ABLE;
 3669                 } else {
 3670                         cpi->hba_misc = PIM_SEQSCAN;
 3671                         cpi->base_transfer_speed = 3300;
 3672                         cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
 3673                 }
 3674 #endif
 3675 
 3676                 /*
 3677                  * We give our fake RAID passhtru bus a width that is MaxVolumes
 3678                  * wide and restrict it to one lun.
 3679                  */
 3680                 if (raid_passthru) {
 3681                         cpi->max_target = mpt->ioc_page2->MaxPhysDisks - 1;
 3682                         cpi->initiator_id = cpi->max_target + 1;
 3683                         cpi->max_lun = 0;
 3684                 }
 3685 
 3686                 if ((mpt->role & MPT_ROLE_INITIATOR) == 0) {
 3687                         cpi->hba_misc |= PIM_NOINITIATOR;
 3688                 }
 3689                 if (mpt->is_fc && (mpt->role & MPT_ROLE_TARGET)) {
 3690                         cpi->target_sprt =
 3691                             PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO;
 3692                 } else {
 3693                         cpi->target_sprt = 0;
 3694                 }
 3695                 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
 3696                 strncpy(cpi->hba_vid, "LSI", HBA_IDLEN);
 3697                 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
 3698                 cpi->unit_number = cam_sim_unit(sim);
 3699                 cpi->ccb_h.status = CAM_REQ_CMP;
 3700                 break;
 3701         }
 3702         case XPT_EN_LUN:                /* Enable LUN as a target */
 3703         {
 3704                 int result;
 3705 
 3706                 if (ccb->cel.enable)
 3707                         result = mpt_enable_lun(mpt,
 3708                             ccb->ccb_h.target_id, ccb->ccb_h.target_lun);
 3709                 else
 3710                         result = mpt_disable_lun(mpt,
 3711                             ccb->ccb_h.target_id, ccb->ccb_h.target_lun);
 3712                 if (result == 0) {
 3713                         mpt_set_ccb_status(ccb, CAM_REQ_CMP);
 3714                 } else {
 3715                         mpt_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
 3716                 }
 3717                 break;
 3718         }
 3719         case XPT_NOTIFY_ACK:            /* recycle notify ack */
 3720         case XPT_IMMED_NOTIFY:          /* Add Immediate Notify Resource */
 3721         case XPT_ACCEPT_TARGET_IO:      /* Add Accept Target IO Resource */
 3722         {
 3723                 tgt_resource_t *trtp;
 3724                 lun_id_t lun = ccb->ccb_h.target_lun;
 3725                 ccb->ccb_h.sim_priv.entries[0].field = 0;
 3726                 ccb->ccb_h.sim_priv.entries[1].ptr = mpt;
 3727                 ccb->ccb_h.flags = 0;
 3728 
 3729                 if (lun == CAM_LUN_WILDCARD) {
 3730                         if (ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
 3731                                 mpt_set_ccb_status(ccb, CAM_REQ_INVALID);
 3732                                 break;
 3733                         }
 3734                         trtp = &mpt->trt_wildcard;
 3735                 } else if (lun >= MPT_MAX_LUNS) {
 3736                         mpt_set_ccb_status(ccb, CAM_REQ_INVALID);
 3737                         break;
 3738                 } else {
 3739                         trtp = &mpt->trt[lun];
 3740                 }
 3741                 if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
 3742                         mpt_lprt(mpt, MPT_PRT_DEBUG1,
 3743                             "Put FREE ATIO %p lun %d\n", ccb, lun);
 3744                         STAILQ_INSERT_TAIL(&trtp->atios, &ccb->ccb_h,
 3745                             sim_links.stqe);
 3746                 } else if (ccb->ccb_h.func_code == XPT_IMMED_NOTIFY) {
 3747                         mpt_lprt(mpt, MPT_PRT_DEBUG1,
 3748                             "Put FREE INOT lun %d\n", lun);
 3749                         STAILQ_INSERT_TAIL(&trtp->inots, &ccb->ccb_h,
 3750                             sim_links.stqe);
 3751                 } else {
 3752                         mpt_lprt(mpt, MPT_PRT_ALWAYS, "Got Notify ACK\n");
 3753                 }
 3754                 mpt_set_ccb_status(ccb, CAM_REQ_INPROG);
 3755                 return;
 3756         }
 3757         case XPT_CONT_TARGET_IO:
 3758                 mpt_target_start_io(mpt, ccb);
 3759                 return;
 3760 
 3761         default:
 3762                 ccb->ccb_h.status = CAM_REQ_INVALID;
 3763                 break;
 3764         }
 3765         xpt_done(ccb);
 3766 }
 3767 
 3768 static int
 3769 mpt_get_spi_settings(struct mpt_softc *mpt, struct ccb_trans_settings *cts)
 3770 {
 3771 #ifdef  CAM_NEW_TRAN_CODE
 3772         struct ccb_trans_settings_scsi *scsi = &cts->proto_specific.scsi;
 3773         struct ccb_trans_settings_spi *spi = &cts->xport_specific.spi;
 3774 #endif
 3775         target_id_t tgt;
 3776         uint32_t dval, pval, oval;
 3777         int rv;
 3778 
 3779         if (IS_CURRENT_SETTINGS(cts) == 0) {
 3780                 tgt = cts->ccb_h.target_id;
 3781         } else if (xpt_path_sim(cts->ccb_h.path) == mpt->phydisk_sim) {
 3782                 if (mpt_map_physdisk(mpt, (union ccb *)cts, &tgt)) {
 3783                         return (-1);
 3784                 }
 3785         } else {
 3786                 tgt = cts->ccb_h.target_id;
 3787         }
 3788 
 3789         /*
 3790          * We aren't looking at Port Page 2 BIOS settings here-
 3791          * sometimes these have been known to be bogus XXX.
 3792          *
 3793          * For user settings, we pick the max from port page 0
 3794          * 
 3795          * For current settings we read the current settings out from
 3796          * device page 0 for that target.
 3797          */
 3798         if (IS_CURRENT_SETTINGS(cts)) {
 3799                 CONFIG_PAGE_SCSI_DEVICE_0 tmp;
 3800                 dval = 0;
 3801 
 3802                 tmp = mpt->mpt_dev_page0[tgt];
 3803                 rv = mpt_read_cur_cfg_page(mpt, tgt, &tmp.Header,
 3804                     sizeof(tmp), FALSE, 5000);
 3805                 if (rv) {
 3806                         mpt_prt(mpt, "can't get tgt %d config page 0\n", tgt);
 3807                         return (rv);
 3808                 }
 3809                 mpt2host_config_page_scsi_device_0(&tmp);
 3810                 
 3811                 mpt_lprt(mpt, MPT_PRT_DEBUG,
 3812                     "mpt_get_spi_settings[%d]: current NP %x Info %x\n", tgt,
 3813                     tmp.NegotiatedParameters, tmp.Information);
 3814                 dval |= (tmp.NegotiatedParameters & MPI_SCSIDEVPAGE0_NP_WIDE) ?
 3815                     DP_WIDE : DP_NARROW;
 3816                 dval |= (mpt->mpt_disc_enable & (1 << tgt)) ?
 3817                     DP_DISC_ENABLE : DP_DISC_DISABL;
 3818                 dval |= (mpt->mpt_tag_enable & (1 << tgt)) ?
 3819                     DP_TQING_ENABLE : DP_TQING_DISABL;
 3820                 oval = tmp.NegotiatedParameters;
 3821                 oval &= MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK;
 3822                 oval >>= MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_OFFSET;
 3823                 pval = tmp.NegotiatedParameters;
 3824                 pval &= MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK;
 3825                 pval >>= MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_PERIOD;
 3826                 mpt->mpt_dev_page0[tgt] = tmp;
 3827         } else {
 3828                 dval = DP_WIDE|DP_DISC_ENABLE|DP_TQING_ENABLE|DP_SYNC;
 3829                 oval = mpt->mpt_port_page0.Capabilities;
 3830                 oval = MPI_SCSIPORTPAGE0_CAP_GET_MAX_SYNC_OFFSET(oval);
 3831                 pval = mpt->mpt_port_page0.Capabilities;
 3832                 pval = MPI_SCSIPORTPAGE0_CAP_GET_MIN_SYNC_PERIOD(pval);
 3833         }
 3834 
 3835 #ifndef CAM_NEW_TRAN_CODE
 3836         cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB);
 3837         cts->valid = 0;
 3838         cts->sync_period = pval;
 3839         cts->sync_offset = oval;
 3840         cts->valid |= CCB_TRANS_SYNC_RATE_VALID;
 3841         cts->valid |= CCB_TRANS_SYNC_OFFSET_VALID;
 3842         cts->valid |= CCB_TRANS_BUS_WIDTH_VALID;
 3843         if (dval & DP_WIDE) {
 3844                 cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
 3845         } else {
 3846                 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
 3847         }
 3848         if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) {
 3849                 cts->valid |= CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
 3850                 if (dval & DP_DISC_ENABLE) {
 3851                         cts->flags |= CCB_TRANS_DISC_ENB;
 3852                 }
 3853                 if (dval & DP_TQING_ENABLE) {
 3854                         cts->flags |= CCB_TRANS_TAG_ENB;
 3855                 }
 3856         }
 3857 #else
 3858         spi->valid = 0;
 3859         scsi->valid = 0;
 3860         spi->flags = 0;
 3861         scsi->flags = 0;
 3862         spi->sync_offset = oval;
 3863         spi->sync_period = pval;
 3864         spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
 3865         spi->valid |= CTS_SPI_VALID_SYNC_RATE;
 3866         spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
 3867         if (dval & DP_WIDE) {
 3868                 spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
 3869         } else {
 3870                 spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
 3871         }
 3872         if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) {
 3873                 scsi->valid = CTS_SCSI_VALID_TQ;
 3874                 if (dval & DP_TQING_ENABLE) {
 3875                         scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
 3876                 }
 3877                 spi->valid |= CTS_SPI_VALID_DISC;
 3878                 if (dval & DP_DISC_ENABLE) {
 3879                         spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
 3880                 }
 3881         }
 3882 #endif
 3883         mpt_lprt(mpt, MPT_PRT_NEGOTIATION,
 3884             "mpt_get_spi_settings[%d]: %s flags 0x%x per 0x%x off=%d\n", tgt,
 3885             IS_CURRENT_SETTINGS(cts)? "ACTIVE" : "NVRAM ", dval, pval, oval);
 3886         return (0);
 3887 }
 3888 
 3889 static void
 3890 mpt_setwidth(struct mpt_softc *mpt, int tgt, int onoff)
 3891 {
 3892         PTR_CONFIG_PAGE_SCSI_DEVICE_1 ptr;
 3893 
 3894         ptr = &mpt->mpt_dev_page1[tgt];
 3895         if (onoff) {
 3896                 ptr->RequestedParameters |= MPI_SCSIDEVPAGE1_RP_WIDE;
 3897         } else {
 3898                 ptr->RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_WIDE;
 3899         }
 3900 }
 3901 
 3902 static void
 3903 mpt_setsync(struct mpt_softc *mpt, int tgt, int period, int offset)
 3904 {
 3905         PTR_CONFIG_PAGE_SCSI_DEVICE_1 ptr;
 3906 
 3907         ptr = &mpt->mpt_dev_page1[tgt];
 3908         ptr->RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK;
 3909         ptr->RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK;
 3910         ptr->RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_DT;
 3911         ptr->RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_QAS;
 3912         ptr->RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_IU;
 3913         if (period == 0) {
 3914                 return;
 3915         }
 3916         ptr->RequestedParameters |=
 3917             period << MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD;
 3918         ptr->RequestedParameters |=
 3919             offset << MPI_SCSIDEVPAGE1_RP_SHIFT_MAX_SYNC_OFFSET;
 3920         if (period < 0xa) {
 3921                 ptr->RequestedParameters |= MPI_SCSIDEVPAGE1_RP_DT;
 3922         }
 3923         if (period < 0x9) {
 3924                 ptr->RequestedParameters |= MPI_SCSIDEVPAGE1_RP_QAS;
 3925                 ptr->RequestedParameters |= MPI_SCSIDEVPAGE1_RP_IU;
 3926         }
 3927 }
 3928 
 3929 static int
 3930 mpt_update_spi_config(struct mpt_softc *mpt, int tgt)
 3931 {
 3932         CONFIG_PAGE_SCSI_DEVICE_1 tmp;
 3933         int rv;
 3934 
 3935         mpt_lprt(mpt, MPT_PRT_NEGOTIATION,
 3936             "mpt_update_spi_config[%d].page1: Requested Params 0x%08x\n",
 3937             tgt, mpt->mpt_dev_page1[tgt].RequestedParameters);
 3938         tmp = mpt->mpt_dev_page1[tgt];
 3939         host2mpt_config_page_scsi_device_1(&tmp);
 3940         rv = mpt_write_cur_cfg_page(mpt, tgt,
 3941             &tmp.Header, sizeof(tmp), FALSE, 5000);
 3942         if (rv) {
 3943                 mpt_prt(mpt, "mpt_update_spi_config: write cur page failed\n");
 3944                 return (-1);
 3945         }
 3946         return (0);
 3947 }
 3948 
 3949 /****************************** Timeout Recovery ******************************/
 3950 static int
 3951 mpt_spawn_recovery_thread(struct mpt_softc *mpt)
 3952 {
 3953         int error;
 3954 
 3955         error = mpt_kthread_create(mpt_recovery_thread, mpt,
 3956             &mpt->recovery_thread, /*flags*/0,
 3957             /*altstack*/0, "mpt_recovery%d", mpt->unit);
 3958         return (error);
 3959 }
 3960 
 3961 static void
 3962 mpt_terminate_recovery_thread(struct mpt_softc *mpt)
 3963 {
 3964 
 3965         if (mpt->recovery_thread == NULL) {
 3966                 return;
 3967         }
 3968         mpt->shutdwn_recovery = 1;
 3969         wakeup(mpt);
 3970         /*
 3971          * Sleep on a slightly different location
 3972          * for this interlock just for added safety.
 3973          */
 3974         mpt_sleep(mpt, &mpt->recovery_thread, PUSER, "thtrm", 0);
 3975 }
 3976 
 3977 static void
 3978 mpt_recovery_thread(void *arg)
 3979 {
 3980         struct mpt_softc *mpt;
 3981 
 3982         mpt = (struct mpt_softc *)arg;
 3983         MPT_LOCK(mpt);
 3984         for (;;) {
 3985                 if (TAILQ_EMPTY(&mpt->request_timeout_list) != 0) {
 3986                         if (mpt->shutdwn_recovery == 0) {
 3987                                 mpt_sleep(mpt, mpt, PUSER, "idle", 0);
 3988                         }
 3989                 }
 3990                 if (mpt->shutdwn_recovery != 0) {
 3991                         break;
 3992                 }
 3993                 mpt_recover_commands(mpt);
 3994         }
 3995         mpt->recovery_thread = NULL;
 3996         wakeup(&mpt->recovery_thread);
 3997         MPT_UNLOCK(mpt);
 3998         mpt_kthread_exit(0);
 3999 }
 4000 
 4001 static int
 4002 mpt_scsi_send_tmf(struct mpt_softc *mpt, u_int type, u_int flags,
 4003     u_int channel, u_int target, u_int lun, u_int abort_ctx, int sleep_ok)
 4004 {
 4005         MSG_SCSI_TASK_MGMT *tmf_req;
 4006         int                 error;
 4007 
 4008         /*
 4009          * Wait for any current TMF request to complete.
 4010          * We're only allowed to issue one TMF at a time.
 4011          */
 4012         error = mpt_wait_req(mpt, mpt->tmf_req, REQ_STATE_FREE, REQ_STATE_FREE,
 4013             sleep_ok, MPT_TMF_MAX_TIMEOUT);
 4014         if (error != 0) {
 4015                 mpt_reset(mpt, TRUE);
 4016                 return (ETIMEDOUT);
 4017         }
 4018 
 4019         mpt_assign_serno(mpt, mpt->tmf_req);
 4020         mpt->tmf_req->state = REQ_STATE_ALLOCATED|REQ_STATE_QUEUED;
 4021 
 4022         tmf_req = (MSG_SCSI_TASK_MGMT *)mpt->tmf_req->req_vbuf;
 4023         memset(tmf_req, 0, sizeof(*tmf_req));
 4024         tmf_req->TargetID = target;
 4025         tmf_req->Bus = channel;
 4026         tmf_req->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
 4027         tmf_req->TaskType = type;
 4028         tmf_req->MsgFlags = flags;
 4029         tmf_req->MsgContext =
 4030             htole32(mpt->tmf_req->index | scsi_tmf_handler_id);
 4031         if (lun > MPT_MAX_LUNS) {
 4032                 tmf_req->LUN[0] = 0x40 | ((lun >> 8) & 0x3f);
 4033                 tmf_req->LUN[1] = lun & 0xff;
 4034         } else {
 4035                 tmf_req->LUN[1] = lun;
 4036         }
 4037         tmf_req->TaskMsgContext = abort_ctx;
 4038 
 4039         mpt_lprt(mpt, MPT_PRT_DEBUG,
 4040             "Issuing TMF %p:%u with MsgContext of 0x%x\n", mpt->tmf_req,
 4041             mpt->tmf_req->serno, tmf_req->MsgContext);
 4042         if (mpt->verbose > MPT_PRT_DEBUG) {
 4043                 mpt_print_request(tmf_req);
 4044         }
 4045 
 4046         KASSERT(mpt_req_on_pending_list(mpt, mpt->tmf_req) == 0,
 4047             ("mpt_scsi_send_tmf: tmf_req already on pending list"));
 4048         TAILQ_INSERT_HEAD(&mpt->request_pending_list, mpt->tmf_req, links);
 4049         error = mpt_send_handshake_cmd(mpt, sizeof(*tmf_req), tmf_req);
 4050         if (error != MPT_OK) {
 4051                 TAILQ_REMOVE(&mpt->request_pending_list, mpt->tmf_req, links);
 4052                 mpt->tmf_req->state = REQ_STATE_FREE;
 4053                 mpt_reset(mpt, TRUE);
 4054         }
 4055         return (error);
 4056 }
 4057 
 4058 /*
 4059  * When a command times out, it is placed on the requeust_timeout_list
 4060  * and we wake our recovery thread.  The MPT-Fusion architecture supports
 4061  * only a single TMF operation at a time, so we serially abort/bdr, etc,
 4062  * the timedout transactions.  The next TMF is issued either by the
 4063  * completion handler of the current TMF waking our recovery thread,
 4064  * or the TMF timeout handler causing a hard reset sequence.
 4065  */
 4066 static void
 4067 mpt_recover_commands(struct mpt_softc *mpt)
 4068 {
 4069         request_t          *req;
 4070         union ccb          *ccb;
 4071         int                 error;
 4072 
 4073         if (TAILQ_EMPTY(&mpt->request_timeout_list) != 0) {
 4074                 /*
 4075                  * No work to do- leave.
 4076                  */
 4077                 mpt_prt(mpt, "mpt_recover_commands: no requests.\n");
 4078                 return;
 4079         }
 4080 
 4081         /*
 4082          * Flush any commands whose completion coincides with their timeout.
 4083          */
 4084         mpt_intr(mpt);
 4085 
 4086         if (TAILQ_EMPTY(&mpt->request_timeout_list) != 0) {
 4087                 /*
 4088                  * The timedout commands have already
 4089                  * completed.  This typically means
 4090                  * that either the timeout value was on
 4091                  * the hairy edge of what the device
 4092                  * requires or - more likely - interrupts
 4093                  * are not happening.
 4094                  */
 4095                 mpt_prt(mpt, "Timedout requests already complete. "
 4096                     "Interrupts may not be functioning.\n");
 4097                 mpt_enable_ints(mpt);
 4098                 return;
 4099         }
 4100 
 4101         /*
 4102          * We have no visibility into the current state of the
 4103          * controller, so attempt to abort the commands in the
 4104          * order they timed-out. For initiator commands, we
 4105          * depend on the reply handler pulling requests off
 4106          * the timeout list.
 4107          */
 4108         while ((req = TAILQ_FIRST(&mpt->request_timeout_list)) != NULL) {
 4109                 uint16_t status;
 4110                 uint8_t response;
 4111                 MSG_REQUEST_HEADER *hdrp = req->req_vbuf;
 4112 
 4113                 mpt_prt(mpt, "attempting to abort req %p:%u function %x\n",
 4114                     req, req->serno, hdrp->Function);
 4115                 ccb = req->ccb;
 4116                 if (ccb == NULL) {
 4117                         mpt_prt(mpt, "null ccb in timed out request. "
 4118                             "Resetting Controller.\n");
 4119                         mpt_reset(mpt, TRUE);
 4120                         continue;
 4121                 }
 4122                 mpt_set_ccb_status(ccb, CAM_CMD_TIMEOUT);
 4123 
 4124                 /*
 4125                  * Check to see if this is not an initiator command and
 4126                  * deal with it differently if it is.
 4127                  */
 4128                 switch (hdrp->Function) {
 4129                 case MPI_FUNCTION_SCSI_IO_REQUEST:
 4130                 case MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
 4131                         break;
 4132                 default:
 4133                         /*
 4134                          * XXX: FIX ME: need to abort target assists...
 4135                          */
 4136                         mpt_prt(mpt, "just putting it back on the pend q\n");
 4137                         TAILQ_REMOVE(&mpt->request_timeout_list, req, links);
 4138                         TAILQ_INSERT_HEAD(&mpt->request_pending_list, req,
 4139                             links);
 4140                         continue;
 4141                 }
 4142 
 4143                 error = mpt_scsi_send_tmf(mpt,
 4144                     MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
 4145                     0, 0, ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
 4146                     htole32(req->index | scsi_io_handler_id), TRUE);
 4147 
 4148                 if (error != 0) {
 4149                         /*
 4150                          * mpt_scsi_send_tmf hard resets on failure, so no
 4151                          * need to do so here.  Our queue should be emptied
 4152                          * by the hard reset.
 4153                          */
 4154                         continue;
 4155                 }
 4156 
 4157                 error = mpt_wait_req(mpt, mpt->tmf_req, REQ_STATE_DONE,
 4158                     REQ_STATE_DONE, TRUE, 500);
 4159 
 4160                 status = le16toh(mpt->tmf_req->IOCStatus);
 4161                 response = mpt->tmf_req->ResponseCode;
 4162                 mpt->tmf_req->state = REQ_STATE_FREE;
 4163 
 4164                 if (error != 0) {
 4165                         /*
 4166                          * If we've errored out,, reset the controller.
 4167                          */
 4168                         mpt_prt(mpt, "mpt_recover_commands: abort timed-out. "
 4169                             "Resetting controller\n");
 4170                         mpt_reset(mpt, TRUE);
 4171                         continue;
 4172                 }
 4173 
 4174                 if ((status & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
 4175                         mpt_prt(mpt, "mpt_recover_commands: IOC Status 0x%x. "
 4176                             "Resetting controller.\n", status);
 4177                         mpt_reset(mpt, TRUE);
 4178                         continue;
 4179                 }
 4180 
 4181                 if (response != MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED &&
 4182                     response != MPI_SCSITASKMGMT_RSP_TM_COMPLETE) {
 4183                         mpt_prt(mpt, "mpt_recover_commands: TMF Response 0x%x. "
 4184                             "Resetting controller.\n", response);
 4185                         mpt_reset(mpt, TRUE);
 4186                         continue;
 4187                 }
 4188                 mpt_prt(mpt, "abort of req %p:%u completed\n", req, req->serno);
 4189         }
 4190 }
 4191 
 4192 /************************ Target Mode Support ****************************/
 4193 static void
 4194 mpt_fc_post_els(struct mpt_softc *mpt, request_t *req, int ioindex)
 4195 {
 4196         MSG_LINK_SERVICE_BUFFER_POST_REQUEST *fc;
 4197         PTR_SGE_TRANSACTION32 tep;
 4198         PTR_SGE_SIMPLE32 se;
 4199         bus_addr_t paddr;
 4200         uint32_t fl;
 4201 
 4202         paddr = req->req_pbuf;
 4203         paddr += MPT_RQSL(mpt);
 4204 
 4205         fc = req->req_vbuf;
 4206         memset(fc, 0, MPT_REQUEST_AREA);
 4207         fc->BufferCount = 1;
 4208         fc->Function = MPI_FUNCTION_FC_LINK_SRVC_BUF_POST;
 4209         fc->MsgContext = htole32(req->index | fc_els_handler_id);
 4210 
 4211         /*
 4212          * Okay, set up ELS buffer pointers. ELS buffer pointers
 4213          * consist of a TE SGL element (with details length of zero)
 4214          * followed by a SIMPLE SGL element which holds the address
 4215          * of the buffer.
 4216          */
 4217 
 4218         tep = (PTR_SGE_TRANSACTION32) &fc->SGL;
 4219 
 4220         tep->ContextSize = 4;
 4221         tep->Flags = 0;
 4222         tep->TransactionContext[0] = htole32(ioindex);
 4223 
 4224         se = (PTR_SGE_SIMPLE32) &tep->TransactionDetails[0];
 4225         fl =
 4226                 MPI_SGE_FLAGS_HOST_TO_IOC       |
 4227                 MPI_SGE_FLAGS_SIMPLE_ELEMENT    |
 4228                 MPI_SGE_FLAGS_LAST_ELEMENT      |
 4229                 MPI_SGE_FLAGS_END_OF_LIST       |
 4230                 MPI_SGE_FLAGS_END_OF_BUFFER;
 4231         fl <<= MPI_SGE_FLAGS_SHIFT;
 4232         fl |= (MPT_NRFM(mpt) - MPT_RQSL(mpt));
 4233         se->FlagsLength = htole32(fl);
 4234         se->Address = htole32((uint32_t) paddr);
 4235         mpt_lprt(mpt, MPT_PRT_DEBUG,
 4236             "add ELS index %d ioindex %d for %p:%u\n",
 4237             req->index, ioindex, req, req->serno);
 4238         KASSERT(((req->state & REQ_STATE_LOCKED) != 0),
 4239             ("mpt_fc_post_els: request not locked"));
 4240         mpt_send_cmd(mpt, req);
 4241 }
 4242 
 4243 static void
 4244 mpt_post_target_command(struct mpt_softc *mpt, request_t *req, int ioindex)
 4245 {
 4246         PTR_MSG_TARGET_CMD_BUFFER_POST_REQUEST fc;
 4247         PTR_CMD_BUFFER_DESCRIPTOR cb;
 4248         bus_addr_t paddr;
 4249 
 4250         paddr = req->req_pbuf;
 4251         paddr += MPT_RQSL(mpt);
 4252         memset(req->req_vbuf, 0, MPT_REQUEST_AREA);
 4253         MPT_TGT_STATE(mpt, req)->state = TGT_STATE_LOADING;
 4254 
 4255         fc = req->req_vbuf;
 4256         fc->BufferCount = 1;
 4257         fc->Function = MPI_FUNCTION_TARGET_CMD_BUFFER_POST;
 4258         fc->MsgContext = htole32(req->index | mpt->scsi_tgt_handler_id);
 4259 
 4260         cb = &fc->Buffer[0];
 4261         cb->IoIndex = htole16(ioindex);
 4262         cb->u.PhysicalAddress32 = htole32((U32) paddr);
 4263 
 4264         mpt_check_doorbell(mpt);
 4265         mpt_send_cmd(mpt, req);
 4266 }
 4267 
 4268 static int
 4269 mpt_add_els_buffers(struct mpt_softc *mpt)
 4270 {
 4271         int i;
 4272 
 4273         if (mpt->is_fc == 0) {
 4274                 return (TRUE);
 4275         }
 4276 
 4277         if (mpt->els_cmds_allocated) {
 4278                 return (TRUE);
 4279         }
 4280 
 4281         mpt->els_cmd_ptrs = malloc(MPT_MAX_ELS * sizeof (request_t *),
 4282             M_DEVBUF, M_NOWAIT | M_ZERO);
 4283 
 4284         if (mpt->els_cmd_ptrs == NULL) {
 4285                 return (FALSE);
 4286         }
 4287 
 4288         /*
 4289          * Feed the chip some ELS buffer resources
 4290          */
 4291         for (i = 0; i < MPT_MAX_ELS; i++) {
 4292                 request_t *req = mpt_get_request(mpt, FALSE);
 4293                 if (req == NULL) {
 4294                         break;
 4295                 }
 4296                 req->state |= REQ_STATE_LOCKED;
 4297                 mpt->els_cmd_ptrs[i] = req;
 4298                 mpt_fc_post_els(mpt, req, i);
 4299         }
 4300 
 4301         if (i == 0) {
 4302                 mpt_prt(mpt, "unable to add ELS buffer resources\n");
 4303                 free(mpt->els_cmd_ptrs, M_DEVBUF);
 4304                 mpt->els_cmd_ptrs = NULL;
 4305                 return (FALSE);
 4306         }
 4307         if (i != MPT_MAX_ELS) {
 4308                 mpt_lprt(mpt, MPT_PRT_INFO,
 4309                     "only added %d of %d  ELS buffers\n", i, MPT_MAX_ELS);
 4310         }
 4311         mpt->els_cmds_allocated = i;
 4312         return(TRUE);
 4313 }
 4314 
 4315 static int
 4316 mpt_add_target_commands(struct mpt_softc *mpt)
 4317 {
 4318         int i, max;
 4319 
 4320         if (mpt->tgt_cmd_ptrs) {
 4321                 return (TRUE);
 4322         }
 4323 
 4324         max = MPT_MAX_REQUESTS(mpt) >> 1;
 4325         if (max > mpt->mpt_max_tgtcmds) {
 4326                 max = mpt->mpt_max_tgtcmds;
 4327         }
 4328         mpt->tgt_cmd_ptrs =
 4329             malloc(max * sizeof (request_t *), M_DEVBUF, M_NOWAIT | M_ZERO);
 4330         if (mpt->tgt_cmd_ptrs == NULL) {
 4331                 mpt_prt(mpt,
 4332                     "mpt_add_target_commands: could not allocate cmd ptrs\n");
 4333                 return (FALSE);
 4334         }
 4335 
 4336         for (i = 0; i < max; i++) {
 4337                 request_t *req;
 4338 
 4339                 req = mpt_get_request(mpt, FALSE);
 4340                 if (req == NULL) {
 4341                         break;
 4342                 }
 4343                 req->state |= REQ_STATE_LOCKED;
 4344                 mpt->tgt_cmd_ptrs[i] = req;
 4345                 mpt_post_target_command(mpt, req, i);
 4346         }
 4347 
 4348 
 4349         if (i == 0) {
 4350                 mpt_lprt(mpt, MPT_PRT_ERROR, "could not add any target bufs\n");
 4351                 free(mpt->tgt_cmd_ptrs, M_DEVBUF);
 4352                 mpt->tgt_cmd_ptrs = NULL;
 4353                 return (FALSE);
 4354         }
 4355 
 4356         mpt->tgt_cmds_allocated = i;
 4357 
 4358         if (i < max) {
 4359                 mpt_lprt(mpt, MPT_PRT_INFO,
 4360                     "added %d of %d target bufs\n", i, max);
 4361         }
 4362         return (i);
 4363 }
 4364 
 4365 static int
 4366 mpt_enable_lun(struct mpt_softc *mpt, target_id_t tgt, lun_id_t lun)
 4367 {
 4368 
 4369         if (tgt == CAM_TARGET_WILDCARD && lun == CAM_LUN_WILDCARD) {
 4370                 mpt->twildcard = 1;
 4371         } else if (lun >= MPT_MAX_LUNS) {
 4372                 return (EINVAL);
 4373         } else if (tgt != CAM_TARGET_WILDCARD && tgt != 0) {
 4374                 return (EINVAL);
 4375         }
 4376         if (mpt->tenabled == 0) {
 4377                 if (mpt->is_fc) {
 4378                         (void) mpt_fc_reset_link(mpt, 0);
 4379                 }
 4380                 mpt->tenabled = 1;
 4381         }
 4382         if (lun == CAM_LUN_WILDCARD) {
 4383                 mpt->trt_wildcard.enabled = 1;
 4384         } else {
 4385                 mpt->trt[lun].enabled = 1;
 4386         }
 4387         return (0);
 4388 }
 4389 
 4390 static int
 4391 mpt_disable_lun(struct mpt_softc *mpt, target_id_t tgt, lun_id_t lun)
 4392 {
 4393         int i;
 4394 
 4395         if (tgt == CAM_TARGET_WILDCARD && lun == CAM_LUN_WILDCARD) {
 4396                 mpt->twildcard = 0;
 4397         } else if (lun >= MPT_MAX_LUNS) {
 4398                 return (EINVAL);
 4399         } else if (tgt != CAM_TARGET_WILDCARD && tgt != 0) {
 4400                 return (EINVAL);
 4401         }
 4402         if (lun == CAM_LUN_WILDCARD) {
 4403                 mpt->trt_wildcard.enabled = 0;
 4404         } else {
 4405                 mpt->trt[lun].enabled = 0;
 4406         }
 4407         for (i = 0; i < MPT_MAX_LUNS; i++) {
 4408                 if (mpt->trt[lun].enabled) {
 4409                         break;
 4410                 }
 4411         }
 4412         if (i == MPT_MAX_LUNS && mpt->twildcard == 0) {
 4413                 if (mpt->is_fc) {
 4414                         (void) mpt_fc_reset_link(mpt, 0);
 4415                 }
 4416                 mpt->tenabled = 0;
 4417         }
 4418         return (0);
 4419 }
 4420 
 4421 /*
 4422  * Called with MPT lock held
 4423  */
 4424 static void
 4425 mpt_target_start_io(struct mpt_softc *mpt, union ccb *ccb)
 4426 {
 4427         struct ccb_scsiio *csio = &ccb->csio;
 4428         request_t *cmd_req = MPT_TAG_2_REQ(mpt, csio->tag_id);
 4429         mpt_tgt_state_t *tgt = MPT_TGT_STATE(mpt, cmd_req);
 4430 
 4431         switch (tgt->state) {
 4432         case TGT_STATE_IN_CAM:
 4433                 break;
 4434         case TGT_STATE_MOVING_DATA:
 4435                 mpt_set_ccb_status(ccb, CAM_REQUEUE_REQ);
 4436                 xpt_freeze_simq(mpt->sim, 1);
 4437                 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 4438                 tgt->ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
 4439                 xpt_done(ccb);
 4440                 return;
 4441         default:
 4442                 mpt_prt(mpt, "ccb %p flags 0x%x tag 0x%08x had bad request "
 4443                     "starting I/O\n", ccb, csio->ccb_h.flags, csio->tag_id);
 4444                 mpt_tgt_dump_req_state(mpt, cmd_req);
 4445                 mpt_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
 4446                 xpt_done(ccb);
 4447                 return;
 4448         }
 4449 
 4450         if (csio->dxfer_len) {
 4451                 bus_dmamap_callback_t *cb;
 4452                 PTR_MSG_TARGET_ASSIST_REQUEST ta;
 4453                 request_t *req;
 4454 
 4455                 KASSERT((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE,
 4456                     ("dxfer_len %u but direction is NONE", csio->dxfer_len));
 4457 
 4458                 if ((req = mpt_get_request(mpt, FALSE)) == NULL) {
 4459                         if (mpt->outofbeer == 0) {
 4460                                 mpt->outofbeer = 1;
 4461                                 xpt_freeze_simq(mpt->sim, 1);
 4462                                 mpt_lprt(mpt, MPT_PRT_DEBUG, "FREEZEQ\n");
 4463                         }
 4464                         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 4465                         mpt_set_ccb_status(ccb, CAM_REQUEUE_REQ);
 4466                         xpt_done(ccb);
 4467                         return;
 4468                 }
 4469                 ccb->ccb_h.status = CAM_SIM_QUEUED | CAM_REQ_INPROG;
 4470                 if (sizeof (bus_addr_t) > 4) {
 4471                         cb = mpt_execute_req_a64;
 4472                 } else {
 4473                         cb = mpt_execute_req;
 4474                 }
 4475 
 4476                 req->ccb = ccb;
 4477                 ccb->ccb_h.ccb_req_ptr = req;
 4478 
 4479                 /*
 4480                  * Record the currently active ccb and the
 4481                  * request for it in our target state area.
 4482                  */
 4483                 tgt->ccb = ccb;
 4484                 tgt->req = req;
 4485 
 4486                 memset(req->req_vbuf, 0, MPT_RQSL(mpt));
 4487                 ta = req->req_vbuf;
 4488 
 4489                 if (mpt->is_sas) {
 4490                         PTR_MPI_TARGET_SSP_CMD_BUFFER ssp =
 4491                              cmd_req->req_vbuf;
 4492                         ta->QueueTag = ssp->InitiatorTag;
 4493                 } else if (mpt->is_spi) {
 4494                         PTR_MPI_TARGET_SCSI_SPI_CMD_BUFFER sp =
 4495                              cmd_req->req_vbuf;
 4496                         ta->QueueTag = sp->Tag;
 4497                 }
 4498                 ta->Function = MPI_FUNCTION_TARGET_ASSIST;
 4499                 ta->MsgContext = htole32(req->index | mpt->scsi_tgt_handler_id);
 4500                 ta->ReplyWord = htole32(tgt->reply_desc);
 4501                 if (csio->ccb_h.target_lun > MPT_MAX_LUNS) {
 4502                         ta->LUN[0] =
 4503                             0x40 | ((csio->ccb_h.target_lun >> 8) & 0x3f);
 4504                         ta->LUN[1] = csio->ccb_h.target_lun & 0xff;
 4505                 } else {
 4506                         ta->LUN[1] = csio->ccb_h.target_lun;
 4507                 }
 4508 
 4509                 ta->RelativeOffset = tgt->bytes_xfered;
 4510                 ta->DataLength = ccb->csio.dxfer_len;
 4511                 if (ta->DataLength > tgt->resid) {
 4512                         ta->DataLength = tgt->resid;
 4513                 }
 4514 
 4515                 /*
 4516                  * XXX Should be done after data transfer completes?
 4517                  */
 4518                 tgt->resid -= csio->dxfer_len;
 4519                 tgt->bytes_xfered += csio->dxfer_len;
 4520 
 4521                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
 4522                         ta->TargetAssistFlags |=
 4523                             TARGET_ASSIST_FLAGS_DATA_DIRECTION;
 4524                 }
 4525 
 4526 #ifdef  WE_TRUST_AUTO_GOOD_STATUS
 4527                 if ((ccb->ccb_h.flags & CAM_SEND_STATUS) &&
 4528                     csio->scsi_status == SCSI_STATUS_OK && tgt->resid == 0) {
 4529                         ta->TargetAssistFlags |=
 4530                             TARGET_ASSIST_FLAGS_AUTO_STATUS;
 4531                 }
 4532 #endif
 4533                 tgt->state = TGT_STATE_SETTING_UP_FOR_DATA;
 4534 
 4535                 mpt_lprt(mpt, MPT_PRT_DEBUG, 
 4536                     "DATA_CCB %p tag %x %u bytes %u resid flg %x req %p:%u "
 4537                     "nxtstate=%d\n", csio, csio->tag_id, csio->dxfer_len,
 4538                     tgt->resid, ccb->ccb_h.flags, req, req->serno, tgt->state);
 4539 
 4540                 if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
 4541                         if ((ccb->ccb_h.flags & CAM_DATA_PHYS) == 0) {
 4542                                 int error;
 4543                                 int s = splsoftvm();
 4544                                 error = bus_dmamap_load(mpt->buffer_dmat,
 4545                                     req->dmap, csio->data_ptr, csio->dxfer_len,
 4546                                     cb, req, 0);
 4547                                 splx(s);
 4548                                 if (error == EINPROGRESS) {
 4549                                         xpt_freeze_simq(mpt->sim, 1);
 4550                                         ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
 4551                                 }
 4552                         } else {
 4553                                 /*
 4554                                  * We have been given a pointer to single
 4555                                  * physical buffer.
 4556                                  */
 4557                                 struct bus_dma_segment seg;
 4558                                 seg.ds_addr = (bus_addr_t)
 4559                                     (vm_offset_t)csio->data_ptr;
 4560                                 seg.ds_len = csio->dxfer_len;
 4561                                 (*cb)(req, &seg, 1, 0);
 4562                         }
 4563                 } else {
 4564                         /*
 4565                          * We have been given a list of addresses.
 4566                          * This case could be easily supported but they are not
 4567                          * currently generated by the CAM subsystem so there
 4568                          * is no point in wasting the time right now.
 4569                          */
 4570                         struct bus_dma_segment *sgs;
 4571                         if ((ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) {
 4572                                 (*cb)(req, NULL, 0, EFAULT);
 4573                         } else {
 4574                                 /* Just use the segments provided */
 4575                                 sgs = (struct bus_dma_segment *)csio->data_ptr;
 4576                                 (*cb)(req, sgs, csio->sglist_cnt, 0);
 4577                         }
 4578                 }
 4579         } else {
 4580                 uint8_t *sp = NULL, sense[MPT_SENSE_SIZE];
 4581 
 4582                 /*
 4583                  * XXX: I don't know why this seems to happen, but
 4584                  * XXX: completing the CCB seems to make things happy.
 4585                  * XXX: This seems to happen if the initiator requests
 4586                  * XXX: enough data that we have to do multiple CTIOs.
 4587                  */
 4588                 if ((ccb->ccb_h.flags & CAM_SEND_STATUS) == 0) {
 4589                         mpt_lprt(mpt, MPT_PRT_DEBUG,
 4590                             "Meaningless STATUS CCB (%p): flags %x status %x "
 4591                             "resid %d bytes_xfered %u\n", ccb, ccb->ccb_h.flags,
 4592                             ccb->ccb_h.status, tgt->resid, tgt->bytes_xfered);
 4593                         mpt_set_ccb_status(ccb, CAM_REQ_CMP);
 4594                         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 4595                         xpt_done(ccb);
 4596                         return;
 4597                 }
 4598                 if (ccb->ccb_h.flags & CAM_SEND_SENSE) {
 4599                         sp = sense;
 4600                         memcpy(sp, &csio->sense_data,
 4601                            min(csio->sense_len, MPT_SENSE_SIZE));
 4602                 }
 4603                 mpt_scsi_tgt_status(mpt, ccb, cmd_req, csio->scsi_status, sp);
 4604         }
 4605 }
 4606 
 4607 static void
 4608 mpt_scsi_tgt_local(struct mpt_softc *mpt, request_t *cmd_req,
 4609     uint32_t lun, int send, uint8_t *data, size_t length)
 4610 {
 4611         mpt_tgt_state_t *tgt;
 4612         PTR_MSG_TARGET_ASSIST_REQUEST ta;
 4613         SGE_SIMPLE32 *se;
 4614         uint32_t flags;
 4615         uint8_t *dptr;
 4616         bus_addr_t pptr;
 4617         request_t *req;
 4618 
 4619         /*
 4620          * We enter with resid set to the data load for the command.
 4621          */
 4622         tgt = MPT_TGT_STATE(mpt, cmd_req);
 4623         if (length == 0 || tgt->resid == 0) {
 4624                 tgt->resid = 0;
 4625                 mpt_scsi_tgt_status(mpt, NULL, cmd_req, 0, NULL);
 4626                 return;
 4627         }
 4628 
 4629         if ((req = mpt_get_request(mpt, FALSE)) == NULL) {
 4630                 mpt_prt(mpt, "out of resources- dropping local response\n");
 4631                 return;
 4632         }
 4633         tgt->is_local = 1;
 4634 
 4635 
 4636         memset(req->req_vbuf, 0, MPT_RQSL(mpt));
 4637         ta = req->req_vbuf;
 4638 
 4639         if (mpt->is_sas) {
 4640                 PTR_MPI_TARGET_SSP_CMD_BUFFER ssp = cmd_req->req_vbuf;
 4641                 ta->QueueTag = ssp->InitiatorTag;
 4642         } else if (mpt->is_spi) {
 4643                 PTR_MPI_TARGET_SCSI_SPI_CMD_BUFFER sp = cmd_req->req_vbuf;
 4644                 ta->QueueTag = sp->Tag;
 4645         }
 4646         ta->Function = MPI_FUNCTION_TARGET_ASSIST;
 4647         ta->MsgContext = htole32(req->index | mpt->scsi_tgt_handler_id);
 4648         ta->ReplyWord = htole32(tgt->reply_desc);
 4649         if (lun > MPT_MAX_LUNS) {
 4650                 ta->LUN[0] = 0x40 | ((lun >> 8) & 0x3f);
 4651                 ta->LUN[1] = lun & 0xff;
 4652         } else {
 4653                 ta->LUN[1] = lun;
 4654         }
 4655         ta->RelativeOffset = 0;
 4656         ta->DataLength = length;
 4657 
 4658         dptr = req->req_vbuf;
 4659         dptr += MPT_RQSL(mpt);
 4660         pptr = req->req_pbuf;
 4661         pptr += MPT_RQSL(mpt);
 4662         memcpy(dptr, data, min(length, MPT_RQSL(mpt)));
 4663 
 4664         se = (SGE_SIMPLE32 *) &ta->SGL[0];
 4665         memset(se, 0,sizeof (*se));
 4666 
 4667         flags = MPI_SGE_FLAGS_SIMPLE_ELEMENT;
 4668         if (send) {
 4669                 ta->TargetAssistFlags |= TARGET_ASSIST_FLAGS_DATA_DIRECTION;
 4670                 flags |= MPI_SGE_FLAGS_HOST_TO_IOC;
 4671         }
 4672         se->Address = pptr;
 4673         MPI_pSGE_SET_LENGTH(se, length);
 4674         flags |= MPI_SGE_FLAGS_LAST_ELEMENT;
 4675         flags |= MPI_SGE_FLAGS_END_OF_LIST | MPI_SGE_FLAGS_END_OF_BUFFER;
 4676         MPI_pSGE_SET_FLAGS(se, flags);
 4677 
 4678         tgt->ccb = NULL;
 4679         tgt->req = req;
 4680         tgt->resid -= length;
 4681         tgt->bytes_xfered = length;
 4682 #ifdef  WE_TRUST_AUTO_GOOD_STATUS
 4683         tgt->state = TGT_STATE_MOVING_DATA_AND_STATUS;
 4684 #else
 4685         tgt->state = TGT_STATE_MOVING_DATA;
 4686 #endif
 4687         mpt_send_cmd(mpt, req);
 4688 }
 4689 
 4690 /*
 4691  * Abort queued up CCBs
 4692  */
 4693 static cam_status
 4694 mpt_abort_target_ccb(struct mpt_softc *mpt, union ccb *ccb)
 4695 {
 4696         struct mpt_hdr_stailq *lp;
 4697         struct ccb_hdr *srch;
 4698         int found = 0;
 4699         union ccb *accb = ccb->cab.abort_ccb;
 4700         tgt_resource_t *trtp;
 4701 
 4702         mpt_lprt(mpt, MPT_PRT_DEBUG, "aborting ccb %p\n", accb);
 4703 
 4704         if (ccb->ccb_h.target_lun == CAM_LUN_WILDCARD) {
 4705                 trtp = &mpt->trt_wildcard;
 4706         } else {
 4707                 trtp = &mpt->trt[ccb->ccb_h.target_lun];
 4708         }
 4709 
 4710         if (accb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
 4711                 lp = &trtp->atios;
 4712         } else if (accb->ccb_h.func_code == XPT_IMMED_NOTIFY) {
 4713                 lp = &trtp->inots;
 4714         } else {
 4715                 return (CAM_REQ_INVALID);
 4716         }
 4717 
 4718         STAILQ_FOREACH(srch, lp, sim_links.stqe) {
 4719                 if (srch == &accb->ccb_h) {
 4720                         found = 1;
 4721                         STAILQ_REMOVE(lp, srch, ccb_hdr, sim_links.stqe);
 4722                         break;
 4723                 }
 4724         }
 4725         if (found) {
 4726                 accb->ccb_h.status = CAM_REQ_ABORTED;
 4727                 xpt_done(accb);
 4728                 return (CAM_REQ_CMP);
 4729         }
 4730         mpt_prt(mpt, "mpt_abort_tgt_ccb: CCB %p not found\n", ccb);
 4731         return (CAM_PATH_INVALID);
 4732 }
 4733 
 4734 /*
 4735  * Ask the MPT to abort the current target command
 4736  */ 
 4737 static int
 4738 mpt_abort_target_cmd(struct mpt_softc *mpt, request_t *cmd_req)
 4739 {
 4740         int error;
 4741         request_t *req;
 4742         PTR_MSG_TARGET_MODE_ABORT abtp;
 4743 
 4744         req = mpt_get_request(mpt, FALSE);
 4745         if (req == NULL) {
 4746                 return (-1);
 4747         }
 4748         abtp = req->req_vbuf;
 4749         memset(abtp, 0, sizeof (*abtp));
 4750 
 4751         abtp->MsgContext = htole32(req->index | mpt->scsi_tgt_handler_id);
 4752         abtp->AbortType = TARGET_MODE_ABORT_TYPE_EXACT_IO;
 4753         abtp->Function = MPI_FUNCTION_TARGET_MODE_ABORT;
 4754         abtp->ReplyWord = htole32(MPT_TGT_STATE(mpt, cmd_req)->reply_desc);
 4755         error = 0;
 4756         if (mpt->is_fc || mpt->is_sas) {
 4757                 mpt_send_cmd(mpt, req);
 4758         } else {
 4759                 error = mpt_send_handshake_cmd(mpt, sizeof(*req), req);
 4760         }
 4761         return (error);
 4762 }
 4763 
 4764 /*
 4765  * WE_TRUST_AUTO_GOOD_STATUS- I've found that setting 
 4766  * TARGET_STATUS_SEND_FLAGS_AUTO_GOOD_STATUS leads the
 4767  * FC929 to set bogus FC_RSP fields (nonzero residuals
 4768  * but w/o RESID fields set). This causes QLogic initiators
 4769  * to think maybe that a frame was lost.
 4770  *
 4771  * WE_CAN_USE_AUTO_REPOST- we can't use AUTO_REPOST because
 4772  * we use allocated requests to do TARGET_ASSIST and we
 4773  * need to know when to release them.
 4774  */
 4775 
 4776 static void
 4777 mpt_scsi_tgt_status(struct mpt_softc *mpt, union ccb *ccb, request_t *cmd_req,
 4778     uint8_t status, uint8_t const *sense_data)
 4779 {
 4780         uint8_t *cmd_vbuf;
 4781         mpt_tgt_state_t *tgt;
 4782         PTR_MSG_TARGET_STATUS_SEND_REQUEST tp;
 4783         request_t *req;
 4784         bus_addr_t paddr;
 4785         int resplen = 0;
 4786         uint32_t fl;
 4787 
 4788         cmd_vbuf = cmd_req->req_vbuf;
 4789         cmd_vbuf += MPT_RQSL(mpt);
 4790         tgt = MPT_TGT_STATE(mpt, cmd_req);
 4791 
 4792         if ((req = mpt_get_request(mpt, FALSE)) == NULL) {
 4793                 if (mpt->outofbeer == 0) {
 4794                         mpt->outofbeer = 1;
 4795                         xpt_freeze_simq(mpt->sim, 1);
 4796                         mpt_lprt(mpt, MPT_PRT_DEBUG, "FREEZEQ\n");
 4797                 }
 4798                 if (ccb) {
 4799                         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 4800                         mpt_set_ccb_status(ccb, CAM_REQUEUE_REQ);
 4801                         xpt_done(ccb);
 4802                 } else {
 4803                         mpt_prt(mpt,
 4804                             "could not allocate status request- dropping\n");
 4805                 }
 4806                 return;
 4807         }
 4808         req->ccb = ccb;
 4809         if (ccb) {
 4810                 ccb->ccb_h.ccb_mpt_ptr = mpt;
 4811                 ccb->ccb_h.ccb_req_ptr = req;
 4812         }
 4813 
 4814         /*
 4815          * Record the currently active ccb, if any, and the
 4816          * request for it in our target state area.
 4817          */
 4818         tgt->ccb = ccb;
 4819         tgt->req = req;
 4820         tgt->state = TGT_STATE_SENDING_STATUS;
 4821 
 4822         tp = req->req_vbuf;
 4823         paddr = req->req_pbuf;
 4824         paddr += MPT_RQSL(mpt);
 4825 
 4826         memset(tp, 0, sizeof (*tp));
 4827         tp->Function = MPI_FUNCTION_TARGET_STATUS_SEND;
 4828         if (mpt->is_fc) {
 4829                 PTR_MPI_TARGET_FCP_CMD_BUFFER fc =
 4830                     (PTR_MPI_TARGET_FCP_CMD_BUFFER) cmd_vbuf;
 4831                 uint8_t *sts_vbuf;
 4832                 uint32_t *rsp;
 4833 
 4834                 sts_vbuf = req->req_vbuf;
 4835                 sts_vbuf += MPT_RQSL(mpt);
 4836                 rsp = (uint32_t *) sts_vbuf;
 4837                 memcpy(tp->LUN, fc->FcpLun, sizeof (tp->LUN));
 4838 
 4839                 /*
 4840                  * The MPI_TARGET_FCP_RSP_BUFFER define is unfortunate.
 4841                  * It has to be big-endian in memory and is organized
 4842                  * in 32 bit words, which are much easier to deal with
 4843                  * as words which are swizzled as needed.
 4844                  *
 4845                  * All we're filling here is the FC_RSP payload.
 4846                  * We may just have the chip synthesize it if
 4847                  * we have no residual and an OK status.
 4848                  *
 4849                  */
 4850                 memset(rsp, 0, sizeof (MPI_TARGET_FCP_RSP_BUFFER));
 4851 
 4852                 rsp[2] = status;
 4853                 if (tgt->resid) {
 4854                         rsp[2] |= 0x800;        /* XXXX NEED MNEMONIC!!!! */
 4855                         rsp[3] = htobe32(tgt->resid);
 4856 #ifdef  WE_TRUST_AUTO_GOOD_STATUS
 4857                         resplen = sizeof (MPI_TARGET_FCP_RSP_BUFFER);
 4858 #endif
 4859                 }
 4860                 if (status == SCSI_STATUS_CHECK_COND) {
 4861                         int i;
 4862 
 4863                         rsp[2] |= 0x200;        /* XXXX NEED MNEMONIC!!!! */
 4864                         rsp[4] = htobe32(MPT_SENSE_SIZE);
 4865                         if (sense_data) {
 4866                                 memcpy(&rsp[8], sense_data, MPT_SENSE_SIZE);
 4867                         } else {
 4868                                 mpt_prt(mpt, "mpt_scsi_tgt_status: CHECK CONDI"
 4869                                     "TION but no sense data?\n");
 4870                                 memset(&rsp, 0, MPT_SENSE_SIZE);
 4871                         }
 4872                         for (i = 8; i < (8 + (MPT_SENSE_SIZE >> 2)); i++) {
 4873                                 rsp[i] = htobe32(rsp[i]);
 4874                         }
 4875 #ifdef  WE_TRUST_AUTO_GOOD_STATUS
 4876                         resplen = sizeof (MPI_TARGET_FCP_RSP_BUFFER);
 4877 #endif
 4878                 }
 4879 #ifndef WE_TRUST_AUTO_GOOD_STATUS
 4880                 resplen = sizeof (MPI_TARGET_FCP_RSP_BUFFER);
 4881 #endif
 4882                 rsp[2] = htobe32(rsp[2]);
 4883         } else if (mpt->is_sas) {
 4884                 PTR_MPI_TARGET_SSP_CMD_BUFFER ssp =
 4885                     (PTR_MPI_TARGET_SSP_CMD_BUFFER) cmd_vbuf;
 4886                 memcpy(tp->LUN, ssp->LogicalUnitNumber, sizeof (tp->LUN));
 4887         } else {
 4888                 PTR_MPI_TARGET_SCSI_SPI_CMD_BUFFER sp =
 4889                     (PTR_MPI_TARGET_SCSI_SPI_CMD_BUFFER) cmd_vbuf;
 4890                 tp->StatusCode = status;
 4891                 tp->QueueTag = htole16(sp->Tag);
 4892                 memcpy(tp->LUN, sp->LogicalUnitNumber, sizeof (tp->LUN));
 4893         }
 4894 
 4895         tp->ReplyWord = htole32(tgt->reply_desc);
 4896         tp->MsgContext = htole32(req->index | mpt->scsi_tgt_handler_id);
 4897 
 4898 #ifdef  WE_CAN_USE_AUTO_REPOST
 4899         tp->MsgFlags = TARGET_STATUS_SEND_FLAGS_REPOST_CMD_BUFFER;
 4900 #endif
 4901         if (status == SCSI_STATUS_OK && resplen == 0) {
 4902                 tp->MsgFlags |= TARGET_STATUS_SEND_FLAGS_AUTO_GOOD_STATUS;
 4903         } else {
 4904                 tp->StatusDataSGE.u.Address32 = htole32((uint32_t) paddr);
 4905                 fl =
 4906                         MPI_SGE_FLAGS_HOST_TO_IOC       |
 4907                         MPI_SGE_FLAGS_SIMPLE_ELEMENT    |
 4908                         MPI_SGE_FLAGS_LAST_ELEMENT      |
 4909                         MPI_SGE_FLAGS_END_OF_LIST       |
 4910                         MPI_SGE_FLAGS_END_OF_BUFFER;
 4911                 fl <<= MPI_SGE_FLAGS_SHIFT;
 4912                 fl |= resplen;
 4913                 tp->StatusDataSGE.FlagsLength = htole32(fl);
 4914         }
 4915 
 4916         mpt_lprt(mpt, MPT_PRT_DEBUG, 
 4917             "STATUS_CCB %p (wit%s sense) tag %x req %p:%u resid %u\n",
 4918             ccb, sense_data?"h" : "hout", ccb? ccb->csio.tag_id : -1, req,
 4919             req->serno, tgt->resid);
 4920         if (ccb) {
 4921                 ccb->ccb_h.status = CAM_SIM_QUEUED | CAM_REQ_INPROG;
 4922                 mpt_req_timeout(req, 60 * hz, mpt_timeout, ccb);
 4923         }
 4924         mpt_send_cmd(mpt, req);
 4925 }
 4926 
 4927 static void
 4928 mpt_scsi_tgt_tsk_mgmt(struct mpt_softc *mpt, request_t *req, mpt_task_mgmt_t fc,
 4929     tgt_resource_t *trtp, int init_id)
 4930 {
 4931         struct ccb_immed_notify *inot;
 4932         mpt_tgt_state_t *tgt;
 4933 
 4934         tgt = MPT_TGT_STATE(mpt, req);
 4935         inot = (struct ccb_immed_notify *) STAILQ_FIRST(&trtp->inots);
 4936         if (inot == NULL) {
 4937                 mpt_lprt(mpt, MPT_PRT_WARN, "no INOTSs- sending back BSY\n");
 4938                 mpt_scsi_tgt_status(mpt, NULL, req, SCSI_STATUS_BUSY, NULL);
 4939                 return;
 4940         }
 4941         STAILQ_REMOVE_HEAD(&trtp->inots, sim_links.stqe);
 4942         mpt_lprt(mpt, MPT_PRT_DEBUG1,
 4943             "Get FREE INOT %p lun %d\n", inot, inot->ccb_h.target_lun);
 4944 
 4945         memset(&inot->sense_data, 0, sizeof (inot->sense_data));
 4946         inot->sense_len = 0;
 4947         memset(inot->message_args, 0, sizeof (inot->message_args));
 4948         inot->initiator_id = init_id;   /* XXX */
 4949 
 4950         /*
 4951          * This is a somewhat grotesque attempt to map from task management
 4952          * to old style SCSI messages. God help us all.
 4953          */
 4954         switch (fc) {
 4955         case MPT_ABORT_TASK_SET:
 4956                 inot->message_args[0] = MSG_ABORT_TAG;
 4957                 break;
 4958         case MPT_CLEAR_TASK_SET:
 4959                 inot->message_args[0] = MSG_CLEAR_TASK_SET;
 4960                 break;
 4961         case MPT_TARGET_RESET:
 4962                 inot->message_args[0] = MSG_TARGET_RESET;
 4963                 break;
 4964         case MPT_CLEAR_ACA:
 4965                 inot->message_args[0] = MSG_CLEAR_ACA;
 4966                 break;
 4967         case MPT_TERMINATE_TASK:
 4968                 inot->message_args[0] = MSG_ABORT_TAG;
 4969                 break;
 4970         default:
 4971                 inot->message_args[0] = MSG_NOOP;
 4972                 break;
 4973         }
 4974         tgt->ccb = (union ccb *) inot;
 4975         inot->ccb_h.status = CAM_MESSAGE_RECV|CAM_DEV_QFRZN;
 4976         xpt_done((union ccb *)inot);
 4977 }
 4978 
 4979 static void
 4980 mpt_scsi_tgt_atio(struct mpt_softc *mpt, request_t *req, uint32_t reply_desc)
 4981 {
 4982         static uint8_t null_iqd[SHORT_INQUIRY_LENGTH] = {
 4983             0x7f, 0x00, 0x02, 0x02, 0x20, 0x00, 0x00, 0x32,
 4984              'F',  'R',  'E',  'E',  'B',  'S',  'D',  ' ',
 4985              'L',  'S',  'I',  '-',  'L',  'O',  'G',  'I',
 4986              'C',  ' ',  'N',  'U',  'L',  'D',  'E',  'V',
 4987              '',  '',  '',  '1'
 4988         };
 4989         struct ccb_accept_tio *atiop;
 4990         lun_id_t lun;
 4991         int tag_action = 0;
 4992         mpt_tgt_state_t *tgt;
 4993         tgt_resource_t *trtp = NULL;
 4994         U8 *lunptr;
 4995         U8 *vbuf;
 4996         U16 itag;
 4997         U16 ioindex;
 4998         mpt_task_mgmt_t fct = MPT_NIL_TMT_VALUE;
 4999         uint8_t *cdbp;
 5000 
 5001         /*
 5002          * Stash info for the current command where we can get at it later.
 5003          */
 5004         vbuf = req->req_vbuf;
 5005         vbuf += MPT_RQSL(mpt);
 5006 
 5007         /*
 5008          * Get our state pointer set up.
 5009          */
 5010         tgt = MPT_TGT_STATE(mpt, req);
 5011         if (tgt->state != TGT_STATE_LOADED) {
 5012                 mpt_tgt_dump_req_state(mpt, req);
 5013                 panic("bad target state in mpt_scsi_tgt_atio");
 5014         }
 5015         memset(tgt, 0, sizeof (mpt_tgt_state_t));
 5016         tgt->state = TGT_STATE_IN_CAM;
 5017         tgt->reply_desc = reply_desc;
 5018         ioindex = GET_IO_INDEX(reply_desc);
 5019         if (mpt->verbose >= MPT_PRT_DEBUG) {
 5020                 mpt_dump_data(mpt, "mpt_scsi_tgt_atio response", vbuf,
 5021                     max(sizeof (MPI_TARGET_FCP_CMD_BUFFER),
 5022                     max(sizeof (MPI_TARGET_SSP_CMD_BUFFER),
 5023                     sizeof (MPI_TARGET_SCSI_SPI_CMD_BUFFER))));
 5024         }
 5025         if (mpt->is_fc) {
 5026                 PTR_MPI_TARGET_FCP_CMD_BUFFER fc;
 5027                 fc = (PTR_MPI_TARGET_FCP_CMD_BUFFER) vbuf;
 5028                 if (fc->FcpCntl[2]) {
 5029                         /*
 5030                          * Task Management Request
 5031                          */
 5032                         switch (fc->FcpCntl[2]) {
 5033                         case 0x2:
 5034                                 fct = MPT_ABORT_TASK_SET;
 5035                                 break;
 5036                         case 0x4:
 5037                                 fct = MPT_CLEAR_TASK_SET;
 5038                                 break;
 5039                         case 0x20:
 5040                                 fct = MPT_TARGET_RESET;
 5041                                 break;
 5042                         case 0x40:
 5043                                 fct = MPT_CLEAR_ACA;
 5044                                 break;
 5045                         case 0x80:
 5046                                 fct = MPT_TERMINATE_TASK;
 5047                                 break;
 5048                         default:
 5049                                 mpt_prt(mpt, "CORRUPTED TASK MGMT BITS: 0x%x\n",
 5050                                     fc->FcpCntl[2]);
 5051                                 mpt_scsi_tgt_status(mpt, 0, req,
 5052                                     SCSI_STATUS_OK, 0);
 5053                                 return;
 5054                         }
 5055                 } else {
 5056                         switch (fc->FcpCntl[1]) {
 5057                         case 0:
 5058                                 tag_action = MSG_SIMPLE_Q_TAG;
 5059                                 break;
 5060                         case 1:
 5061                                 tag_action = MSG_HEAD_OF_Q_TAG;
 5062                                 break;
 5063                         case 2:
 5064                                 tag_action = MSG_ORDERED_Q_TAG;
 5065                                 break;
 5066                         default:
 5067                                 /*
 5068                                  * Bah. Ignore Untagged Queing and ACA
 5069                                  */
 5070                                 tag_action = MSG_SIMPLE_Q_TAG;
 5071                                 break;
 5072                         }
 5073                 }
 5074                 tgt->resid = be32toh(fc->FcpDl);
 5075                 cdbp = fc->FcpCdb;
 5076                 lunptr = fc->FcpLun;
 5077                 itag = be16toh(fc->OptionalOxid);
 5078         } else if (mpt->is_sas) {
 5079                 PTR_MPI_TARGET_SSP_CMD_BUFFER ssp;
 5080                 ssp = (PTR_MPI_TARGET_SSP_CMD_BUFFER) vbuf;
 5081                 cdbp = ssp->CDB;
 5082                 lunptr = ssp->LogicalUnitNumber;
 5083                 itag = ssp->InitiatorTag;
 5084         } else {
 5085                 PTR_MPI_TARGET_SCSI_SPI_CMD_BUFFER sp;
 5086                 sp = (PTR_MPI_TARGET_SCSI_SPI_CMD_BUFFER) vbuf;
 5087                 cdbp = sp->CDB;
 5088                 lunptr = sp->LogicalUnitNumber;
 5089                 itag = sp->Tag;
 5090         }
 5091 
 5092         /*
 5093          * Generate a simple lun
 5094          */
 5095         switch (lunptr[0] & 0xc0) {
 5096         case 0x40:
 5097                 lun = ((lunptr[0] & 0x3f) << 8) | lunptr[1];
 5098                 break;
 5099         case 0:
 5100                 lun = lunptr[1];
 5101                 break;
 5102         default:
 5103                 mpt_lprt(mpt, MPT_PRT_ERROR, "cannot handle this type lun\n");
 5104                 lun = 0xffff;
 5105                 break;
 5106         }
 5107 
 5108         /*
 5109          * Deal with non-enabled or bad luns here.
 5110          */
 5111         if (lun >= MPT_MAX_LUNS || mpt->tenabled == 0 ||
 5112             mpt->trt[lun].enabled == 0) {
 5113                 if (mpt->twildcard) {
 5114                         trtp = &mpt->trt_wildcard;
 5115                 } else if (fct == MPT_NIL_TMT_VALUE) {
 5116                         /*
 5117                          * In this case, we haven't got an upstream listener
 5118                          * for either a specific lun or wildcard luns. We
 5119                          * have to make some sensible response. For regular
 5120                          * inquiry, just return some NOT HERE inquiry data.
 5121                          * For VPD inquiry, report illegal field in cdb.
 5122                          * For REQUEST SENSE, just return NO SENSE data.
 5123                          * REPORT LUNS gets illegal command.
 5124                          * All other commands get 'no such device'.
 5125                          */
 5126                         uint8_t *sp, cond, buf[MPT_SENSE_SIZE];
 5127                         size_t len;
 5128 
 5129                         memset(buf, 0, MPT_SENSE_SIZE);
 5130                         cond = SCSI_STATUS_CHECK_COND;
 5131                         buf[0] = 0xf0;
 5132                         buf[2] = 0x5;
 5133                         buf[7] = 0x8;
 5134                         sp = buf;
 5135                         tgt->tag_id = MPT_MAKE_TAGID(mpt, req, ioindex);
 5136 
 5137                         switch (cdbp[0]) {
 5138                         case INQUIRY:
 5139                         {
 5140                                 if (cdbp[1] != 0) {
 5141                                         buf[12] = 0x26;
 5142                                         buf[13] = 0x01;
 5143                                         break;
 5144                                 }
 5145                                 len = min(tgt->resid, cdbp[4]);
 5146                                 len = min(len, sizeof (null_iqd));
 5147                                 mpt_lprt(mpt, MPT_PRT_DEBUG,
 5148                                     "local inquiry %ld bytes\n", (long) len);
 5149                                 mpt_scsi_tgt_local(mpt, req, lun, 1,
 5150                                     null_iqd, len);
 5151                                 return;
 5152                         }
 5153                         case REQUEST_SENSE:
 5154                         {
 5155                                 buf[2] = 0x0;
 5156                                 len = min(tgt->resid, cdbp[4]);
 5157                                 len = min(len, sizeof (buf));
 5158                                 mpt_lprt(mpt, MPT_PRT_DEBUG,
 5159                                     "local reqsense %ld bytes\n", (long) len);
 5160                                 mpt_scsi_tgt_local(mpt, req, lun, 1,
 5161                                     buf, len);
 5162                                 return;
 5163                         }
 5164                         case REPORT_LUNS:
 5165                                 mpt_lprt(mpt, MPT_PRT_DEBUG, "REPORT LUNS\n");
 5166                                 buf[12] = 0x26;
 5167                                 return;
 5168                         default:
 5169                                 mpt_lprt(mpt, MPT_PRT_DEBUG,
 5170                                     "CMD 0x%x to unmanaged lun %u\n",
 5171                                     cdbp[0], lun);
 5172                                 buf[12] = 0x25;
 5173                                 break;
 5174                         }
 5175                         mpt_scsi_tgt_status(mpt, NULL, req, cond, sp);
 5176                         return;
 5177                 }
 5178                 /* otherwise, leave trtp NULL */
 5179         } else {
 5180                 trtp = &mpt->trt[lun];
 5181         }
 5182 
 5183         /*
 5184          * Deal with any task management
 5185          */
 5186         if (fct != MPT_NIL_TMT_VALUE) {
 5187                 if (trtp == NULL) {
 5188                         mpt_prt(mpt, "task mgmt function %x but no listener\n",
 5189                             fct);
 5190                         mpt_scsi_tgt_status(mpt, 0, req,
 5191                             SCSI_STATUS_OK, 0);
 5192                 } else {
 5193                         mpt_scsi_tgt_tsk_mgmt(mpt, req, fct, trtp,
 5194                             GET_INITIATOR_INDEX(reply_desc));
 5195                 }
 5196                 return;
 5197         }
 5198 
 5199 
 5200         atiop = (struct ccb_accept_tio *) STAILQ_FIRST(&trtp->atios);
 5201         if (atiop == NULL) {
 5202                 mpt_lprt(mpt, MPT_PRT_WARN,
 5203                     "no ATIOs for lun %u- sending back %s\n", lun,
 5204                     mpt->tenabled? "QUEUE FULL" : "BUSY");
 5205                 mpt_scsi_tgt_status(mpt, NULL, req,
 5206                     mpt->tenabled? SCSI_STATUS_QUEUE_FULL : SCSI_STATUS_BUSY,
 5207                     NULL);
 5208                 return;
 5209         }
 5210         STAILQ_REMOVE_HEAD(&trtp->atios, sim_links.stqe);
 5211         mpt_lprt(mpt, MPT_PRT_DEBUG1,
 5212             "Get FREE ATIO %p lun %d\n", atiop, atiop->ccb_h.target_lun);
 5213         atiop->ccb_h.ccb_mpt_ptr = mpt;
 5214         atiop->ccb_h.status = CAM_CDB_RECVD;
 5215         atiop->ccb_h.target_lun = lun;
 5216         atiop->sense_len = 0;
 5217         atiop->init_id = GET_INITIATOR_INDEX(reply_desc);
 5218         atiop->cdb_len = mpt_cdblen(cdbp[0], 16);
 5219         memcpy(atiop->cdb_io.cdb_bytes, cdbp, atiop->cdb_len);
 5220 
 5221         /*
 5222          * The tag we construct here allows us to find the
 5223          * original request that the command came in with.
 5224          *
 5225          * This way we don't have to depend on anything but the
 5226          * tag to find things when CCBs show back up from CAM.
 5227          */
 5228         atiop->tag_id = MPT_MAKE_TAGID(mpt, req, ioindex);
 5229         tgt->tag_id = atiop->tag_id;
 5230         if (tag_action) {
 5231                 atiop->tag_action = tag_action;
 5232                 atiop->ccb_h.flags = CAM_TAG_ACTION_VALID;
 5233         }
 5234         if (mpt->verbose >= MPT_PRT_DEBUG) {
 5235                 int i;
 5236                 mpt_prt(mpt, "START_CCB %p for lun %u CDB=<", atiop,
 5237                     atiop->ccb_h.target_lun);
 5238                 for (i = 0; i < atiop->cdb_len; i++) {
 5239                         mpt_prtc(mpt, "%02x%c", cdbp[i] & 0xff,
 5240                             (i == (atiop->cdb_len - 1))? '>' : ' ');
 5241                 }
 5242                 mpt_prtc(mpt, " itag %x tag %x rdesc %x dl=%u\n",
 5243                     itag, atiop->tag_id, tgt->reply_desc, tgt->resid);
 5244         }
 5245         
 5246         xpt_done((union ccb *)atiop);
 5247 }
 5248 
 5249 static void
 5250 mpt_tgt_dump_tgt_state(struct mpt_softc *mpt, request_t *req)
 5251 {
 5252         mpt_tgt_state_t *tgt = MPT_TGT_STATE(mpt, req);
 5253 
 5254         mpt_prt(mpt, "req %p:%u tgt:rdesc 0x%x resid %u xfrd %u ccb %p treq %p "
 5255             "nx %d tag 0x%08x state=%d\n", req, req->serno, tgt->reply_desc,
 5256             tgt->resid, tgt->bytes_xfered, tgt->ccb, tgt->req, tgt->nxfers,
 5257             tgt->tag_id, tgt->state);
 5258 }
 5259 
 5260 static void
 5261 mpt_tgt_dump_req_state(struct mpt_softc *mpt, request_t *req)
 5262 {
 5263 
 5264         mpt_prt(mpt, "req %p:%u index %u (%x) state %x\n", req, req->serno,
 5265             req->index, req->index, req->state);
 5266         mpt_tgt_dump_tgt_state(mpt, req);
 5267 }
 5268 
 5269 static int
 5270 mpt_scsi_tgt_reply_handler(struct mpt_softc *mpt, request_t *req,
 5271     uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame)
 5272 {
 5273         int dbg;
 5274         union ccb *ccb;
 5275         U16 status;
 5276 
 5277         if (reply_frame == NULL) {
 5278                 /*
 5279                  * Figure out what the state of the command is.
 5280                  */
 5281                 mpt_tgt_state_t *tgt = MPT_TGT_STATE(mpt, req);
 5282 
 5283 #ifdef  INVARIANTS
 5284                 mpt_req_spcl(mpt, req, "turbo scsi_tgt_reply", __LINE__);
 5285                 if (tgt->req) {
 5286                         mpt_req_not_spcl(mpt, tgt->req,
 5287                             "turbo scsi_tgt_reply associated req", __LINE__);
 5288                 }
 5289 #endif
 5290                 switch(tgt->state) {
 5291                 case TGT_STATE_LOADED:
 5292                         /*
 5293                          * This is a new command starting.
 5294                          */
 5295                         mpt_scsi_tgt_atio(mpt, req, reply_desc);
 5296                         break;
 5297                 case TGT_STATE_MOVING_DATA:
 5298                 {
 5299                         uint8_t *sp = NULL, sense[MPT_SENSE_SIZE];
 5300 
 5301                         ccb = tgt->ccb;
 5302                         if (tgt->req == NULL) {
 5303                                 panic("mpt: turbo target reply with null "
 5304                                     "associated request moving data");
 5305                                 /* NOTREACHED */
 5306                         }
 5307                         if (ccb == NULL) {
 5308                                 if (tgt->is_local == 0) {
 5309                                         panic("mpt: turbo target reply with "
 5310                                             "null associated ccb moving data");
 5311                                         /* NOTREACHED */
 5312                                 }
 5313                                 mpt_lprt(mpt, MPT_PRT_DEBUG,
 5314                                     "TARGET_ASSIST local done\n");
 5315                                 TAILQ_REMOVE(&mpt->request_pending_list,
 5316                                     tgt->req, links);
 5317                                 mpt_free_request(mpt, tgt->req);
 5318                                 tgt->req = NULL;
 5319                                 mpt_scsi_tgt_status(mpt, NULL, req,
 5320                                     0, NULL);
 5321                                 return (TRUE);
 5322                         }
 5323                         tgt->ccb = NULL;
 5324                         tgt->nxfers++;
 5325                         mpt_req_untimeout(req, mpt_timeout, ccb);
 5326                         mpt_lprt(mpt, MPT_PRT_DEBUG,
 5327                             "TARGET_ASSIST %p (req %p:%u) done tag 0x%x\n",
 5328                             ccb, tgt->req, tgt->req->serno, ccb->csio.tag_id);
 5329                         /*
 5330                          * Free the Target Assist Request
 5331                          */
 5332                         KASSERT(tgt->req->ccb == ccb,
 5333                             ("tgt->req %p:%u tgt->req->ccb %p", tgt->req,
 5334                             tgt->req->serno, tgt->req->ccb));
 5335                         TAILQ_REMOVE(&mpt->request_pending_list,
 5336                             tgt->req, links);
 5337                         mpt_free_request(mpt, tgt->req);
 5338                         tgt->req = NULL;
 5339 
 5340                         /*
 5341                          * Do we need to send status now? That is, are
 5342                          * we done with all our data transfers?
 5343                          */
 5344                         if ((ccb->ccb_h.flags & CAM_SEND_STATUS) == 0) {
 5345                                 mpt_set_ccb_status(ccb, CAM_REQ_CMP);
 5346                                 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 5347                                 KASSERT(ccb->ccb_h.status,
 5348                                     ("zero ccb sts at %d", __LINE__));
 5349                                 tgt->state = TGT_STATE_IN_CAM;
 5350                                 if (mpt->outofbeer) {
 5351                                         ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
 5352                                         mpt->outofbeer = 0;
 5353                                         mpt_lprt(mpt, MPT_PRT_DEBUG, "THAWQ\n");
 5354                                 }
 5355                                 xpt_done(ccb);
 5356                                 break;
 5357                         }
 5358                         /*
 5359                          * Otherwise, send status (and sense)
 5360                          */
 5361                         if (ccb->ccb_h.flags & CAM_SEND_SENSE) {
 5362                                 sp = sense;
 5363                                 memcpy(sp, &ccb->csio.sense_data,
 5364                                    min(ccb->csio.sense_len, MPT_SENSE_SIZE));
 5365                         }
 5366                         mpt_scsi_tgt_status(mpt, ccb, req,
 5367                             ccb->csio.scsi_status, sp);
 5368                         break;
 5369                 }
 5370                 case TGT_STATE_SENDING_STATUS:
 5371                 case TGT_STATE_MOVING_DATA_AND_STATUS:
 5372                 {
 5373                         int ioindex;
 5374                         ccb = tgt->ccb;
 5375 
 5376                         if (tgt->req == NULL) {
 5377                                 panic("mpt: turbo target reply with null "
 5378                                     "associated request sending status");
 5379                                 /* NOTREACHED */
 5380                         }
 5381 
 5382                         if (ccb) {
 5383                                 tgt->ccb = NULL;
 5384                                 if (tgt->state ==
 5385                                     TGT_STATE_MOVING_DATA_AND_STATUS) {
 5386                                         tgt->nxfers++;
 5387                                 }
 5388                                 mpt_req_untimeout(req, mpt_timeout, ccb);
 5389                                 if (ccb->ccb_h.flags & CAM_SEND_SENSE) {
 5390                                         ccb->ccb_h.status |= CAM_SENT_SENSE;
 5391                                 }
 5392                                 mpt_lprt(mpt, MPT_PRT_DEBUG,
 5393                                     "TARGET_STATUS tag %x sts %x flgs %x req "
 5394                                     "%p\n", ccb->csio.tag_id, ccb->ccb_h.status,
 5395                                     ccb->ccb_h.flags, tgt->req);
 5396                                 /*
 5397                                  * Free the Target Send Status Request
 5398                                  */
 5399                                 KASSERT(tgt->req->ccb == ccb,
 5400                                     ("tgt->req %p:%u tgt->req->ccb %p",
 5401                                     tgt->req, tgt->req->serno, tgt->req->ccb));
 5402                                 /*
 5403                                  * Notify CAM that we're done
 5404                                  */
 5405                                 mpt_set_ccb_status(ccb, CAM_REQ_CMP);
 5406                                 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 5407                                 KASSERT(ccb->ccb_h.status,
 5408                                     ("ZERO ccb sts at %d", __LINE__));
 5409                                 tgt->ccb = NULL;
 5410                         } else {
 5411                                 mpt_lprt(mpt, MPT_PRT_DEBUG,
 5412                                     "TARGET_STATUS non-CAM for  req %p:%u\n",
 5413                                     tgt->req, tgt->req->serno);
 5414                         }
 5415                         TAILQ_REMOVE(&mpt->request_pending_list,
 5416                             tgt->req, links);
 5417                         mpt_free_request(mpt, tgt->req);
 5418                         tgt->req = NULL;
 5419 
 5420                         /*
 5421                          * And re-post the Command Buffer.
 5422                          * This will reset the state.
 5423                          */
 5424                         ioindex = GET_IO_INDEX(reply_desc);
 5425                         TAILQ_REMOVE(&mpt->request_pending_list, req, links);
 5426                         tgt->is_local = 0;
 5427                         mpt_post_target_command(mpt, req, ioindex);
 5428 
 5429                         /*
 5430                          * And post a done for anyone who cares
 5431                          */
 5432                         if (ccb) {
 5433                                 if (mpt->outofbeer) {
 5434                                         ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
 5435                                         mpt->outofbeer = 0;
 5436                                         mpt_lprt(mpt, MPT_PRT_DEBUG, "THAWQ\n");
 5437                                 }
 5438                                 xpt_done(ccb);
 5439                         }
 5440                         break;
 5441                 }
 5442                 case TGT_STATE_NIL:     /* XXX This Never Happens XXX */
 5443                         tgt->state = TGT_STATE_LOADED;
 5444                         break;
 5445                 default:
 5446                         mpt_prt(mpt, "Unknown Target State 0x%x in Context "
 5447                             "Reply Function\n", tgt->state);
 5448                 }
 5449                 return (TRUE);
 5450         }
 5451 
 5452         status = le16toh(reply_frame->IOCStatus);
 5453         if (status != MPI_IOCSTATUS_SUCCESS) {
 5454                 dbg = MPT_PRT_ERROR;
 5455         } else {
 5456                 dbg = MPT_PRT_DEBUG1;
 5457         }
 5458 
 5459         mpt_lprt(mpt, dbg,
 5460             "SCSI_TGT REPLY: req=%p:%u reply=%p func=%x IOCstatus 0x%x\n",
 5461              req, req->serno, reply_frame, reply_frame->Function, status);
 5462 
 5463         switch (reply_frame->Function) {
 5464         case MPI_FUNCTION_TARGET_CMD_BUFFER_POST:
 5465         {
 5466                 mpt_tgt_state_t *tgt;
 5467 #ifdef  INVARIANTS
 5468                 mpt_req_spcl(mpt, req, "tgt reply BUFFER POST", __LINE__);
 5469 #endif
 5470                 if (status != MPI_IOCSTATUS_SUCCESS) {
 5471                         /*
 5472                          * XXX What to do?
 5473                          */
 5474                         break;
 5475                 }
 5476                 tgt = MPT_TGT_STATE(mpt, req);
 5477                 KASSERT(tgt->state == TGT_STATE_LOADING,
 5478                     ("bad state 0x%x on reply to buffer post", tgt->state));
 5479                 mpt_assign_serno(mpt, req);
 5480                 tgt->state = TGT_STATE_LOADED;
 5481                 break;
 5482         }
 5483         case MPI_FUNCTION_TARGET_ASSIST:
 5484 #ifdef  INVARIANTS
 5485                 mpt_req_not_spcl(mpt, req, "tgt reply TARGET ASSIST", __LINE__);
 5486 #endif
 5487                 mpt_prt(mpt, "target assist completion\n");
 5488                 TAILQ_REMOVE(&mpt->request_pending_list, req, links);
 5489                 mpt_free_request(mpt, req);
 5490                 break;
 5491         case MPI_FUNCTION_TARGET_STATUS_SEND:
 5492 #ifdef  INVARIANTS
 5493                 mpt_req_not_spcl(mpt, req, "tgt reply STATUS SEND", __LINE__);
 5494 #endif
 5495                 mpt_prt(mpt, "status send completion\n");
 5496                 TAILQ_REMOVE(&mpt->request_pending_list, req, links);
 5497                 mpt_free_request(mpt, req);
 5498                 break;
 5499         case MPI_FUNCTION_TARGET_MODE_ABORT:
 5500         {
 5501                 PTR_MSG_TARGET_MODE_ABORT_REPLY abtrp =
 5502                     (PTR_MSG_TARGET_MODE_ABORT_REPLY) reply_frame;
 5503                 PTR_MSG_TARGET_MODE_ABORT abtp =
 5504                     (PTR_MSG_TARGET_MODE_ABORT) req->req_vbuf;
 5505                 uint32_t cc = GET_IO_INDEX(le32toh(abtp->ReplyWord));
 5506 #ifdef  INVARIANTS
 5507                 mpt_req_not_spcl(mpt, req, "tgt reply TMODE ABORT", __LINE__);
 5508 #endif
 5509                 mpt_prt(mpt, "ABORT RX_ID 0x%x Complete; status 0x%x cnt %u\n",
 5510                     cc, le16toh(abtrp->IOCStatus), le32toh(abtrp->AbortCount));
 5511                 TAILQ_REMOVE(&mpt->request_pending_list, req, links);
 5512                 mpt_free_request(mpt, req);
 5513                 break;
 5514         }
 5515         default:
 5516                 mpt_prt(mpt, "Unknown Target Address Reply Function code: "
 5517                     "0x%x\n", reply_frame->Function);
 5518                 break;
 5519         }
 5520         return (TRUE);
 5521 }

Cache object: e630c0ace6cf654abbd235b56b25bb63


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