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/ocs_fc/ocs_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  * Copyright (c) 2017 Broadcom. All rights reserved.
    3  * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions are met:
    7  *
    8  * 1. Redistributions of source code must retain the above copyright notice,
    9  *    this list of conditions and the following disclaimer.
   10  *
   11  * 2. Redistributions in binary form must reproduce the above copyright notice,
   12  *    this list of conditions and the following disclaimer in the documentation
   13  *    and/or other materials provided with the distribution.
   14  *
   15  * 3. Neither the name of the copyright holder nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  *
   31  * $FreeBSD$
   32  */
   33 
   34 /**
   35  * @defgroup scsi_api_target SCSI Target API
   36  * @defgroup scsi_api_initiator SCSI Initiator API
   37  * @defgroup cam_api Common Access Method (CAM) API
   38  * @defgroup cam_io CAM IO
   39  */
   40 
   41 /**
   42  * @file
   43  * Provides CAM functionality.
   44  */
   45 
   46 #include "ocs.h"
   47 #include "ocs_scsi.h"
   48 #include "ocs_device.h"
   49 
   50 /* Default IO timeout value for initiators is 30 seconds */
   51 #define OCS_CAM_IO_TIMEOUT      30
   52 
   53 typedef struct {
   54         ocs_scsi_sgl_t *sgl;
   55         uint32_t sgl_max;
   56         uint32_t sgl_count;
   57         int32_t rc;
   58 } ocs_dmamap_load_arg_t;
   59 
   60 static void ocs_action(struct cam_sim *, union ccb *);
   61 static void ocs_poll(struct cam_sim *);
   62 
   63 static ocs_tgt_resource_t *ocs_tgt_resource_get(ocs_fcport *,
   64                                         struct ccb_hdr *, uint32_t *);
   65 static int32_t ocs_tgt_resource_abort(struct ocs_softc *, ocs_tgt_resource_t *);
   66 static uint32_t ocs_abort_initiator_io(struct ocs_softc *ocs, union ccb *accb);
   67 static void ocs_abort_inot(struct ocs_softc *ocs, union ccb *ccb);
   68 static void ocs_abort_atio(struct ocs_softc *ocs, union ccb *ccb);
   69 static int32_t ocs_target_tmf_cb(ocs_io_t *, ocs_scsi_io_status_e, uint32_t, void *);
   70 static int32_t ocs_io_abort_cb(ocs_io_t *, ocs_scsi_io_status_e, uint32_t, void *);
   71 static int32_t ocs_task_set_full_or_busy(ocs_io_t *io);
   72 static int32_t ocs_initiator_tmf_cb(ocs_io_t *, ocs_scsi_io_status_e,
   73                 ocs_scsi_cmd_resp_t *, uint32_t, void *);
   74 static uint32_t
   75 ocs_fcp_change_role(struct ocs_softc *ocs, ocs_fcport *fcp, uint32_t new_role);
   76 
   77 static void ocs_ldt(void *arg);
   78 static void ocs_ldt_task(void *arg, int pending);
   79 static void ocs_delete_target(ocs_t *ocs, ocs_fcport *fcp, int tgt);
   80 uint32_t ocs_add_new_tgt(ocs_node_t *node, ocs_fcport *fcp);
   81 uint32_t ocs_update_tgt(ocs_node_t *node, ocs_fcport *fcp, uint32_t tgt_id);
   82 
   83 int32_t ocs_tgt_find(ocs_fcport *fcp, ocs_node_t *node);
   84 
   85 static inline ocs_io_t *ocs_scsi_find_io(struct ocs_softc *ocs, uint32_t tag)
   86 {
   87 
   88         return ocs_io_get_instance(ocs, tag);
   89 }
   90 
   91 static inline void ocs_target_io_free(ocs_io_t *io)
   92 {
   93         io->tgt_io.state = OCS_CAM_IO_FREE;
   94         io->tgt_io.flags = 0;
   95         io->tgt_io.app = NULL;
   96         ocs_scsi_io_complete(io);
   97         if(io->ocs->io_in_use != 0)
   98                 atomic_subtract_acq_32(&io->ocs->io_in_use, 1);
   99 }
  100 
  101 static int32_t
  102 ocs_attach_port(ocs_t *ocs, int chan)
  103 {
  104 
  105         struct cam_sim  *sim = NULL;
  106         struct cam_path *path = NULL;
  107         uint32_t        max_io = ocs_scsi_get_property(ocs, OCS_SCSI_MAX_IOS);
  108         ocs_fcport *fcp = FCPORT(ocs, chan);
  109 
  110         if (NULL == (sim = cam_sim_alloc(ocs_action, ocs_poll, 
  111                                 device_get_name(ocs->dev), ocs, 
  112                                 device_get_unit(ocs->dev), &ocs->sim_lock,
  113                                 max_io, max_io, ocs->devq))) {
  114                 device_printf(ocs->dev, "Can't allocate SIM\n");
  115                 return 1;
  116         }
  117 
  118         mtx_lock(&ocs->sim_lock);
  119         if (CAM_SUCCESS != xpt_bus_register(sim, ocs->dev, chan)) {
  120                 device_printf(ocs->dev, "Can't register bus %d\n", 0);
  121                 mtx_unlock(&ocs->sim_lock);
  122                 cam_sim_free(sim, FALSE);
  123                 return 1;
  124         }
  125         mtx_unlock(&ocs->sim_lock);
  126 
  127         if (CAM_REQ_CMP != xpt_create_path(&path, NULL, cam_sim_path(sim),
  128                                 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD)) {
  129                 device_printf(ocs->dev, "Can't create path\n");
  130                 xpt_bus_deregister(cam_sim_path(sim));
  131                 mtx_unlock(&ocs->sim_lock);
  132                 cam_sim_free(sim, FALSE);
  133                 return 1;
  134         }
  135 
  136         fcp->ocs = ocs;
  137         fcp->sim  = sim;
  138         fcp->path = path;
  139 
  140         callout_init_mtx(&fcp->ldt, &ocs->sim_lock, 0);
  141         TASK_INIT(&fcp->ltask, 1, ocs_ldt_task, fcp);
  142 
  143         return 0;
  144 }
  145 
  146 static int32_t
  147 ocs_detach_port(ocs_t *ocs, int32_t chan)
  148 {
  149         ocs_fcport *fcp = NULL;
  150         struct cam_sim  *sim = NULL;
  151         struct cam_path *path = NULL;
  152         fcp = FCPORT(ocs, chan);
  153 
  154         sim = fcp->sim;
  155         path = fcp->path;
  156 
  157         callout_drain(&fcp->ldt);
  158         ocs_ldt_task(fcp, 0);   
  159 
  160         if (fcp->sim) {
  161                 mtx_lock(&ocs->sim_lock);
  162                         ocs_tgt_resource_abort(ocs, &fcp->targ_rsrc_wildcard);
  163                         if (path) {
  164                                 xpt_async(AC_LOST_DEVICE, path, NULL);
  165                                 xpt_free_path(path);
  166                                 fcp->path = NULL;
  167                         }
  168                         xpt_bus_deregister(cam_sim_path(sim));
  169 
  170                         cam_sim_free(sim, FALSE);
  171                         fcp->sim = NULL;
  172                 mtx_unlock(&ocs->sim_lock);
  173         }
  174 
  175         return 0;
  176 }
  177 
  178 int32_t
  179 ocs_cam_attach(ocs_t *ocs)
  180 {
  181         struct cam_devq *devq = NULL;
  182         int     i = 0;
  183         uint32_t        max_io = ocs_scsi_get_property(ocs, OCS_SCSI_MAX_IOS);
  184 
  185         if (NULL == (devq = cam_simq_alloc(max_io))) {
  186                 device_printf(ocs->dev, "Can't allocate SIMQ\n");
  187                 return -1;
  188         }
  189 
  190         ocs->devq = devq;
  191 
  192         if (mtx_initialized(&ocs->sim_lock) == 0) {
  193                 mtx_init(&ocs->sim_lock, "ocs_sim_lock", NULL, MTX_DEF);
  194         }
  195 
  196         for (i = 0; i < (ocs->num_vports + 1); i++) {
  197                 if (ocs_attach_port(ocs, i)) {
  198                         ocs_log_err(ocs, "Attach port failed for chan: %d\n", i);
  199                         goto detach_port;
  200                 }
  201         }
  202 
  203         ocs->io_high_watermark = max_io;
  204         ocs->io_in_use = 0;
  205         return 0;
  206 
  207 detach_port:
  208         while (--i >= 0) {
  209                 ocs_detach_port(ocs, i);
  210         }
  211 
  212         cam_simq_free(ocs->devq);
  213 
  214         if (mtx_initialized(&ocs->sim_lock))
  215                 mtx_destroy(&ocs->sim_lock);
  216 
  217         return 1;       
  218 }
  219 
  220 int32_t
  221 ocs_cam_detach(ocs_t *ocs)
  222 {
  223         int i = 0;
  224 
  225         for (i = (ocs->num_vports); i >= 0; i--) {
  226                 ocs_detach_port(ocs, i);
  227         }
  228 
  229         cam_simq_free(ocs->devq);
  230 
  231         if (mtx_initialized(&ocs->sim_lock))
  232                 mtx_destroy(&ocs->sim_lock);
  233 
  234         return 0;
  235 }
  236 
  237 /***************************************************************************
  238  * Functions required by SCSI base driver API
  239  */
  240 
  241 /**
  242  * @ingroup scsi_api_target
  243  * @brief Attach driver to the BSD SCSI layer (a.k.a CAM)
  244  *
  245  * Allocates + initializes CAM related resources and attaches to the CAM
  246  *
  247  * @param ocs the driver instance's software context
  248  *
  249  * @return 0 on success, non-zero otherwise
  250  */
  251 int32_t
  252 ocs_scsi_tgt_new_device(ocs_t *ocs)
  253 {
  254         ocs->enable_task_set_full = ocs_scsi_get_property(ocs, 
  255                                         OCS_SCSI_ENABLE_TASK_SET_FULL);
  256         ocs_log_debug(ocs, "task set full processing is %s\n",
  257                 ocs->enable_task_set_full ? "enabled" : "disabled");
  258 
  259         return 0;
  260 }
  261 
  262 /**
  263  * @ingroup scsi_api_target
  264  * @brief Tears down target members of ocs structure.
  265  *
  266  * Called by OS code when device is removed.
  267  *
  268  * @param ocs pointer to ocs
  269  *
  270  * @return returns 0 for success, a negative error code value for failure.
  271  */
  272 int32_t
  273 ocs_scsi_tgt_del_device(ocs_t *ocs)
  274 {
  275 
  276         return 0;
  277 }
  278 
  279 /**
  280  * @ingroup scsi_api_target
  281  * @brief accept new domain notification
  282  *
  283  * Called by base drive when new domain is discovered.  A target-server
  284  * will use this call to prepare for new remote node notifications
  285  * arising from ocs_scsi_new_initiator().
  286  *
  287  * The domain context has an element <b>ocs_scsi_tgt_domain_t tgt_domain</b> 
  288  * which is declared by the target-server code and is used for target-server 
  289  * private data.
  290  *
  291  * This function will only be called if the base-driver has been enabled for 
  292  * target capability.
  293  *
  294  * Note that this call is made to target-server backends, 
  295  * the ocs_scsi_ini_new_domain() function is called to initiator-client backends.
  296  *
  297  * @param domain pointer to domain
  298  *
  299  * @return returns 0 for success, a negative error code value for failure.
  300  */
  301 int32_t
  302 ocs_scsi_tgt_new_domain(ocs_domain_t *domain)
  303 {
  304         return 0;
  305 }
  306 
  307 /**
  308  * @ingroup scsi_api_target
  309  * @brief accept domain lost notification
  310  *
  311  * Called by base-driver when a domain goes away.  A target-server will
  312  * use this call to clean up all domain scoped resources.
  313  *
  314  * Note that this call is made to target-server backends,
  315  * the ocs_scsi_ini_del_domain() function is called to initiator-client backends.
  316  *
  317  * @param domain pointer to domain
  318  *
  319  * @return returns 0 for success, a negative error code value for failure.
  320  */
  321 void
  322 ocs_scsi_tgt_del_domain(ocs_domain_t *domain)
  323 {
  324 }
  325 
  326 /**
  327  * @ingroup scsi_api_target
  328  * @brief accept new sli port (sport) notification
  329  *
  330  * Called by base drive when new sport is discovered.  A target-server
  331  * will use this call to prepare for new remote node notifications
  332  * arising from ocs_scsi_new_initiator().
  333  *
  334  * The domain context has an element <b>ocs_scsi_tgt_sport_t tgt_sport</b> 
  335  * which is declared by the target-server code and is used for
  336  * target-server private data.
  337  *
  338  * This function will only be called if the base-driver has been enabled for 
  339  * target capability.
  340  *
  341  * Note that this call is made to target-server backends,
  342  * the ocs_scsi_tgt_new_domain() is called to initiator-client backends.
  343  *
  344  * @param sport pointer to SLI port
  345  *
  346  * @return returns 0 for success, a negative error code value for failure.
  347  */
  348 int32_t
  349 ocs_scsi_tgt_new_sport(ocs_sport_t *sport)
  350 {
  351         ocs_t *ocs = sport->ocs;
  352 
  353         if(!sport->is_vport) {
  354                 sport->tgt_data = FCPORT(ocs, 0);
  355         }
  356 
  357         return 0;
  358 }
  359 
  360 /**
  361  * @ingroup scsi_api_target
  362  * @brief accept SLI port gone notification
  363  *
  364  * Called by base-driver when a sport goes away.  A target-server will
  365  * use this call to clean up all sport scoped resources.
  366  *
  367  * Note that this call is made to target-server backends,
  368  * the ocs_scsi_ini_del_sport() is called to initiator-client backends.
  369  *
  370  * @param sport pointer to SLI port
  371  *
  372  * @return returns 0 for success, a negative error code value for failure.
  373  */
  374 void
  375 ocs_scsi_tgt_del_sport(ocs_sport_t *sport)
  376 {
  377         return;
  378 }
  379 
  380 /**
  381  * @ingroup scsi_api_target
  382  * @brief receive notification of a new SCSI initiator node
  383  *
  384  * Sent by base driver to notify a target-server of the presense of a new
  385  * remote initiator.   The target-server may use this call to prepare for
  386  * inbound IO from this node.
  387  *
  388  * The ocs_node_t structure has and elment of type ocs_scsi_tgt_node_t named
  389  * tgt_node that is declared and used by a target-server for private
  390  * information.
  391  *
  392  * This function is only called if the target capability is enabled in driver.
  393  *
  394  * @param node pointer to new remote initiator node
  395  *
  396  * @return returns 0 for success, a negative error code value for failure.
  397  *
  398  * @note
  399  */
  400 int32_t
  401 ocs_scsi_new_initiator(ocs_node_t *node)
  402 {
  403         ocs_t   *ocs = node->ocs;
  404         struct ac_contract ac;
  405         struct ac_device_changed *adc;
  406 
  407         ocs_fcport      *fcp = NULL;
  408 
  409         fcp = node->sport->tgt_data;
  410         if (fcp == NULL) {
  411                 ocs_log_err(ocs, "FCP is NULL \n");
  412                 return 1;
  413         }       
  414 
  415         /*
  416          * Update the IO watermark by decrementing it by the
  417          * number of IOs reserved for each initiator.
  418          */
  419         atomic_subtract_acq_32(&ocs->io_high_watermark, OCS_RSVD_INI_IO);
  420 
  421         ac.contract_number = AC_CONTRACT_DEV_CHG;
  422         adc = (struct ac_device_changed *) ac.contract_data;
  423         adc->wwpn = ocs_node_get_wwpn(node);
  424         adc->port = node->rnode.fc_id;
  425         adc->target = node->instance_index;
  426         adc->arrived = 1;
  427         xpt_async(AC_CONTRACT, fcp->path, &ac);
  428 
  429         return 0;
  430 }
  431 
  432 /**
  433  * @ingroup scsi_api_target
  434  * @brief validate new initiator
  435  *
  436  * Sent by base driver to validate a remote initiatiator.   The target-server
  437  * returns TRUE if this initiator should be accepted.
  438  *
  439  * This function is only called if the target capability is enabled in driver.
  440  *
  441  * @param node pointer to remote initiator node to validate
  442  *
  443  * @return TRUE if initiator should be accepted, FALSE if it should be rejected
  444  *
  445  * @note
  446  */
  447 
  448 int32_t
  449 ocs_scsi_validate_initiator(ocs_node_t *node)
  450 {
  451         return 1;
  452 }
  453 
  454 /**
  455  * @ingroup scsi_api_target
  456  * @brief Delete a SCSI initiator node
  457  *
  458  * Sent by base driver to notify a target-server that a remote initiator
  459  * is now gone. The base driver will have terminated all outstanding IOs 
  460  * and the target-server will receive appropriate completions.
  461  *
  462  * This function is only called if the base driver is enabled for
  463  * target capability.
  464  *
  465  * @param node pointer node being deleted
  466  * @param reason Reason why initiator is gone.
  467  *
  468  * @return OCS_SCSI_CALL_COMPLETE to indicate that all work was completed
  469  *
  470  * @note
  471  */
  472 int32_t
  473 ocs_scsi_del_initiator(ocs_node_t *node, ocs_scsi_del_initiator_reason_e reason)
  474 {
  475         ocs_t   *ocs = node->ocs;
  476 
  477         struct ac_contract ac;
  478         struct ac_device_changed *adc;
  479         ocs_fcport      *fcp = NULL;
  480 
  481         fcp = node->sport->tgt_data;
  482         if (fcp == NULL) {
  483                 ocs_log_err(ocs, "FCP is NULL \n");
  484                 return 1;
  485         }
  486 
  487         ac.contract_number = AC_CONTRACT_DEV_CHG;
  488         adc = (struct ac_device_changed *) ac.contract_data;
  489         adc->wwpn = ocs_node_get_wwpn(node);
  490         adc->port = node->rnode.fc_id;
  491         adc->target = node->instance_index;
  492         adc->arrived = 0;
  493         xpt_async(AC_CONTRACT, fcp->path, &ac);
  494 
  495         if (reason == OCS_SCSI_INITIATOR_MISSING) {
  496                 return OCS_SCSI_CALL_COMPLETE;
  497         }
  498 
  499         /*
  500          * Update the IO watermark by incrementing it by the
  501          * number of IOs reserved for each initiator.
  502          */
  503         atomic_add_acq_32(&ocs->io_high_watermark, OCS_RSVD_INI_IO);
  504 
  505         return OCS_SCSI_CALL_COMPLETE;
  506 }
  507 
  508 /**
  509  * @ingroup scsi_api_target
  510  * @brief receive FCP SCSI Command
  511  *
  512  * Called by the base driver when a new SCSI command has been received.   The
  513  * target-server will process the command, and issue data and/or response phase
  514  * requests to the base driver.
  515  *
  516  * The IO context (ocs_io_t) structure has and element of type 
  517  * ocs_scsi_tgt_io_t named tgt_io that is declared and used by 
  518  * a target-server for private information.
  519  *
  520  * @param io pointer to IO context
  521  * @param lun LUN for this IO
  522  * @param cdb pointer to SCSI CDB
  523  * @param cdb_len length of CDB in bytes
  524  * @param flags command flags
  525  *
  526  * @return returns 0 for success, a negative error code value for failure.
  527  */
  528 int32_t ocs_scsi_recv_cmd(ocs_io_t *io, uint64_t lun, uint8_t *cdb,
  529                                 uint32_t cdb_len, uint32_t flags)
  530 {
  531         ocs_t *ocs = io->ocs;
  532         struct ccb_accept_tio *atio = NULL;
  533         ocs_node_t      *node = io->node;
  534         ocs_tgt_resource_t *trsrc = NULL;
  535         int32_t         rc = -1;
  536         ocs_fcport      *fcp = NULL;
  537 
  538         fcp = node->sport->tgt_data;
  539         if (fcp == NULL) {
  540                 ocs_log_err(ocs, "FCP is NULL \n");
  541                 return 1;
  542         }
  543 
  544         atomic_add_acq_32(&ocs->io_in_use, 1);
  545 
  546         /* set target io timeout */
  547         io->timeout = ocs->target_io_timer_sec;
  548 
  549         if (ocs->enable_task_set_full && 
  550                 (ocs->io_in_use >= ocs->io_high_watermark)) {
  551                 return ocs_task_set_full_or_busy(io);
  552         } else {
  553                 atomic_store_rel_32(&io->node->tgt_node.busy_sent, FALSE);
  554         }
  555 
  556         if ((lun < OCS_MAX_LUN) && fcp->targ_rsrc[lun].enabled) {
  557                 trsrc = &fcp->targ_rsrc[lun];
  558         } else if (fcp->targ_rsrc_wildcard.enabled) {
  559                 trsrc = &fcp->targ_rsrc_wildcard;
  560         }
  561 
  562         if (trsrc) {
  563                 atio = (struct ccb_accept_tio *)STAILQ_FIRST(&trsrc->atio);
  564         }
  565 
  566         if (atio) {
  567                 STAILQ_REMOVE_HEAD(&trsrc->atio, sim_links.stqe);
  568 
  569                 atio->ccb_h.status = CAM_CDB_RECVD;
  570                 atio->ccb_h.target_lun = lun;
  571                 atio->sense_len = 0;
  572 
  573                 atio->init_id = node->instance_index;
  574                 atio->tag_id = io->tag;
  575                 atio->ccb_h.ccb_io_ptr = io;
  576 
  577                 if (flags & OCS_SCSI_CMD_SIMPLE)
  578                         atio->tag_action = MSG_SIMPLE_Q_TAG;
  579                 else if (flags & OCS_SCSI_CMD_HEAD_OF_QUEUE)
  580                         atio->tag_action = MSG_HEAD_OF_Q_TAG;
  581                 else if (flags & OCS_SCSI_CMD_ORDERED)
  582                         atio->tag_action = MSG_ORDERED_Q_TAG;
  583                 else if (flags & OCS_SCSI_CMD_ACA)
  584                         atio->tag_action = MSG_ACA_TASK;
  585                 else
  586                         atio->tag_action = CAM_TAG_ACTION_NONE;
  587                 atio->priority = (flags & OCS_SCSI_PRIORITY_MASK) >>
  588                     OCS_SCSI_PRIORITY_SHIFT;
  589 
  590                 atio->cdb_len = cdb_len;
  591                 ocs_memcpy(atio->cdb_io.cdb_bytes, cdb, cdb_len);
  592 
  593                 io->tgt_io.flags = 0;
  594                 io->tgt_io.state = OCS_CAM_IO_COMMAND;
  595                 io->tgt_io.lun = lun;
  596 
  597                 xpt_done((union ccb *)atio);
  598 
  599                 rc = 0;
  600         } else {
  601                 device_printf(
  602                         ocs->dev, "%s: no ATIO for LUN %lx (en=%s) OX_ID %#x\n",
  603                         __func__, (unsigned long)lun,
  604                         trsrc ? (trsrc->enabled ? "T" : "F") : "X",
  605                         be16toh(io->init_task_tag));
  606 
  607                 io->tgt_io.state = OCS_CAM_IO_MAX;
  608                 ocs_target_io_free(io);
  609         }
  610 
  611         return rc;
  612 }
  613 
  614 /**
  615  * @ingroup scsi_api_target
  616  * @brief receive FCP SCSI Command with first burst data.
  617  *
  618  * Receive a new FCP SCSI command from the base driver with first burst data.
  619  *
  620  * @param io pointer to IO context
  621  * @param lun LUN for this IO
  622  * @param cdb pointer to SCSI CDB
  623  * @param cdb_len length of CDB in bytes
  624  * @param flags command flags
  625  * @param first_burst_buffers first burst buffers
  626  * @param first_burst_buffer_count The number of bytes received in the first burst
  627  *
  628  * @return returns 0 for success, a negative error code value for failure.
  629  */
  630 int32_t ocs_scsi_recv_cmd_first_burst(ocs_io_t *io, uint64_t lun, uint8_t *cdb,
  631                                         uint32_t cdb_len, uint32_t flags, 
  632                                         ocs_dma_t first_burst_buffers[], 
  633                                         uint32_t first_burst_buffer_count)
  634 {
  635         return -1;
  636 }
  637 
  638 /**
  639  * @ingroup scsi_api_target
  640  * @brief receive a TMF command IO
  641  *
  642  * Called by the base driver when a SCSI TMF command has been received.   The
  643  * target-server will process the command, aborting commands as needed, and post
  644  * a response using ocs_scsi_send_resp()
  645  *
  646  * The IO context (ocs_io_t) structure has and element of type ocs_scsi_tgt_io_t named
  647  * tgt_io that is declared and used by a target-server for private information.
  648  *
  649  * If the target-server walks the nodes active_ios linked list, and starts IO
  650  * abort processing, the code <b>must</b> be sure not to abort the IO passed into the
  651  * ocs_scsi_recv_tmf() command.
  652  *
  653  * @param tmfio pointer to IO context
  654  * @param lun logical unit value
  655  * @param cmd command request
  656  * @param abortio pointer to IO object to abort for TASK_ABORT (NULL for all other TMF)
  657  * @param flags flags
  658  *
  659  * @return returns 0 for success, a negative error code value for failure.
  660  */
  661 int32_t ocs_scsi_recv_tmf(ocs_io_t *tmfio, uint64_t lun, ocs_scsi_tmf_cmd_e cmd,
  662                                 ocs_io_t *abortio, uint32_t flags)
  663 {
  664         ocs_t *ocs = tmfio->ocs;
  665         ocs_node_t *node = tmfio->node;
  666         ocs_tgt_resource_t *trsrc = NULL;
  667         struct ccb_immediate_notify *inot = NULL;
  668         int32_t         rc = -1;
  669         ocs_fcport      *fcp = NULL;
  670 
  671         fcp = node->sport->tgt_data;
  672         if (fcp == NULL) {
  673                 ocs_log_err(ocs, "FCP is NULL \n");
  674                 return 1;
  675         }
  676 
  677         if ((lun < OCS_MAX_LUN) && fcp->targ_rsrc[lun].enabled) {
  678                 trsrc = &fcp->targ_rsrc[lun];
  679         } else if (fcp->targ_rsrc_wildcard.enabled) {
  680                 trsrc = &fcp->targ_rsrc_wildcard;
  681         }
  682 
  683         device_printf(tmfio->ocs->dev, "%s: io=%p cmd=%#x LU=%lx en=%s\n",
  684                         __func__, tmfio, cmd, (unsigned long)lun,
  685                         trsrc ? (trsrc->enabled ? "T" : "F") : "X");
  686         if (trsrc) {
  687                 inot = (struct ccb_immediate_notify *)STAILQ_FIRST(&trsrc->inot);
  688         }
  689 
  690         if (!inot) {
  691                 device_printf(
  692                         ocs->dev, "%s: no INOT for LUN %llx (en=%s) OX_ID %#x\n",
  693                         __func__, (unsigned long long)lun, trsrc ? (trsrc->enabled ? "T" : "F") : "X",
  694                         be16toh(tmfio->init_task_tag));
  695 
  696                 if (abortio) {
  697                         ocs_scsi_io_complete(abortio);
  698                 }
  699                 ocs_scsi_io_complete(tmfio);
  700                 goto ocs_scsi_recv_tmf_out;
  701         }
  702 
  703         tmfio->tgt_io.app = abortio;
  704 
  705         STAILQ_REMOVE_HEAD(&trsrc->inot, sim_links.stqe);
  706 
  707         inot->tag_id = tmfio->tag;
  708         inot->seq_id = tmfio->tag;
  709 
  710         if ((lun < OCS_MAX_LUN) && fcp->targ_rsrc[lun].enabled) {
  711                 inot->initiator_id = node->instance_index;
  712         } else {
  713                 inot->initiator_id = CAM_TARGET_WILDCARD;
  714         } 
  715 
  716         inot->ccb_h.status = CAM_MESSAGE_RECV;
  717         inot->ccb_h.target_lun = lun;
  718 
  719         switch (cmd) {
  720         case OCS_SCSI_TMF_ABORT_TASK:
  721                 inot->arg = MSG_ABORT_TASK;
  722                 inot->seq_id = abortio->tag;
  723                 device_printf(ocs->dev, "%s: ABTS IO.%#x st=%#x\n", 
  724                         __func__, abortio->tag, abortio->tgt_io.state);
  725                 abortio->tgt_io.flags |= OCS_CAM_IO_F_ABORT_RECV;
  726                 abortio->tgt_io.flags |= OCS_CAM_IO_F_ABORT_NOTIFY;
  727                 break;
  728         case OCS_SCSI_TMF_QUERY_TASK_SET:
  729                 device_printf(ocs->dev, 
  730                         "%s: OCS_SCSI_TMF_QUERY_TASK_SET not supported\n",
  731                                 __func__);
  732                 STAILQ_INSERT_TAIL(&trsrc->inot, &inot->ccb_h, sim_links.stqe);
  733                 ocs_scsi_io_complete(tmfio);
  734                 goto ocs_scsi_recv_tmf_out;
  735                 break;
  736         case OCS_SCSI_TMF_ABORT_TASK_SET:
  737                 inot->arg = MSG_ABORT_TASK_SET;
  738                 break;
  739         case OCS_SCSI_TMF_CLEAR_TASK_SET:
  740                 inot->arg = MSG_CLEAR_TASK_SET;
  741                 break;
  742         case OCS_SCSI_TMF_QUERY_ASYNCHRONOUS_EVENT:
  743                 inot->arg = MSG_QUERY_ASYNC_EVENT;
  744                 break;
  745         case OCS_SCSI_TMF_LOGICAL_UNIT_RESET:
  746                 inot->arg = MSG_LOGICAL_UNIT_RESET;
  747                 break;
  748         case OCS_SCSI_TMF_CLEAR_ACA:
  749                 inot->arg = MSG_CLEAR_ACA;
  750                 break;
  751         case OCS_SCSI_TMF_TARGET_RESET:
  752                 inot->arg = MSG_TARGET_RESET;
  753                 break;
  754         default:
  755                 device_printf(ocs->dev, "%s: unsupported TMF %#x\n",
  756                                                          __func__, cmd);
  757                 STAILQ_INSERT_TAIL(&trsrc->inot, &inot->ccb_h, sim_links.stqe);
  758                 goto ocs_scsi_recv_tmf_out;
  759         }
  760 
  761         rc = 0;
  762 
  763         xpt_print(inot->ccb_h.path, "%s: func=%#x stat=%#x id=%#x lun=%#x"
  764                         " flags=%#x tag=%#x seq=%#x ini=%#x arg=%#x\n", 
  765                         __func__, inot->ccb_h.func_code, inot->ccb_h.status,
  766                         inot->ccb_h.target_id, 
  767                         (unsigned int)inot->ccb_h.target_lun, inot->ccb_h.flags,
  768                         inot->tag_id, inot->seq_id, inot->initiator_id,
  769                         inot->arg);
  770         xpt_done((union ccb *)inot);
  771 
  772         if (abortio) {
  773                 abortio->tgt_io.flags |= OCS_CAM_IO_F_ABORT_DEV;
  774                 rc = ocs_scsi_tgt_abort_io(abortio, ocs_io_abort_cb, tmfio);
  775         }
  776 
  777 ocs_scsi_recv_tmf_out:
  778         return rc;
  779 }
  780 
  781 /**
  782  * @ingroup scsi_api_initiator
  783  * @brief Initializes any initiator fields on the ocs structure.
  784  *
  785  * Called by OS initialization code when a new device is discovered.
  786  *
  787  * @param ocs pointer to ocs
  788  *
  789  * @return returns 0 for success, a negative error code value for failure.
  790  */
  791 int32_t
  792 ocs_scsi_ini_new_device(ocs_t *ocs)
  793 {
  794 
  795         return 0;
  796 }
  797 
  798 /**
  799  * @ingroup scsi_api_initiator
  800  * @brief Tears down initiator members of ocs structure.
  801  *
  802  * Called by OS code when device is removed.
  803  *
  804  * @param ocs pointer to ocs
  805  *
  806  * @return returns 0 for success, a negative error code value for failure.
  807  */
  808 
  809 int32_t
  810 ocs_scsi_ini_del_device(ocs_t *ocs)
  811 {
  812 
  813         return 0;
  814 }
  815 
  816 /**
  817  * @ingroup scsi_api_initiator
  818  * @brief accept new domain notification
  819  *
  820  * Called by base drive when new domain is discovered.  An initiator-client
  821  * will accept this call to prepare for new remote node notifications
  822  * arising from ocs_scsi_new_target().
  823  *
  824  * The domain context has the element <b>ocs_scsi_ini_domain_t ini_domain</b>
  825  * which is declared by the initiator-client code and is used for 
  826  * initiator-client private data.
  827  *
  828  * This function will only be called if the base-driver has been enabled for 
  829  * initiator capability.
  830  *
  831  * Note that this call is made to initiator-client backends, 
  832  * the ocs_scsi_tgt_new_domain() function is called to target-server backends.
  833  *
  834  * @param domain pointer to domain
  835  *
  836  * @return returns 0 for success, a negative error code value for failure.
  837  */
  838 int32_t
  839 ocs_scsi_ini_new_domain(ocs_domain_t *domain)
  840 {
  841         return 0;
  842 }
  843 
  844 /**
  845  * @ingroup scsi_api_initiator
  846  * @brief accept domain lost notification
  847  *
  848  * Called by base-driver when a domain goes away.  An initiator-client will
  849  * use this call to clean up all domain scoped resources.
  850  *
  851  * This function will only be called if the base-driver has been enabled for
  852  * initiator capability.
  853  *
  854  * Note that this call is made to initiator-client backends,
  855  * the ocs_scsi_tgt_del_domain() function is called to target-server backends.
  856  *
  857  * @param domain pointer to domain
  858  *
  859  * @return returns 0 for success, a negative error code value for failure.
  860  */
  861 void
  862 ocs_scsi_ini_del_domain(ocs_domain_t *domain)
  863 {
  864 }
  865 
  866 /**
  867  * @ingroup scsi_api_initiator
  868  * @brief accept new sli port notification
  869  *
  870  * Called by base drive when new sli port (sport) is discovered.
  871  * A target-server will use this call to prepare for new remote node
  872  * notifications arising from ocs_scsi_new_initiator().
  873  *
  874  * This function will only be called if the base-driver has been enabled for
  875  * target capability.
  876  *
  877  * Note that this call is made to target-server backends,
  878  * the ocs_scsi_ini_new_sport() function is called to initiator-client backends.
  879  *
  880  * @param sport pointer to sport
  881  *
  882  * @return returns 0 for success, a negative error code value for failure.
  883  */
  884 int32_t
  885 ocs_scsi_ini_new_sport(ocs_sport_t *sport)
  886 {
  887         ocs_t *ocs = sport->ocs;
  888         ocs_fcport *fcp = FCPORT(ocs, 0);
  889 
  890         if (!sport->is_vport) {
  891                 sport->tgt_data = fcp;
  892                 fcp->fc_id = sport->fc_id;      
  893         }
  894 
  895         return 0;
  896 }
  897 
  898 /**
  899  * @ingroup scsi_api_initiator
  900  * @brief accept sli port gone notification
  901  *
  902  * Called by base-driver when a sport goes away.  A target-server will
  903  * use this call to clean up all sport scoped resources.
  904  *
  905  * Note that this call is made to target-server backends,
  906  * the ocs_scsi_ini_del_sport() function is called to initiator-client backends.
  907  *
  908  * @param sport pointer to SLI port
  909  *
  910  * @return returns 0 for success, a negative error code value for failure.
  911  */
  912 void
  913 ocs_scsi_ini_del_sport(ocs_sport_t *sport)
  914 {
  915         ocs_t *ocs = sport->ocs;
  916         ocs_fcport *fcp = FCPORT(ocs, 0);
  917 
  918         if (!sport->is_vport) {
  919                 fcp->fc_id = 0; 
  920         }
  921 }
  922 
  923 void 
  924 ocs_scsi_sport_deleted(ocs_sport_t *sport)
  925 {
  926         ocs_t *ocs = sport->ocs;
  927         ocs_fcport *fcp = NULL;
  928 
  929         ocs_xport_stats_t value;
  930 
  931         if (!sport->is_vport) {
  932                 return;
  933         }
  934 
  935         fcp = sport->tgt_data;
  936 
  937         ocs_xport_status(ocs->xport, OCS_XPORT_PORT_STATUS, &value);
  938 
  939         if (value.value == 0) {
  940                 ocs_log_debug(ocs, "PORT offline,.. skipping\n");
  941                 return;
  942         }       
  943 
  944         if ((fcp->role != KNOB_ROLE_NONE)) {
  945                 if(fcp->vport->sport != NULL) {
  946                         ocs_log_debug(ocs,"sport is not NULL, skipping\n");
  947                         return;
  948                 }
  949 
  950                 ocs_sport_vport_alloc(ocs->domain, fcp->vport);
  951                 return;
  952         }
  953 
  954 }
  955 
  956 int32_t
  957 ocs_tgt_find(ocs_fcport *fcp, ocs_node_t *node)
  958 {
  959         ocs_fc_target_t *tgt = NULL;
  960         uint32_t i;
  961 
  962         for (i = 0; i < OCS_MAX_TARGETS; i++) {
  963                 tgt = &fcp->tgt[i];
  964 
  965                 if (tgt->state == OCS_TGT_STATE_NONE)
  966                         continue;
  967                 
  968                 if (ocs_node_get_wwpn(node) == tgt->wwpn) {
  969                         return i;
  970                 }
  971         }
  972 
  973         return -1;
  974 }
  975 
  976 /**
  977  * @ingroup scsi_api_initiator
  978  * @brief receive notification of a new SCSI target node
  979  *
  980  * Sent by base driver to notify an initiator-client of the presense of a new
  981  * remote target.   The initiator-server may use this call to prepare for
  982  * inbound IO from this node.
  983  *
  984  * This function is only called if the base driver is enabled for
  985  * initiator capability.
  986  *
  987  * @param node pointer to new remote initiator node
  988  *
  989  * @return none
  990  *
  991  * @note
  992  */
  993 
  994 uint32_t
  995 ocs_update_tgt(ocs_node_t *node, ocs_fcport *fcp, uint32_t tgt_id)
  996 {
  997         ocs_fc_target_t *tgt = NULL;
  998 
  999         tgt = &fcp->tgt[tgt_id];
 1000 
 1001         tgt->node_id = node->instance_index;
 1002         tgt->state = OCS_TGT_STATE_VALID;
 1003 
 1004         tgt->port_id = node->rnode.fc_id;
 1005         tgt->wwpn = ocs_node_get_wwpn(node);
 1006         tgt->wwnn = ocs_node_get_wwnn(node);
 1007         return 0;
 1008 }
 1009 
 1010 uint32_t
 1011 ocs_add_new_tgt(ocs_node_t *node, ocs_fcport *fcp)
 1012 {
 1013         uint32_t i;
 1014 
 1015         struct ocs_softc *ocs = node->ocs;
 1016         union ccb *ccb = NULL;
 1017         for (i = 0; i < OCS_MAX_TARGETS; i++) {
 1018                 if (fcp->tgt[i].state == OCS_TGT_STATE_NONE)
 1019                         break;
 1020         }
 1021 
 1022         if (NULL == (ccb = xpt_alloc_ccb_nowait())) {
 1023                 device_printf(ocs->dev, "%s: ccb allocation failed\n", __func__);
 1024                 return -1;
 1025         }
 1026 
 1027         if (CAM_REQ_CMP != xpt_create_path(&ccb->ccb_h.path, xpt_periph,
 1028                                 cam_sim_path(fcp->sim),
 1029                                 i, CAM_LUN_WILDCARD)) {
 1030                 device_printf(
 1031                         ocs->dev, "%s: target path creation failed\n", __func__);
 1032                 xpt_free_ccb(ccb);
 1033                 return -1;
 1034         }
 1035 
 1036         ocs_update_tgt(node, fcp, i);
 1037         xpt_rescan(ccb);
 1038         return 0;
 1039 }
 1040 
 1041 int32_t
 1042 ocs_scsi_new_target(ocs_node_t *node)
 1043 {
 1044         ocs_fcport      *fcp = NULL;
 1045         int32_t i;
 1046 
 1047         fcp = node->sport->tgt_data;
 1048         if (fcp == NULL) {
 1049                 printf("%s:FCP is NULL \n", __func__);
 1050                 return 0;
 1051         }
 1052 
 1053         i = ocs_tgt_find(fcp, node);
 1054 
 1055         if (i < 0) {
 1056                 ocs_add_new_tgt(node, fcp);
 1057                 return 0;
 1058         }
 1059 
 1060         ocs_update_tgt(node, fcp, i);
 1061         return 0;
 1062 }
 1063 
 1064 static void
 1065 ocs_delete_target(ocs_t *ocs, ocs_fcport *fcp, int tgt)
 1066 {
 1067         struct cam_path *cpath = NULL;
 1068 
 1069         if (!fcp->sim) { 
 1070                 device_printf(ocs->dev, "%s: calling with NULL sim\n", __func__); 
 1071                 return;
 1072         }
 1073 
 1074         if (CAM_REQ_CMP == xpt_create_path(&cpath, NULL, cam_sim_path(fcp->sim),
 1075                                 tgt, CAM_LUN_WILDCARD)) {
 1076                 xpt_async(AC_LOST_DEVICE, cpath, NULL);
 1077                 
 1078                 xpt_free_path(cpath);
 1079         }
 1080 }
 1081 
 1082 /*
 1083  * Device Lost Timer Function- when we have decided that a device was lost,
 1084  * we wait a specific period of time prior to telling the OS about lost device.
 1085  *
 1086  * This timer function gets activated when the device was lost. 
 1087  * This function fires once a second and then scans the port database
 1088  * for devices that are marked dead but still have a virtual target assigned.
 1089  * We decrement a counter for that port database entry, and when it hits zero,
 1090  * we tell the OS the device was lost. Timer will be stopped when the device
 1091  * comes back active or removed from the OS.
 1092  */
 1093 static void
 1094 ocs_ldt(void *arg)
 1095 {
 1096         ocs_fcport *fcp = arg;
 1097         taskqueue_enqueue(taskqueue_thread, &fcp->ltask);
 1098 }
 1099 
 1100 static void
 1101 ocs_ldt_task(void *arg, int pending)
 1102 {
 1103         ocs_fcport *fcp = arg;
 1104         ocs_t   *ocs = fcp->ocs;
 1105         int i, more_to_do = 0;
 1106         ocs_fc_target_t *tgt = NULL;
 1107 
 1108         for (i = 0; i < OCS_MAX_TARGETS; i++) {
 1109                 tgt = &fcp->tgt[i];
 1110 
 1111                 if (tgt->state != OCS_TGT_STATE_LOST) {
 1112                         continue;
 1113                 }
 1114 
 1115                 if ((tgt->gone_timer != 0) && (ocs->attached)){
 1116                         tgt->gone_timer -= 1;
 1117                         more_to_do++;
 1118                         continue;
 1119                 }
 1120 
 1121                 if (tgt->is_target) {
 1122                         tgt->is_target = 0;
 1123                         ocs_delete_target(ocs, fcp, i);
 1124                 }
 1125 
 1126                 tgt->state = OCS_TGT_STATE_NONE;
 1127         }
 1128 
 1129         if (more_to_do) {
 1130                 callout_reset(&fcp->ldt, hz, ocs_ldt, fcp);
 1131         } else {
 1132                 callout_deactivate(&fcp->ldt);
 1133         }
 1134 
 1135 }
 1136 
 1137 /**
 1138  * @ingroup scsi_api_initiator
 1139  * @brief Delete a SCSI target node
 1140  *
 1141  * Sent by base driver to notify a initiator-client that a remote target 
 1142  * is now gone. The base driver will have terminated all  outstanding IOs 
 1143  * and the initiator-client will receive appropriate completions.
 1144  *
 1145  * The ocs_node_t structure has and elment of type ocs_scsi_ini_node_t named
 1146  * ini_node that is declared and used by a target-server for private
 1147  * information.
 1148  *
 1149  * This function is only called if the base driver is enabled for
 1150  * initiator capability.
 1151  *
 1152  * @param node pointer node being deleted
 1153  * @param reason reason for deleting the target
 1154  *
 1155  * @return Returns OCS_SCSI_CALL_ASYNC if target delete is queued for async 
 1156  * completion and OCS_SCSI_CALL_COMPLETE if call completed or error.
 1157  *
 1158  * @note
 1159  */
 1160 int32_t
 1161 ocs_scsi_del_target(ocs_node_t *node, ocs_scsi_del_target_reason_e reason)
 1162 {
 1163         struct ocs_softc *ocs = node->ocs;
 1164         ocs_fcport      *fcp = NULL;
 1165         ocs_fc_target_t *tgt = NULL;
 1166         int32_t tgt_id;
 1167 
 1168         if (ocs == NULL) {
 1169                 ocs_log_err(ocs,"OCS is NULL \n");
 1170                 return -1;
 1171         }
 1172 
 1173         fcp = node->sport->tgt_data;
 1174         if (fcp == NULL) {
 1175                 ocs_log_err(ocs,"FCP is NULL \n");
 1176                 return -1;
 1177         }
 1178 
 1179         tgt_id = ocs_tgt_find(fcp, node);
 1180         if (tgt_id == -1) {
 1181                 ocs_log_err(ocs,"target is invalid\n");
 1182                 return -1;
 1183         }
 1184 
 1185         tgt = &fcp->tgt[tgt_id];
 1186 
 1187         // IF in shutdown delete target.
 1188         if(!ocs->attached) {
 1189                 ocs_delete_target(ocs, fcp, tgt_id);
 1190         } else {
 1191                 tgt->state = OCS_TGT_STATE_LOST;
 1192                 tgt->gone_timer = 30;
 1193                 if (!callout_active(&fcp->ldt)) {
 1194                         callout_reset(&fcp->ldt, hz, ocs_ldt, fcp);
 1195                 }
 1196         }
 1197 
 1198         return 0;
 1199 }
 1200 
 1201 /**
 1202  * @brief Initialize SCSI IO
 1203  *
 1204  * Initialize SCSI IO, this function is called once per IO during IO pool
 1205  * allocation so that the target server may initialize any of its own private
 1206  * data.
 1207  *
 1208  * @param io pointer to SCSI IO object
 1209  *
 1210  * @return returns 0 for success, a negative error code value for failure.
 1211  */
 1212 int32_t
 1213 ocs_scsi_tgt_io_init(ocs_io_t *io)
 1214 {
 1215         return 0;
 1216 }
 1217 
 1218 /**
 1219  * @brief Uninitialize SCSI IO
 1220  *
 1221  * Uninitialize target server private data in a SCSI io object
 1222  *
 1223  * @param io pointer to SCSI IO object
 1224  *
 1225  * @return returns 0 for success, a negative error code value for failure.
 1226  */
 1227 int32_t
 1228 ocs_scsi_tgt_io_exit(ocs_io_t *io)
 1229 {
 1230         return 0;
 1231 }
 1232 
 1233 /**
 1234  * @brief Initialize SCSI IO
 1235  *
 1236  * Initialize SCSI IO, this function is called once per IO during IO pool
 1237  * allocation so that the initiator client may initialize any of its own private
 1238  * data.
 1239  *
 1240  * @param io pointer to SCSI IO object
 1241  *
 1242  * @return returns 0 for success, a negative error code value for failure.
 1243  */
 1244 int32_t
 1245 ocs_scsi_ini_io_init(ocs_io_t *io)
 1246 {
 1247         return 0;
 1248 }
 1249 
 1250 /**
 1251  * @brief Uninitialize SCSI IO
 1252  *
 1253  * Uninitialize initiator client private data in a SCSI io object
 1254  *
 1255  * @param io pointer to SCSI IO object
 1256  *
 1257  * @return returns 0 for success, a negative error code value for failure.
 1258  */
 1259 int32_t
 1260 ocs_scsi_ini_io_exit(ocs_io_t *io)
 1261 {
 1262         return 0;
 1263 }
 1264 /*
 1265  * End of functions required by SCSI base driver API
 1266  ***************************************************************************/
 1267 
 1268 static __inline void
 1269 ocs_set_ccb_status(union ccb *ccb, cam_status status)
 1270 {
 1271         ccb->ccb_h.status &= ~CAM_STATUS_MASK;
 1272         ccb->ccb_h.status |= status;
 1273 }
 1274 
 1275 static int32_t
 1276 ocs_task_set_full_or_busy_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status,
 1277                                                 uint32_t flags, void *arg)
 1278 {
 1279 
 1280         ocs_target_io_free(io);
 1281 
 1282         return 0;
 1283 }
 1284 
 1285 /**
 1286  * @brief send SCSI task set full or busy status
 1287  *
 1288  * A SCSI task set full or busy response is sent depending on whether
 1289  * another IO is already active on the LUN.
 1290  *
 1291  * @param io pointer to IO context
 1292  *
 1293  * @return returns 0 for success, a negative error code value for failure.
 1294  */
 1295 
 1296 static int32_t
 1297 ocs_task_set_full_or_busy(ocs_io_t *io)
 1298 {
 1299         ocs_scsi_cmd_resp_t rsp = { 0 };
 1300         ocs_t *ocs = io->ocs;
 1301 
 1302         /*
 1303          * If there is another command for the LUN, then send task set full,
 1304          * if this is the first one, then send the busy status.
 1305          *
 1306          * if 'busy sent' is FALSE, set it to TRUE and send BUSY
 1307          * otherwise send FULL
 1308          */
 1309         if (atomic_cmpset_acq_32(&io->node->tgt_node.busy_sent, FALSE, TRUE)) {
 1310                 rsp.scsi_status = SCSI_STATUS_BUSY; /* Busy */
 1311                 printf("%s: busy [%s] tag=%x iiu=%d ihw=%d\n", __func__,
 1312                                 io->node->display_name, io->tag,
 1313                                 io->ocs->io_in_use, io->ocs->io_high_watermark);
 1314         } else {
 1315                 rsp.scsi_status = SCSI_STATUS_TASK_SET_FULL; /* Task set full */
 1316                 printf("%s: full tag=%x iiu=%d\n", __func__, io->tag,
 1317                         io->ocs->io_in_use);
 1318         }
 1319 
 1320         /* Log a message here indicating a busy or task set full state */
 1321         if (OCS_LOG_ENABLE_Q_FULL_BUSY_MSG(ocs)) {
 1322                 /* Log Task Set Full */
 1323                 if (rsp.scsi_status == SCSI_STATUS_TASK_SET_FULL) {
 1324                         /* Task Set Full Message */
 1325                         ocs_log_info(ocs, "OCS CAM TASK SET FULL. Tasks >= %d\n",
 1326                                         ocs->io_high_watermark);
 1327                 }
 1328                 else if (rsp.scsi_status == SCSI_STATUS_BUSY) {
 1329                         /* Log Busy Message */
 1330                         ocs_log_info(ocs, "OCS CAM SCSI BUSY\n");
 1331                 }
 1332         }
 1333 
 1334         /* Send the response */
 1335         return 
 1336         ocs_scsi_send_resp(io, 0, &rsp, ocs_task_set_full_or_busy_cb, NULL);
 1337 }
 1338 
 1339 /**
 1340  * @ingroup cam_io
 1341  * @brief Process target IO completions
 1342  *
 1343  * @param io 
 1344  * @param scsi_status did the IO complete successfully
 1345  * @param flags 
 1346  * @param arg application specific pointer provided in the call to ocs_target_io()
 1347  *
 1348  * @todo
 1349  */
 1350 static int32_t ocs_scsi_target_io_cb(ocs_io_t *io, 
 1351                                 ocs_scsi_io_status_e scsi_status,
 1352                                 uint32_t flags, void *arg)
 1353 {
 1354         union ccb *ccb = arg;
 1355         struct ccb_scsiio *csio = &ccb->csio;
 1356         struct ocs_softc *ocs = csio->ccb_h.ccb_ocs_ptr;
 1357         uint32_t cam_dir = ccb->ccb_h.flags & CAM_DIR_MASK;
 1358         uint32_t io_is_done = 
 1359                 (ccb->ccb_h.flags & CAM_SEND_STATUS) == CAM_SEND_STATUS;
 1360 
 1361         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 1362 
 1363         if (CAM_DIR_NONE != cam_dir) {
 1364                 bus_dmasync_op_t op;
 1365 
 1366                 if (CAM_DIR_IN == cam_dir) {
 1367                         op = BUS_DMASYNC_POSTREAD;
 1368                 } else {
 1369                         op = BUS_DMASYNC_POSTWRITE;
 1370                 }
 1371                 /* Synchronize the DMA memory with the CPU and free the mapping */
 1372                 bus_dmamap_sync(ocs->buf_dmat, io->tgt_io.dmap, op);
 1373                 if (io->tgt_io.flags & OCS_CAM_IO_F_DMAPPED) {
 1374                         bus_dmamap_unload(ocs->buf_dmat, io->tgt_io.dmap);
 1375                 }
 1376         }
 1377 
 1378         if (io->tgt_io.sendresp) {
 1379                 io->tgt_io.sendresp = 0;
 1380                 ocs_scsi_cmd_resp_t  resp = { 0 };
 1381                 io->tgt_io.state = OCS_CAM_IO_RESP;
 1382                 resp.scsi_status = scsi_status;
 1383                 if (ccb->ccb_h.flags & CAM_SEND_SENSE) {
 1384                         resp.sense_data = (uint8_t *)&csio->sense_data;
 1385                         resp.sense_data_length = csio->sense_len;
 1386                 }
 1387                 resp.residual = io->exp_xfer_len - io->transferred;
 1388 
 1389                 return ocs_scsi_send_resp(io, 0, &resp, ocs_scsi_target_io_cb, ccb);
 1390         }
 1391 
 1392         switch (scsi_status) {
 1393         case OCS_SCSI_STATUS_GOOD:
 1394                 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
 1395                 break;
 1396         case OCS_SCSI_STATUS_ABORTED:
 1397                 ocs_set_ccb_status(ccb, CAM_REQ_ABORTED);
 1398                 break;
 1399         default:
 1400                 ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
 1401         }
 1402 
 1403         if (io_is_done) {
 1404                 if ((io->tgt_io.flags & OCS_CAM_IO_F_ABORT_NOTIFY) == 0) {
 1405                         ocs_target_io_free(io);
 1406                 }
 1407         } else {
 1408                 io->tgt_io.state = OCS_CAM_IO_DATA_DONE;
 1409                 /*device_printf(ocs->dev, "%s: CTIO state=%d tag=%#x\n",
 1410                                 __func__, io->tgt_io.state, io->tag);*/
 1411         }
 1412 
 1413         xpt_done(ccb);
 1414 
 1415         return 0;
 1416 }
 1417 
 1418 /**
 1419  * @note        1. Since the CCB is assigned to the ocs_io_t on an XPT_CONT_TARGET_IO
 1420  *                 action, if an initiator aborts a command prior to the SIM receiving
 1421  *                 a CTIO, the IO's CCB will be NULL.
 1422  */
 1423 static int32_t
 1424 ocs_io_abort_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status, uint32_t flags, void *arg)
 1425 {
 1426         struct ocs_softc *ocs = NULL;
 1427         ocs_io_t        *tmfio = arg;
 1428         ocs_scsi_tmf_resp_e tmf_resp = OCS_SCSI_TMF_FUNCTION_COMPLETE;
 1429         int32_t rc = 0;
 1430 
 1431         ocs = io->ocs;
 1432 
 1433         io->tgt_io.flags &= ~OCS_CAM_IO_F_ABORT_DEV;
 1434 
 1435         /* A good status indicates the IO was aborted and will be completed in
 1436          * the IO's completion handler. Handle the other cases here. */
 1437         switch (scsi_status) {
 1438         case OCS_SCSI_STATUS_GOOD:
 1439                 break;
 1440         case OCS_SCSI_STATUS_NO_IO:
 1441                 break;
 1442         default:
 1443                 device_printf(ocs->dev, "%s: unhandled status %d\n",
 1444                                 __func__, scsi_status);
 1445                 tmf_resp = OCS_SCSI_TMF_FUNCTION_REJECTED;
 1446                 rc = -1;
 1447         }
 1448 
 1449         ocs_scsi_send_tmf_resp(tmfio, tmf_resp, NULL, ocs_target_tmf_cb, NULL);
 1450 
 1451         return rc;
 1452 }
 1453 
 1454 /**
 1455  * @ingroup cam_io
 1456  * @brief Process initiator IO completions
 1457  *
 1458  * @param io 
 1459  * @param scsi_status did the IO complete successfully
 1460  * @param rsp pointer to response buffer
 1461  * @param flags 
 1462  * @param arg application specific pointer provided in the call to ocs_target_io()
 1463  *
 1464  * @todo
 1465  */
 1466 static int32_t ocs_scsi_initiator_io_cb(ocs_io_t *io,
 1467                                         ocs_scsi_io_status_e scsi_status,
 1468                                         ocs_scsi_cmd_resp_t *rsp,
 1469                                         uint32_t flags, void *arg)
 1470 {
 1471         union ccb *ccb = arg;
 1472         struct ccb_scsiio *csio = &ccb->csio;
 1473         struct ocs_softc *ocs = csio->ccb_h.ccb_ocs_ptr;
 1474         uint32_t cam_dir = ccb->ccb_h.flags & CAM_DIR_MASK;
 1475         cam_status ccb_status= CAM_REQ_CMP_ERR;
 1476 
 1477         if (CAM_DIR_NONE != cam_dir) {
 1478                 bus_dmasync_op_t op;
 1479 
 1480                 if (CAM_DIR_IN == cam_dir) {
 1481                         op = BUS_DMASYNC_POSTREAD;
 1482                 } else {
 1483                         op = BUS_DMASYNC_POSTWRITE;
 1484                 }
 1485                 /* Synchronize the DMA memory with the CPU and free the mapping */
 1486                 bus_dmamap_sync(ocs->buf_dmat, io->tgt_io.dmap, op);
 1487                 if (io->tgt_io.flags & OCS_CAM_IO_F_DMAPPED) {
 1488                         bus_dmamap_unload(ocs->buf_dmat, io->tgt_io.dmap);
 1489                 }
 1490         }
 1491 
 1492         if (scsi_status == OCS_SCSI_STATUS_CHECK_RESPONSE) {
 1493                 csio->scsi_status = rsp->scsi_status;
 1494                 if (SCSI_STATUS_OK != rsp->scsi_status) {
 1495                         ccb_status = CAM_SCSI_STATUS_ERROR;
 1496                 }
 1497 
 1498                 csio->resid = rsp->residual;
 1499                 if (rsp->residual > 0) {
 1500                         uint32_t length = rsp->response_wire_length;
 1501                         /* underflow */
 1502                         if (csio->dxfer_len == (length + csio->resid)) {
 1503                                 ccb_status = CAM_REQ_CMP;
 1504                         }
 1505                 } else if (rsp->residual < 0) {
 1506                         ccb_status = CAM_DATA_RUN_ERR;
 1507                 }
 1508 
 1509                 if ((rsp->sense_data_length) &&
 1510                         !(ccb->ccb_h.flags & (CAM_SENSE_PHYS | CAM_SENSE_PTR))) {
 1511                         uint32_t        sense_len = 0;
 1512 
 1513                         ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
 1514                         if (rsp->sense_data_length < csio->sense_len) {
 1515                                 csio->sense_resid = 
 1516                                         csio->sense_len - rsp->sense_data_length;
 1517                                 sense_len = rsp->sense_data_length;
 1518                         } else {
 1519                                 csio->sense_resid = 0;
 1520                                 sense_len = csio->sense_len;
 1521                         }
 1522                         ocs_memcpy(&csio->sense_data, rsp->sense_data, sense_len);
 1523                 }
 1524         } else if (scsi_status != OCS_SCSI_STATUS_GOOD) {
 1525                 ccb_status = CAM_REQ_CMP_ERR;
 1526                 ocs_set_ccb_status(ccb, ccb_status);
 1527                 csio->ccb_h.status |= CAM_DEV_QFRZN;
 1528                 xpt_freeze_devq(csio->ccb_h.path, 1);
 1529 
 1530         } else {
 1531                 ccb_status = CAM_REQ_CMP;
 1532         }
 1533 
 1534         ocs_set_ccb_status(ccb, ccb_status);
 1535 
 1536         ocs_scsi_io_free(io);
 1537 
 1538         csio->ccb_h.ccb_io_ptr = NULL;
 1539         csio->ccb_h.ccb_ocs_ptr = NULL;
 1540         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 1541 
 1542         xpt_done(ccb);
 1543 
 1544         return 0;
 1545 }
 1546 
 1547 /**
 1548  * @brief Load scatter-gather list entries into an IO
 1549  *
 1550  * This routine relies on the driver instance's software context pointer and
 1551  * the IO object pointer having been already assigned to hooks in the CCB.
 1552  * Although the routine does not return success/fail, callers can look at the
 1553  * n_sge member to determine if the mapping failed (0 on failure).
 1554  *
 1555  * @param arg pointer to the CAM ccb for this IO
 1556  * @param seg DMA address/length pairs
 1557  * @param nseg number of DMA address/length pairs
 1558  * @param error any errors while mapping the IO
 1559  */
 1560 static void
 1561 ocs_scsi_dmamap_load(void *arg, bus_dma_segment_t *seg, int nseg, int error)
 1562 {
 1563         ocs_dmamap_load_arg_t *sglarg = (ocs_dmamap_load_arg_t*) arg;
 1564 
 1565         if (error) {
 1566                 printf("%s: seg=%p nseg=%d error=%d\n",
 1567                                 __func__, seg, nseg, error);
 1568                 sglarg->rc = -1;
 1569         } else {
 1570                 uint32_t i = 0;
 1571                 uint32_t c = 0;
 1572 
 1573                 if ((sglarg->sgl_count + nseg) > sglarg->sgl_max) {
 1574                         printf("%s: sgl_count=%d nseg=%d max=%d\n", __func__,
 1575                                 sglarg->sgl_count, nseg, sglarg->sgl_max);
 1576                         sglarg->rc = -2;
 1577                         return;
 1578                 }
 1579 
 1580                 for (i = 0, c = sglarg->sgl_count; i < nseg; i++, c++) {
 1581                         sglarg->sgl[c].addr = seg[i].ds_addr;
 1582                         sglarg->sgl[c].len  = seg[i].ds_len;
 1583                 }
 1584 
 1585                 sglarg->sgl_count = c;
 1586 
 1587                 sglarg->rc = 0;
 1588         }
 1589 }
 1590 
 1591 /**
 1592  * @brief Build a scatter-gather list from a CAM CCB
 1593  *
 1594  * @param ocs the driver instance's software context
 1595  * @param ccb pointer to the CCB
 1596  * @param io pointer to the previously allocated IO object
 1597  * @param sgl pointer to SGL
 1598  * @param sgl_max number of entries in sgl
 1599  *
 1600  * @return 0 on success, non-zero otherwise
 1601  */
 1602 static int32_t
 1603 ocs_build_scsi_sgl(struct ocs_softc *ocs, union ccb *ccb, ocs_io_t *io,
 1604                 ocs_scsi_sgl_t *sgl, uint32_t sgl_max)
 1605 {
 1606         ocs_dmamap_load_arg_t dmaarg;
 1607         int32_t err = 0;
 1608 
 1609         if (!ocs || !ccb || !io || !sgl) {
 1610                 printf("%s: bad param o=%p c=%p i=%p s=%p\n", __func__,
 1611                                 ocs, ccb, io, sgl);
 1612                 return -1;
 1613         }
 1614 
 1615         io->tgt_io.flags &= ~OCS_CAM_IO_F_DMAPPED;
 1616 
 1617         dmaarg.sgl = sgl;
 1618         dmaarg.sgl_count = 0;
 1619         dmaarg.sgl_max = sgl_max;
 1620         dmaarg.rc = 0;
 1621 
 1622         err = bus_dmamap_load_ccb(ocs->buf_dmat, io->tgt_io.dmap, ccb,
 1623                         ocs_scsi_dmamap_load, &dmaarg, 0);
 1624 
 1625         if (err || dmaarg.rc) {
 1626                 device_printf(
 1627                         ocs->dev, "%s: bus_dmamap_load_ccb error (%d %d)\n",
 1628                                 __func__, err, dmaarg.rc);
 1629                 return -1;
 1630         }
 1631 
 1632         io->tgt_io.flags |= OCS_CAM_IO_F_DMAPPED;
 1633         return dmaarg.sgl_count;
 1634 }
 1635 
 1636 /**
 1637  * @ingroup cam_io
 1638  * @brief Send a target IO
 1639  *
 1640  * @param ocs the driver instance's software context
 1641  * @param ccb pointer to the CCB
 1642  *
 1643  * @return 0 on success, non-zero otherwise
 1644  */
 1645 static int32_t
 1646 ocs_target_io(struct ocs_softc *ocs, union ccb *ccb)
 1647 {
 1648         struct ccb_scsiio *csio = &ccb->csio;
 1649         ocs_io_t *io = NULL;
 1650         uint32_t cam_dir = ccb->ccb_h.flags & CAM_DIR_MASK;
 1651         bool sendstatus = ccb->ccb_h.flags & CAM_SEND_STATUS;
 1652         uint32_t xferlen = csio->dxfer_len;
 1653         int32_t rc = 0;
 1654 
 1655         io = ocs_scsi_find_io(ocs, csio->tag_id);
 1656         if (io == NULL) {
 1657                 ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
 1658                 panic("bad tag value");
 1659                 return 1;
 1660         }
 1661 
 1662         /* Received an ABORT TASK for this IO */
 1663         if (io->tgt_io.flags & OCS_CAM_IO_F_ABORT_RECV) {
 1664                 /*device_printf(ocs->dev,
 1665                         "%s: XPT_CONT_TARGET_IO state=%d tag=%#x xid=%#x flags=%#x\n",
 1666                         __func__, io->tgt_io.state, io->tag, io->init_task_tag,
 1667                         io->tgt_io.flags);*/
 1668                 io->tgt_io.flags |= OCS_CAM_IO_F_ABORT_CAM;
 1669 
 1670                 if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
 1671                         ocs_set_ccb_status(ccb, CAM_REQ_CMP);
 1672                         ocs_target_io_free(io);
 1673                         return 1;
 1674                 } 
 1675 
 1676                 ocs_set_ccb_status(ccb, CAM_REQ_ABORTED);
 1677 
 1678                 return 1;
 1679         }
 1680 
 1681         io->tgt_io.app = ccb;
 1682 
 1683         ocs_set_ccb_status(ccb, CAM_REQ_INPROG);
 1684         ccb->ccb_h.status |= CAM_SIM_QUEUED;
 1685 
 1686         csio->ccb_h.ccb_ocs_ptr = ocs;
 1687         csio->ccb_h.ccb_io_ptr  = io;
 1688 
 1689         if ((sendstatus && (xferlen == 0))) {
 1690                 ocs_scsi_cmd_resp_t     resp = { 0 };
 1691 
 1692                 ocs_assert(ccb->ccb_h.flags & CAM_SEND_STATUS, -1);
 1693 
 1694                 io->tgt_io.state = OCS_CAM_IO_RESP;
 1695 
 1696                 resp.scsi_status = csio->scsi_status;
 1697 
 1698                 if (ccb->ccb_h.flags & CAM_SEND_SENSE) {
 1699                         resp.sense_data = (uint8_t *)&csio->sense_data;
 1700                         resp.sense_data_length = csio->sense_len;
 1701                 }
 1702 
 1703                 resp.residual = io->exp_xfer_len - io->transferred;
 1704                 rc = ocs_scsi_send_resp(io, 0, &resp, ocs_scsi_target_io_cb, ccb);
 1705 
 1706         } else if (xferlen != 0) {
 1707                 ocs_scsi_sgl_t sgl[OCS_FC_MAX_SGL];
 1708                 int32_t sgl_count = 0;
 1709 
 1710                 io->tgt_io.state = OCS_CAM_IO_DATA;
 1711                 
 1712                 if (sendstatus)
 1713                         io->tgt_io.sendresp = 1;
 1714 
 1715                 sgl_count = ocs_build_scsi_sgl(ocs, ccb, io, sgl, ARRAY_SIZE(sgl));
 1716                 if (sgl_count > 0) {
 1717                         if (cam_dir == CAM_DIR_IN) {
 1718                                 rc = ocs_scsi_send_rd_data(io, 0, NULL, sgl,
 1719                                                 sgl_count, csio->dxfer_len,
 1720                                                 ocs_scsi_target_io_cb, ccb);
 1721                         } else if (cam_dir == CAM_DIR_OUT) {
 1722                                 rc = ocs_scsi_recv_wr_data(io, 0, NULL, sgl,
 1723                                                 sgl_count, csio->dxfer_len,
 1724                                                 ocs_scsi_target_io_cb, ccb);
 1725                         } else {
 1726                                 device_printf(ocs->dev, "%s:"
 1727                                                 " unknown CAM direction %#x\n",
 1728                                                 __func__, cam_dir);
 1729                                 ocs_set_ccb_status(ccb, CAM_REQ_INVALID);
 1730                                 rc = 1;
 1731                         }
 1732                 } else {
 1733                         device_printf(ocs->dev, "%s: building SGL failed\n",
 1734                                                 __func__);
 1735                         ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
 1736                         rc = 1;
 1737                 }
 1738         } else {
 1739                 device_printf(ocs->dev, "%s: Wrong value xfer and sendstatus"
 1740                                         " are 0 \n", __func__);
 1741                 ocs_set_ccb_status(ccb, CAM_REQ_INVALID);
 1742                 rc = 1;
 1743         }
 1744 
 1745         if (rc) {
 1746                 ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
 1747                 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 1748                 io->tgt_io.state = OCS_CAM_IO_DATA_DONE;
 1749                 device_printf(ocs->dev, "%s: CTIO state=%d tag=%#x\n",
 1750                                 __func__, io->tgt_io.state, io->tag);
 1751         if ((sendstatus && (xferlen == 0))) {
 1752                         ocs_target_io_free(io);
 1753                 }
 1754         }
 1755 
 1756         return rc;
 1757 }
 1758 
 1759 static int32_t
 1760 ocs_target_tmf_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status, uint32_t flags,
 1761                 void *arg)
 1762 {
 1763 
 1764         /*device_printf(io->ocs->dev, "%s: tag=%x io=%p s=%#x\n",
 1765                          __func__, io->tag, io, scsi_status);*/
 1766         ocs_scsi_io_complete(io);
 1767 
 1768         return 0;
 1769 }
 1770 
 1771 /**
 1772  * @ingroup cam_io
 1773  * @brief Send an initiator IO
 1774  *
 1775  * @param ocs the driver instance's software context
 1776  * @param ccb pointer to the CCB
 1777  *
 1778  * @return 0 on success, non-zero otherwise
 1779  */
 1780 static int32_t
 1781 ocs_initiator_io(struct ocs_softc *ocs, union ccb *ccb)
 1782 {
 1783         int32_t rc;
 1784         struct ccb_scsiio *csio = &ccb->csio;
 1785         struct ccb_hdr *ccb_h = &csio->ccb_h;
 1786         ocs_node_t *node = NULL;
 1787         ocs_io_t *io = NULL;
 1788         ocs_scsi_sgl_t sgl[OCS_FC_MAX_SGL];
 1789         int32_t flags, sgl_count;
 1790         ocs_fcport      *fcp;
 1791 
 1792         fcp = FCPORT(ocs, cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path)));
 1793 
 1794         if (fcp->tgt[ccb_h->target_id].state == OCS_TGT_STATE_LOST) {
 1795                 device_printf(ocs->dev, "%s: device LOST %d\n", __func__,
 1796                                                         ccb_h->target_id);
 1797                 return CAM_REQUEUE_REQ;
 1798         }
 1799 
 1800         if (fcp->tgt[ccb_h->target_id].state == OCS_TGT_STATE_NONE) {
 1801                 device_printf(ocs->dev, "%s: device not ready %d\n", __func__,
 1802                                                         ccb_h->target_id);
 1803                 return CAM_SEL_TIMEOUT;
 1804         }
 1805 
 1806         node = ocs_node_get_instance(ocs, fcp->tgt[ccb_h->target_id].node_id);
 1807         if (node == NULL) {
 1808                 device_printf(ocs->dev, "%s: no device %d\n", __func__,
 1809                                                         ccb_h->target_id);
 1810                 return CAM_SEL_TIMEOUT;
 1811         }
 1812 
 1813         if (!node->targ) {
 1814                 device_printf(ocs->dev, "%s: not target device %d\n", __func__,
 1815                                                         ccb_h->target_id);
 1816                 return CAM_SEL_TIMEOUT;
 1817         }
 1818 
 1819         io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_ORIGINATOR);
 1820         if (io == NULL) {
 1821                 device_printf(ocs->dev, "%s: unable to alloc IO\n", __func__);
 1822                 return -1;
 1823         }
 1824 
 1825         /* eventhough this is INI, use target structure as ocs_build_scsi_sgl
 1826          * only references the tgt_io part of an ocs_io_t */
 1827         io->tgt_io.app = ccb;
 1828 
 1829         csio->ccb_h.ccb_ocs_ptr = ocs;
 1830         csio->ccb_h.ccb_io_ptr  = io;
 1831 
 1832         sgl_count = ocs_build_scsi_sgl(ocs, ccb, io, sgl, ARRAY_SIZE(sgl));
 1833         if (sgl_count < 0) {
 1834                 ocs_scsi_io_free(io);
 1835                 device_printf(ocs->dev, "%s: building SGL failed\n", __func__);
 1836                 return -1;
 1837         }
 1838 
 1839         if (ccb->ccb_h.timeout == CAM_TIME_INFINITY) {
 1840                 io->timeout = 0;
 1841         } else if (ccb->ccb_h.timeout == CAM_TIME_DEFAULT) {
 1842                 io->timeout = OCS_CAM_IO_TIMEOUT;
 1843         } else {
 1844                 io->timeout = ccb->ccb_h.timeout;
 1845         }
 1846 
 1847         switch (csio->tag_action) {
 1848         case MSG_HEAD_OF_Q_TAG:
 1849                 flags = OCS_SCSI_CMD_HEAD_OF_QUEUE;
 1850                 break;
 1851         case MSG_ORDERED_Q_TAG:
 1852                 flags = OCS_SCSI_CMD_ORDERED;
 1853                 break;
 1854         case MSG_ACA_TASK:
 1855                 flags = OCS_SCSI_CMD_ACA;
 1856                 break;
 1857         case CAM_TAG_ACTION_NONE:
 1858         case MSG_SIMPLE_Q_TAG:
 1859         default:
 1860                 flags = OCS_SCSI_CMD_SIMPLE;
 1861                 break;
 1862         }
 1863         flags |= (csio->priority << OCS_SCSI_PRIORITY_SHIFT) &
 1864             OCS_SCSI_PRIORITY_MASK;
 1865 
 1866         switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
 1867         case CAM_DIR_NONE:
 1868                 rc = ocs_scsi_send_nodata_io(node, io, ccb_h->target_lun,
 1869                                 ccb->ccb_h.flags & CAM_CDB_POINTER ? 
 1870                                 csio->cdb_io.cdb_ptr: csio->cdb_io.cdb_bytes,
 1871                                 csio->cdb_len,
 1872                                 ocs_scsi_initiator_io_cb, ccb, flags);
 1873                 break;
 1874         case CAM_DIR_IN:
 1875                 rc = ocs_scsi_send_rd_io(node, io, ccb_h->target_lun,
 1876                                 ccb->ccb_h.flags & CAM_CDB_POINTER ? 
 1877                                 csio->cdb_io.cdb_ptr: csio->cdb_io.cdb_bytes,
 1878                                 csio->cdb_len,
 1879                                 NULL,
 1880                                 sgl, sgl_count, csio->dxfer_len,
 1881                                 ocs_scsi_initiator_io_cb, ccb, flags);
 1882                 break;
 1883         case CAM_DIR_OUT:
 1884                 rc = ocs_scsi_send_wr_io(node, io, ccb_h->target_lun,
 1885                                 ccb->ccb_h.flags & CAM_CDB_POINTER ? 
 1886                                 csio->cdb_io.cdb_ptr: csio->cdb_io.cdb_bytes,
 1887                                 csio->cdb_len,
 1888                                 NULL,
 1889                                 sgl, sgl_count, csio->dxfer_len,
 1890                                 ocs_scsi_initiator_io_cb, ccb, flags);
 1891                 break;
 1892         default:
 1893                 panic("%s invalid data direction %08x\n", __func__, 
 1894                                                         ccb->ccb_h.flags);
 1895                 break;
 1896         }
 1897 
 1898         return rc;
 1899 }
 1900 
 1901 static uint32_t
 1902 ocs_fcp_change_role(struct ocs_softc *ocs, ocs_fcport *fcp, uint32_t new_role)
 1903 {
 1904 
 1905         uint32_t rc = 0, was = 0, i = 0;
 1906         ocs_vport_spec_t *vport = fcp->vport;
 1907 
 1908         for (was = 0, i = 0; i < (ocs->num_vports + 1); i++) {
 1909                 if (FCPORT(ocs, i)->role != KNOB_ROLE_NONE)
 1910                 was++;
 1911         }
 1912 
 1913         // Physical port        
 1914         if ((was == 0) || (vport == NULL)) { 
 1915                 fcp->role = new_role;
 1916                 if (vport == NULL) {
 1917                         ocs->enable_ini = (new_role & KNOB_ROLE_INITIATOR)? 1:0;
 1918                         ocs->enable_tgt = (new_role & KNOB_ROLE_TARGET)? 1:0;
 1919                 } else {
 1920                         vport->enable_ini = (new_role & KNOB_ROLE_INITIATOR)? 1:0;
 1921                         vport->enable_tgt = (new_role & KNOB_ROLE_TARGET)? 1:0;
 1922                 }
 1923 
 1924                 rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE);
 1925                 if (rc) {
 1926                         ocs_log_debug(ocs, "port offline failed : %d\n", rc);
 1927                 }
 1928 
 1929                 rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE);
 1930                 if (rc) {
 1931                         ocs_log_debug(ocs, "port online failed : %d\n", rc);
 1932                 }
 1933                 
 1934                 return 0;
 1935         }
 1936 
 1937         if ((fcp->role != KNOB_ROLE_NONE)){
 1938                 fcp->role = new_role;
 1939                 vport->enable_ini = (new_role & KNOB_ROLE_INITIATOR)? 1:0;
 1940                 vport->enable_tgt = (new_role & KNOB_ROLE_TARGET)? 1:0;
 1941                 /* New Sport will be created in sport deleted cb */
 1942                 return ocs_sport_vport_del(ocs, ocs->domain, vport->wwpn, vport->wwnn);
 1943         }
 1944 
 1945         fcp->role = new_role;
 1946 
 1947         vport->enable_ini = (new_role & KNOB_ROLE_INITIATOR)? 1:0;
 1948         vport->enable_tgt = (new_role & KNOB_ROLE_TARGET)? 1:0;
 1949 
 1950         if (fcp->role != KNOB_ROLE_NONE) {
 1951                 return ocs_sport_vport_alloc(ocs->domain, vport);
 1952         }
 1953 
 1954         return (0);
 1955 }
 1956 
 1957 /**
 1958  * @ingroup cam_api
 1959  * @brief Process CAM actions
 1960  *
 1961  * The driver supplies this routine to the CAM during intialization and
 1962  * is the main entry point for processing CAM Control Blocks (CCB)
 1963  *
 1964  * @param sim pointer to the SCSI Interface Module
 1965  * @param ccb CAM control block
 1966  *
 1967  * @todo
 1968  *  - populate path inquiry data via info retrieved from SLI port
 1969  */
 1970 static void
 1971 ocs_action(struct cam_sim *sim, union ccb *ccb)
 1972 {
 1973         struct ocs_softc *ocs = (struct ocs_softc *)cam_sim_softc(sim);
 1974         struct ccb_hdr  *ccb_h = &ccb->ccb_h;
 1975 
 1976         int32_t rc, bus;
 1977         bus = cam_sim_bus(sim);
 1978 
 1979         switch (ccb_h->func_code) {
 1980         case XPT_SCSI_IO:
 1981 
 1982                 if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
 1983                         if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) {
 1984                                 ccb->ccb_h.status = CAM_REQ_INVALID;
 1985                                 xpt_done(ccb);
 1986                                 break;
 1987                         }
 1988                 }
 1989 
 1990                 rc = ocs_initiator_io(ocs, ccb);
 1991                 if (0 == rc) {
 1992                         ocs_set_ccb_status(ccb, CAM_REQ_INPROG | CAM_SIM_QUEUED);
 1993                         break;
 1994                 } else {
 1995                         if (rc == CAM_REQUEUE_REQ) {
 1996                                 cam_freeze_devq(ccb->ccb_h.path);
 1997                                 cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 100, 0);
 1998                                 ccb->ccb_h.status = CAM_REQUEUE_REQ;
 1999                                 xpt_done(ccb);
 2000                                 break;
 2001                         }
 2002 
 2003                         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 2004                         if (rc > 0) {
 2005                                 ocs_set_ccb_status(ccb, rc);
 2006                         } else {
 2007                                 ocs_set_ccb_status(ccb, CAM_SEL_TIMEOUT);
 2008                         }
 2009                 }
 2010                 xpt_done(ccb);
 2011                 break;
 2012         case XPT_PATH_INQ:
 2013         {
 2014                 struct ccb_pathinq *cpi = &ccb->cpi;
 2015                 struct ccb_pathinq_settings_fc *fc = &cpi->xport_specific.fc;
 2016                 ocs_fcport *fcp = FCPORT(ocs, bus);
 2017 
 2018                 uint64_t wwn = 0;
 2019                 ocs_xport_stats_t value;
 2020 
 2021                 cpi->version_num = 1;
 2022 
 2023                 cpi->protocol = PROTO_SCSI;
 2024                 cpi->protocol_version = SCSI_REV_SPC;
 2025 
 2026                 if (ocs->ocs_xport == OCS_XPORT_FC) {
 2027                         cpi->transport = XPORT_FC;
 2028                 } else {
 2029                         cpi->transport = XPORT_UNKNOWN;
 2030                 }
 2031 
 2032                 cpi->transport_version = 0;
 2033 
 2034                 /* Set the transport parameters of the SIM */
 2035                 ocs_xport_status(ocs->xport, OCS_XPORT_LINK_SPEED, &value);
 2036                 fc->bitrate = value.value * 1000;       /* speed in Mbps */
 2037 
 2038                 wwn = *((uint64_t *)ocs_scsi_get_property_ptr(ocs, OCS_SCSI_WWPN));
 2039                 fc->wwpn = be64toh(wwn);
 2040 
 2041                 wwn = *((uint64_t *)ocs_scsi_get_property_ptr(ocs, OCS_SCSI_WWNN));
 2042                 fc->wwnn = be64toh(wwn);
 2043 
 2044                 fc->port = fcp->fc_id;
 2045 
 2046                 if (ocs->config_tgt) {
 2047                         cpi->target_sprt =
 2048                                 PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO;
 2049                 }
 2050 
 2051                 cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED;
 2052                 cpi->hba_misc |= PIM_EXTLUNS | PIM_NOSCAN;
 2053 
 2054                 cpi->hba_inquiry = PI_TAG_ABLE; 
 2055                 cpi->max_target = OCS_MAX_TARGETS;
 2056                 cpi->initiator_id = ocs->max_remote_nodes + 1;
 2057 
 2058                 if (!ocs->enable_ini) {
 2059                         cpi->hba_misc |= PIM_NOINITIATOR;
 2060                 }
 2061 
 2062                 cpi->max_lun = OCS_MAX_LUN;
 2063                 cpi->bus_id = cam_sim_bus(sim);
 2064 
 2065                 /* Need to supply a base transfer speed prior to linking up
 2066                  * Worst case, this would be FC 1Gbps */
 2067                 cpi->base_transfer_speed = 1 * 1000 * 1000;
 2068 
 2069                 /* Calculate the max IO supported
 2070                  * Worst case would be an OS page per SGL entry */
 2071                 cpi->maxio = PAGE_SIZE * 
 2072                         (ocs_scsi_get_property(ocs, OCS_SCSI_MAX_SGL) - 1);
 2073 
 2074                 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
 2075                 strncpy(cpi->hba_vid, "Emulex", HBA_IDLEN);
 2076                 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
 2077                 cpi->unit_number = cam_sim_unit(sim);
 2078 
 2079                 cpi->ccb_h.status = CAM_REQ_CMP;
 2080                 xpt_done(ccb);
 2081                 break;
 2082         }
 2083         case XPT_GET_TRAN_SETTINGS:
 2084         {
 2085                 struct ccb_trans_settings *cts = &ccb->cts;
 2086                 struct ccb_trans_settings_scsi *scsi = &cts->proto_specific.scsi;
 2087                 struct ccb_trans_settings_fc *fc = &cts->xport_specific.fc;
 2088                 ocs_xport_stats_t value;
 2089                 ocs_fcport *fcp = FCPORT(ocs, bus);
 2090                 ocs_fc_target_t *tgt = NULL;
 2091 
 2092                 if (ocs->ocs_xport != OCS_XPORT_FC) {
 2093                         ocs_set_ccb_status(ccb, CAM_REQ_INVALID);
 2094                         xpt_done(ccb);
 2095                         break;
 2096                 }
 2097 
 2098                 if (cts->ccb_h.target_id > OCS_MAX_TARGETS) {
 2099                         ocs_set_ccb_status(ccb, CAM_DEV_NOT_THERE);
 2100                         xpt_done(ccb);
 2101                         break;
 2102                 }
 2103 
 2104                 tgt = &fcp->tgt[cts->ccb_h.target_id];
 2105                 if (tgt->state == OCS_TGT_STATE_NONE) { 
 2106                         ocs_set_ccb_status(ccb, CAM_DEV_NOT_THERE);
 2107                         xpt_done(ccb);
 2108                         break;
 2109                 }
 2110 
 2111                 cts->protocol = PROTO_SCSI;
 2112                 cts->protocol_version = SCSI_REV_SPC2;
 2113                 cts->transport = XPORT_FC;
 2114                 cts->transport_version = 2;
 2115 
 2116                 scsi->valid = CTS_SCSI_VALID_TQ;
 2117                 scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
 2118 
 2119                 /* speed in Mbps */
 2120                 ocs_xport_status(ocs->xport, OCS_XPORT_LINK_SPEED, &value);
 2121                 fc->bitrate = value.value * 100;
 2122 
 2123                 fc->wwpn = tgt->wwpn;
 2124 
 2125                 fc->wwnn = tgt->wwnn;
 2126 
 2127                 fc->port = tgt->port_id;
 2128 
 2129                 fc->valid = CTS_FC_VALID_SPEED |
 2130                         CTS_FC_VALID_WWPN |
 2131                         CTS_FC_VALID_WWNN |
 2132                         CTS_FC_VALID_PORT;
 2133 
 2134                 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
 2135                 xpt_done(ccb);
 2136                 break;
 2137         }
 2138         case XPT_SET_TRAN_SETTINGS:
 2139                 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
 2140                 xpt_done(ccb);
 2141                 break;
 2142 
 2143         case XPT_CALC_GEOMETRY:
 2144                 cam_calc_geometry(&ccb->ccg, TRUE);
 2145                 xpt_done(ccb);
 2146                 break;
 2147 
 2148         case XPT_GET_SIM_KNOB:
 2149         {
 2150                 struct ccb_sim_knob *knob = &ccb->knob;
 2151                 uint64_t wwn = 0;
 2152                 ocs_fcport *fcp = FCPORT(ocs, bus);
 2153 
 2154                 if (ocs->ocs_xport != OCS_XPORT_FC) {
 2155                         ocs_set_ccb_status(ccb, CAM_REQ_INVALID);
 2156                         xpt_done(ccb);
 2157                         break;
 2158                 }
 2159                 
 2160                 if (bus == 0) {
 2161                         wwn = *((uint64_t *)ocs_scsi_get_property_ptr(ocs,
 2162                                                 OCS_SCSI_WWNN));
 2163                         knob->xport_specific.fc.wwnn = be64toh(wwn);
 2164 
 2165                         wwn = *((uint64_t *)ocs_scsi_get_property_ptr(ocs,
 2166                                                 OCS_SCSI_WWPN));
 2167                         knob->xport_specific.fc.wwpn = be64toh(wwn);
 2168                 } else {
 2169                         knob->xport_specific.fc.wwnn = fcp->vport->wwnn;
 2170                         knob->xport_specific.fc.wwpn = fcp->vport->wwpn;
 2171                 }
 2172 
 2173                 knob->xport_specific.fc.role = fcp->role;
 2174                 knob->xport_specific.fc.valid = KNOB_VALID_ADDRESS |
 2175                                                 KNOB_VALID_ROLE;
 2176 
 2177                 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
 2178                 xpt_done(ccb);
 2179                 break;
 2180         }
 2181         case XPT_SET_SIM_KNOB:
 2182         {
 2183                 struct ccb_sim_knob *knob = &ccb->knob;
 2184                 bool role_changed = FALSE;
 2185                 ocs_fcport *fcp = FCPORT(ocs, bus);
 2186 
 2187                 if (ocs->ocs_xport != OCS_XPORT_FC) {
 2188                         ocs_set_ccb_status(ccb, CAM_REQ_INVALID);
 2189                         xpt_done(ccb);
 2190                         break;
 2191                 }
 2192                         
 2193                 if (knob->xport_specific.fc.valid & KNOB_VALID_ADDRESS) {
 2194                         device_printf(ocs->dev, 
 2195                                 "%s: XPT_SET_SIM_KNOB wwnn=%llx wwpn=%llx\n",
 2196                                         __func__,
 2197                                         (unsigned long long)knob->xport_specific.fc.wwnn,
 2198                                         (unsigned long long)knob->xport_specific.fc.wwpn);
 2199                 }
 2200 
 2201                 if (knob->xport_specific.fc.valid & KNOB_VALID_ROLE) {
 2202                         switch (knob->xport_specific.fc.role) {
 2203                         case KNOB_ROLE_NONE:
 2204                                 if (fcp->role != KNOB_ROLE_NONE) {
 2205                                         role_changed = TRUE;
 2206                                 }
 2207                                 break;
 2208                         case KNOB_ROLE_TARGET:
 2209                                 if (fcp->role != KNOB_ROLE_TARGET) {
 2210                                         role_changed = TRUE;
 2211                                 }
 2212                                 break;
 2213                         case KNOB_ROLE_INITIATOR:
 2214                                 if (fcp->role != KNOB_ROLE_INITIATOR) {
 2215                                         role_changed = TRUE;
 2216                                 }
 2217                                 break;
 2218                         case KNOB_ROLE_BOTH:
 2219                                 if (fcp->role != KNOB_ROLE_BOTH) {
 2220                                         role_changed = TRUE;
 2221                                 }
 2222                                 break;
 2223                         default:
 2224                                 device_printf(ocs->dev,
 2225                                         "%s: XPT_SET_SIM_KNOB unsupported role: %d\n",
 2226                                         __func__, knob->xport_specific.fc.role);
 2227                         }
 2228 
 2229                         if (role_changed) {
 2230                                 device_printf(ocs->dev,
 2231                                                 "BUS:%d XPT_SET_SIM_KNOB old_role: %d new_role: %d\n",
 2232                                                 bus, fcp->role, knob->xport_specific.fc.role);
 2233 
 2234                                 ocs_fcp_change_role(ocs, fcp, knob->xport_specific.fc.role);
 2235                         }
 2236                 }
 2237 
 2238                 
 2239 
 2240                 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
 2241                 xpt_done(ccb);
 2242                 break;
 2243         }
 2244         case XPT_ABORT:
 2245         {
 2246                 union ccb *accb = ccb->cab.abort_ccb;
 2247 
 2248                 switch (accb->ccb_h.func_code) {
 2249                 case XPT_ACCEPT_TARGET_IO:
 2250                         ocs_abort_atio(ocs, ccb);
 2251                         break;
 2252                 case XPT_IMMEDIATE_NOTIFY:
 2253                         ocs_abort_inot(ocs, ccb);
 2254                         break;
 2255                 case XPT_SCSI_IO:
 2256                         rc = ocs_abort_initiator_io(ocs, accb);
 2257                         if (rc) {
 2258                                 ccb->ccb_h.status = CAM_UA_ABORT;
 2259                         } else {
 2260                                 ccb->ccb_h.status = CAM_REQ_CMP;
 2261                         }
 2262 
 2263                         break;
 2264                 default:
 2265                         printf("abort of unknown func %#x\n",
 2266                                         accb->ccb_h.func_code);
 2267                         ccb->ccb_h.status = CAM_REQ_INVALID;
 2268                         break;
 2269                 }
 2270                 break;
 2271         }
 2272         case XPT_RESET_BUS:
 2273                 if (ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE) == 0) {
 2274                         rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE);
 2275                         if (rc) {
 2276                                 ocs_log_debug(ocs, "Failed to bring port online"
 2277                                                                 " : %d\n", rc);
 2278                         }
 2279                         ocs_set_ccb_status(ccb, CAM_REQ_CMP);
 2280                 } else {
 2281                         ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
 2282                 }
 2283                 xpt_done(ccb);
 2284                 break;
 2285         case XPT_RESET_DEV:
 2286         {
 2287                 ocs_node_t      *node = NULL;
 2288                 ocs_io_t        *io = NULL;
 2289                 int32_t         rc = 0;
 2290                 ocs_fcport *fcp = FCPORT(ocs, bus);
 2291 
 2292                 node = ocs_node_get_instance(ocs, fcp->tgt[ccb_h->target_id].node_id);
 2293                 if (node == NULL) {
 2294                         device_printf(ocs->dev, "%s: no device %d\n",
 2295                                                 __func__, ccb_h->target_id);
 2296                         ocs_set_ccb_status(ccb, CAM_DEV_NOT_THERE);
 2297                         xpt_done(ccb);
 2298                         break;
 2299                 }
 2300 
 2301                 io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_ORIGINATOR);
 2302                 if (io == NULL) {
 2303                         device_printf(ocs->dev, "%s: unable to alloc IO\n",
 2304                                                                  __func__);
 2305                         ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
 2306                         xpt_done(ccb);
 2307                         break;
 2308                 }
 2309 
 2310                 rc = ocs_scsi_send_tmf(node, io, NULL, ccb_h->target_lun,
 2311                                 OCS_SCSI_TMF_LOGICAL_UNIT_RESET,
 2312                                 NULL, 0, 0,     /* sgl, sgl_count, length */
 2313                                 ocs_initiator_tmf_cb, NULL/*arg*/);
 2314 
 2315                 if (rc) {
 2316                         ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
 2317                 } else {
 2318                         ocs_set_ccb_status(ccb, CAM_REQ_CMP);
 2319                 }
 2320                 
 2321                 if (node->fcp2device) {
 2322                         ocs_reset_crn(node, ccb_h->target_lun);
 2323                 }
 2324 
 2325                 xpt_done(ccb);
 2326                 break;
 2327         }
 2328         case XPT_EN_LUN:        /* target support */
 2329         {
 2330                 ocs_tgt_resource_t *trsrc = NULL;
 2331                 uint32_t        status = 0;
 2332                 ocs_fcport *fcp = FCPORT(ocs, bus);
 2333 
 2334                 device_printf(ocs->dev, "XPT_EN_LUN %sable %d:%d\n",
 2335                                 ccb->cel.enable ? "en" : "dis",
 2336                                 ccb->ccb_h.target_id,
 2337                                 (unsigned int)ccb->ccb_h.target_lun);
 2338 
 2339                 trsrc = ocs_tgt_resource_get(fcp, &ccb->ccb_h, &status);
 2340                 if (trsrc) {
 2341                         trsrc->enabled = ccb->cel.enable;
 2342 
 2343                         /* Abort all ATIO/INOT on LUN disable */
 2344                         if (trsrc->enabled == FALSE) {
 2345                                 ocs_tgt_resource_abort(ocs, trsrc);
 2346                         } else {
 2347                                 STAILQ_INIT(&trsrc->atio);
 2348                                 STAILQ_INIT(&trsrc->inot);
 2349                         }
 2350                         status = CAM_REQ_CMP;
 2351                 }
 2352 
 2353                 ocs_set_ccb_status(ccb, status);
 2354                 xpt_done(ccb);
 2355                 break;
 2356         }
 2357         /*
 2358          * The flow of target IOs in CAM is:
 2359          *  - CAM supplies a number of CCBs to the driver used for received
 2360          *    commands.
 2361          *  - when the driver receives a command, it copies the relevant
 2362          *    information to the CCB and returns it to the CAM using xpt_done()
 2363          *  - after the target server processes the request, it creates
 2364          *    a new CCB containing information on how to continue the IO and 
 2365          *    passes that to the driver
 2366          *  - the driver processes the "continue IO" (a.k.a CTIO) CCB
 2367          *  - once the IO completes, the driver returns the CTIO to the CAM 
 2368          *    using xpt_done()
 2369          */
 2370         case XPT_ACCEPT_TARGET_IO:      /* used to inform upper layer of 
 2371                                                 received CDB (a.k.a. ATIO) */
 2372         case XPT_IMMEDIATE_NOTIFY:      /* used to inform upper layer of other
 2373                                                          event (a.k.a. INOT) */
 2374         {
 2375                 ocs_tgt_resource_t *trsrc = NULL;
 2376                 uint32_t        status = 0;
 2377                 ocs_fcport *fcp = FCPORT(ocs, bus);
 2378 
 2379                 /*printf("XPT_%s %p\n", ccb_h->func_code == XPT_ACCEPT_TARGET_IO ?
 2380                                 "ACCEPT_TARGET_IO" : "IMMEDIATE_NOTIFY", ccb);*/
 2381                 trsrc = ocs_tgt_resource_get(fcp, &ccb->ccb_h, &status);
 2382                 if (trsrc == NULL) {
 2383                         ocs_set_ccb_status(ccb, CAM_DEV_NOT_THERE);
 2384                         xpt_done(ccb);
 2385                         break;
 2386                 }
 2387 
 2388                 if (XPT_ACCEPT_TARGET_IO == ccb->ccb_h.func_code) {
 2389                         struct ccb_accept_tio *atio = NULL;
 2390 
 2391                         atio = (struct ccb_accept_tio *)ccb;
 2392                         atio->init_id = 0x0badbeef;
 2393                         atio->tag_id  = 0xdeadc0de;
 2394 
 2395                         STAILQ_INSERT_TAIL(&trsrc->atio, &ccb->ccb_h, 
 2396                                         sim_links.stqe);
 2397                 } else {
 2398                         STAILQ_INSERT_TAIL(&trsrc->inot, &ccb->ccb_h, 
 2399                                         sim_links.stqe);
 2400                 }
 2401                 ccb->ccb_h.ccb_io_ptr  = NULL;
 2402                 ccb->ccb_h.ccb_ocs_ptr = ocs;
 2403                 ocs_set_ccb_status(ccb, CAM_REQ_INPROG);
 2404                 /*
 2405                  * These actions give resources to the target driver.
 2406                  * If we didn't return here, this function would call
 2407                  * xpt_done(), signaling to the upper layers that an
 2408                  * IO or other event had arrived.
 2409                  */
 2410                 break;
 2411         }
 2412         case XPT_NOTIFY_ACKNOWLEDGE:
 2413         {
 2414                 ocs_io_t *io = NULL;
 2415                 ocs_io_t *abortio = NULL;
 2416 
 2417                 /* Get the IO reference for this tag */
 2418                 io = ocs_scsi_find_io(ocs, ccb->cna2.tag_id);
 2419                 if (io == NULL) {
 2420                         device_printf(ocs->dev,
 2421                                 "%s: XPT_NOTIFY_ACKNOWLEDGE no IO with tag %#x\n",
 2422                                         __func__, ccb->cna2.tag_id);
 2423                         ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
 2424                         xpt_done(ccb);
 2425                         break;
 2426                 }
 2427 
 2428                 abortio = io->tgt_io.app;
 2429                 if (abortio) {
 2430                         abortio->tgt_io.flags &= ~OCS_CAM_IO_F_ABORT_NOTIFY;
 2431                         device_printf(ocs->dev,
 2432                                 "%s: XPT_NOTIFY_ACK state=%d tag=%#x xid=%#x"
 2433                                 " flags=%#x\n", __func__, abortio->tgt_io.state,
 2434                                 abortio->tag, abortio->init_task_tag,
 2435                                         abortio->tgt_io.flags);
 2436                         /* TMF response was sent in abort callback */
 2437                 } else {
 2438                         ocs_scsi_send_tmf_resp(io, 
 2439                                         OCS_SCSI_TMF_FUNCTION_COMPLETE,
 2440                                         NULL, ocs_target_tmf_cb, NULL);
 2441                 }
 2442 
 2443                 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
 2444                 xpt_done(ccb);
 2445                 break;
 2446         }
 2447         case XPT_CONT_TARGET_IO:        /* continue target IO, sending data/response (a.k.a. CTIO) */
 2448                 if (ocs_target_io(ocs, ccb)) {
 2449                         device_printf(ocs->dev, 
 2450                                 "XPT_CONT_TARGET_IO failed flags=%x tag=%#x\n",
 2451                                 ccb->ccb_h.flags, ccb->csio.tag_id);
 2452                         xpt_done(ccb);
 2453                 }
 2454                 break;
 2455         default:
 2456                 device_printf(ocs->dev, "unhandled func_code = %#x\n",
 2457                                 ccb_h->func_code);
 2458                 ccb_h->status = CAM_REQ_INVALID;
 2459                 xpt_done(ccb);
 2460                 break;
 2461         }
 2462 }
 2463 
 2464 /**
 2465  * @ingroup cam_api
 2466  * @brief Process events
 2467  *
 2468  * @param sim pointer to the SCSI Interface Module
 2469  *
 2470  */
 2471 static void
 2472 ocs_poll(struct cam_sim *sim)
 2473 {
 2474         printf("%s\n", __func__);
 2475 }
 2476 
 2477 static int32_t
 2478 ocs_initiator_tmf_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status,
 2479                 ocs_scsi_cmd_resp_t *rsp, uint32_t flags, void *arg)
 2480 {
 2481         int32_t rc = 0;
 2482 
 2483         switch (scsi_status) {
 2484         case OCS_SCSI_STATUS_GOOD:
 2485         case OCS_SCSI_STATUS_NO_IO:
 2486                 break;
 2487         case OCS_SCSI_STATUS_CHECK_RESPONSE:
 2488                 if (rsp->response_data_length == 0) {
 2489                         ocs_log_test(io->ocs, "check response without data?!?\n");
 2490                         rc = -1;
 2491                         break;
 2492                 }
 2493 
 2494                 if (rsp->response_data[3] != 0) {
 2495                         ocs_log_test(io->ocs, "TMF status %08x\n",
 2496                                 be32toh(*((uint32_t *)rsp->response_data)));
 2497                         rc = -1;
 2498                         break;
 2499                 }
 2500                 break;
 2501         default:
 2502                 ocs_log_test(io->ocs, "status=%#x\n", scsi_status);
 2503                 rc = -1;
 2504         }
 2505 
 2506         ocs_scsi_io_free(io);
 2507 
 2508         return rc;
 2509 }
 2510 
 2511 /**
 2512  * @brief lookup target resource structure
 2513  *
 2514  * Arbitrarily support
 2515  *  - wildcard target ID + LU
 2516  *  - 0 target ID + non-wildcard LU
 2517  *
 2518  * @param ocs the driver instance's software context
 2519  * @param ccb_h pointer to the CCB header
 2520  * @param status returned status value
 2521  *
 2522  * @return pointer to the target resource, NULL if none available (e.g. if LU
 2523  *         is not enabled)
 2524  */
 2525 static ocs_tgt_resource_t *ocs_tgt_resource_get(ocs_fcport *fcp, 
 2526                                 struct ccb_hdr *ccb_h, uint32_t *status)
 2527 {
 2528         target_id_t     tid = ccb_h->target_id;
 2529         lun_id_t        lun = ccb_h->target_lun;
 2530 
 2531         if (CAM_TARGET_WILDCARD == tid) {
 2532                 if (CAM_LUN_WILDCARD != lun) {
 2533                         *status = CAM_LUN_INVALID;
 2534                         return NULL;
 2535                 }
 2536                 return &fcp->targ_rsrc_wildcard;
 2537         } else {
 2538                 if (lun < OCS_MAX_LUN) {
 2539                         return &fcp->targ_rsrc[lun];
 2540                 } else {
 2541                         *status = CAM_LUN_INVALID;
 2542                         return NULL;
 2543                 }
 2544         } 
 2545 
 2546 }
 2547 
 2548 static int32_t
 2549 ocs_tgt_resource_abort(struct ocs_softc *ocs, ocs_tgt_resource_t *trsrc)
 2550 {
 2551         union ccb *ccb = NULL;
 2552         uint32_t        count;
 2553 
 2554         count = 0;
 2555         do {
 2556                 ccb = (union ccb *)STAILQ_FIRST(&trsrc->atio);
 2557                 if (ccb) {
 2558                         STAILQ_REMOVE_HEAD(&trsrc->atio, sim_links.stqe);
 2559                         ccb->ccb_h.status = CAM_REQ_ABORTED;
 2560                         xpt_done(ccb);
 2561                         count++;
 2562                 }
 2563         } while (ccb);
 2564 
 2565         count = 0;
 2566         do {
 2567                 ccb = (union ccb *)STAILQ_FIRST(&trsrc->inot);
 2568                 if (ccb) {
 2569                         STAILQ_REMOVE_HEAD(&trsrc->inot, sim_links.stqe);
 2570                         ccb->ccb_h.status = CAM_REQ_ABORTED;
 2571                         xpt_done(ccb);
 2572                         count++;
 2573                 }
 2574         } while (ccb);
 2575 
 2576         return 0;
 2577 }
 2578 
 2579 static void
 2580 ocs_abort_atio(struct ocs_softc *ocs, union ccb *ccb)
 2581 {
 2582 
 2583         ocs_io_t        *aio = NULL;
 2584         ocs_tgt_resource_t *trsrc = NULL;
 2585         uint32_t        status = CAM_REQ_INVALID;
 2586         struct ccb_hdr *cur = NULL;
 2587         union ccb *accb = ccb->cab.abort_ccb;
 2588 
 2589         int bus = cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path));
 2590         ocs_fcport *fcp = FCPORT(ocs, bus); 
 2591 
 2592         trsrc = ocs_tgt_resource_get(fcp, &accb->ccb_h, &status);
 2593         if (trsrc != NULL) {
 2594                 STAILQ_FOREACH(cur, &trsrc->atio, sim_links.stqe) {
 2595                         if (cur != &accb->ccb_h) 
 2596                                 continue;
 2597 
 2598                         STAILQ_REMOVE(&trsrc->atio, cur, ccb_hdr,
 2599                                                         sim_links.stqe);
 2600                         accb->ccb_h.status = CAM_REQ_ABORTED;
 2601                         xpt_done(accb);
 2602                         ocs_set_ccb_status(ccb, CAM_REQ_CMP);
 2603                         return;
 2604                 }
 2605         }
 2606 
 2607         /* if the ATIO has a valid IO pointer, CAM is telling
 2608          * the driver that the ATIO (which represents the entire
 2609          * exchange) has been aborted. */
 2610 
 2611         aio = accb->ccb_h.ccb_io_ptr;
 2612         if (aio == NULL) {
 2613                 ccb->ccb_h.status = CAM_UA_ABORT;
 2614                 return;
 2615         }
 2616 
 2617         device_printf(ocs->dev,
 2618                         "%s: XPT_ABORT ATIO state=%d tag=%#x"
 2619                         " xid=%#x flags=%#x\n", __func__, 
 2620                         aio->tgt_io.state, aio->tag, 
 2621                         aio->init_task_tag, aio->tgt_io.flags);
 2622         /* Expectations are:
 2623          *  - abort task was received
 2624          *  - already aborted IO in the DEVICE
 2625          *  - already received NOTIFY ACKNOWLEDGE */
 2626 
 2627         if ((aio->tgt_io.flags & OCS_CAM_IO_F_ABORT_RECV) == 0) {
 2628                 device_printf(ocs->dev, "%s: abort not received or io completed \n", __func__);
 2629                 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
 2630                 return;
 2631         }
 2632 
 2633         aio->tgt_io.flags |= OCS_CAM_IO_F_ABORT_CAM;
 2634         ocs_target_io_free(aio);
 2635         ocs_set_ccb_status(ccb, CAM_REQ_CMP);
 2636 
 2637         return;
 2638 }
 2639 
 2640 static void
 2641 ocs_abort_inot(struct ocs_softc *ocs, union ccb *ccb)
 2642 {
 2643         ocs_tgt_resource_t *trsrc = NULL;
 2644         uint32_t        status = CAM_REQ_INVALID;
 2645         struct ccb_hdr *cur = NULL;
 2646         union ccb *accb = ccb->cab.abort_ccb;
 2647 
 2648         int bus = cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path));
 2649         ocs_fcport *fcp = FCPORT(ocs, bus); 
 2650 
 2651         trsrc = ocs_tgt_resource_get(fcp, &accb->ccb_h, &status);
 2652         if (trsrc) {
 2653                 STAILQ_FOREACH(cur, &trsrc->inot, sim_links.stqe) {
 2654                         if (cur != &accb->ccb_h) 
 2655                                 continue;
 2656 
 2657                         STAILQ_REMOVE(&trsrc->inot, cur, ccb_hdr,
 2658                                                         sim_links.stqe);
 2659                         accb->ccb_h.status = CAM_REQ_ABORTED;
 2660                         xpt_done(accb);
 2661                         ocs_set_ccb_status(ccb, CAM_REQ_CMP);
 2662                         return;
 2663                 }
 2664         }
 2665 
 2666         ocs_set_ccb_status(ccb, CAM_UA_ABORT);
 2667         return;
 2668 }
 2669 
 2670 static uint32_t
 2671 ocs_abort_initiator_io(struct ocs_softc *ocs, union ccb *accb)
 2672 {
 2673 
 2674         ocs_node_t      *node = NULL;
 2675         ocs_io_t        *io = NULL;
 2676         int32_t         rc = 0;
 2677         struct ccb_scsiio *csio = &accb->csio;
 2678 
 2679         ocs_fcport *fcp = FCPORT(ocs, cam_sim_bus(xpt_path_sim((accb)->ccb_h.path)));
 2680         node = ocs_node_get_instance(ocs, fcp->tgt[accb->ccb_h.target_id].node_id);
 2681         if (node == NULL) {
 2682                 device_printf(ocs->dev, "%s: no device %d\n", 
 2683                                 __func__, accb->ccb_h.target_id);
 2684                 ocs_set_ccb_status(accb, CAM_DEV_NOT_THERE);
 2685                 xpt_done(accb);
 2686                 return (-1);
 2687         }
 2688 
 2689         io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_ORIGINATOR);
 2690         if (io == NULL) {
 2691                 device_printf(ocs->dev,
 2692                                 "%s: unable to alloc IO\n", __func__);
 2693                 ocs_set_ccb_status(accb, CAM_REQ_CMP_ERR);
 2694                 xpt_done(accb);
 2695                 return (-1);
 2696         }
 2697 
 2698         rc = ocs_scsi_send_tmf(node, io, 
 2699                         (ocs_io_t *)csio->ccb_h.ccb_io_ptr,
 2700                         accb->ccb_h.target_lun,
 2701                         OCS_SCSI_TMF_ABORT_TASK,
 2702                         NULL, 0, 0,
 2703                         ocs_initiator_tmf_cb, NULL/*arg*/);
 2704 
 2705         return rc;
 2706 }
 2707 
 2708 void
 2709 ocs_scsi_ini_ddump(ocs_textbuf_t *textbuf, ocs_scsi_ddump_type_e type, void *obj)
 2710 {
 2711         switch(type) {
 2712         case OCS_SCSI_DDUMP_DEVICE: {
 2713                 //ocs_t *ocs = obj;
 2714                 break;
 2715         }
 2716         case OCS_SCSI_DDUMP_DOMAIN: {
 2717                 //ocs_domain_t *domain = obj;
 2718                 break;
 2719         }
 2720         case OCS_SCSI_DDUMP_SPORT: {
 2721                 //ocs_sport_t *sport = obj;
 2722                 break;
 2723         }
 2724         case OCS_SCSI_DDUMP_NODE: {
 2725                 //ocs_node_t *node = obj;
 2726                 break;
 2727         }
 2728         case OCS_SCSI_DDUMP_IO: {
 2729                 //ocs_io_t *io = obj;
 2730                 break;
 2731         }
 2732         default: {
 2733                 break;
 2734         }
 2735         }
 2736 }
 2737 
 2738 void
 2739 ocs_scsi_tgt_ddump(ocs_textbuf_t *textbuf, ocs_scsi_ddump_type_e type, void *obj)
 2740 {
 2741         switch(type) {
 2742         case OCS_SCSI_DDUMP_DEVICE: {
 2743                 //ocs_t *ocs = obj;
 2744                 break;
 2745         }
 2746         case OCS_SCSI_DDUMP_DOMAIN: {
 2747                 //ocs_domain_t *domain = obj;
 2748                 break;
 2749         }
 2750         case OCS_SCSI_DDUMP_SPORT: {
 2751                 //ocs_sport_t *sport = obj;
 2752                 break;
 2753         }
 2754         case OCS_SCSI_DDUMP_NODE: {
 2755                 //ocs_node_t *node = obj;
 2756                 break;
 2757         }
 2758         case OCS_SCSI_DDUMP_IO: {
 2759                 ocs_io_t *io = obj;
 2760                 char *state_str = NULL;
 2761 
 2762                 switch (io->tgt_io.state) {
 2763                 case OCS_CAM_IO_FREE:
 2764                         state_str = "FREE";
 2765                         break;
 2766                 case OCS_CAM_IO_COMMAND:
 2767                         state_str = "COMMAND";
 2768                         break;
 2769                 case OCS_CAM_IO_DATA:
 2770                         state_str = "DATA";
 2771                         break;
 2772                 case OCS_CAM_IO_DATA_DONE:
 2773                         state_str = "DATA_DONE";
 2774                         break;
 2775                 case OCS_CAM_IO_RESP:
 2776                         state_str = "RESP";
 2777                         break;
 2778                 default:
 2779                         state_str = "xxx BAD xxx";
 2780                 }
 2781                 ocs_ddump_value(textbuf, "cam_st", "%s", state_str);
 2782                 if (io->tgt_io.app) {
 2783                         ocs_ddump_value(textbuf, "cam_flags", "%#x",
 2784                                 ((union ccb *)(io->tgt_io.app))->ccb_h.flags);
 2785                         ocs_ddump_value(textbuf, "cam_status", "%#x",
 2786                                 ((union ccb *)(io->tgt_io.app))->ccb_h.status);
 2787                 }
 2788 
 2789                 break;
 2790         }
 2791         default: {
 2792                 break;
 2793         }
 2794         }
 2795 }
 2796 
 2797 int32_t ocs_scsi_get_block_vaddr(ocs_io_t *io, uint64_t blocknumber,
 2798                                 ocs_scsi_vaddr_len_t addrlen[],
 2799                                 uint32_t max_addrlen, void **dif_vaddr)
 2800 {
 2801         return -1;
 2802 }
 2803 
 2804 uint32_t
 2805 ocs_get_crn(ocs_node_t *node, uint8_t *crn, uint64_t lun)
 2806 {
 2807         uint32_t idx;
 2808         struct ocs_lun_crn *lcrn = NULL;
 2809         idx = lun % OCS_MAX_LUN;
 2810 
 2811         lcrn = node->ini_node.lun_crn[idx];
 2812 
 2813         if (lcrn == NULL) {
 2814                 lcrn = ocs_malloc(node->ocs, sizeof(struct ocs_lun_crn),
 2815                                         M_ZERO|M_NOWAIT);
 2816                 if (lcrn == NULL) {
 2817                         return (1);
 2818                 }
 2819                 
 2820                 lcrn->lun = lun;
 2821                 node->ini_node.lun_crn[idx] = lcrn;
 2822         }
 2823 
 2824         if (lcrn->lun != lun) {
 2825                 return (1);
 2826         }       
 2827 
 2828         if (lcrn->crnseed == 0)
 2829                 lcrn->crnseed = 1;
 2830 
 2831         *crn = lcrn->crnseed++;
 2832         return (0);
 2833 }
 2834 
 2835 void
 2836 ocs_del_crn(ocs_node_t *node)
 2837 {
 2838         uint32_t i;
 2839         struct ocs_lun_crn *lcrn = NULL;
 2840 
 2841         for(i = 0; i < OCS_MAX_LUN; i++) {
 2842                 lcrn = node->ini_node.lun_crn[i];
 2843                 if (lcrn) {
 2844                         ocs_free(node->ocs, lcrn, sizeof(*lcrn));
 2845                 }
 2846         }
 2847 
 2848         return;
 2849 }
 2850 
 2851 void
 2852 ocs_reset_crn(ocs_node_t *node, uint64_t lun)
 2853 {
 2854         uint32_t idx;
 2855         struct ocs_lun_crn *lcrn = NULL;
 2856         idx = lun % OCS_MAX_LUN;
 2857 
 2858         lcrn = node->ini_node.lun_crn[idx];
 2859         if (lcrn)
 2860                 lcrn->crnseed = 0;
 2861 
 2862         return;
 2863 }

Cache object: 9fa550cc705e828e765664d487da65d7


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