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

Cache object: 5baac6e19b24f4f322379378bdd10291


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